mirror of
https://github.com/PaperMC/Paper.git
synced 2025-03-13 11:18:23 +01:00
Extend HumanEntity#dropItem API (#11810)
This commit is contained in:
parent
18da1ae4c0
commit
93a3df085c
4 changed files with 168 additions and 6 deletions
|
@ -2,10 +2,12 @@ package org.bukkit.entity;
|
|||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
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;
|
||||
|
@ -14,6 +16,7 @@ import org.bukkit.inventory.MainHand;
|
|||
import org.bukkit.inventory.Merchant;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -703,8 +706,115 @@ public interface HumanEntity extends LivingEntity, AnimalTamer, InventoryHolder
|
|||
*
|
||||
* @param dropAll True to drop entire stack, false to drop 1 of the stack
|
||||
* @return True if item was dropped successfully
|
||||
* @apiNote You should instead use {@link #dropItem(EquipmentSlot, int)} or {@link #dropItem(EquipmentSlot)} with a {@link EquipmentSlot#HAND} parameter.
|
||||
*/
|
||||
public boolean dropItem(boolean dropAll);
|
||||
@ApiStatus.Obsolete(since = "1.21.4")
|
||||
boolean dropItem(boolean dropAll);
|
||||
|
||||
/**
|
||||
* Makes the player drop all items from their inventory based on the inventory slot.
|
||||
*
|
||||
* @param slot the equipment slot to drop
|
||||
* @return the dropped item entity, or null if the action was unsuccessful
|
||||
*/
|
||||
@Nullable
|
||||
default Item dropItem(final int slot) {
|
||||
return this.dropItem(slot, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the player drop an item from their inventory based on the inventory slot.
|
||||
*
|
||||
* @param slot the slot to drop
|
||||
* @param amount the number of items to drop from this slot. Values below one always return null
|
||||
* @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
|
||||
*/
|
||||
@Nullable
|
||||
default Item dropItem(final int slot, final int amount) {
|
||||
return this.dropItem(slot, amount, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the player drop an item from their inventory based on the inventory slot.
|
||||
*
|
||||
* @param slot the slot to drop
|
||||
* @param amount the number of items to drop from this slot. Values below one always return null
|
||||
* @param throwRandomly controls the randomness of the dropped items velocity, where {@code true} mimics dropped
|
||||
* items during a player's death, while {@code false} acts like a normal item drop.
|
||||
* @param entityOperation the function to be run before adding the entity into the world
|
||||
* @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
|
||||
*/
|
||||
@Nullable
|
||||
Item dropItem(int slot, int amount, boolean throwRandomly, @Nullable Consumer<Item> entityOperation);
|
||||
|
||||
/**
|
||||
* Makes the player drop all items from their inventory based on the equipment slot.
|
||||
*
|
||||
* @param slot the equipment slot to drop
|
||||
* @return the dropped item entity, or null if the action was unsuccessful
|
||||
*/
|
||||
@Nullable
|
||||
default Item dropItem(final @NotNull EquipmentSlot slot) {
|
||||
return this.dropItem(slot, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 one always return null
|
||||
* @return the dropped item entity, or null if the action was unsuccessful
|
||||
*/
|
||||
@Nullable
|
||||
default Item dropItem(final @NotNull EquipmentSlot slot, final int amount) {
|
||||
return this.dropItem(slot, amount, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 one always return null
|
||||
* @param throwRandomly controls the randomness of the dropped items velocity, where {@code true} mimics dropped
|
||||
* items during a player's death, while {@code false} acts like a normal item drop.
|
||||
* @param entityOperation the function to be run before adding the entity into the world
|
||||
* @return the dropped item entity, or null if the action was unsuccessful
|
||||
*/
|
||||
@Nullable
|
||||
Item dropItem(@NotNull EquipmentSlot slot, int amount, boolean throwRandomly, @Nullable Consumer<Item> entityOperation);
|
||||
|
||||
/**
|
||||
* Makes the player drop any arbitrary {@link ItemStack}, independently of whether the player actually
|
||||
* has that item in their inventory.
|
||||
* <p>
|
||||
* This method modifies neither the item nor the player's inventory.
|
||||
* Item removal has to be handled by the method caller.
|
||||
*
|
||||
* @param itemStack the itemstack to drop
|
||||
* @return the dropped item entity, or null if the action was unsuccessful
|
||||
*/
|
||||
@Nullable
|
||||
default Item dropItem(final @NotNull ItemStack itemStack) {
|
||||
return this.dropItem(itemStack, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the player drop any arbitrary {@link ItemStack}, independently of whether the player actually
|
||||
* has that item in their inventory.
|
||||
* <p>
|
||||
* This method modifies neither the item nor the player's inventory.
|
||||
* Item removal has to be handled by the method caller.
|
||||
*
|
||||
* @param itemStack the itemstack to drop
|
||||
* @param throwRandomly controls the randomness of the dropped items velocity, where {@code true} mimics dropped
|
||||
* items during a player's death, while {@code false} acts like a normal item drop.
|
||||
* @param entityOperation the function to be run before adding the entity into the world
|
||||
* @return the dropped item entity, or null if the action was unsuccessful
|
||||
*/
|
||||
@Nullable
|
||||
Item dropItem(final @NotNull ItemStack itemStack, boolean throwRandomly, @Nullable Consumer<Item> entityOperation);
|
||||
|
||||
/**
|
||||
* Gets the players current exhaustion level.
|
||||
|
|
|
@ -1342,17 +1342,18 @@
|
|||
}
|
||||
|
||||
public SectionPos getLastSectionPos() {
|
||||
@@ -1930,21 +_,54 @@
|
||||
@@ -1930,21 +_,55 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem) {
|
||||
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem, boolean callEvent) { // CraftBukkit - SPIGOT-2942: Add boolean to call event
|
||||
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean traceItem, boolean callEvent, @Nullable java.util.function.Consumer<org.bukkit.entity.Item> entityOperation) { // Paper start - Extend HumanEntity#dropItem API
|
||||
ItemEntity itemEntity = this.createItemStackToDrop(droppedItem, dropAround, traceItem);
|
||||
if (itemEntity == null) {
|
||||
return null;
|
||||
} else {
|
||||
+ // CraftBukkit start - fire PlayerDropItemEvent
|
||||
+ if (entityOperation != null) entityOperation.accept((org.bukkit.entity.Item) itemEntity.getBukkitEntity());
|
||||
+ if (callEvent) {
|
||||
+ org.bukkit.entity.Player player = this.getBukkitEntity();
|
||||
+ org.bukkit.entity.Item drop = (org.bukkit.entity.Item) itemEntity.getBukkitEntity();
|
||||
|
|
|
@ -112,16 +112,21 @@
|
|||
this.removeEntitiesOnShoulder();
|
||||
}
|
||||
}
|
||||
@@ -717,6 +_,13 @@
|
||||
@@ -717,6 +_,18 @@
|
||||
|
||||
@Nullable
|
||||
public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) {
|
||||
+ // CraftBukkit start - SPIGOT-2942: Add boolean to call event
|
||||
+ return this.drop(droppedItem, dropAround, includeThrowerName, true);
|
||||
+ return this.drop(droppedItem, dropAround, includeThrowerName, true, null);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName, boolean callEvent) {
|
||||
+ return this.drop(droppedItem, dropAround, includeThrowerName, callEvent, null);
|
||||
+ }
|
||||
+
|
||||
+ @Nullable
|
||||
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName, boolean callEvent, @Nullable java.util.function.Consumer<org.bukkit.entity.Item> entityOperation) {
|
||||
+ // CraftBukkit end
|
||||
if (!droppedItem.isEmpty() && this.level().isClientSide) {
|
||||
this.swing(InteractionHand.MAIN_HAND);
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
|
@ -19,6 +20,7 @@ import net.minecraft.world.entity.Entity;
|
|||
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;
|
||||
|
@ -48,13 +50,14 @@ import org.bukkit.craftbukkit.inventory.CraftInventoryView;
|
|||
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;
|
||||
|
@ -66,6 +69,8 @@ import org.bukkit.permissions.Permission;
|
|||
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;
|
||||
|
@ -801,6 +806,47 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity {
|
|||
// Paper end - Fix HumanEntity#drop not updating the client inv
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Item dropItem(final int slot, final int amount, final boolean throwRandomly, final @Nullable Consumer<Item> entityOperation) {
|
||||
Preconditions.checkArgument(slot >= 0 && slot < this.inventory.getSize(), "Slot %s is not a valid inventory slot.", slot);
|
||||
|
||||
return internalDropItemFromInventory(this.inventory.getItem(slot), amount, throwRandomly, entityOperation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Item dropItem(final @NotNull EquipmentSlot slot, final int amount, final boolean throwRandomly, final @Nullable Consumer<Item> entityOperation) {
|
||||
return internalDropItemFromInventory(this.inventory.getItem(slot), amount, throwRandomly, entityOperation);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Item internalDropItemFromInventory(final ItemStack originalItemStack, final int amount, final boolean throwRandomly, final @Nullable Consumer<Item> entityOperation) {
|
||||
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);
|
||||
|
||||
// This will return the itemstack back to its original amount in case events fail
|
||||
final ItemEntity droppedEntity = this.getHandle().drop(dropContent, throwRandomly, true, true, entityOperation);
|
||||
return droppedEntity == null ? null : (Item) droppedEntity.getBukkitEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Item dropItem(final @Nullable ItemStack itemStack, final boolean throwRandomly, final @Nullable Consumer<Item> entityOperation) {
|
||||
// This method implementation differs from the previous dropItem implementations, as it does not source
|
||||
// its itemstack from the players inventory. As such, we cannot reuse #internalDropItemFromInventory.
|
||||
Preconditions.checkArgument(itemStack != null, "Cannot drop a null itemstack");
|
||||
if (itemStack.isEmpty()) return null;
|
||||
|
||||
final net.minecraft.world.item.ItemStack nmsItemStack = CraftItemStack.asNMSCopy(itemStack);
|
||||
|
||||
// Do *not* call the event here, the item is not in the player inventory, they are not dropping it / do not need recovering logic (which would be a dupe).
|
||||
final ItemEntity droppedEntity = this.getHandle().drop(nmsItemStack, throwRandomly, true, false, entityOperation);
|
||||
return droppedEntity == null ? null : (Item) droppedEntity.getBukkitEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getExhaustion() {
|
||||
return this.getHandle().getFoodData().exhaustionLevel;
|
||||
|
|
Loading…
Add table
Reference in a new issue