--- ../src-base/minecraft/net/minecraft/entity/item/EntityItem.java +++ ../src-work/minecraft/net/minecraft/entity/item/EntityItem.java @@ -22,6 +22,11 @@ import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.Event.Result; +// CraftBukkit start +import org.bukkit.event.player.PlayerPickupItemEvent; +import net.minecraft.server.MinecraftServer; +// CraftBukkit end + public class EntityItem extends Entity { private static final Logger logger = LogManager.getLogger(); @@ -31,6 +36,7 @@ private String field_145801_f; private String field_145802_g; public float hoverStart; + private int lastTick = MinecraftServer.currentTick; // CraftBukkit private static final String __OBFID = "CL_00001669"; /** @@ -55,6 +61,15 @@ public EntityItem(World p_i1710_1_, double p_i1710_2_, double p_i1710_4_, double p_i1710_6_, ItemStack p_i1710_8_) { this(p_i1710_1_, p_i1710_2_, p_i1710_4_, p_i1710_6_); + + // CraftBukkit start - Can't set null items in the datawatcher + if (p_i1710_8_ == null || p_i1710_8_.getItem() == null) + { + return; + } + + // CraftBukkit end + this.setEntityItemStack(p_i1710_8_); this.lifespan = (p_i1710_8_.getItem() == null ? 6000 : p_i1710_8_.getItem().getEntityLifespan(p_i1710_8_, p_i1710_1_)); } @@ -81,6 +96,10 @@ public void onUpdate() { ItemStack stack = this.getDataWatcher().getWatchableObjectItemStack(10); + if (stack == null || stack.stackSize == 0) { + setDead(); + return; + } if (stack != null && stack.getItem() != null) { if (stack.getItem().onEntityItemUpdate(this)) @@ -89,93 +108,103 @@ } } - if (this.getEntityItem() == null) - { - this.setDead(); + super.onUpdate(); + // CraftBukkit start - Use wall time for pickup and despawn timers + int elapsedTicks = MinecraftServer.currentTick - this.lastTick; + this.delayBeforeCanPickup -= elapsedTicks; + if (this.delayBeforeCanPickup < 0) this.delayBeforeCanPickup = 0; // Cauldron + this.age += elapsedTicks; + this.lastTick = MinecraftServer.currentTick; + // CraftBukkit end + + boolean forceUpdate = this.ticksExisted > 0 && this.ticksExisted % 25 == 0; // Cauldron - optimize item tick updates + this.prevPosX = this.posX; + this.prevPosY = this.posY; + this.prevPosZ = this.posZ; + this.motionY -= 0.03999999910593033D; + // Cauldron start - if forced + if (forceUpdate || noClip) { + this.noClip = this.func_145771_j(this.posX, (this.boundingBox.minY + this.boundingBox.maxY) / 2.0D, this.posZ); } - else - { - super.onUpdate(); + // Cauldron end + this.moveEntity(this.motionX, this.motionY, this.motionZ); + boolean flag = (int)this.prevPosX != (int)this.posX || (int)this.prevPosY != (int)this.posY || (int)this.prevPosZ != (int)this.posZ; - if (this.delayBeforeCanPickup > 0) + if ((flag && this.ticksExisted % 5 == 0) || forceUpdate) // Cauldron - if forced + { + if (this.worldObj.getBlock(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)).getMaterial() == Material.lava) { - --this.delayBeforeCanPickup; + this.motionY = 0.20000000298023224D; + this.motionX = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F); + this.motionZ = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F); + this.playSound("random.fizz", 0.4F, 2.0F + this.rand.nextFloat() * 0.4F); } - this.prevPosX = this.posX; - this.prevPosY = this.posY; - this.prevPosZ = this.posZ; - this.motionY -= 0.03999999910593033D; - this.noClip = this.func_145771_j(this.posX, (this.boundingBox.minY + this.boundingBox.maxY) / 2.0D, this.posZ); - this.moveEntity(this.motionX, this.motionY, this.motionZ); - boolean flag = (int)this.prevPosX != (int)this.posX || (int)this.prevPosY != (int)this.posY || (int)this.prevPosZ != (int)this.posZ; - - if (flag || this.ticksExisted % 25 == 0) + if (forceUpdate && !this.worldObj.isRemote) // Cauldron - if forced { - if (this.worldObj.getBlock(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)).getMaterial() == Material.lava) - { - this.motionY = 0.20000000298023224D; - this.motionX = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F); - this.motionZ = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F); - this.playSound("random.fizz", 0.4F, 2.0F + this.rand.nextFloat() * 0.4F); - } - - if (!this.worldObj.isRemote) - { - this.searchForOtherItemsNearby(); - } + this.searchForOtherItemsNearby(); } + } - float f = 0.98F; + float f = 0.98F; - if (this.onGround) - { - f = this.worldObj.getBlock(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ)).slipperiness * 0.98F; - } + if (this.onGround) + { + f = this.worldObj.getBlock(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ)).slipperiness * 0.98F; + } - this.motionX *= (double)f; - this.motionY *= 0.9800000190734863D; - this.motionZ *= (double)f; + this.motionX *= (double)f; + this.motionY *= 0.9800000190734863D; + this.motionZ *= (double)f; - if (this.onGround) - { - this.motionY *= -0.5D; - } + if (this.onGround) + { + this.motionY *= -0.5D; + } - ++this.age; + // ++this.age; // CraftBukkit - Moved up (base age on wall time) - ItemStack item = getDataWatcher().getWatchableObjectItemStack(10); - - if (!this.worldObj.isRemote && this.age >= lifespan) + ItemStack item = getDataWatcher().getWatchableObjectItemStack(10); + + if (!this.worldObj.isRemote && this.age >= lifespan - 1) // Cauldron adjust for age being off by one when it is first dropped + { + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { - if (item != null) - { - ItemExpireEvent event = new ItemExpireEvent(this, (item.getItem() == null ? 6000 : item.getItem().getEntityLifespan(item, worldObj))); - if (MinecraftForge.EVENT_BUS.post(event)) - { - lifespan += event.extraLife; - } - else - { - this.setDead(); - } + this.age = 0; + return; + } + // CraftBukkit end + if (item != null) + { + ItemExpireEvent event = new ItemExpireEvent(this, (item.getItem() == null ? this.worldObj.getSpigotConfig().itemDespawnRate : item.getItem().getEntityLifespan(item, worldObj))); // Spigot // Cauldron + if (MinecraftForge.EVENT_BUS.post(event)) + { + lifespan += event.extraLife; } else { this.setDead(); } } - - if (item != null && item.stackSize <= 0) + else { this.setDead(); } } + + if (item != null && item.stackSize <= 0) + { + this.setDead(); + } } private void searchForOtherItemsNearby() { - Iterator iterator = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(0.5D, 0.0D, 0.5D)).iterator(); + // Spigot start + double radius = worldObj.getSpigotConfig().itemMerge; // Cauldron + Iterator iterator = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(radius, radius, radius)).iterator(); + // Spigot end while (iterator.hasNext()) { @@ -225,11 +254,13 @@ } else { - itemstack1.stackSize += itemstack.stackSize; - p_70289_1_.delayBeforeCanPickup = Math.max(p_70289_1_.delayBeforeCanPickup, this.delayBeforeCanPickup); - p_70289_1_.age = Math.min(p_70289_1_.age, this.age); - p_70289_1_.setEntityItemStack(itemstack1); - this.setDead(); + // Spigot start + itemstack.stackSize += itemstack1.stackSize; + this.delayBeforeCanPickup = Math.max(p_70289_1_.delayBeforeCanPickup, this.delayBeforeCanPickup); + this.age = Math.min(p_70289_1_.age, this.age); + this.setEntityItemStack(itemstack); + p_70289_1_.setDead(); + // Spigot end return true; } } @@ -316,8 +347,27 @@ } NBTTagCompound nbttagcompound1 = p_70037_1_.getCompoundTag("Item"); - this.setEntityItemStack(ItemStack.loadItemStackFromNBT(nbttagcompound1)); + // CraftBukkit start + if (nbttagcompound1 != null) + { + ItemStack itemstack = ItemStack.loadItemStackFromNBT(nbttagcompound1); + + if (itemstack != null) + { + this.setEntityItemStack(itemstack); + } + else + { + this.setDead(); + } + } + else + { + this.setDead(); + } + + // CraftBukkit end ItemStack item = getDataWatcher().getWatchableObjectItemStack(10); if (item == null || item.stackSize <= 0) @@ -350,6 +400,31 @@ ItemStack itemstack = this.getEntityItem(); int i = itemstack.stackSize; + // CraftBukkit start + int canHold = p_70100_1_.inventory.canHold(itemstack); + int remaining = itemstack.stackSize - canHold; + + if (this.delayBeforeCanPickup <= 0 && canHold > 0) + { + itemstack.stackSize = canHold; + // Cauldron start - rename to cbEvent to fix naming collision + PlayerPickupItemEvent cbEvent = new PlayerPickupItemEvent((org.bukkit.entity.Player) p_70100_1_.getBukkitEntity(), (org.bukkit.entity.Item) this.getBukkitEntity(), remaining); + //cbEvent.setCancelled(!par1EntityPlayer.canPickUpLoot); TODO + this.worldObj.getServer().getPluginManager().callEvent(cbEvent); + itemstack.stackSize = canHold + remaining; + + if (cbEvent.isCancelled()) + { + return; + } + // Cauldron end + + // Possibly < 0; fix here so we do not have to modify code below + this.delayBeforeCanPickup = 0; + } + + // CraftBukkit end + if (this.delayBeforeCanPickup <= 0 && (this.field_145802_g == null || lifespan - this.age <= 200 || this.field_145802_g.equals(p_70100_1_.getCommandSenderName())) && (event.getResult() == Result.ALLOW || i <= 0 || p_70100_1_.inventory.addItemStackToInventory(itemstack))) { if (itemstack.getItem() == Item.getItemFromBlock(Blocks.log)) @@ -423,7 +498,7 @@ public ItemStack getEntityItem() { ItemStack itemstack = this.getDataWatcher().getWatchableObjectItemStack(10); - return itemstack == null ? new ItemStack(Blocks.stone) : itemstack; + return itemstack == null ? new ItemStack(Blocks.air, 0) : itemstack; } public void setEntityItemStack(ItemStack p_92058_1_) @@ -451,4 +526,10 @@ { this.field_145801_f = p_145799_1_; } + + @Override + public boolean entityAllowedToSpawn() { + ItemStack stack = getDataWatcher().getWatchableObjectItemStack(10); + return stack != null && stack.getItem() != null && stack.stackSize > 0; + } }