From 9d44d319d1d1e3f20979601dbb2d916683186c2c Mon Sep 17 00:00:00 2001 From: Adam Macdonald Date: Thu, 24 Apr 2025 20:06:24 +0100 Subject: [PATCH] Add support for food items --- .../java/xyz/twokilohertz/HotbarReplace.java | 5 +- .../twokilohertz/mixin/ItemStackMixin.java | 71 +++++++++++++++++-- .../resources/hotbarreplace.mixins.json | 1 + 3 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/client/java/xyz/twokilohertz/HotbarReplace.java b/src/client/java/xyz/twokilohertz/HotbarReplace.java index d3842c7..8cc704d 100644 --- a/src/client/java/xyz/twokilohertz/HotbarReplace.java +++ b/src/client/java/xyz/twokilohertz/HotbarReplace.java @@ -50,8 +50,7 @@ public class HotbarReplace implements ClientModInitializer { // I honestly do not know Minecraft internals enough to be sure that there won't // be de-sync issues. - int current_fps = client.getCurrentFps(); - int click_delay = Math.round(1.0f / (float) current_fps) * 1000; + final int click_delay_ms = 50; client.interactionManager.clickSlot(player.currentScreenHandler.syncId, i, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.PICKUP, player); @@ -62,7 +61,7 @@ public class HotbarReplace implements ClientModInitializer { client.interactionManager.clickSlot(player.currentScreenHandler.syncId, slot + PlayerInventory.MAIN_SIZE, GLFW.GLFW_MOUSE_BUTTON_1, SlotActionType.PICKUP, player); - }, click_delay, TimeUnit.MILLISECONDS); + }, click_delay_ms, TimeUnit.MILLISECONDS); return; } diff --git a/src/client/java/xyz/twokilohertz/mixin/ItemStackMixin.java b/src/client/java/xyz/twokilohertz/mixin/ItemStackMixin.java index 6b96d4c..44d4a12 100644 --- a/src/client/java/xyz/twokilohertz/mixin/ItemStackMixin.java +++ b/src/client/java/xyz/twokilohertz/mixin/ItemStackMixin.java @@ -22,28 +22,54 @@ public class ItemStackMixin { @Inject(at = @At("HEAD"), method = "use") private void ItemStack_use_HEAD(World world, PlayerEntity player, Hand hand, CallbackInfoReturnable info) { - lastUsedItem = player.getStackInHand(hand).getItem(); + if (!world.isClient()) + return; + + Item item = player.getStackInHand(hand).getItem(); + if (item == null) + return; + + lastUsedItem = item; } @Inject(at = @At("HEAD"), method = "useOnBlock") private void ItemStack_useOnBlock_HEAD(ItemUsageContext context, CallbackInfoReturnable info) { - lastUsedItem = context.getPlayer().getStackInHand(context.getHand()).getItem(); + if (!context.getWorld().isClient()) + return; + + Item item = context.getPlayer().getStackInHand(context.getHand()).getItem(); + if (item == null) + return; + + lastUsedItem = item; } @Inject(at = @At("HEAD"), method = "useOnEntity") private void ItemStack_useOnEntity_HEAD(PlayerEntity player, LivingEntity entity, Hand hand, CallbackInfoReturnable info) { - lastUsedItem = player.getStackInHand(hand).getItem(); + if (!player.getWorld().isClient()) + return; + + Item item = player.getStackInHand(hand).getItem(); + if (item == null) + return; + + lastUsedItem = item; } @Inject(at = @At("TAIL"), method = "use") private void ItemStack_use_TAIL(World world, PlayerEntity player, Hand hand, CallbackInfoReturnable info) { + if (!world.isClient()) + return; + if (info.getReturnValue() != ActionResult.SUCCESS) return; - if (player.getStackInHand(hand).getCount() != 0) + ItemStack stack = player.getStackInHand(hand); + + if (stack.getCount() > 1) return; HotbarReplace.tryReplaceSlot(player, hand, lastUsedItem); @@ -51,13 +77,17 @@ public class ItemStackMixin { @Inject(at = @At("TAIL"), method = "useOnBlock") private void ItemStack_useOnBlock_TAIL(ItemUsageContext context, CallbackInfoReturnable info) { + if (!context.getWorld().isClient()) + return; + if (info.getReturnValue() != ActionResult.SUCCESS) return; PlayerEntity player = context.getPlayer(); Hand hand = context.getHand(); + ItemStack stack = player.getStackInHand(hand); - if (player.getStackInHand(hand).getCount() != 0) + if (stack.getCount() != 0) return; HotbarReplace.tryReplaceSlot(player, hand, lastUsedItem); @@ -69,9 +99,38 @@ public class ItemStackMixin { if (info.getReturnValue() != ActionResult.SUCCESS) return; - if (player.getStackInHand(hand).getCount() != 0) + ItemStack stack = player.getStackInHand(hand); + + if (stack.getCount() > 1) return; HotbarReplace.tryReplaceSlot(player, hand, lastUsedItem); } + + @Inject(at = @At("HEAD"), method = "Lnet/minecraft/item/ItemStack;finishUsing(Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;)Lnet/minecraft/item/ItemStack;") + private void ItemStack_finishUsing_HEAD(World world, LivingEntity user, + CallbackInfoReturnable info) { + if (!world.isClient()) + return; + + ItemStack stack = (ItemStack) (Object) this; + // ItemStack stack = info.getReturnValue(); -- only applicable when injecting at TAIL + + if (lastUsedItem != stack.getItem()) + return; + + // Food items disappear into thin (minecraft:)air before their stack size reaches 0 + if (stack.getCount() > 1) + return; + + if (!user.isPlayer()) + return; + + PlayerEntity player = (PlayerEntity) user; + + if (!player.isMainPlayer()) + return; + + HotbarReplace.tryReplaceSlot(player, player.getActiveHand(), lastUsedItem); + } } diff --git a/src/client/resources/hotbarreplace.mixins.json b/src/client/resources/hotbarreplace.mixins.json index ba0221e..7401983 100644 --- a/src/client/resources/hotbarreplace.mixins.json +++ b/src/client/resources/hotbarreplace.mixins.json @@ -6,6 +6,7 @@ "client": [ "ItemStackMixin" ], + "server": [], "injectors": { "defaultRequire": 1 }