Extend HumanEntity#dropItem API
Closes #11656
Motive
Developers currently have to either use NMS or copy-paste the already existing NMS implementation. This PR aims to fix that by exposing ways to call that NMS implementation more easily by extending onto the (Human)Player#dropItem method to provide more extensive ways of making the player drop items.
What does it add?
The following overloads to the HumanPlayer#dropItem(...) method have been added:
Item dropItem(ItemStack itemStack)Item dropItem(ItemStack itemStack, boolean persistThrower)Item dropItem(ItemStack itemStack, boolean persistThrower, boolean throwRandomly)Item dropItem(int slot)Item dropItem(int slot, boolean persistThrower)Item dropItem(int slot, boolean persistThrower, boolean throwRandomly)Item dropItem(EquipmentSlot slot)Item dropItem(EquipmentSlot slot, boolean persistThrower)Item dropItem(EquipmentSlot slot, boolean persistThrower, boolean throwRandomly)
Implementation details
Internally, the implementation calls net.minecraft.world.entity.player.Player#dropItem(...), making it a fairly maintainable API. But as that method does not remove the item, I have added that by calling this.inventory.setItem(slot, null).
JavaDocs status
I have added simple JavaDocs, but the methods should be fairly self explanatory.
Usage example
/**
* Makes the player drop an item of the type they using. Does not cancel the event
*/
@EventHandler
public void onInteract(final PlayerInteractEvent event) {
event.getPlayer().dropItem(event.getItem());
event.setCancelled(true);
}
/**
* Strips the player of all currently wearing armor
*/
private void stripOfArmor(final Player player) {
player.dropItem(EquipmentSlot.HEAD);
player.dropItem(EquipmentSlot.CHEST);
player.dropItem(EquipmentSlot.LEGS);
player.dropItem(EquipmentSlot.FEET);
}
[!NOTE] I am not 100% certain that the methods work in every possible scenario, as I don't know how to test that. If somebody finds a bug, make sure to tell me and I will make sure to fix it.
Thanks for that PR, I was too lazy to do it myself :smile: Internally, the item is already being removed from the player's inventory by setting its type to air and amount to 0 so you don't need to remove it yourself though
I don't think slot related methods are a good idea having methods for itemstack and equipment slots cover basically all needs
I don't think slot related methods are a good idea having methods for itemstack and equipment slots cover basically all needs
The issue with that is that dropping by ItemStack pretty much always forces the first ItemStack to be dropped. Dropping by slot allows to choose an explicit one, like the one current held, as example
Internally, the item is already being removed from the player's inventory by setting its type to air and amount to 0 so you don't need to remove it yourself though
That sadly not the case for items equipped on armor. I am not quite sure why, but in my testing, armor items did not get cleared by themselves
Internally, the item is already being removed from the player's inventory by setting its type to air and amount to 0 so you don't need to remove it yourself though
That sadly not the case for items equipped on armor. I am not quite sure why, but in my testing, armor items did not get cleared by themselves
in my tests it worked (1.21.1 and 1.21.3)
I don't think slot related methods are a good idea having methods for itemstack and equipment slots cover basically all needs
The issue with that is that dropping by ItemStack pretty much always forces the first ItemStack to be dropped. Dropping by slot allows to choose an explicit one, like the one current held, as example
I did not think of that in that case, it totally makes sense
in my tests it worked (1.21.1 and 1.21.3)
When I remove that line, it turns into an dupe glitch 😥
https://github.com/user-attachments/assets/86db1db4-a9ba-4c8a-9ac8-1acd7d08951e
@EventHandler
public void onInventoryClick(final InventoryClickEvent event) {
if (!event.getClickedInventory().equals(event.getWhoClicked().getInventory())) {
return;
}
event.setCancelled(true);
event.getWhoClicked().dropItem(event.getSlot());
}
hmm i see
Oops, the patch has a problem. Give me a second to fix it
Now let's wait for a maintainer for review
Instead of the persistThrower boolean, I would find an optional UUID argument allowing you to directly set the thrower more useful. Especially given that method already exists on the resulting Item entity anyways.
Also some Javadoc clarification on what throwRandomly does surely would be helpful, without looking at the NMS code I have no clue what that would do.
Closing pre softspoon PR in favour of new one