Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend HumanEntity#dropItem API #11689

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

Strokkur424
Copy link

@Strokkur424 Strokkur424 commented Nov 30, 2024

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.

@Strokkur424 Strokkur424 requested a review from a team as a code owner November 30, 2024 11:27
@NonSwag
Copy link
Contributor

NonSwag commented Nov 30, 2024

Thanks for that PR, I was too lazy to do it myself 😄
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

@NonSwag
Copy link
Contributor

NonSwag commented Nov 30, 2024

I don't think slot related methods are a good idea
having methods for itemstack and equipment slots cover basically all needs

@Strokkur424
Copy link
Author

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

@Strokkur424
Copy link
Author

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

@NonSwag
Copy link
Contributor

NonSwag commented Nov 30, 2024

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)

@NonSwag
Copy link
Contributor

NonSwag commented Nov 30, 2024

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

@Strokkur424
Copy link
Author

in my tests it worked (1.21.1 and 1.21.3)

When I remove that line, it turns into an dupe glitch 😥

2024-11-30_14-24-31.mp4
@EventHandler
public void onInventoryClick(final InventoryClickEvent event) {
    if (!event.getClickedInventory().equals(event.getWhoClicked().getInventory())) {
        return;
    }

    event.setCancelled(true);
    event.getWhoClicked().dropItem(event.getSlot());
}

@NonSwag
Copy link
Contributor

NonSwag commented Nov 30, 2024

hmm i see

@Strokkur424
Copy link
Author

Oops, the patch has a problem. Give me a second to fix it

Strokkur24 added 3 commits November 30, 2024 15:33
…ayer-dropItem

# Conflicts:
#	patches/api/0501-Extend-HumanEntity-dropItem-API.patch
#	patches/server/1073-Extend-HumanEntity-dropItem-API.patch
@Strokkur424 Strokkur424 requested a review from NonSwag November 30, 2024 19:26
@NonSwag
Copy link
Contributor

NonSwag commented Nov 30, 2024

Now let's wait for a maintainer for review

@Malfrador
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Awaiting review
Development

Successfully merging this pull request may close these issues.

Player#dropItem(ItemStack)
3 participants