--- a/net/minecraft/world/entity/item/EntityItem.java +++ b/net/minecraft/world/entity/item/EntityItem.java @@ -31,6 +31,14 @@ import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.phys.Vec3D; +// CraftBukkit start +import net.minecraft.server.MinecraftServer; +import org.bukkit.craftbukkit.event.CraftEventFactory; +import org.bukkit.entity.Player; +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); @@ -47,6 +55,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); @@ -128,9 +137,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(); @@ -180,9 +192,11 @@ this.mergeWithNeighbours(); } + /* CraftBukkit start - moved up if (this.age != -32768) { ++this.age; } + // CraftBukkit end */ this.hasImpulse |= this.updateInWaterStateAndDoFluidPushing(); if (!this.level().isClientSide) { @@ -194,6 +208,12 @@ } if (!this.level().isClientSide && this.age >= 6000) { + // CraftBukkit start - fire ItemDespawnEvent + if (CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { + this.age = 0; + return; + } + // CraftBukkit end this.discard(); } @@ -277,6 +297,11 @@ } private static void merge(EntityItem entityitem, ItemStack itemstack, EntityItem entityitem1, ItemStack itemstack1) { + // CraftBukkit start + if (!CraftEventFactory.callItemMergeEvent(entityitem1, entityitem)) { + return; + } + // CraftBukkit end merge(entityitem, itemstack, itemstack1); entityitem.pickupDelay = Math.max(entityitem.pickupDelay, entityitem1.pickupDelay); entityitem.age = Math.min(entityitem.age, entityitem1.age); @@ -302,6 +327,11 @@ } else if (this.level().isClientSide) { return true; } else { + // CraftBukkit start + if (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()); @@ -366,6 +396,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((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((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()) {