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