--- a/net/minecraft/server/EntityItem.java +++ b/net/minecraft/server/EntityItem.java @@ -5,6 +5,10 @@ import java.util.Objects; import java.util.UUID; import javax.annotation.Nullable; +// CraftBukkit start +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +// CraftBukkit end public class EntityItem extends Entity { @@ -15,6 +19,7 @@ private UUID thrower; private UUID owner; public final float b; + private int lastTick = MinecraftServer.currentTick - 1; // CraftBukkit public EntityItem(EntityTypes entitytypes, World world) { super(entitytypes, world); @@ -50,9 +55,12 @@ this.die(); } 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.lastX = this.locX(); this.lastY = this.locY(); @@ -108,9 +116,11 @@ } } + /* CraftBukkit start - moved up if (this.age != -32768) { ++this.age; } + // CraftBukkit end */ this.impulse |= this.aJ(); if (!this.world.isClientSide) { @@ -122,6 +132,12 @@ } if (!this.world.isClientSide && this.age >= 6000) { + // CraftBukkit start - fire ItemDespawnEvent + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; + return; + } + // CraftBukkit end this.die(); } @@ -197,10 +213,11 @@ private static void a(EntityItem entityitem, ItemStack itemstack, ItemStack itemstack1) { ItemStack itemstack2 = a(itemstack, itemstack1, 64); - entityitem.setItemStack(itemstack2); + if (!itemstack2.isEmpty()) entityitem.setItemStack(itemstack2); // CraftBukkit - don't set empty stacks } private static void a(EntityItem entityitem, ItemStack itemstack, EntityItem entityitem1, ItemStack itemstack1) { + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemMergeEvent(entityitem1, entityitem).isCancelled()) return; // CraftBukkit a(entityitem, itemstack, itemstack1); entityitem.pickupDelay = Math.max(entityitem.pickupDelay, entityitem1.pickupDelay); entityitem.age = Math.min(entityitem.age, entityitem1.age); @@ -224,6 +241,11 @@ } else if (!this.getItemStack().getItem().a(damagesource)) { return false; } else { + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f)) { + return false; + } + // CraftBukkit end this.velocityChanged(); this.f = (int) ((float) this.f - f); if (this.f <= 0) { @@ -285,6 +307,40 @@ Item item = itemstack.getItem(); int i = itemstack.getCount(); + // CraftBukkit start - fire PlayerPickupItemEvent + int canHold = entityhuman.inventory.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(!entityhuman.canPickUpLoot); + this.world.getServer().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(!entityhuman.canPickUpLoot); + this.world.getServer().getPluginManager().callEvent(entityEvent); + if (entityEvent.isCancelled()) { + itemstack.setCount(i); // SPIGOT-5294 - restore count + return; + } + + 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.owner == null || this.owner.equals(entityhuman.getUniqueID())) && entityhuman.inventory.pickup(itemstack)) { entityhuman.receive(this, i); if (itemstack.isEmpty()) { @@ -328,7 +384,9 @@ } public void setItemStack(ItemStack itemstack) { + com.google.common.base.Preconditions.checkArgument(!itemstack.isEmpty(), "Cannot drop air"); // CraftBukkit this.getDataWatcher().set(EntityItem.ITEM, itemstack); + this.getDataWatcher().markDirty(EntityItem.ITEM); // CraftBukkit - SPIGOT-4591, must mark dirty } @Override