diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 7a63b31..294b107 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -11,9 +11,9 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: '17' + java-version: '21' - name: Validate gradlew integrity - uses: gradle/wrapper-validation-action@v3 + uses: gradle/actions/wrapper-validation@v3 - name: Cache uses: actions/cache@v4 with: @@ -35,7 +35,7 @@ jobs: run: | VERSION=$(awk -F '=' '/^version/ { print $2; }' build.properties) BUILD=$(awk -F '=' '/build_number/ { print $2; }' build.properties) - echo "forge=build/libs/AkashicTome-${VERSION}-${BUILD}.jar" >> "$GITHUB_OUTPUT" + echo "neoforge=build/libs/AkashicTome-${VERSION}-${BUILD}.jar" >> "$GITHUB_OUTPUT" - name: Sign jars env: SIGNING_KEY: ${{ secrets.VIOLET_MOON_SIGNING_KEY }} @@ -43,20 +43,21 @@ jobs: run: | echo "${SIGNING_KEY}" | gpg --import - gpg --local-user "Violet Moon Signing Key" --armor \ - --detach-sign ${{ steps.calculate_artifact_names.outputs.forge }} - - name: Archive Forge Artifacts + --detach-sign ${{ steps.calculate_artifact_names.outputs.neoforge }} + - name: Archive NeoForge Artifacts + uses: actions/upload-artifact@v4 with: - name: Forge + name: NeoForge path: | - ${{ steps.calculate_artifact_names.outputs.forge }} - ${{ steps.calculate_artifact_names.outputs.forge }}.asc + ${{ steps.calculate_artifact_names.outputs.neoforge }} + ${{ steps.calculate_artifact_names.outputs.neoforge }}.asc - name: Upload Releases if: startsWith(github.ref, 'refs/tags/release-') env: GH_TOKEN: ${{ github.token }} GIT_REF: ${{ github.ref }} - FORGE_JAR: ${{ steps.calculate_artifact_names.outputs.forge }} + NEOFORGE_JAR: ${{ steps.calculate_artifact_names.outputs.neoforge }} CURSEFORGE_TOKEN: ${{ secrets.VAZKII_CURSEFORGE_TOKEN }} MODRINTH_TOKEN: ${{ secrets.VAZKII_MODRINTH_TOKEN }} run: | diff --git a/.gitignore b/.gitignore index c53f725..c044b64 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ Thumbs.db ## ForgeGradle /run +/runs ## eclipse /.settings diff --git a/build.gradle b/build.gradle index b46662f..a1fb9a8 100644 --- a/build.gradle +++ b/build.gradle @@ -2,10 +2,8 @@ plugins { id 'eclipse' id 'maven-publish' id 'pmd' - id 'com.diffplug.spotless' version '5.12.5' - id 'net.minecraftforge.gradle' version '5.1.+' - id 'org.parchmentmc.librarian.forgegradle' version '1.+' - id 'org.spongepowered.mixin' version '0.7.+' + id 'com.diffplug.spotless' version '6.25.0' + id 'net.neoforged.gradle.userdev' version '7.0.145' } ext.configFile = file('build.properties') @@ -15,7 +13,15 @@ version = "${config.version}-${config.build_number}" group = "vazkii.${config.mod_id}" // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = config.mod_name -java.toolchain.languageVersion = JavaLanguageVersion.of(17) +repositories { + mavenLocal() +} + +base { + archivesName = config.mod_name +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(21) compileJava.options.compilerArgs << "-Xlint:all,-classfile,-processing,-deprecation" << "-Werror" @@ -23,50 +29,14 @@ if (System.getenv('BUILD_NUMBER') != null) { version += "." + System.getenv('BUILD_NUMBER') } -minecraft { - // The mappings can be changed at any time, and must be in the following format. - // snapshot_YYYYMMDD Snapshot are built nightly. - // stable_# Stables are built at the discretion of the MCP team. - // Use non-default mappings at your own risk. they may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - - mappings channel: "${config.mapping_channel}", version: "${config.mapping_version}" - // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. - - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - client { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - - // Recommended logging level for the console - property 'forge.logging.console.level', 'debug' - - mods { - akashictome { - source sourceSets.main - } - } - } - - server { - workingDirectory project.file('run') - - // Recommended logging data for a userdev environment - property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' - - // Recommended logging level for the console - property 'forge.logging.console.level', 'debug' +runs { + configureEach { + systemProperty 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + systemProperty 'forge.logging.console.level', 'debug' + modSource project.sourceSets.main + } - mods { - akashictome { - source sourceSets.main - } - } - } + client { } } @@ -77,10 +47,9 @@ repositories { } dependencies { - minecraft "net.minecraftforge:forge:${config.mc_version}-${config.forge_version}" - implementation fg.deobf("curse.maven:curios-309927:5367944") - implementation fg.deobf("curse.maven:patchouli-306770:4966125") - implementation fg.deobf("curse.maven:botania-225643:5594997") + implementation "net.neoforged:neoforge:21.1.1" + implementation "curse.maven:patchouli-306770:5683901" + implementation "curse.maven:forcecraft-454802:6020123" } spotless { @@ -96,10 +65,8 @@ spotless { } pmd { - toolVersion '6.22.0' - // no way around this warning unless we upgrade Gradle, apparently - //incrementalAnalysis.set(true) - ruleSets.clear() + toolVersion '6.35.0' + incrementalAnalysis.set(true) ruleSetFiles = files("spotless/pmd-ruleset.xml") } @@ -118,7 +85,7 @@ task incrementBuildNumber { import java.util.regex.Pattern task sortArtifacts(type: Copy) { - from jar.destinationDir + from jar.getDestinationDirectory() into config.dir_output //Put each jar with a classifier in a subfolder with the classifier as its name eachFile { @@ -145,7 +112,7 @@ def parseConfig(File config) { jar { //rename the default output, for some better... sanity with scipts - archiveName = "${baseName}-${version}.${extension}" + //archiveName = "${baseName}-${version}.${extension}" manifest { attributes([ diff --git a/build.properties b/build.properties index c7021ae..234d88e 100644 --- a/build.properties +++ b/build.properties @@ -1,11 +1,11 @@ #Wed Aug 07 18:14:17 UTC 2024 -mapping_channel=parchment -forge_version=47.2.0 +neoforge_version=21.1.90 mod_id=akashictome dir_repo=./ build_number=28 dir_output=../Build Output/AkashicTome/ -mapping_version=2023.09.03-1.20.1 -version=1.7 +version=1.8 mod_name=AkashicTome -mc_version=1.20.1 +mc_version=1.21.1 +neogradle.subsystems.parchment.minecraftVersion=1.21 +neogradle.subsystems.parchment.mappingsVersion=2024.11.17 diff --git a/changelog.txt b/changelog.txt index a84328f..deab754 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1 @@ -- Ported to 1.20.1 (1.21 port is coming next) -- Book is now slightly different rendered -- Book render now changes height based on the selection area's height -- Fix: Removing a book from the Tome changes its title to the raw name -- Fix: Changing book option when looking at a mod's block is using the raw name \ No newline at end of file +- Ported to 1.21.1 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3c472b9..60a4196 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip \ No newline at end of file diff --git a/scripts/upload_releases.sh b/scripts/upload_releases.sh index 8f1e71b..b61253c 100755 --- a/scripts/upload_releases.sh +++ b/scripts/upload_releases.sh @@ -19,19 +19,19 @@ function release_github() { -f tag_name="${TAGNAME}")" GH_RELEASE_PAGE=$(echo "$GH_RELEASE_RESPONSE" | jq -r .html_url) - echo >&2 'Uploading Forge Jar and Signature to GitHub' - gh release upload "${TAGNAME}" "${FORGE_JAR}#Forge Jar" - gh release upload "${TAGNAME}" "${FORGE_JAR}.asc#Forge Signature" + echo >&2 'Uploading NeoForge Jar and Signature to GitHub' + gh release upload "${TAGNAME}" "${NEOFORGE_JAR}#NeoForge Jar" + gh release upload "${TAGNAME}" "${NEOFORGE_JAR}.asc#NeoForge Signature" } function release_modrinth() { - echo >&2 'Uploading Forge Jar to Modrinth' - local MODRINTH_FORGE_SPEC - MODRINTH_FORGE_SPEC=$(cat <&2 'Uploading NeoForge Jar to Modrinth' + local MODRINTH_NEOFORGE_SPEC + MODRINTH_NEOFORGE_SPEC=$(cat <&2 'Uploading Forge Jar to CurseForge' - local CURSEFORGE_FORGE_SPEC - CURSEFORGE_FORGE_SPEC=$(cat <&2 'Uploading NeoForge Jar to CurseForge' + local CURSEFORGE_NEOFORGE_SPEC + CURSEFORGE_NEOFORGE_SPEC=$(cat < ClientProxy::new, () -> CommonProxy::new); + proxy = dist.isClient() ? new ClientProxy() : new CommonProxy(); proxy.preInit(); } - - public void commonSetup(FMLCommonSetupEvent event) { - NetworkHandler.register(); - } - - private void addToCreativeTab(BuildCreativeModeTabContentsEvent event) { - if (event.getTabKey() == CreativeModeTabs.TOOLS_AND_UTILITIES) { - event.accept(Registries.TOME); - } - } } diff --git a/src/main/java/vazkii/akashictome/AttachementRecipe.java b/src/main/java/vazkii/akashictome/AttachementRecipe.java index 341ce35..62a678b 100644 --- a/src/main/java/vazkii/akashictome/AttachementRecipe.java +++ b/src/main/java/vazkii/akashictome/AttachementRecipe.java @@ -1,41 +1,45 @@ package vazkii.akashictome; +import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; -import net.minecraft.core.RegistryAccess; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingInput; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.level.Level; -import net.minecraftforge.registries.ForgeRegistries; + +import vazkii.akashictome.data_components.ToolContentComponent; public class AttachementRecipe extends CustomRecipe { - public AttachementRecipe(ResourceLocation idIn, CraftingBookCategory pCategory) { - super(idIn, pCategory); + public AttachementRecipe(CraftingBookCategory pCategory) { + super(pCategory); } @Override - public boolean matches(CraftingContainer var1, Level var2) { + public boolean matches(CraftingInput input, Level level) { boolean foundTool = false; boolean foundTarget = false; - for (int i = 0; i < var1.getContainerSize(); i++) { - ItemStack stack = var1.getItem(i); + for (int i = 0; i < input.size(); i++) { + ItemStack stack = input.getItem(i); if (!stack.isEmpty()) { if (isTarget(stack)) { - if (foundTarget) + if (foundTarget) { return false; + } foundTarget = true; } else if (stack.is(Registries.TOME.get())) { - if (foundTool) + if (foundTool) { return false; + } foundTool = true; - } else + } else { return false; + } } } @@ -43,47 +47,46 @@ public boolean matches(CraftingContainer var1, Level var2) { } @Override - public ItemStack assemble(CraftingContainer var1, RegistryAccess pRegistryAccess) { + public ItemStack assemble(CraftingInput input, HolderLookup.Provider provider) { ItemStack tool = ItemStack.EMPTY; ItemStack target = ItemStack.EMPTY; - for (int i = 0; i < var1.getContainerSize(); i++) { - ItemStack stack = var1.getItem(i); + for (int i = 0; i < input.size(); i++) { + ItemStack stack = input.getItem(i); if (!stack.isEmpty()) { - if (stack.is(Registries.TOME.get())) + if (stack.is(Registries.TOME.get())) { tool = stack; - else + } else { target = stack; + } } } + if (!tool.has(Registries.TOOL_CONTENT)) + return ItemStack.EMPTY; ItemStack copy = tool.copy(); - CompoundTag cmp = copy.getTag(); - if (cmp == null) { - cmp = new CompoundTag(); - copy.setTag(cmp); + ToolContentComponent contents = copy.get(Registries.TOOL_CONTENT); + if (contents == null) { + return ItemStack.EMPTY; } - if (!cmp.contains(MorphingHandler.TAG_TOME_DATA)) - cmp.put(MorphingHandler.TAG_TOME_DATA, new CompoundTag()); - - CompoundTag morphData = cmp.getCompound(MorphingHandler.TAG_TOME_DATA); - String mod = MorphingHandler.getModFromStack(target); String modRoot = mod; int tries = 0; - while (morphData.contains(mod) && tries < 99) { + while (contents.hasDefinedMod(mod) && tries < 99) { mod = modRoot + "_" + tries; tries++; } - CompoundTag modCmp = new CompoundTag(); - if (tries > 0) - NBTUtils.setString(target, MorphingHandler.TAG_ITEM_DEFINED_MOD, mod); + target.set(Registries.DEFINED_MOD, mod); + + ToolContentComponent.Mutable mutable = new ToolContentComponent.Mutable(contents); + if (!target.isEmpty()) { + mutable.tryInsert(target); + } - target.save(modCmp); - morphData.put(mod, modCmp); + copy.set(Registries.TOOL_CONTENT, mutable.toImmutable()); return copy; } @@ -111,7 +114,7 @@ public boolean isTarget(ItemStack stack) { if (stack.getItem() instanceof IModdedBook) return true; - ResourceLocation registryNameRL = ForgeRegistries.ITEMS.getKey(stack.getItem()); + ResourceLocation registryNameRL = BuiltInRegistries.ITEM.getKey(stack.getItem()); String registryName = registryNameRL.toString(); if (ConfigHandler.whitelistedItems.get().contains(registryName) || ConfigHandler.whitelistedItems.get().contains(registryName + ":" + stack.getDamageValue())) return true; @@ -125,13 +128,13 @@ public boolean isTarget(ItemStack stack) { } @Override - public ItemStack getResultItem(RegistryAccess pRegistryAccess) { + public ItemStack getResultItem(HolderLookup.Provider provider) { return ItemStack.EMPTY; } @Override - public NonNullList getRemainingItems(CraftingContainer inv) { - return NonNullList.withSize(inv.getContainerSize(), ItemStack.EMPTY); + public NonNullList getRemainingItems(CraftingInput craftingInput) { + return NonNullList.withSize(craftingInput.size(), ItemStack.EMPTY); } @Override diff --git a/src/main/java/vazkii/akashictome/ConfigHandler.java b/src/main/java/vazkii/akashictome/ConfigHandler.java index 2239aea..022ad96 100644 --- a/src/main/java/vazkii/akashictome/ConfigHandler.java +++ b/src/main/java/vazkii/akashictome/ConfigHandler.java @@ -2,7 +2,7 @@ import com.google.common.collect.Lists; -import net.minecraftforge.common.ForgeConfigSpec; +import net.neoforged.neoforge.common.ModConfigSpec; import org.apache.commons.lang3.tuple.Pair; @@ -11,21 +11,21 @@ public class ConfigHandler { - public static ForgeConfigSpec.BooleanValue allItems; - public static ForgeConfigSpec.ConfigValue> whitelistedItems, whitelistedNames, blacklistedMods; - public static ForgeConfigSpec.ConfigValue> aliasesList; - public static ForgeConfigSpec.BooleanValue hideBookRender; - + public static ModConfigSpec.BooleanValue allItems; + public static ModConfigSpec.ConfigValue> whitelistedItems, whitelistedNames, blacklistedMods; + public static ModConfigSpec.ConfigValue> aliasesList; + public static ModConfigSpec.BooleanValue hideBookRender; + static final ConfigHandler CONFIG; - static final ForgeConfigSpec CONFIG_SPEC; + static final ModConfigSpec CONFIG_SPEC; static { - final Pair specPair = new ForgeConfigSpec.Builder().configure(ConfigHandler::new); + final Pair specPair = new ModConfigSpec.Builder().configure(ConfigHandler::new); CONFIG = specPair.getLeft(); CONFIG_SPEC = specPair.getRight(); } - public ConfigHandler(ForgeConfigSpec.Builder builder) { + public ConfigHandler(ModConfigSpec.Builder builder) { allItems = builder.define("Allow all items to be added", false); Predicate validator = o -> o instanceof String; @@ -47,7 +47,8 @@ public ConfigHandler(ForgeConfigSpec.Builder builder) { "tconstruct:tinkers_gadgetry", "tconstruct:fantastic_foundry", "tetra:holo", - "occultism:dictionary_of_spirits"), validator); + "occultism:dictionary_of_spirits"), + validator); whitelistedNames = builder.defineList("Whitelisted Names", Lists.newArrayList("book", @@ -86,7 +87,7 @@ public ConfigHandler(ForgeConfigSpec.Builder builder) { "buildcraftfactory=buildcraft", "buildcraftsilicon=buildcraft"), validator); - + hideBookRender = builder.define("Hide Book Render", false); } } diff --git a/src/main/java/vazkii/akashictome/MorphingHandler.java b/src/main/java/vazkii/akashictome/MorphingHandler.java index cdc78a3..ff5bbd9 100644 --- a/src/main/java/vazkii/akashictome/MorphingHandler.java +++ b/src/main/java/vazkii/akashictome/MorphingHandler.java @@ -1,24 +1,25 @@ package vazkii.akashictome; import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.chat.Style; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.event.entity.item.ItemTossEvent; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.forgespi.language.IModInfo; -import net.minecraftforge.registries.ForgeRegistries; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.ModList; +import net.neoforged.neoforge.event.entity.item.ItemTossEvent; +import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; +import net.neoforged.neoforgespi.language.IModInfo; +import vazkii.akashictome.data_components.ToolContentComponent; import vazkii.akashictome.network.MessageUnmorphTome; import vazkii.akashictome.network.NetworkHandler; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -28,11 +29,6 @@ public final class MorphingHandler { public static final String MINECRAFT = "minecraft"; - public static final String TAG_MORPHING = "akashictome:is_morphing"; - public static final String TAG_TOME_DATA = "akashictome:data"; - public static final String TAG_TOME_DISPLAY_NAME = "akashictome:displayName"; - public static final String TAG_ITEM_DEFINED_MOD = "akashictome:definedMod"; - @SubscribeEvent public void onPlayerLeftClick(PlayerInteractEvent.LeftClickEmpty event) { ItemStack stack = event.getItemStack(); @@ -43,18 +39,24 @@ public void onPlayerLeftClick(PlayerInteractEvent.LeftClickEmpty event) { @SubscribeEvent public void onItemDropped(ItemTossEvent event) { - if (!event.getPlayer().isDiscrete()) + if (!event.getPlayer().isDiscrete()) { return; + } ItemEntity e = event.getEntity(); ItemStack stack = e.getItem(); + if (!stack.isEmpty() && isAkashicTome(stack) && !stack.is(Registries.TOME.get())) { - CompoundTag morphData = stack.getTag().getCompound(TAG_TOME_DATA).copy(); - String currentMod = NBTUtils.getString(stack, TAG_ITEM_DEFINED_MOD, getModFromStack(stack)); + ToolContentComponent contents = stack.get(Registries.TOOL_CONTENT); + if (contents == null) { + return; + } + ToolContentComponent.Mutable mutable = new ToolContentComponent.Mutable(contents); + + mutable.remove(stack); + stack.set(Registries.TOOL_CONTENT, mutable.toImmutable()); - ItemStack morph = makeMorphedStack(stack, MINECRAFT, morphData); - CompoundTag newMorphData = morph.getTag().getCompound(TAG_TOME_DATA); - newMorphData.remove(currentMod); + ItemStack morph = makeMorphedStack(stack, MINECRAFT, true); if (!e.getCommandSenderWorld().isClientSide) { ItemEntity newItem = new ItemEntity(e.getCommandSenderWorld(), e.getX(), e.getY(), e.getZ(), morph); @@ -62,28 +64,23 @@ public void onItemDropped(ItemTossEvent event) { } ItemStack copy = stack.copy(); - CompoundTag copyCmp = copy.getTag(); - if (copyCmp == null) { - copyCmp = new CompoundTag(); - copy.setTag(copyCmp); - } - - copyCmp.remove("display"); - - copyCmp.remove(TAG_MORPHING); - copyCmp.remove(TAG_TOME_DISPLAY_NAME); - copyCmp.remove(TAG_TOME_DATA); + copy.remove(Registries.TOOL_CONTENT); + copy.remove(Registries.IS_MORPHED); + copy.remove(DataComponents.CUSTOM_NAME); + copy.remove(Registries.OG_DISPLAY_NAME); + copy.remove(Registries.DEFINED_MOD); e.setItem(copy); } } public static String getModFromState(BlockState state) { - return getModOrAlias(ForgeRegistries.BLOCKS.getKey(state.getBlock()).getNamespace()); + return getModOrAlias(BuiltInRegistries.BLOCK.getKey(state.getBlock()).getNamespace()); } public static String getModFromStack(ItemStack stack) { - return getModOrAlias(stack.isEmpty() ? MINECRAFT : stack.getItem().getCreatorModId(stack)); + String modId = stack.getItem().getCreatorModId(stack); + return getModOrAlias(stack.isEmpty() ? MINECRAFT : modId != null ? modId : MINECRAFT); } public static String getModOrAlias(String mod) { @@ -98,95 +95,116 @@ public static String getModOrAlias(String mod) { return aliases.getOrDefault(mod, mod); } - public static boolean doesStackHaveModAttached(ItemStack stack, String mod) { //TODO what was this used for? - if (!stack.hasTag()) - return false; - - CompoundTag morphData = stack.getTag().getCompound(TAG_TOME_DATA); - return morphData.contains(mod); - } - public static ItemStack getShiftStackForMod(ItemStack stack, String mod) { - if (!stack.hasTag()) + if (!stack.has(Registries.TOOL_CONTENT)) { return stack; + } String currentMod = getModFromStack(stack); - String defined = NBTUtils.getString(stack, TAG_ITEM_DEFINED_MOD, ""); - if (!defined.isEmpty()) + + String defined = ""; + if (stack.has(Registries.DEFINED_MOD)) { + defined = stack.get(Registries.DEFINED_MOD); + } + + if (!defined.isEmpty()) { currentMod = defined; + } - if (mod.equals(currentMod)) + if (mod.equals(currentMod)) { return stack; + } - CompoundTag morphData = stack.getTag().getCompound(TAG_TOME_DATA); - return makeMorphedStack(stack, mod, morphData); + return makeMorphedStack(stack, mod, false); } - public static ItemStack makeMorphedStack(ItemStack currentStack, String targetMod, CompoundTag morphData) { + public static ItemStack makeMorphedStack(ItemStack currentStack, String targetMod, boolean calledOnRemove) { String currentMod = getModFromStack(currentStack); - String defined = NBTUtils.getString(currentStack, TAG_ITEM_DEFINED_MOD, ""); - if (!defined.isEmpty()) + + String defined = ""; + if (currentStack.has(Registries.DEFINED_MOD)) { + defined = currentStack.get(Registries.DEFINED_MOD); + } + + if (!defined.isEmpty()) { currentMod = defined; + } - CompoundTag currentCmp = new CompoundTag(); - currentStack.save(currentCmp); - currentCmp = currentCmp.copy(); - if (currentCmp.contains("tag")) - currentCmp.getCompound("tag").remove(TAG_TOME_DATA); + ToolContentComponent currentContent = currentStack.get(Registries.TOOL_CONTENT); + currentStack.remove(Registries.TOOL_CONTENT); + ToolContentComponent newStackComponent = new ToolContentComponent(List.of(currentStack)); + if (currentContent == null) + return ItemStack.EMPTY; - if (!currentMod.equalsIgnoreCase(MINECRAFT) && !currentMod.equalsIgnoreCase(AkashicTome.MOD_ID)) - morphData.put(currentMod, currentCmp); + ToolContentComponent.Mutable mutable = getMutable(currentContent, newStackComponent, currentMod, calledOnRemove); ItemStack stack; - if (targetMod.equals(MINECRAFT)) + if (targetMod.equals(MINECRAFT)) { stack = new ItemStack(Registries.TOME.get()); - else { - CompoundTag targetCmp = morphData.getCompound(targetMod); - morphData.remove(targetMod); + } else { + stack = getStackFromMod(currentContent, targetMod); - stack = ItemStack.of(targetCmp); - if (stack.isEmpty()) + if (stack.isEmpty()) { stack = new ItemStack(Registries.TOME.get()); + } } - if (!stack.hasTag()) - stack.setTag(new CompoundTag()); + mutable.remove(stack); - CompoundTag stackCmp = stack.getTag(); - stackCmp.put(TAG_TOME_DATA, morphData); - stackCmp.putBoolean(TAG_MORPHING, true); + stack.set(Registries.TOOL_CONTENT, mutable.toImmutable()); + stack.set(Registries.IS_MORPHED, true); if (!stack.is(Registries.TOME.get())) { - CompoundTag displayName = new CompoundTag(); - CompoundTag ogDisplayName = displayName; - displayName.putString("text", Component.Serializer.toJson(stack.getHoverName())); + Component hoverName = getOrSetOGName(stack); + Component stackName = Component.literal(hoverName.getString()).setStyle(Style.EMPTY.applyFormats(ChatFormatting.GREEN)); + Component comp = Component.translatable("akashictome.sudo_name", stackName); + stack.set(DataComponents.CUSTOM_NAME, comp); + } - if (stackCmp.contains(TAG_TOME_DISPLAY_NAME)) - displayName = (CompoundTag) stackCmp.get(TAG_TOME_DISPLAY_NAME); - else - stackCmp.put(TAG_TOME_DISPLAY_NAME, displayName); + stack.setCount(1); + return stack; + } + private static Component getOrSetOGName(ItemStack stack) { + Component hoverName = stack.getHoverName(); + if (!stack.has(Registries.OG_DISPLAY_NAME)) { + stack.set(Registries.OG_DISPLAY_NAME, hoverName); + } else { + hoverName = stack.get(Registries.OG_DISPLAY_NAME); + } - MutableComponent rawComp = Component.Serializer.fromJson(displayName.getString("text")); - if (rawComp == null) { - stackCmp.put(TAG_TOME_DISPLAY_NAME, displayName); - displayName = ogDisplayName; - } + return hoverName; + } - Component stackName = rawComp.setStyle(Style.EMPTY.applyFormats(ChatFormatting.GREEN)); - Component comp = Component.translatable("akashictome.sudo_name", stackName); - stack.setHoverName(comp); + private static ToolContentComponent.Mutable getMutable(ToolContentComponent currentContent, ToolContentComponent newStackComponent, String currentMod, boolean calledOnRemove) { + ToolContentComponent.Mutable currentContentMutable = new ToolContentComponent.Mutable(currentContent); + if (!currentMod.equalsIgnoreCase(MINECRAFT) && !currentMod.equalsIgnoreCase(AkashicTome.MOD_ID) && !calledOnRemove) { + currentContentMutable.tryInsert(newStackComponent.getItems().getFirst()); } + return currentContentMutable; + } - stack.setCount(1); - return stack; + public static ItemStack getStackFromMod(ToolContentComponent component, String mod) { + if (component != null && !component.isEmpty()) { + for (ItemStack contentStack : component.getItems()) { + if (contentStack.has(Registries.DEFINED_MOD)) { + if (contentStack.get(Registries.DEFINED_MOD).equals(mod)) { + return contentStack; + } else if (BuiltInRegistries.ITEM.getKey(contentStack.getItem()).getNamespace().equals(mod)) { + return contentStack; + } + } + } + } + return ItemStack.EMPTY; } private static final Map modNames = new HashMap<>(); static { - for (IModInfo modEntry : ModList.get().getMods()) + for (IModInfo modEntry : ModList.get().getMods()) { modNames.put(modEntry.getModId().toLowerCase(Locale.ENGLISH), modEntry.getDisplayName()); + } } public static String getModNameForId(String modId) { @@ -201,7 +219,7 @@ public static boolean isAkashicTome(ItemStack stack) { if (stack.is(Registries.TOME.get())) return true; - return stack.hasTag() && stack.getTag().getBoolean(TAG_MORPHING); + return stack.has(Registries.IS_MORPHED) && Boolean.TRUE.equals(stack.get(Registries.IS_MORPHED)); } } diff --git a/src/main/java/vazkii/akashictome/NBTUtils.java b/src/main/java/vazkii/akashictome/NBTUtils.java deleted file mode 100644 index ef91789..0000000 --- a/src/main/java/vazkii/akashictome/NBTUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -package vazkii.akashictome; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; - -//Some Nbt Utils ported from ARL which doesn't exist anymore -public class NBTUtils { - public static CompoundTag getNBT(ItemStack stack) { - if(!stack.hasTag()) { - stack.setTag(new CompoundTag()); - } - return stack.getTag(); - } - - public static boolean verifyExistence(ItemStack stack, String tag) { - return !stack.isEmpty() && stack.hasTag() && getNBT(stack).contains(tag); - } - - public static String getString(ItemStack stack, String tag, String defaultExpected) { - return verifyExistence(stack, tag) ? getNBT(stack).getString(tag) : defaultExpected; - } - - public static void setString(ItemStack stack, String tag, String s) { - getNBT(stack).putString(tag, s); - } - - public static CompoundTag getCompound(ItemStack stack, String tag, boolean nullifyOnFail) { - return verifyExistence(stack, tag) ? getNBT(stack).getCompound(tag) : nullifyOnFail ? null : new CompoundTag(); - } -} diff --git a/src/main/java/vazkii/akashictome/Registries.java b/src/main/java/vazkii/akashictome/Registries.java index 08dc8ce..c11755a 100644 --- a/src/main/java/vazkii/akashictome/Registries.java +++ b/src/main/java/vazkii/akashictome/Registries.java @@ -1,18 +1,34 @@ package vazkii.akashictome; +import com.mojang.serialization.Codec; + +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; +import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; -import net.minecraftforge.registries.DeferredRegister; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegistryObject; +import net.neoforged.neoforge.registries.DeferredItem; +import net.neoforged.neoforge.registries.DeferredRegister; + +import vazkii.akashictome.data_components.ToolContentComponent; + +import java.util.function.Supplier; public final class Registries { - public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, AkashicTome.MOD_ID); - public static final DeferredRegister> SERIALIZERS = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, AkashicTome.MOD_ID); + public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(AkashicTome.MOD_ID); + public static final DeferredRegister> SERIALIZERS = DeferredRegister.create(BuiltInRegistries.RECIPE_SERIALIZER, AkashicTome.MOD_ID); + public static final DeferredRegister.DataComponents DATA_COMPONENTS = DeferredRegister.createDataComponents(AkashicTome.MOD_ID); + + public static final Supplier> TOOL_CONTENT = DATA_COMPONENTS.registerComponentType("tool_content", builder -> builder.persistent(ToolContentComponent.CODEC).networkSynchronized(ToolContentComponent.STREAM_CODEC).cacheEncoding()); + public static final Supplier> IS_MORPHED = DATA_COMPONENTS.registerComponentType("is_morphed", builder -> builder.persistent(Codec.BOOL).networkSynchronized(ByteBufCodecs.BOOL)); + public static final Supplier> OG_DISPLAY_NAME = DATA_COMPONENTS.register("og_display_name", () -> DataComponentType.builder().persistent(ComponentSerialization.FLAT_CODEC).networkSynchronized(ComponentSerialization.STREAM_CODEC).build()); + public static final Supplier> DEFINED_MOD = DATA_COMPONENTS.register("defined_mod", () -> DataComponentType.builder().persistent(Codec.STRING).networkSynchronized(ByteBufCodecs.STRING_UTF8).build()); - public static final RegistryObject TOME = ITEMS.register("tome", TomeItem::new); + public static final DeferredItem TOME = ITEMS.registerItem("tome", TomeItem::new); - public static final RegistryObject> ATTACHMENT = SERIALIZERS.register("attachment", () -> new SimpleCraftingRecipeSerializer<>(AttachementRecipe::new)); + public static final Supplier> ATTACHMENT = SERIALIZERS.register("attachment", () -> new SimpleCraftingRecipeSerializer<>(AttachementRecipe::new)); } diff --git a/src/main/java/vazkii/akashictome/TomeItem.java b/src/main/java/vazkii/akashictome/TomeItem.java index e0d69ad..36b4ec9 100644 --- a/src/main/java/vazkii/akashictome/TomeItem.java +++ b/src/main/java/vazkii/akashictome/TomeItem.java @@ -1,35 +1,28 @@ package vazkii.akashictome; -import com.google.common.collect.Lists; - import net.minecraft.ChatFormatting; import net.minecraft.client.gui.screens.Screen; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Style; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; -import net.minecraft.world.item.Item.Properties; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; -import javax.annotation.Nullable; +import vazkii.akashictome.data_components.ToolContentComponent; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; public class TomeItem extends Item { - public TomeItem() { - super(new Properties().stacksTo(1)); + public TomeItem(Properties properties) { + super(properties.stacksTo(1).component(Registries.IS_MORPHED, false).component(Registries.TOOL_CONTENT, ToolContentComponent.EMPTY)); } @Override @@ -60,39 +53,32 @@ public InteractionResultHolder use(Level worldIn, Player playerIn, In } @Override - public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag advanced) { - if (!stack.hasTag() || !stack.getTag().contains(MorphingHandler.TAG_TOME_DATA)) + public void appendHoverText(ItemStack stack, Item.TooltipContext tooltipContext, List tooltip, TooltipFlag advanced) { + if (!stack.has(Registries.TOOL_CONTENT)) return; - CompoundTag data = stack.getTag().getCompound(MorphingHandler.TAG_TOME_DATA); - if (data.getAllKeys().isEmpty()) + ToolContentComponent contents = stack.get(Registries.TOOL_CONTENT); + if (contents == null || contents.isEmpty()) return; if (Screen.hasShiftDown()) { - List keys = Lists.newArrayList(data.getAllKeys()); - Collections.sort(keys); String currMod = ""; + for (ItemStack contentStack : contents.getItems()) { + if (!contentStack.isEmpty()) { + Component name; + if (contentStack.has(Registries.OG_DISPLAY_NAME)) { + name = contentStack.get(Registries.OG_DISPLAY_NAME); + } else { + name = contentStack.getHoverName(); + } - for (String s : keys) { - CompoundTag cmp = data.getCompound(s); - if (cmp != null) { - ItemStack modStack = ItemStack.of(cmp); - if (!modStack.isEmpty()) { - String name = modStack.getHoverName().getString(); - if (modStack.hasTag() && modStack.getTag().contains(MorphingHandler.TAG_TOME_DISPLAY_NAME)) { - CompoundTag rawName = ((CompoundTag) modStack.getTag().get(MorphingHandler.TAG_TOME_DISPLAY_NAME)); - Component nameComp = Component.Serializer.fromJson(rawName.getString("text")); - if (nameComp != null) - name = nameComp.getString(); - } - String mod = MorphingHandler.getModFromStack(modStack); - - if (!currMod.equals(mod)) - tooltip.add(Component.literal(MorphingHandler.getModNameForId(mod)).setStyle(Style.EMPTY.applyFormats(ChatFormatting.AQUA))); - tooltip.add(Component.literal(" ┠ " + name)); + String mod = MorphingHandler.getModFromStack(contentStack); - currMod = mod; + if (!currMod.equals(mod)) { + tooltip.add(Component.literal(MorphingHandler.getModNameForId(mod)).setStyle(Style.EMPTY.applyFormats(ChatFormatting.AQUA))); } + tooltip.add(Component.literal(" ┠ " + name.getString())); + currMod = mod; } } } else { diff --git a/src/main/java/vazkii/akashictome/client/AkashicTomeClient.java b/src/main/java/vazkii/akashictome/client/AkashicTomeClient.java new file mode 100644 index 0000000..57a7363 --- /dev/null +++ b/src/main/java/vazkii/akashictome/client/AkashicTomeClient.java @@ -0,0 +1,29 @@ +package vazkii.akashictome.client; + +import net.minecraft.world.item.CreativeModeTabs; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.client.gui.ConfigurationScreen; +import net.neoforged.neoforge.client.gui.IConfigScreenFactory; +import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; + +import vazkii.akashictome.AkashicTome; +import vazkii.akashictome.Registries; + +@Mod(value = AkashicTome.MOD_ID, dist = Dist.CLIENT) +public class AkashicTomeClient { + + public AkashicTomeClient(IEventBus bus, ModContainer modContainer) { + bus.addListener(this::addToCreativeTab); + + modContainer.registerExtensionPoint(IConfigScreenFactory.class, ConfigurationScreen::new); + } + + private void addToCreativeTab(BuildCreativeModeTabContentsEvent event) { + if (event.getTabKey() == CreativeModeTabs.TOOLS_AND_UTILITIES) { + event.accept(Registries.TOME); + } + } +} diff --git a/src/main/java/vazkii/akashictome/client/HUDHandler.java b/src/main/java/vazkii/akashictome/client/HUDHandler.java index 2f0a3f5..c744f5a 100644 --- a/src/main/java/vazkii/akashictome/client/HUDHandler.java +++ b/src/main/java/vazkii/akashictome/client/HUDHandler.java @@ -6,36 +6,29 @@ import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; -import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; -import net.minecraftforge.client.event.RenderGuiOverlayEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.neoforge.client.event.RenderGuiLayerEvent; import org.lwjgl.opengl.GL11; import vazkii.akashictome.MorphingHandler; -import vazkii.akashictome.NBTUtils; import vazkii.akashictome.Registries; public class HUDHandler { @SubscribeEvent - public void onDrawScreen(RenderGuiOverlayEvent.Post event) { - // if (event.getType() != ElementType.ALL) - // return; - + public void onDrawScreen(RenderGuiLayerEvent.Post event) { Minecraft mc = Minecraft.getInstance(); HitResult pos = mc.hitResult; - Window res = event.getWindow(); + Window res = mc.getWindow(); GuiGraphics guiGraphics = event.getGuiGraphics(); - if (pos != null && pos instanceof BlockHitResult) { - BlockHitResult bpos = (BlockHitResult) pos; + if (pos instanceof BlockHitResult blockHitResult) { ItemStack tomeStack = mc.player.getMainHandItem(); boolean hasTome = !tomeStack.isEmpty() && tomeStack.is(Registries.TOME.get()); @@ -49,30 +42,29 @@ public void onDrawScreen(RenderGuiOverlayEvent.Post event) { tomeStack = tomeStack.copy(); - BlockState state = mc.level.getBlockState(bpos.getBlockPos()); + BlockState state = mc.level.getBlockState(blockHitResult.getBlockPos()); if (!state.isAir()) { ItemStack drawStack = ItemStack.EMPTY; - String line1 = ""; - String line2 = ""; + Component line1 = Component.empty(); + Component line2 = Component.empty(); String mod = MorphingHandler.getModFromState(state); ItemStack morphStack = MorphingHandler.getShiftStackForMod(tomeStack, mod); - - if (!morphStack.isEmpty() && !ItemStack.isSameItemSameTags(morphStack, tomeStack)) { + + if (!morphStack.isEmpty() && !ItemStack.isSameItemSameComponents(morphStack, tomeStack)) { drawStack = morphStack; - line1 = NBTUtils.getCompound(morphStack, MorphingHandler.TAG_TOME_DISPLAY_NAME, false).getString("text"); - line2 = ChatFormatting.GRAY + I18n.get("akashictome.click_morph"); + line1 = morphStack.getOrDefault(Registries.OG_DISPLAY_NAME, Component.empty()); + line2 = Component.translatable("akashictome.click_morph").withStyle(ChatFormatting.GRAY); } - MutableComponent line1Component = Component.Serializer.fromJson(line1); - if (!drawStack.isEmpty() && line1Component != null) { + if (!drawStack.isEmpty() && !line1.getString().isEmpty()) { RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); int sx = res.getGuiScaledWidth() / 2 - 17; int sy = res.getGuiScaledHeight() / 2 + 2; guiGraphics.renderItem(drawStack, sx, sy); - guiGraphics.drawString(mc.font, line1Component.withStyle(ChatFormatting.GREEN), sx + 20, sy + 4, 0xFFFFFFFF); + guiGraphics.drawString(mc.font, line1.copy().withStyle(ChatFormatting.GREEN), sx + 20, sy + 4, 0xFFFFFFFF); guiGraphics.drawString(mc.font, line2, sx + 25, sy + 14, 0xFFFFFFFF); } } diff --git a/src/main/java/vazkii/akashictome/client/TomeScreen.java b/src/main/java/vazkii/akashictome/client/TomeScreen.java index d274636..dcab361 100644 --- a/src/main/java/vazkii/akashictome/client/TomeScreen.java +++ b/src/main/java/vazkii/akashictome/client/TomeScreen.java @@ -5,39 +5,36 @@ import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.math.Axis; + import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.model.BookModel; import net.minecraft.client.model.geom.ModelLayers; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.Mth; import net.minecraft.world.item.ItemStack; -import org.joml.Matrix4f; import vazkii.akashictome.AkashicTome; import vazkii.akashictome.ConfigHandler; import vazkii.akashictome.MorphingHandler; -import vazkii.akashictome.NBTUtils; +import vazkii.akashictome.Registries; +import vazkii.akashictome.data_components.ToolContentComponent; import vazkii.akashictome.network.MessageMorphTome; import vazkii.akashictome.network.NetworkHandler; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; public class TomeScreen extends Screen { - private static final ResourceLocation BOOK_TEXTURE = new ResourceLocation("akashictome:textures/models/book.png"); + private static final ResourceLocation BOOK_TEXTURE = ResourceLocation.fromNamespaceAndPath(AkashicTome.MOD_ID, "textures/models/book.png"); private final BookModel BOOK_MODEL; final ItemStack tome; @@ -45,19 +42,19 @@ public class TomeScreen extends Screen { public TomeScreen(ItemStack tome) { super(Component.empty()); - this.tome = tome; + this.tome = tome.copy(); BOOK_MODEL = new BookModel(Minecraft.getInstance().getEntityModels().bakeLayer(ModelLayers.BOOK)); } @Override - public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) { - if (p_mouseClicked_5_ == 0 && this.definedMod != null) { + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (button == 0 && this.definedMod != null) { NetworkHandler.sendToServer(new MessageMorphTome(this.definedMod)); this.minecraft.setScreen(null); return true; } - return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_); + return super.mouseClicked(mouseX, mouseY, button); } @Override @@ -67,24 +64,19 @@ public boolean isPauseScreen() { @Override public void render(GuiGraphics pGuiGraphics, int mouseX, int mouseY, float partialTicks) { - PoseStack matrixStack = pGuiGraphics.pose(); + PoseStack poseStack = pGuiGraphics.pose(); this.definedMod = null; super.render(pGuiGraphics, mouseX, mouseY, partialTicks); - List stacks = new ArrayList<>(); + if (!tome.has(Registries.TOOL_CONTENT)) { + return; + } - if (this.tome.hasTag()) { - CompoundTag data = this.tome.getTag().getCompound(MorphingHandler.TAG_TOME_DATA); - List keys = Lists.newArrayList(data.getAllKeys()); - Collections.sort(keys); + List stacks = Lists.newArrayList(); - for (String s : keys) { - CompoundTag cmp = data.getCompound(s); - if (cmp != null) { - ItemStack modStack = ItemStack.of(cmp); - stacks.add(modStack); - } - } + ToolContentComponent contents = tome.get(Registries.TOOL_CONTENT); + if (contents != null && !contents.isEmpty()) { + stacks = new ArrayList<>(contents.getItems()); } Window window = this.minecraft.getWindow(); @@ -124,41 +116,46 @@ public void render(GuiGraphics pGuiGraphics, int mouseX, int mouseY, float parti } if (!tooltipStack.isEmpty()) { - CompoundTag name = NBTUtils.getCompound(tooltipStack, MorphingHandler.TAG_TOME_DISPLAY_NAME, false); + Component ogDisplayName; + if (tooltipStack.has(Registries.OG_DISPLAY_NAME)) { + ogDisplayName = tooltipStack.get(Registries.OG_DISPLAY_NAME); + } else { + ogDisplayName = tooltipStack.getHoverName(); + } + String tempDefinedMod = MorphingHandler.getModFromStack(tooltipStack); String mod = ChatFormatting.GRAY + MorphingHandler.getModNameForId(tempDefinedMod); - tempDefinedMod = NBTUtils.getString(tooltipStack, MorphingHandler.TAG_ITEM_DEFINED_MOD, tempDefinedMod); - Component comp = Component.Serializer.fromJson(name.getString("text")); - if (comp == null) - comp = tooltipStack.getHoverName(); + if (tooltipStack.has(Registries.DEFINED_MOD)) { + tempDefinedMod = tooltipStack.get(Registries.DEFINED_MOD); + } - List tooltipList = Arrays.asList(comp, Component.literal(mod)); + List tooltipList = Arrays.asList(ogDisplayName, Component.literal(mod)); pGuiGraphics.renderComponentTooltip(this.font, tooltipList, mouseX, mouseY); this.definedMod = tempDefinedMod; } - if(!ConfigHandler.hideBookRender.get()) { + if (!ConfigHandler.hideBookRender.get()) { float f = 1.0F; float f1 = 0.0F; Lighting.setupForEntityInInventory(); - matrixStack.pushPose(); - matrixStack.translate((startX + endX) / 2.0, startY - 45, 100.0F); + poseStack.pushPose(); + poseStack.translate((startX + endX) / 2.0, startY - 45, 100.0F); float f2 = 100.0F; - matrixStack.scale(-f2, f2, f2); - matrixStack.mulPose(Axis.XP.rotationDegrees(30.0F)); - matrixStack.translate((1.0F - f) * 0.2F, (1.0F - f) * 0.1F, (1.0F - f) * 0.25F); + poseStack.scale(-f2, f2, f2); + poseStack.mulPose(Axis.XP.rotationDegrees(30.0F)); + poseStack.translate((1.0F - f) * 0.2F, (1.0F - f) * 0.1F, (1.0F - f) * 0.25F); float f3 = -(1.0F - f) * 90.0F - 91.0F; - matrixStack.mulPose(Axis.YP.rotationDegrees(f3)); - matrixStack.mulPose(Axis.XP.rotationDegrees(180.0F)); + poseStack.mulPose(Axis.YP.rotationDegrees(f3)); + poseStack.mulPose(Axis.XP.rotationDegrees(180.0F)); float f4 = Mth.clamp(Mth.frac(f1 + 0.25F) * 1.6F - 0.3F, 0.0F, 1.0F); float f5 = Mth.clamp(Mth.frac(f1 + 0.75F) * 1.6F - 0.3F, 0.0F, 1.0F); this.BOOK_MODEL.setupAnim(0.0F, f4, f5, f); VertexConsumer vertexconsumer = pGuiGraphics.bufferSource().getBuffer(this.BOOK_MODEL.renderType(BOOK_TEXTURE)); - this.BOOK_MODEL.renderToBuffer(matrixStack, vertexconsumer, 15728880, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F); + this.BOOK_MODEL.renderToBuffer(poseStack, vertexconsumer, 15728880, OverlayTexture.NO_OVERLAY, -1); pGuiGraphics.flush(); - matrixStack.popPose(); + poseStack.popPose(); Lighting.setupFor3DItems(); } diff --git a/src/main/java/vazkii/akashictome/data_components/ToolContentComponent.java b/src/main/java/vazkii/akashictome/data_components/ToolContentComponent.java new file mode 100644 index 0000000..763148a --- /dev/null +++ b/src/main/java/vazkii/akashictome/data_components/ToolContentComponent.java @@ -0,0 +1,97 @@ +package vazkii.akashictome.data_components; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; + +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.item.ItemStack; + +import vazkii.akashictome.Registries; + +import java.util.ArrayList; +import java.util.List; + +public class ToolContentComponent { + public static final ToolContentComponent EMPTY = new ToolContentComponent(List.of()); + public static final Codec CODEC = ItemStack.CODEC + .listOf() + .flatXmap(ToolContentComponent::checkAndCreate, component -> DataResult.success(component.items)); + public static final StreamCodec STREAM_CODEC = ItemStack.STREAM_CODEC + .apply(ByteBufCodecs.list()) + .map(ToolContentComponent::new, component -> component.items); + final List items; + + public ToolContentComponent(List contents) { + this.items = contents; + } + + private static DataResult checkAndCreate(List stacks) { + return DataResult.success(new ToolContentComponent(stacks)); + } + + public boolean isEmpty() { + return this.items.isEmpty(); + } + + public List getItems() { + return this.items; + } + + public boolean hasDefinedMod(String mod) { + for (ItemStack stack : this.items) { + if (stack.has(Registries.DEFINED_MOD)) { + if (stack.get(Registries.DEFINED_MOD).equals(mod)) { + return true; + } + } else if (BuiltInRegistries.ITEM.getKey(stack.getItem()).getNamespace().equals(mod)) { + return true; + } + } + return false; + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } else { + return object instanceof ToolContentComponent component && ItemStack.listMatches(this.items, component.items); + } + } + + @Override + public int hashCode() { + return ItemStack.hashStackList(this.items); + } + + @Override + public String toString() { + return "ToolContents" + this.items; + } + + public static class Mutable { + private final List items; + + public Mutable(ToolContentComponent component) { + this.items = new ArrayList<>(component.items); + } + + public void tryInsert(ItemStack stack) { + if (!stack.isEmpty()) { + ItemStack itemstack1 = stack.copy(); + this.items.add(itemstack1); + } + } + + public void remove(ItemStack stack) { + this.items.remove(stack); + } + + public ToolContentComponent toImmutable() { + return new ToolContentComponent(List.copyOf(this.items)); + } + } +} diff --git a/src/main/java/vazkii/akashictome/network/MessageMorphTome.java b/src/main/java/vazkii/akashictome/network/MessageMorphTome.java index 2600ec5..ac1bc82 100644 --- a/src/main/java/vazkii/akashictome/network/MessageMorphTome.java +++ b/src/main/java/vazkii/akashictome/network/MessageMorphTome.java @@ -1,40 +1,42 @@ package vazkii.akashictome.network; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; +import vazkii.akashictome.AkashicTome; import vazkii.akashictome.MorphingHandler; import vazkii.akashictome.Registries; -import java.util.function.Supplier; +public record MessageMorphTome(String modid) implements CustomPacketPayload { + public static final StreamCodec CODEC = CustomPacketPayload.codec( + MessageMorphTome::serialize, + MessageMorphTome::new); -public class MessageMorphTome { - public String modid; + public static final Type ID = new Type<>(ResourceLocation.fromNamespaceAndPath(AkashicTome.MOD_ID, "morph_tome")); - public MessageMorphTome() {} - - public MessageMorphTome(String modid) { - this.modid = modid; + public MessageMorphTome(final FriendlyByteBuf buf) { + this(buf.readUtf()); } - public static void serialize(final MessageMorphTome msg, final FriendlyByteBuf buf) { - buf.writeUtf(msg.modid); + public void serialize(final FriendlyByteBuf buf) { + buf.writeUtf(modid); + } - public static MessageMorphTome deserialize(final FriendlyByteBuf buf) { - final MessageMorphTome msg = new MessageMorphTome(); - msg.modid = buf.readUtf(); - return msg; + @Override + public Type type() { + return ID; } - public static void handle(MessageMorphTome msg, Supplier ctx) { - NetworkEvent.Context context = ctx.get(); - Player player = context.getSender(); - if (player != null) { - context.enqueueWork(() -> { + public static void handle(MessageMorphTome msg, final IPayloadContext ctx) { + ctx.enqueueWork(() -> { + if (ctx.player() instanceof ServerPlayer player) { ItemStack tomeStack = player.getMainHandItem(); InteractionHand hand = InteractionHand.MAIN_HAND; @@ -49,8 +51,7 @@ public static void handle(MessageMorphTome msg, Supplier c ItemStack newStack = MorphingHandler.getShiftStackForMod(tomeStack, msg.modid); player.setItemInHand(hand, newStack); } - }); - } - context.setPacketHandled(true); + } + }); } } diff --git a/src/main/java/vazkii/akashictome/network/MessageUnmorphTome.java b/src/main/java/vazkii/akashictome/network/MessageUnmorphTome.java index bd81edd..50b1a0e 100644 --- a/src/main/java/vazkii/akashictome/network/MessageUnmorphTome.java +++ b/src/main/java/vazkii/akashictome/network/MessageUnmorphTome.java @@ -1,30 +1,38 @@ package vazkii.akashictome.network; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.player.Player; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; import vazkii.akashictome.AkashicTome; import vazkii.akashictome.MorphingHandler; import vazkii.akashictome.Registries; -import java.util.function.Supplier; +public record MessageUnmorphTome() implements CustomPacketPayload { + public static final StreamCodec CODEC = CustomPacketPayload.codec( + MessageUnmorphTome::serialize, + MessageUnmorphTome::new); -public class MessageUnmorphTome { - public MessageUnmorphTome() {} + public static final Type ID = new Type<>(ResourceLocation.fromNamespaceAndPath(AkashicTome.MOD_ID, "unmorph_tome")); - public static void serialize(final MessageUnmorphTome msg, final FriendlyByteBuf buf) {} + public MessageUnmorphTome(final FriendlyByteBuf buf) { + this(); + } + + public void serialize(final FriendlyByteBuf buf) {} - public static MessageUnmorphTome deserialize(final FriendlyByteBuf buf) { - return new MessageUnmorphTome(); + @Override + public Type type() { + return ID; } - public static void handle(MessageUnmorphTome msg, Supplier ctx) { - NetworkEvent.Context context = ctx.get(); - Player player = context.getSender(); - if (player != null) { - context.enqueueWork(() -> { + public static void handle(MessageUnmorphTome msg, final IPayloadContext ctx) { + ctx.enqueueWork(() -> { + if (ctx.player() instanceof ServerPlayer player) { ItemStack stack = player.getMainHandItem(); if (!stack.isEmpty() && MorphingHandler.isAkashicTome(stack) && !stack.is(Registries.TOME.get())) { ItemStack newStack = MorphingHandler.getShiftStackForMod(stack, MorphingHandler.MINECRAFT); @@ -32,9 +40,8 @@ public static void handle(MessageUnmorphTome msg, Supplier inventory.setItem(inventory.selected, newStack); AkashicTome.proxy.updateEquippedItem(); } - }); - } - context.setPacketHandled(true); + } + }); } } diff --git a/src/main/java/vazkii/akashictome/network/NetworkHandler.java b/src/main/java/vazkii/akashictome/network/NetworkHandler.java index df6d101..139dcec 100644 --- a/src/main/java/vazkii/akashictome/network/NetworkHandler.java +++ b/src/main/java/vazkii/akashictome/network/NetworkHandler.java @@ -1,27 +1,21 @@ package vazkii.akashictome.network; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.simple.SimpleChannel; -import vazkii.akashictome.AkashicTome; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.neoforged.neoforge.network.PacketDistributor; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; public class NetworkHandler { - private static SimpleChannel channel; - private static int id = 0; - public static void register() { - final String protocolVersion = "1"; - channel = NetworkRegistry.ChannelBuilder.named(new ResourceLocation(AkashicTome.MOD_ID, "main")) - .networkProtocolVersion(() -> protocolVersion) - .clientAcceptedVersions(protocolVersion::equals) - .serverAcceptedVersions(protocolVersion::equals) - .simpleChannel(); - channel.registerMessage(id++, MessageMorphTome.class, MessageMorphTome::serialize, MessageMorphTome::deserialize, MessageMorphTome::handle); - channel.registerMessage(id++, MessageUnmorphTome.class, MessageUnmorphTome::serialize, MessageUnmorphTome::deserialize, MessageUnmorphTome::handle); - } + public static void registerPayloadHandler(final RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar("1"); - public static void sendToServer(MSG msg) { - channel.sendToServer(msg); - } + registrar.playToServer(MessageMorphTome.ID, MessageMorphTome.CODEC, MessageMorphTome::handle); + registrar.playToServer(MessageUnmorphTome.ID, MessageUnmorphTome.CODEC, MessageUnmorphTome::handle); + } + + public static void sendToServer(CustomPacketPayload msg) { + PacketDistributor.sendToServer(msg); + } } diff --git a/src/main/java/vazkii/akashictome/proxy/ClientProxy.java b/src/main/java/vazkii/akashictome/proxy/ClientProxy.java index 4ac39ef..93bca6a 100644 --- a/src/main/java/vazkii/akashictome/proxy/ClientProxy.java +++ b/src/main/java/vazkii/akashictome/proxy/ClientProxy.java @@ -4,13 +4,15 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.MinecraftForge; +import net.neoforged.neoforge.common.NeoForge; import vazkii.akashictome.client.HUDHandler; import vazkii.akashictome.client.TomeScreen; public class ClientProxy extends CommonProxy { + public ClientProxy() {} + @Override public void updateEquippedItem() { Minecraft.getInstance().gameRenderer.itemInHandRenderer.itemUsed(InteractionHand.MAIN_HAND); @@ -18,14 +20,15 @@ public void updateEquippedItem() { @Override public void initHUD() { - MinecraftForge.EVENT_BUS.register(new HUDHandler()); + NeoForge.EVENT_BUS.register(new HUDHandler()); } @Override public void openTomeGUI(Player player, ItemStack stack) { Minecraft mc = Minecraft.getInstance(); - if (mc.player == player) + if (mc.player == player) { mc.setScreen(new TomeScreen(stack)); + } } } diff --git a/src/main/java/vazkii/akashictome/proxy/CommonProxy.java b/src/main/java/vazkii/akashictome/proxy/CommonProxy.java index 200c101..3b09d75 100644 --- a/src/main/java/vazkii/akashictome/proxy/CommonProxy.java +++ b/src/main/java/vazkii/akashictome/proxy/CommonProxy.java @@ -2,14 +2,14 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.MinecraftForge; +import net.neoforged.neoforge.common.NeoForge; import vazkii.akashictome.MorphingHandler; public class CommonProxy { public void preInit() { - MinecraftForge.EVENT_BUS.register(MorphingHandler.INSTANCE); + NeoForge.EVENT_BUS.register(MorphingHandler.INSTANCE); initHUD(); } diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/neoforge.mods.toml similarity index 64% rename from src/main/resources/META-INF/mods.toml rename to src/main/resources/META-INF/neoforge.mods.toml index 35c7938..af7297f 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -1,5 +1,5 @@ modLoader="javafml" -loaderVersion="[47,)" +loaderVersion="[4,)" issueTrackerURL="https://github.com/Vazkii/AkashicTome" license="Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License" @@ -11,8 +11,15 @@ authors="Vazkii, MoreThanHidden, Uraneptus" description='''The book to end all books.''' [[dependencies.akashictome]] - modId="forge" - mandatory=true - versionRange="[47.1.0,)" + modId="neoforge" + type="required" + versionRange="[21.1.0,)" ordering="AFTER" side="BOTH" + +[[dependencies.akashictome]] + modId="minecraft" + type="required" + versionRange="[1.21,)" + ordering="NONE" + side="BOTH" diff --git a/src/main/resources/assets/akashictome/lang/en_us.json b/src/main/resources/assets/akashictome/lang/en_us.json index 81c83e2..bd596c4 100644 --- a/src/main/resources/assets/akashictome/lang/en_us.json +++ b/src/main/resources/assets/akashictome/lang/en_us.json @@ -2,5 +2,11 @@ "akashictome.sudo_name": "Akashic Tome (%s)", "akashictome.click_morph": "Shift-right click to change", "item.akashictome.tome": "Akashic Tome", - "akashictome.misc.shift_for_info": "§7Hold §bSHIFT§7 for more info" + "akashictome.misc.shift_for_info": "§7Hold §bSHIFT§7 for more info", + "akashictome.configuration.Allow all items to be added": "Allow all items to be added", + "akashictome.configuration.Whitelisted Items": "Whitelisted Items", + "akashictome.configuration.Blacklisted Mods": "Blacklisted Mods", + "akashictome.configuration.Mod Aliases": "Mod Aliases", + "akashictome.configuration.Hide Book Render": "Hide Book Render", + "akashictome.configuration.Whitelisted Names": "Whitelisted Names" } diff --git a/src/main/resources/data/akashictome/recipes/attachment.json b/src/main/resources/data/akashictome/recipe/attachment.json similarity index 100% rename from src/main/resources/data/akashictome/recipes/attachment.json rename to src/main/resources/data/akashictome/recipe/attachment.json diff --git a/src/main/resources/data/akashictome/recipes/tome.json b/src/main/resources/data/akashictome/recipe/tome.json similarity index 79% rename from src/main/resources/data/akashictome/recipes/tome.json rename to src/main/resources/data/akashictome/recipe/tome.json index 56bf642..cbea808 100644 --- a/src/main/resources/data/akashictome/recipes/tome.json +++ b/src/main/resources/data/akashictome/recipe/tome.json @@ -9,7 +9,6 @@ } ], "result": { - "item": "akashictome:tome", - "count": 1 + "id": "akashictome:tome" } } \ No newline at end of file