From ff2fb8b5012427a404e75611f27c356bc2a4c779 Mon Sep 17 00:00:00 2001 From: AlcatrazEscapee Date: Sun, 18 Jun 2023 18:32:51 -0400 Subject: [PATCH] Remove tool type system and replace with vanilla tool queries, as we can't infer types in any sane way anymore that actually improves upon vanilla's data driven system. Fix overriding vanilla recipes not working on Forge. --- .../notreepunching/EventHandler.java | 2 +- .../notreepunching/common/ModTags.java | 1 + .../mixin/ReloadableServerResourcesMixin.java | 1 - .../client/ClientPacketListenerMixin.java | 20 -- .../util/HarvestBlockHandler.java | 193 +----------------- .../notreepunching/util/ToolType.java | 36 ---- .../notreepunching/tags/blocks/mineable.json | 12 ++ .../notreepunching.common.mixins.json | 1 - Data/main.py | 1 + .../main/resources/notreepunching.mixins.json | 1 - Forge/src/main/resources/META-INF/mods.toml | 4 +- 11 files changed, 27 insertions(+), 245 deletions(-) delete mode 100644 Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/client/ClientPacketListenerMixin.java delete mode 100644 Common/src/main/java/com/alcatrazescapee/notreepunching/util/ToolType.java create mode 100644 Common/src/main/resources/data/notreepunching/tags/blocks/mineable.json diff --git a/Common/src/main/java/com/alcatrazescapee/notreepunching/EventHandler.java b/Common/src/main/java/com/alcatrazescapee/notreepunching/EventHandler.java index 60331ed..ab2563b 100644 --- a/Common/src/main/java/com/alcatrazescapee/notreepunching/EventHandler.java +++ b/Common/src/main/java/com/alcatrazescapee/notreepunching/EventHandler.java @@ -41,7 +41,7 @@ public static float modifyBreakSpeed(Player player, BlockState state, @Nullable @Nullable public static InteractionResult onRightClickBlock(Level level, BlockPos pos, Player player, InteractionHand hand, ItemStack stack, @Nullable Direction targetedFace) { - // todo: is there a beter way to detect stone type blocks? This seems like a hack + // todo: is there a better way to detect stone type blocks? This seems like a hack final BlockState state = level.getBlockState(pos); if (Helpers.isItem(stack.getItem(), ModTags.Items.FLINT_KNAPPABLE) && state.getSoundType() == SoundType.STONE) { diff --git a/Common/src/main/java/com/alcatrazescapee/notreepunching/common/ModTags.java b/Common/src/main/java/com/alcatrazescapee/notreepunching/common/ModTags.java index a194556..373955e 100644 --- a/Common/src/main/java/com/alcatrazescapee/notreepunching/common/ModTags.java +++ b/Common/src/main/java/com/alcatrazescapee/notreepunching/common/ModTags.java @@ -42,6 +42,7 @@ public static final class Blocks public static final TagKey LOOSE_ROCK_PLACEABLE_ON = create("loose_rock_placeable_on"); + public static final TagKey MINEABLE = create("mineable"); public static final TagKey MINEABLE_WITH_MATTOCK = create("mineable_with_mattock"); public static final TagKey NEEDS_FLINT_TOOL = create("needs_flint_tool"); diff --git a/Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/ReloadableServerResourcesMixin.java b/Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/ReloadableServerResourcesMixin.java index fd7f1b3..3ed40ce 100644 --- a/Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/ReloadableServerResourcesMixin.java +++ b/Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/ReloadableServerResourcesMixin.java @@ -17,7 +17,6 @@ public abstract class ReloadableServerResourcesMixin @Inject(method = "updateRegistryTags(Lnet/minecraft/core/RegistryAccess;)V", at = @At("RETURN")) private void afterLoadTagsOnServer(RegistryAccess registryAccess, CallbackInfo ci) { - HarvestBlockHandler.inferToolTypesFromTags(); ModRecipes.injectRecipes((ReloadableServerResources) (Object) this, registryAccess); } } diff --git a/Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/client/ClientPacketListenerMixin.java b/Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/client/ClientPacketListenerMixin.java deleted file mode 100644 index 3093144..0000000 --- a/Common/src/main/java/com/alcatrazescapee/notreepunching/mixin/client/ClientPacketListenerMixin.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.alcatrazescapee.notreepunching.mixin.client; - -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.protocol.game.ClientboundUpdateTagsPacket; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import com.alcatrazescapee.notreepunching.util.HarvestBlockHandler; - -@Mixin(ClientPacketListener.class) -public abstract class ClientPacketListenerMixin -{ - @Inject(method = "handleUpdateTags", at = @At("RETURN")) - private void onUpdateTagsOnClient(ClientboundUpdateTagsPacket packet, CallbackInfo ci) - { - HarvestBlockHandler.inferToolTypesFromTags(); - } -} diff --git a/Common/src/main/java/com/alcatrazescapee/notreepunching/util/HarvestBlockHandler.java b/Common/src/main/java/com/alcatrazescapee/notreepunching/util/HarvestBlockHandler.java index 1e9a8fb..da326c5 100644 --- a/Common/src/main/java/com/alcatrazescapee/notreepunching/util/HarvestBlockHandler.java +++ b/Common/src/main/java/com/alcatrazescapee/notreepunching/util/HarvestBlockHandler.java @@ -1,65 +1,25 @@ package com.alcatrazescapee.notreepunching.util; -import java.util.Collections; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Set; import java.util.function.BooleanSupplier; import java.util.function.Supplier; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.tags.BlockTags; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.AxeItem; -import net.minecraft.world.item.DiggerItem; -import net.minecraft.world.item.HoeItem; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.PickaxeItem; -import net.minecraft.world.item.ShearsItem; -import net.minecraft.world.item.ShovelItem; -import net.minecraft.world.item.SwordItem; -import net.minecraft.world.item.Tier; -import net.minecraft.world.item.TieredItem; -import net.minecraft.world.item.Tiers; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import com.alcatrazescapee.notreepunching.Config; import com.alcatrazescapee.notreepunching.common.ModTags; import com.alcatrazescapee.notreepunching.mixin.AbstractBlockAccessor; import com.alcatrazescapee.notreepunching.mixin.AbstractBlockStateAccessor; -import com.alcatrazescapee.notreepunching.mixin.DiggerItemAccessor; -import com.alcatrazescapee.notreepunching.platform.XPlatform; public final class HarvestBlockHandler { - private static final Map BLOCK_TOOL_TYPES = new IdentityHashMap<>(); - private static final Map> ITEM_TOOL_TYPES = new IdentityHashMap<>(); - private static final Map, ToolType> DEFAULT_TOOL_TYPES = new IdentityHashMap<>(); - private static final Map, Set> UNIQUE_TOOL_TYPES = new IdentityHashMap<>(); - - static - { - DEFAULT_TOOL_TYPES.put(BlockTags.MINEABLE_WITH_PICKAXE, ToolType.PICKAXE); - DEFAULT_TOOL_TYPES.put(BlockTags.MINEABLE_WITH_AXE, ToolType.AXE); - DEFAULT_TOOL_TYPES.put(BlockTags.MINEABLE_WITH_SHOVEL, ToolType.SHOVEL); - DEFAULT_TOOL_TYPES.put(BlockTags.MINEABLE_WITH_HOE, ToolType.HOE); - DEFAULT_TOOL_TYPES.put(BlockTags.SWORD_EFFICIENT, ToolType.SHARP); - } - - private static void add(Item item, ToolType tool) - { - ITEM_TOOL_TYPES.computeIfAbsent(item, key -> new HashSet<>()).add(tool); - } - public static void setup() { for (Block block : BuiltInRegistries.BLOCK) @@ -75,111 +35,27 @@ public static void setup() ((AbstractBlockStateAccessor) state).setRequiresCorrectToolForDrops(true); } } - - for (Item item : BuiltInRegistries.ITEM) - { - if (item instanceof DiggerItem digger) - { - // Infer known tags - final TagKey toolTag = ((DiggerItemAccessor) digger).getBlocks(); - final ToolType toolType = toolTypeForMineableTag(toolTag); - if (toolType != ToolType.NONE) - { - add(item, toolType); - } - else - { - // For unknown tags, mark this as a special tool, to be handled later - add(item, ToolType.UNIQUE); - } - } - - // Infer subclasses of vanilla items - if (item instanceof AxeItem) - { - add(item, ToolType.AXE); - } - else if (item instanceof HoeItem) - { - add(item, ToolType.HOE); - } - else if (item instanceof PickaxeItem) - { - add(item, ToolType.PICKAXE); - } - else if (item instanceof ShovelItem) - { - add(item, ToolType.SHOVEL); - } - else if (item instanceof SwordItem || item instanceof ShearsItem) - { - add(item, ToolType.SHARP); - } - } - } - - public static void inferToolTypesFromTags() - { - // Must be called once tags are loaded - UNIQUE_TOOL_TYPES.clear(); - ITEM_TOOL_TYPES.forEach((item, toolTypes) -> { - if (toolTypes.contains(ToolType.UNIQUE) && item instanceof DiggerItem digger) - { - final TagKey toolTag = ((DiggerItemAccessor) digger).getBlocks(); - - // Infer if this is a superset of known tags, and if so, record it as of that tool type. - DEFAULT_TOOL_TYPES.forEach((knownToolTag, toolType) -> { - if (isTagSupersetOfTag(toolTag, knownToolTag)) - { - UNIQUE_TOOL_TYPES.computeIfAbsent(toolTag, key -> new HashSet<>()).add(toolType); - } - }); - } - }); - - BLOCK_TOOL_TYPES.clear(); - for (Map.Entry, ToolType> entry : DEFAULT_TOOL_TYPES.entrySet()) - { - BuiltInRegistries.BLOCK.getOrCreateTag(entry.getKey()) - .forEach(holder -> BLOCK_TOOL_TYPES.put(holder.value(), entry.getValue())); - } - for (Map.Entry, Set> entry : UNIQUE_TOOL_TYPES.entrySet()) - { - BuiltInRegistries.BLOCK.getOrCreateTag(entry.getKey()) - .forEach(holder -> entry.getValue().forEach(tool -> BLOCK_TOOL_TYPES.put(holder.value(), tool))); - } - } - - private static boolean isTagSupersetOfTag(TagKey superset, TagKey set) - { - return BuiltInRegistries.BLOCK.getOrCreateTag(set) - .stream() - .allMatch(holder -> holder.is(superset)); - } - - private static ToolType toolTypeForMineableTag(TagKey tag) - { - return DEFAULT_TOOL_TYPES.getOrDefault(tag, ToolType.NONE); } public static boolean isUsingCorrectToolToMine(BlockState state, @Nullable BlockPos pos, Player player) { - return isUsingCorrectTool(state, pos, player, ModTags.Blocks.ALWAYS_BREAKABLE, Config.INSTANCE.doBlocksMineWithoutCorrectTool, Config.INSTANCE.doInstantBreakBlocksMineWithoutCorrectTool); + return isUsingCorrectTool(state, pos, player, ModTags.Blocks.ALWAYS_BREAKABLE, Config.INSTANCE.doBlocksMineWithoutCorrectTool, Config.INSTANCE.doInstantBreakBlocksMineWithoutCorrectTool, true); } public static boolean isUsingCorrectToolForDrops(BlockState state, @Nullable BlockPos pos, Player player) { - return isUsingCorrectTool(state, pos, player, ModTags.Blocks.ALWAYS_DROPS, Config.INSTANCE.doBlocksDropWithoutCorrectTool, Config.INSTANCE.doInstantBreakBlocksDropWithoutCorrectTool); + return isUsingCorrectTool(state, pos, player, ModTags.Blocks.ALWAYS_DROPS, Config.INSTANCE.doBlocksDropWithoutCorrectTool, Config.INSTANCE.doInstantBreakBlocksDropWithoutCorrectTool, false); } - private static boolean isUsingCorrectTool(BlockState state, @Nullable BlockPos pos, Player player, TagKey alwaysAllowTag, Supplier withoutCorrectTool, BooleanSupplier instantBreakBlocksWithoutCorrectTool) + private static boolean isUsingCorrectTool(BlockState state, @Nullable BlockPos pos, Player player, TagKey alwaysAllowTag, Supplier withoutCorrectTool, BooleanSupplier instantBreakBlocksWithoutCorrectTool, boolean checkingCanMine) { if (withoutCorrectTool.get()) { return true; // Feature is disabled, always allow } - if (getDestroySpeed(state, pos, player) == 0 && instantBreakBlocksWithoutCorrectTool.getAsBoolean()) + final float destroySpeed = getDestroySpeed(state, pos, player); + if (destroySpeed == 0 && instantBreakBlocksWithoutCorrectTool.getAsBoolean()) { return true; // Feature is conditionally disabled for instant break blocks, always allow } @@ -195,66 +71,17 @@ private static boolean isUsingCorrectTool(BlockState state, @Nullable BlockPos p return true; // Tool has already reported itself as the correct tool. This includes a tier check in vanilla. } - final ToolType expectedToolType = BLOCK_TOOL_TYPES.getOrDefault(state.getBlock(), ToolType.NONE); - if (expectedToolType == ToolType.NONE) - { - return true; // No expected tool type, so we have to return true because we don't know otherwise - } - - if (!isUsingCorrectTier(state, stack)) - { - return false; // Not using the correct tier, and the block is tiered. This will only exclude tiered blocks, not those without a tier - } - - // Now, we need to infer if the current item is of a given tool type. - final Set toolTypes = ITEM_TOOL_TYPES.getOrDefault(stack.getItem(), Collections.emptySet()); - - // If this contains a unique tool type, then we also need to check unique tool types, which are based on tag supersets - if (toolTypes.contains(ToolType.UNIQUE) && stack.getItem() instanceof DiggerItem digger) + if (checkingCanMine && stack.getDestroySpeed(state) > 1.0f) { - final TagKey toolTag = ((DiggerItemAccessor) digger).getBlocks(); - final Set uniqueToolTypes = UNIQUE_TOOL_TYPES.getOrDefault(toolTag, Collections.emptySet()); - - if (isUsingAnyOfCorrectTools(expectedToolType, stack, uniqueToolTypes)) - { - return true; // Found a matching unique tool type - } + return true; // Tool reported itself as harvesting faster than normal, in which case when checking if we can *mine* the block, we return true. } - return isUsingAnyOfCorrectTools(expectedToolType, stack, toolTypes); - } - - private static boolean isUsingAnyOfCorrectTools(ToolType expectedToolType, ItemStack stack, Set toolTypes) - { - for (ToolType inferredToolType : toolTypes) + if (!state.is(ModTags.Blocks.MINEABLE)) { - if (inferredToolType == ToolType.UNIQUE) - { - continue; // Just a marker to check the unique based tool types - } - - if (inferredToolType == expectedToolType) - { - return true; // Correct tool type found! - } - - // Otherwise, we check if the expected tool type can identify this item as it's tool - if (expectedToolType.is(stack.getItem())) - { - return true; - } + return true; // If we have no idea what tool can mine this block, we have to return true, as otherwise it's impossible to mine } - return false; - } - private static boolean isUsingCorrectTier(BlockState state, ItemStack stack) - { - Tier tier = Tiers.WOOD; // Assume this is the lowest tier - if (stack.getItem() instanceof TieredItem item) - { - tier = item.getTier(); - } - return XPlatform.INSTANCE.isUsingCorrectTier(state, tier); + return false; // None of our checks have confirmed we can mine this block, so we can't } private static float getDestroySpeed(BlockState state, @Nullable BlockPos pos, Player player) diff --git a/Common/src/main/java/com/alcatrazescapee/notreepunching/util/ToolType.java b/Common/src/main/java/com/alcatrazescapee/notreepunching/util/ToolType.java deleted file mode 100644 index 471675f..0000000 --- a/Common/src/main/java/com/alcatrazescapee/notreepunching/util/ToolType.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.alcatrazescapee.notreepunching.util; - -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.Item; -import org.jetbrains.annotations.Nullable; - -import com.alcatrazescapee.notreepunching.common.ModTags; - -/** - * This represents a primary tool that must be present on a given block - * Blocks can be added to any number of tags to determine their validity with such a tool - * However, all blocks have a fallback 'tool type' which is known to NTP - * This is because when we check if a block is harvestable by an item, we have no way of knowing if that block is harvestable by *any* item. - */ -public enum ToolType -{ - PICKAXE(ModTags.Items.PICKAXE_TOOLS), // Stone - AXE(ModTags.Items.AXE_TOOLS), // Wood - SHOVEL(ModTags.Items.SHOVEL_TOOLS), // Earth, Dirt - HOE(ModTags.Items.HOE_TOOLS), // Plants, Misc. - SHARP(ModTags.Items.SHARP_TOOLS), // (Of Swords and Axes) Plants - UNIQUE(null), - NONE(null); - - @Nullable private final TagKey tag; - - ToolType(@Nullable TagKey tag) - { - this.tag = tag; - } - - public boolean is(Item item) - { - return tag != null && Helpers.isItem(item, tag); - } -} diff --git a/Common/src/main/resources/data/notreepunching/tags/blocks/mineable.json b/Common/src/main/resources/data/notreepunching/tags/blocks/mineable.json new file mode 100644 index 0000000..fdc8ac1 --- /dev/null +++ b/Common/src/main/resources/data/notreepunching/tags/blocks/mineable.json @@ -0,0 +1,12 @@ +{ + "__comment__": "This file was automatically created by mcresources", + "replace": false, + "values": [ + "#notreepunching:mineable_with_mattock", + "#minecraft:mineable/pickaxe", + "#minecraft:mineable/shovel", + "#minecraft:mineable/hoe", + "#minecraft:mineable/axe", + "#minecraft:sword_efficient" + ] +} \ No newline at end of file diff --git a/Common/src/main/resources/notreepunching.common.mixins.json b/Common/src/main/resources/notreepunching.common.mixins.json index e6afa99..60095c1 100644 --- a/Common/src/main/resources/notreepunching.common.mixins.json +++ b/Common/src/main/resources/notreepunching.common.mixins.json @@ -11,7 +11,6 @@ "ReloadableServerResourcesMixin" ], "client": [ - "client.ClientPacketListenerMixin" ], "injectors": { "defaultRequire": 1 diff --git a/Data/main.py b/Data/main.py index 5f92f39..6e48e28 100644 --- a/Data/main.py +++ b/Data/main.py @@ -211,6 +211,7 @@ def do_tags(forge: ResourceManager, fabric: ResourceManager, common: ResourceMan # Misc Tags common.block_tag('needs_with_flint_tool') common.block_tag('mineable_with_mattock', '#minecraft:mineable/shovel', '#minecraft:mineable/hoe', '#minecraft:mineable/axe') + common.block_tag('mineable', '#notreepunching:mineable_with_mattock', '#minecraft:mineable/pickaxe', '#minecraft:mineable/shovel', '#minecraft:mineable/hoe', '#minecraft:mineable/axe', '#minecraft:sword_efficient') common.item_tag('pickaxe_tools') common.item_tag('axe_tools', '#notreepunching:mattocks') common.item_tag('shovel_tools', '#notreepunching:mattocks') diff --git a/Fabric/src/main/resources/notreepunching.mixins.json b/Fabric/src/main/resources/notreepunching.mixins.json index 0860f0f..6b666d3 100644 --- a/Fabric/src/main/resources/notreepunching.mixins.json +++ b/Fabric/src/main/resources/notreepunching.mixins.json @@ -9,7 +9,6 @@ "ServerPlayerGameModeMixin" ], "client": [ - "client.ClientPacketListenerMixin", "client.MultiPlayerGameModeMixin" ], "injectors": { diff --git a/Forge/src/main/resources/META-INF/mods.toml b/Forge/src/main/resources/META-INF/mods.toml index 59aa967..a341877 100644 --- a/Forge/src/main/resources/META-INF/mods.toml +++ b/Forge/src/main/resources/META-INF/mods.toml @@ -17,13 +17,13 @@ issueTrackerURL = "${modIssueUrl}" modId = "forge" mandatory = true versionRange = "${forgeVersionRange}" - ordering = "NONE" + ordering = "AFTER" side = "BOTH" [[dependencies.${modId}]] modId = "minecraft" mandatory = true versionRange = "${minecraftVersionRange}" - ordering = "NONE" + ordering = "AFTER" side = "BOTH"