architectury-api icon indicating copy to clipboard operation
architectury-api copied to clipboard

PlayerEvent.DROP_ITEM doesn't do anything on fabric

Open GuiTaek opened this issue 5 months ago • 1 comments

Reproduce: register an event like so in the mod init:

PlayerEvent.DROP_ITEM.register(
        (player, entity) -> {
            System.out.println("test");
            return EventResult.pass();
        }
);

and then drop something in Fabric When the player drops something, it doesn't do anything. The reason is, that the drop method of Player isn't actually called. The drop method of ServerPlayer and LivingEntity has a different signature and this is the one, that is called. I guess that means, the MixinPlayer has to inject into another drop method.

Here the mixin target from the minecraft plugin(I'm not sure if it works because it's another class):

Lnet/minecraft/world/entity/LivingEntity;drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;

Here the signature:

public ItemEntity drop(ItemStack itemStack, boolean bl, boolean bl2);

GuiTaek avatar Aug 01 '25 18:08 GuiTaek

I used this class in my mod in it works fine:

package <redacted>

import dev.architectury.event.events.common.PlayerEvent;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
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 public class MixinLivingEntity {
    @Inject(method = "Lnet/minecraft/world/entity/LivingEntity;drop(Lnet/minecraft/world/item/ItemStack;ZZ)Lnet/minecraft/world/entity/item/ItemEntity;", at = @At("RETURN"), cancellable = true)
    public void dropInject(ItemStack itemStack, boolean bl, boolean bl2, CallbackInfoReturnable<ItemEntity> cir) {
        if ((Object) this instanceof Player player) {
            if (cir.getReturnValue() != null && PlayerEvent.DROP_ITEM.invoker().drop(player, cir.getReturnValue()).isFalse()) {
                cir.setReturnValue(null);
            }
        }
    }
}

GuiTaek avatar Aug 01 '25 19:08 GuiTaek