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