--- a/net/minecraft/world/entity/item/EntityItem.java +++ b/net/minecraft/world/entity/item/EntityItem.java @@ -31,6 +31,12 @@ import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.phys.Vec3D; +// CraftBukkit start +import net.minecraft.server.MinecraftServer; +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +// CraftBukkit end + public class EntityItem extends Entity implements TraceableEntity { private static final DataWatcherObject DATA_ITEM = DataWatcher.defineId(EntityItem.class, DataWatcherRegistry.ITEM_STACK); @@ -45,6 +51,7 @@ @Nullable public UUID target; public final float bobOffs; + private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit public EntityItem(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -110,9 +117,12 @@ this.discard(); } else { super.tick(); - if (this.pickupDelay > 0 && this.pickupDelay != 32767) { - --this.pickupDelay; - } + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + if (this.pickupDelay != 32767) this.pickupDelay -= elapsedTicks; + if (this.age != -32768) this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end this.xo = this.getX(); this.yo = this.getY(); @@ -162,9 +172,11 @@ this.mergeWithNeighbours(); } + /* CraftBukkit start - moved up if (this.age != -32768) { ++this.age; } + // CraftBukkit end */ this.hasImpulse |= this.updateInWaterStateAndDoFluidPushing(); if (!this.level().isClientSide) { @@ -176,6 +188,12 @@ } if (!this.level().isClientSide && this.age >= 6000) { + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; + return; + } + // CraftBukkit end this.discard(); } @@ -255,10 +273,11 @@ private static void merge(EntityItem entityitem, ItemStack itemstack, ItemStack itemstack1) { ItemStack itemstack2 = merge(itemstack, itemstack1, 64); - entityitem.setItem(itemstack2); + if (!itemstack2.isEmpty()) entityitem.setItem(itemstack2); // CraftBukkit - don't set empty stacks } private static void merge(EntityItem entityitem, ItemStack itemstack, EntityItem entityitem1, ItemStack itemstack1) { + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemMergeEvent(entityitem1, entityitem).isCancelled()) return; // CraftBukkit merge(entityitem, itemstack, itemstack1); entityitem.pickupDelay = Math.max(entityitem.pickupDelay, entityitem1.pickupDelay); entityitem.age = Math.min(entityitem.age, entityitem1.age); @@ -284,6 +303,11 @@ } else if (this.level().isClientSide) { return true; } else { + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f)) { + return false; + } + // CraftBukkit end this.markHurt(); this.health = (int) ((float) this.health - f); this.gameEvent(GameEvent.ENTITY_DAMAGE, damagesource.getEntity()); @@ -347,6 +371,46 @@ Item item = itemstack.getItem(); int i = itemstack.getCount(); + // CraftBukkit start - fire PlayerPickupItemEvent + int canHold = entityhuman.getInventory().canHold(itemstack); + int remaining = i - canHold; + + if (this.pickupDelay <= 0 && canHold > 0) { + itemstack.setCount(canHold); + // Call legacy event + PlayerPickupItemEvent playerEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); + playerEvent.setCancelled(!playerEvent.getPlayer().getCanPickupItems()); + this.level().getCraftServer().getPluginManager().callEvent(playerEvent); + if (playerEvent.isCancelled()) { + itemstack.setCount(i); // SPIGOT-5294 - restore count + return; + } + + // Call newer event afterwards + EntityPickupItemEvent entityEvent = new EntityPickupItemEvent((org.bukkit.entity.Player) entityhuman.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); + entityEvent.setCancelled(!entityEvent.getEntity().getCanPickupItems()); + this.level().getCraftServer().getPluginManager().callEvent(entityEvent); + if (entityEvent.isCancelled()) { + itemstack.setCount(i); // SPIGOT-5294 - restore count + return; + } + + // Update the ItemStack if it was changed in the event + ItemStack current = this.getItem(); + if (!itemstack.equals(current)) { + itemstack = current; + } else { + itemstack.setCount(canHold + remaining); // = i + } + + // Possibly < 0; fix here so we do not have to modify code below + this.pickupDelay = 0; + } else if (this.pickupDelay == 0) { + // ensure that the code below isn't triggered if canHold says we can't pick the items up + this.pickupDelay = -1; + } + // CraftBukkit end + if (this.pickupDelay == 0 && (this.target == null || this.target.equals(entityhuman.getUUID())) && entityhuman.getInventory().add(itemstack)) { entityhuman.take(this, i); if (itemstack.isEmpty()) { @@ -390,7 +454,9 @@ } public void setItem(ItemStack itemstack) { + com.google.common.base.Preconditions.checkArgument(!itemstack.isEmpty(), "Cannot drop air"); // CraftBukkit this.getEntityData().set(EntityItem.DATA_ITEM, itemstack); + this.getEntityData().markDirty(EntityItem.DATA_ITEM); // CraftBukkit - SPIGOT-4591, must mark dirty } @Override