    001    package net.minecraft.src;
    002
    003    import java.util.Iterator;
    004
    005    import net.minecraftforge.common.MinecraftForge;
    006    import net.minecraftforge.event.entity.item.ItemExpireEvent;
    007    import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
    008
    009    import cpw.mods.fml.common.registry.GameRegistry;
    010
    011    public class EntityItem extends Entity
    012    {
    013        /** The item stack of this EntityItem. */
    014        public ItemStack item;
    015
    016        /**
    017         * The age of this EntityItem (used to animate it up and down as well as expire it)
    018         */
    019        public int age = 0;
    020        public int delayBeforeCanPickup;
    021
    022        /** The health of this EntityItem. (For example, damage for tools) */
    023        private int health = 5;
    024
    025        /** The EntityItem's random initial float height. */
    026        public float hoverStart = (float)(Math.random() * Math.PI * 2.0D);
    027
    028        /**
    029         * The maximum age of this EntityItem.  The item is expired once this is reached.
    030         */
    031        public int lifespan = 6000;
    032
    033        public EntityItem(World par1World, double par2, double par4, double par6, ItemStack par8ItemStack)
    034        {
    035            super(par1World);
    036            this.setSize(0.25F, 0.25F);
    037            this.yOffset = this.height / 2.0F;
    038            this.setPosition(par2, par4, par6);
    039            this.item = par8ItemStack;
    040            this.rotationYaw = (float)(Math.random() * 360.0D);
    041            this.motionX = (double)((float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D));
    042            this.motionY = 0.20000000298023224D;
    043            this.motionZ = (double)((float)(Math.random() * 0.20000000298023224D - 0.10000000149011612D));
    044            this.lifespan = (par8ItemStack.getItem() == null ? 6000 : par8ItemStack.getItem().getEntityLifespan(par8ItemStack, par1World));
    045        }
    046
    047        /**
    048         * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
    049         * prevent them from trampling crops
    050         */
    051        protected boolean canTriggerWalking()
    052        {
    053            return false;
    054        }
    055
    056        public EntityItem(World par1World)
    057        {
    058            super(par1World);
    059            this.setSize(0.25F, 0.25F);
    060            this.yOffset = this.height / 2.0F;
    061        }
    062
    063        protected void entityInit() {}
    064
    065        /**
    066         * Called to update the entity's position/logic.
    067         */
    068        public void onUpdate()
    069        {
    070            super.onUpdate();
    071
    072            if (this.delayBeforeCanPickup > 0)
    073            {
    074                --this.delayBeforeCanPickup;
    075            }
    076
    077            this.prevPosX = this.posX;
    078            this.prevPosY = this.posY;
    079            this.prevPosZ = this.posZ;
    080            this.motionY -= 0.03999999910593033D;
    081            this.pushOutOfBlocks(this.posX, (this.boundingBox.minY + this.boundingBox.maxY) / 2.0D, this.posZ);
    082            this.moveEntity(this.motionX, this.motionY, this.motionZ);
    083            boolean var1 = (int)this.prevPosX != (int)this.posX || (int)this.prevPosY != (int)this.posY || (int)this.prevPosZ != (int)this.posZ;
    084
    085            if (var1)
    086            {
    087                if (this.worldObj.getBlockMaterial(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) == Material.lava)
    088                {
    089                    this.motionY = 0.20000000298023224D;
    090                    this.motionX = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
    091                    this.motionZ = (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F);
    092                    this.worldObj.playSoundAtEntity(this, "random.fizz", 0.4F, 2.0F + this.rand.nextFloat() * 0.4F);
    093                }
    094
    095                if (!this.worldObj.isRemote)
    096                {
    097                    Iterator var2 = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(0.5D, 0.0D, 0.5D)).iterator();
    098
    099                    while (var2.hasNext())
    100                    {
    101                        EntityItem var3 = (EntityItem)var2.next();
    102                        this.func_70289_a(var3);
    103                    }
    104                }
    105            }
    106
    107            float var4 = 0.98F;
    108
    109            if (this.onGround)
    110            {
    111                var4 = 0.58800006F;
    112                int var5 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
    113
    114                if (var5 > 0)
    115                {
    116                    var4 = Block.blocksList[var5].slipperiness * 0.98F;
    117                }
    118            }
    119
    120            this.motionX *= (double)var4;
    121            this.motionY *= 0.9800000190734863D;
    122            this.motionZ *= (double)var4;
    123
    124            if (this.onGround)
    125            {
    126                this.motionY *= -0.5D;
    127            }
    128
    129            ++this.age;
    130
    131            if (this.age >= lifespan)
    132            {
    133                ItemExpireEvent event = new ItemExpireEvent(this, (item.getItem() == null ? 6000 : item.getItem().getEntityLifespan(item, worldObj)));
    134                if (MinecraftForge.EVENT_BUS.post(event))
    135                {
    136                    lifespan += event.extraLife;
    137                }
    138                else
    139                {
    140                    this.setDead();
    141                }
    142            }
    143
    144            if (this.item == null || this.item.stackSize <= 0)
    145            {
    146                this.setDead();
    147            }
    148        }
    149
    150        public boolean func_70289_a(EntityItem par1EntityItem)
    151        {
    152            if (par1EntityItem == this)
    153            {
    154                return false;
    155            }
    156            else if (par1EntityItem.isEntityAlive() && this.isEntityAlive())
    157            {
    158                if (par1EntityItem.item.getItem() != this.item.getItem())
    159                {
    160                    return false;
    161                }
    162                else if (par1EntityItem.item.getItem().getHasSubtypes() && par1EntityItem.item.getItemDamage() != this.item.getItemDamage())
    163                {
    164                    return false;
    165                }
    166                else if (par1EntityItem.item.stackSize < this.item.stackSize)
    167                {
    168                    return par1EntityItem.func_70289_a(this);
    169                }
    170                else if (par1EntityItem.item.stackSize + this.item.stackSize > par1EntityItem.item.getMaxStackSize())
    171                {
    172                    return false;
    173                }
    174                else
    175                {
    176                    par1EntityItem.item.stackSize += this.item.stackSize;
    177                    par1EntityItem.delayBeforeCanPickup = Math.max(par1EntityItem.delayBeforeCanPickup, this.delayBeforeCanPickup);
    178                    par1EntityItem.age = Math.min(par1EntityItem.age, this.age);
    179                    this.setDead();
    180                    return true;
    181                }
    182            }
    183            else
    184            {
    185                return false;
    186            }
    187        }
    188
    189        public void func_70288_d()
    190        {
    191            this.age = 4800;
    192        }
    193
    194        /**
    195         * Returns if this entity is in water and will end up adding the waters velocity to the entity
    196         */
    197        public boolean handleWaterMovement()
    198        {
    199            return this.worldObj.handleMaterialAcceleration(this.boundingBox, Material.water, this);
    200        }
    201
    202        /**
    203         * Will deal the specified amount of damage to the entity if the entity isn't immune to fire damage. Args:
    204         * amountDamage
    205         */
    206        protected void dealFireDamage(int par1)
    207        {
    208            this.attackEntityFrom(DamageSource.inFire, par1);
    209        }
    210
    211        /**
    212         * Called when the entity is attacked.
    213         */
    214        public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    215        {
    216            this.setBeenAttacked();
    217            this.health -= par2;
    218
    219            if (this.health <= 0)
    220            {
    221                this.setDead();
    222            }
    223
    224            return false;
    225        }
    226
    227        /**
    228         * (abstract) Protected helper method to write subclass entity data to NBT.
    229         */
    230        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    231        {
    232            par1NBTTagCompound.setShort("Health", (short)((byte)this.health));
    233            par1NBTTagCompound.setShort("Age", (short)this.age);
    234            par1NBTTagCompound.setInteger("Lifespan", lifespan);
    235
    236            if (this.item != null)
    237            {
    238                par1NBTTagCompound.setCompoundTag("Item", this.item.writeToNBT(new NBTTagCompound()));
    239            }
    240        }
    241
    242        /**
    243         * (abstract) Protected helper method to read subclass entity data from NBT.
    244         */
    245        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    246        {
    247            this.health = par1NBTTagCompound.getShort("Health") & 255;
    248            this.age = par1NBTTagCompound.getShort("Age");
    249            NBTTagCompound var2 = par1NBTTagCompound.getCompoundTag("Item");
    250            this.item = ItemStack.loadItemStackFromNBT(var2);
    251
    252            if (this.item == null || this.item.stackSize <= 0)
    253            {
    254                this.setDead();
    255            }
    256
    257            if (par1NBTTagCompound.hasKey("Lifespan"))
    258            {
    259                lifespan = par1NBTTagCompound.getInteger("Lifespan");
    260            }
    261        }
    262
    263        /**
    264         * Called by a player entity when they collide with an entity
    265         */
    266        public void onCollideWithPlayer(EntityPlayer par1EntityPlayer)
    267        {
    268            if (!this.worldObj.isRemote)
    269            {
    270                if (this.delayBeforeCanPickup > 0)
    271                {
    272                    return;
    273                }
    274
    275                EntityItemPickupEvent event = new EntityItemPickupEvent(par1EntityPlayer, this);
    276
    277                if (MinecraftForge.EVENT_BUS.post(event))
    278                {
    279                    return;
    280                }
    281
    282                int var2 = this.item.stackSize;
    283
    284                if (this.delayBeforeCanPickup <= 0 && (event.isHandled() || var2 <= 0 || par1EntityPlayer.inventory.addItemStackToInventory(this.item)))
    285                {
    286                    if (this.item.itemID == Block.wood.blockID)
    287                    {
    288                        par1EntityPlayer.triggerAchievement(AchievementList.mineWood);
    289                    }
    290
    291                    if (this.item.itemID == Item.leather.shiftedIndex)
    292                    {
    293                        par1EntityPlayer.triggerAchievement(AchievementList.killCow);
    294                    }
    295
    296                    if (this.item.itemID == Item.diamond.shiftedIndex)
    297                    {
    298                        par1EntityPlayer.triggerAchievement(AchievementList.diamonds);
    299                    }
    300
    301                    if (this.item.itemID == Item.blazeRod.shiftedIndex)
    302                    {
    303                        par1EntityPlayer.triggerAchievement(AchievementList.blazeRod);
    304                    }
    305
    306                    GameRegistry.onPickupNotification(par1EntityPlayer, this);
    307
    308                    this.worldObj.playSoundAtEntity(this, "random.pop", 0.2F, ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
    309                    par1EntityPlayer.onItemPickup(this, var2);
    310
    311                    if (this.item.stackSize <= 0)
    312                    {
    313                        this.setDead();
    314                    }
    315                }
    316            }
    317        }
    318
    319        /**
    320         * Gets the username of the entity.
    321         */
    322        public String getEntityName()
    323        {
    324            return StatCollector.translateToLocal("item." + this.item.getItemName());
    325        }
    326
    327        /**
    328         * If returns false, the item will not inflict any damage against entities.
    329         */
    330        public boolean canAttackWithItem()
    331        {
    332            return false;
    333        }
    334    }