Architectury API

Architectury API

234M Downloads

PlayerEvent.DROP_ITEM doesn't do anything on fabric

GuiTaek opened this issue ยท 1 comments

commented

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);
commented

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);
            }
        }
    }
}