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 #11810

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
46 changes: 46 additions & 0 deletions paper-api/src/main/java/org/bukkit/entity/HumanEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import java.util.Collection;
import java.util.Set;
import java.util.UUID;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.InventoryView;
Expand Down Expand Up @@ -701,11 +703,55 @@ default void openSign(@NotNull org.bukkit.block.Sign sign) {
* This will force the entity to drop the item they are holding with
* an option to drop the entire {@link ItemStack} or just 1 of the items.
*
* @deprecated You should instead use {@link #dropItem(EquipmentSlot, int)} with a {@link EquipmentSlot#HAND} parameter.
* @param dropAll True to drop entire stack, false to drop 1 of the stack
* @return True if item was dropped successfully
*/
@Deprecated(since = "1.21.4")
public boolean dropItem(boolean dropAll);

/**
* Makes the entity drop an item from their inventory based on the slot.
*
* @param slot The slot to drop
* @param amount The number of items to drop from this slot. Values below 1 don't drop an Item
* @return The dropped item entity, or null if the action was unsuccessful
* @throws IllegalArgumentException If the slot is negative or bigger than the player's inventory
*/
public @Nullable Item dropItem(int slot, int amount);

/**
* Makes the player drop an item from their inventory based on the equipment slot.
*
* @param slot The equipment slot to drop
* @param amount The amount of items to drop from this equipment slot. Values below 1 don't drop an Item
* @return The dropped item entity, or null if the action was unsuccessful
*/
public @Nullable Item dropItem(@NotNull EquipmentSlot slot, int amount);

/**
* Makes the entity drop an item from their inventory based on the slot.
* Instead of the item being dropped where the player is currently looking, this method makes it drop in
* a random direction, similar to how items are dropped after a player's death.
*
* @param slot The slot to drop
* @param amount The number of items to drop from this slot. Values below 1 don't drop an Item
* @return The dropped item entity, or null if the action was unsuccessful
* @throws IllegalArgumentException If the slot is negative or bigger than the player's inventory
*/
public @Nullable Item dropItemRandomly(int slot, int amount);

/**
* Makes the player drop an item from their inventory based on the equipment slot.
* Instead of the item being dropped where the player is currently looking, this method makes it drop in
* a random direction, similar to how items are dropped after a player's death.
*
* @param slot The equipment slot to drop
* @param amount The amount of items to drop from this equipment slot. Values below 1 don't drop an Item
* @return The dropped item entity, or null if the action was unsuccessful
*/
public @Nullable Item dropItemRandomly(@NotNull EquipmentSlot slot, int amount);

Strokkur424 marked this conversation as resolved.
Show resolved Hide resolved
/**
* Gets the players current exhaustion level.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
import net.minecraft.world.inventory.AbstractContainerMenu;
Expand Down Expand Up @@ -48,13 +49,14 @@
import org.bukkit.craftbukkit.inventory.CraftItemStack;
import org.bukkit.craftbukkit.inventory.CraftMerchantCustom;
import org.bukkit.craftbukkit.inventory.CraftRecipe;
import org.bukkit.craftbukkit.util.CraftChatMessage;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.entity.Firework;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Item;
import org.bukkit.entity.Villager;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.inventory.EntityEquipment;
import org.bukkit.inventory.EquipmentSlot;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.inventory.ItemStack;
Expand All @@ -66,6 +68,8 @@
import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
private CraftInventoryPlayer inventory;
Expand Down Expand Up @@ -801,6 +805,50 @@ public boolean dropItem(boolean dropAll) {
// Paper end - Fix HumanEntity#drop not updating the client inv
}

@Override
public @Nullable Item dropItem(final int slot, final int amount) {
if (slot < 0 || slot >= this.inventory.getSize()) {
throw new IllegalArgumentException("Slot " + slot + " is not a valid inventory slot.");
}

return dropItemRaw(this.inventory.getItem(slot), amount, false);
}

@Override
public @Nullable Item dropItem(final @NotNull EquipmentSlot slot, final int amount) {
return dropItemRaw(this.inventory.getItem(slot), amount, false);
}

@Override
public @Nullable Item dropItemRandomly(final int slot, final int amount) {
if (slot < 0 || slot >= this.inventory.getSize()) {
throw new IllegalArgumentException("Slot " + slot + " is not a valid inventory slot.");
}

return dropItemRaw(this.inventory.getItem(slot), amount, true);
}

@Override
public @Nullable Item dropItemRandomly(final @NotNull EquipmentSlot slot, final int amount) {
return dropItemRaw(this.inventory.getItem(slot), amount, true);
}

private @Nullable Item dropItemRaw(final ItemStack originalItemStack, final int amount, final boolean throwRandomly) {
if (originalItemStack == null || originalItemStack.isEmpty() || amount <= 0) {
return null;
}

final net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.unwrap(originalItemStack);
final net.minecraft.world.item.ItemStack dropContent = nmsItemStack.split(amount);

final ItemEntity droppedEntity = this.getHandle().drop(dropContent, throwRandomly, true);
if (droppedEntity == null) {
return null;
}

return (Item) droppedEntity.getBukkitEntity();
}

@Override
public float getExhaustion() {
return this.getHandle().getFoodData().exhaustionLevel;
Expand Down