From 220dc0d13f1d6cae3926eb06d542badc9e21f994 Mon Sep 17 00:00:00 2001 From: Katherine Date: Fri, 15 Nov 2024 14:07:16 -0500 Subject: [PATCH] Use the holding LivingEntity instance for getPreferredEquipmentSlot in getEquipmentSlot (#169) Fixes a crash whenever that method is called, as Item cannot be cast to LivingEntity Signed-off-by: unilock --- .../fabric/impl/item/ItemStackExtensions.java | 9 ++++++++ .../mixin/item/IItemExtensionMixin.java | 6 ++--- .../fabric/mixin/item/ItemStackMixin.java | 19 ++++++++++++++- .../fabric/mixin/item/LivingEntityMixin.java | 23 +++++++++++++++++++ .../resources/fabric-item-api-v1.mixins.json | 3 ++- 5 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/ItemStackExtensions.java create mode 100644 fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/ItemStackExtensions.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/ItemStackExtensions.java new file mode 100644 index 000000000..109ffbfed --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/impl/item/ItemStackExtensions.java @@ -0,0 +1,9 @@ +package net.fabricmc.fabric.impl.item; + +import net.minecraft.world.entity.LivingEntity; +import org.jetbrains.annotations.Nullable; + +public interface ItemStackExtensions { + @Nullable LivingEntity fabric_getLivingEntity(); + void fabric_setLivingEntity(LivingEntity livingEntity); +} diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/IItemExtensionMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/IItemExtensionMixin.java index 30abf2715..b446050c0 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/IItemExtensionMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/IItemExtensionMixin.java @@ -3,9 +3,9 @@ import net.fabricmc.fabric.api.item.v1.EquipmentSlotProvider; import net.fabricmc.fabric.api.item.v1.FabricItem; import net.fabricmc.fabric.impl.item.ItemExtensions; +import net.fabricmc.fabric.impl.item.ItemStackExtensions; import net.fabricmc.fabric.impl.item.RecursivityHelper; import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.common.extensions.IItemExtension; import org.spongepowered.asm.mixin.Mixin; @@ -31,12 +31,12 @@ default void hasCraftingRemainingItem(ItemStack stack, CallbackInfoReturnable cir) { EquipmentSlotProvider equipmentSlotProvider = ((ItemExtensions) this).fabric_getEquipmentSlotProvider(); if (equipmentSlotProvider != null) { - cir.setReturnValue(equipmentSlotProvider.getPreferredEquipmentSlot((LivingEntity) this, stack)); + cir.setReturnValue(equipmentSlotProvider.getPreferredEquipmentSlot(((ItemStackExtensions) (Object) stack).fabric_getLivingEntity(), stack)); } } } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemStackMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemStackMixin.java index 933c9b3b0..dda0f86aa 100644 --- a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemStackMixin.java +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/ItemStackMixin.java @@ -21,9 +21,12 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.llamalad7.mixinextras.sugar.Local; +import net.fabricmc.fabric.impl.item.ItemStackExtensions; import org.apache.commons.lang3.mutable.MutableBoolean; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import net.fabricmc.fabric.api.item.v1.CustomDamageHandler; import net.fabricmc.fabric.api.item.v1.FabricItemStack; @@ -35,7 +38,11 @@ import net.minecraft.world.item.ItemStack; @Mixin(ItemStack.class) -public abstract class ItemStackMixin implements FabricItemStack { +public abstract class ItemStackMixin implements ItemStackExtensions, FabricItemStack { + @Unique + @Nullable + private LivingEntity livingEntity; + @Shadow public abstract Item getItem(); @@ -69,4 +76,14 @@ The other damage method (which original.call discards) handles the creative mode original.call(instance, amount, serverWorld, serverPlayerEntity, consumer); } + + @Override + public @Nullable LivingEntity fabric_getLivingEntity() { + return livingEntity; + } + + @Override + public void fabric_setLivingEntity(LivingEntity livingEntity) { + this.livingEntity = livingEntity; + } } diff --git a/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java new file mode 100644 index 000000000..6ed7749d9 --- /dev/null +++ b/fabric-item-api-v1/src/main/java/net/fabricmc/fabric/mixin/item/LivingEntityMixin.java @@ -0,0 +1,23 @@ +package net.fabricmc.fabric.mixin.item; + +import net.fabricmc.fabric.impl.item.ItemStackExtensions; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; +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.CallbackInfoReturnable; + +@Mixin(LivingEntity.class) +abstract class LivingEntityMixin { + @Inject(method = "getEquipmentSlotForItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;getEquipmentSlot()Lnet/minecraft/world/entity/EquipmentSlot;")) + private void storeLivingEntity(ItemStack arg, CallbackInfoReturnable cir) { + ((ItemStackExtensions) (Object) arg).fabric_setLivingEntity((LivingEntity) (Object) this); + } + + @Inject(method = "getEquipmentSlotForItem", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/item/ItemStack;getEquipmentSlot()Lnet/minecraft/world/entity/EquipmentSlot;")) + private void resetLivingEntity(ItemStack arg, CallbackInfoReturnable cir) { + ((ItemStackExtensions) (Object) arg).fabric_setLivingEntity(null); + } +} diff --git a/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json b/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json index 838f647b4..a9f3ee8b2 100644 --- a/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json +++ b/fabric-item-api-v1/src/main/resources/fabric-item-api-v1.mixins.json @@ -7,11 +7,12 @@ "EnchantCommandMixin", "EnchantmentHelperMixin", "EnchantRandomlyLootFunctionMixin", + "IItemExtensionMixin", "ItemAccessor", "ItemMixin", "ItemSettingsMixin", "ItemStackMixin", - "IItemExtensionMixin" + "LivingEntityMixin" ], "injectors": { "defaultRequire": 1