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"