--- a/net/minecraft/server/EntityItem.java +++ b/net/minecraft/server/EntityItem.java @@ -4,6 +4,10 @@ import java.util.List; 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 { @@ -14,6 +18,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); @@ -49,9 +54,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; @@ -101,9 +109,11 @@ } } + /* Craftbukkit start - moved up if (this.age != -32768) { ++this.age; } + // Craftbukkit end */ this.impulse |= this.ay(); if (!this.world.isClientSide) { @@ -115,6 +125,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(); } @@ -175,13 +191,14 @@ } private static void a(EntityItem entityitem, ItemStack itemstack, EntityItem entityitem1, ItemStack itemstack1) { + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemMergeEvent(entityitem1, entityitem).isCancelled()) return; // CraftBukkit int i = Math.min(itemstack.getMaxStackSize() - itemstack.getCount(), itemstack1.getCount()); ItemStack itemstack2 = itemstack.cloneItemStack(); itemstack2.add(i); entityitem.setItemStack(itemstack2); itemstack1.subtract(i); - entityitem1.setItemStack(itemstack1); + if (!itemstack1.isEmpty()) entityitem1.setItemStack(itemstack1); // CraftBukkit - don't set empty stacks entityitem.pickupDelay = Math.max(entityitem.pickupDelay, entityitem1.pickupDelay); entityitem.age = Math.min(entityitem.age, entityitem1.age); if (itemstack1.isEmpty()) { @@ -195,7 +212,7 @@ } @Override - protected void burn(int i) { + protected void burn(float i) { // CraftBukkit - int -> float this.damageEntity(DamageSource.FIRE, (float) i); } @@ -206,6 +223,11 @@ } else if (!this.getItemStack().isEmpty() && this.getItemStack().getItem() == Items.NETHER_STAR && damagesource.isExplosion()) { 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) { @@ -267,6 +289,38 @@ 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()) { + 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()) { + return; + } + + itemstack.setCount(canHold + remaining); + + // 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 || 6000 - this.age <= 200 || this.owner.equals(entityhuman.getUniqueID())) && entityhuman.inventory.pickup(itemstack)) { entityhuman.receive(this, i); if (itemstack.isEmpty()) { @@ -309,7 +363,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 } @Nullable