Skip to content

Commit

Permalink
Use the holding LivingEntity instance for getPreferredEquipmentSlot i…
Browse files Browse the repository at this point in the history
…n getEquipmentSlot (#169)

Fixes a crash whenever that method is called, as Item cannot be cast to LivingEntity

Signed-off-by: unilock <[email protected]>
  • Loading branch information
unilock authored Nov 15, 2024
1 parent 673c12a commit 220dc0d
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,12 +31,12 @@ default void hasCraftingRemainingItem(ItemStack stack, CallbackInfoReturnable<Bo
}
}

@Inject(method = "getEquipmentSlot", at = @At("HEAD"))
@Inject(method = "getEquipmentSlot", at = @At("HEAD"), cancellable = true)
default void getEquipmentSlot(ItemStack stack, CallbackInfoReturnable<EquipmentSlot> 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));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();

Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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<EquipmentSlot> 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<EquipmentSlot> cir) {
((ItemStackExtensions) (Object) arg).fabric_setLivingEntity(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"EnchantCommandMixin",
"EnchantmentHelperMixin",
"EnchantRandomlyLootFunctionMixin",
"IItemExtensionMixin",
"ItemAccessor",
"ItemMixin",
"ItemSettingsMixin",
"ItemStackMixin",
"IItemExtensionMixin"
"LivingEntityMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit 220dc0d

Please sign in to comment.