001    package net.minecraft.entity.item;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    import java.util.ArrayList;
006    import java.util.Iterator;
007    import net.minecraft.block.Block;
008    import net.minecraft.block.BlockSand;
009    import net.minecraft.entity.Entity;
010    import net.minecraft.item.ItemStack;
011    import net.minecraft.nbt.NBTTagCompound;
012    import net.minecraft.util.DamageSource;
013    import net.minecraft.util.MathHelper;
014    import net.minecraft.world.World;
015    
016    public class EntityFallingSand extends Entity
017    {
018        public int blockID;
019        public int metadata;
020    
021        /** How long the block has been falling for. */
022        public int fallTime;
023        public boolean shouldDropItem;
024        private boolean isBreakingAnvil;
025        private boolean isAnvil;
026        private int field_82156_g;
027        private float field_82158_h;
028    
029        public EntityFallingSand(World par1World)
030        {
031            super(par1World);
032            this.fallTime = 0;
033            this.shouldDropItem = true;
034            this.isBreakingAnvil = false;
035            this.isAnvil = false;
036            this.field_82156_g = 20;
037            this.field_82158_h = 2.0F;
038        }
039    
040        public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8)
041        {
042            this(par1World, par2, par4, par6, par8, 0);
043        }
044    
045        public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8, int par9)
046        {
047            super(par1World);
048            this.fallTime = 0;
049            this.shouldDropItem = true;
050            this.isBreakingAnvil = false;
051            this.isAnvil = false;
052            this.field_82156_g = 20;
053            this.field_82158_h = 2.0F;
054            this.blockID = par8;
055            this.metadata = par9;
056            this.preventEntitySpawning = true;
057            this.setSize(0.98F, 0.98F);
058            this.yOffset = this.height / 2.0F;
059            this.setPosition(par2, par4, par6);
060            this.motionX = 0.0D;
061            this.motionY = 0.0D;
062            this.motionZ = 0.0D;
063            this.prevPosX = par2;
064            this.prevPosY = par4;
065            this.prevPosZ = par6;
066        }
067    
068        /**
069         * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
070         * prevent them from trampling crops
071         */
072        protected boolean canTriggerWalking()
073        {
074            return false;
075        }
076    
077        protected void entityInit() {}
078    
079        /**
080         * Returns true if other Entities should be prevented from moving through this Entity.
081         */
082        public boolean canBeCollidedWith()
083        {
084            return !this.isDead;
085        }
086    
087        /**
088         * Called to update the entity's position/logic.
089         */
090        public void onUpdate()
091        {
092            if (this.blockID == 0)
093            {
094                this.setDead();
095            }
096            else
097            {
098                this.prevPosX = this.posX;
099                this.prevPosY = this.posY;
100                this.prevPosZ = this.posZ;
101                ++this.fallTime;
102                this.motionY -= 0.03999999910593033D;
103                this.moveEntity(this.motionX, this.motionY, this.motionZ);
104                this.motionX *= 0.9800000190734863D;
105                this.motionY *= 0.9800000190734863D;
106                this.motionZ *= 0.9800000190734863D;
107    
108                if (!this.worldObj.isRemote)
109                {
110                    int var1 = MathHelper.floor_double(this.posX);
111                    int var2 = MathHelper.floor_double(this.posY);
112                    int var3 = MathHelper.floor_double(this.posZ);
113    
114                    if (this.fallTime == 1)
115                    {
116                        if (this.fallTime == 1 && this.worldObj.getBlockId(var1, var2, var3) == this.blockID)
117                        {
118                            this.worldObj.setBlockWithNotify(var1, var2, var3, 0);
119                        }
120                        else
121                        {
122                            this.setDead();
123                        }
124                    }
125    
126                    if (this.onGround)
127                    {
128                        this.motionX *= 0.699999988079071D;
129                        this.motionZ *= 0.699999988079071D;
130                        this.motionY *= -0.5D;
131    
132                        if (this.worldObj.getBlockId(var1, var2, var3) != Block.pistonMoving.blockID)
133                        {
134                            this.setDead();
135    
136                            if (!this.isBreakingAnvil && this.worldObj.canPlaceEntityOnSide(this.blockID, var1, var2, var3, true, 1, (Entity)null) && !BlockSand.canFallBelow(this.worldObj, var1, var2 - 1, var3) && this.worldObj.setBlockAndMetadataWithNotify(var1, var2, var3, this.blockID, this.metadata))
137                            {
138                                if (Block.blocksList[this.blockID] instanceof BlockSand)
139                                {
140                                    ((BlockSand)Block.blocksList[this.blockID]).onFinishFalling(this.worldObj, var1, var2, var3, this.metadata);
141                                }
142                            }
143                            else if (this.shouldDropItem && !this.isBreakingAnvil)
144                            {
145                                this.entityDropItem(new ItemStack(this.blockID, 1, Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F);
146                            }
147                        }
148                    }
149                    else if (this.fallTime > 100 && !this.worldObj.isRemote && (var2 < 1 || var2 > 256) || this.fallTime > 600)
150                    {
151                        if (this.shouldDropItem)
152                        {
153                            this.entityDropItem(new ItemStack(this.blockID, 1, Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F);
154                        }
155    
156                        this.setDead();
157                    }
158                }
159            }
160        }
161    
162        /**
163         * Called when the mob is falling. Calculates and applies fall damage.
164         */
165        protected void fall(float par1)
166        {
167            if (this.isAnvil)
168            {
169                int var2 = MathHelper.ceiling_float_int(par1 - 1.0F);
170    
171                if (var2 > 0)
172                {
173                    ArrayList var3 = new ArrayList(this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox));
174                    DamageSource var4 = this.blockID == Block.anvil.blockID ? DamageSource.anvil : DamageSource.fallingBlock;
175                    Iterator var5 = var3.iterator();
176    
177                    while (var5.hasNext())
178                    {
179                        Entity var6 = (Entity)var5.next();
180                        var6.attackEntityFrom(var4, Math.min(MathHelper.floor_float((float)var2 * this.field_82158_h), this.field_82156_g));
181                    }
182    
183                    if (this.blockID == Block.anvil.blockID && (double)this.rand.nextFloat() < 0.05000000074505806D + (double)var2 * 0.05D)
184                    {
185                        int var7 = this.metadata >> 2;
186                        int var8 = this.metadata & 3;
187                        ++var7;
188    
189                        if (var7 > 2)
190                        {
191                            this.isBreakingAnvil = true;
192                        }
193                        else
194                        {
195                            this.metadata = var8 | var7 << 2;
196                        }
197                    }
198                }
199            }
200        }
201    
202        /**
203         * (abstract) Protected helper method to write subclass entity data to NBT.
204         */
205        protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
206        {
207            par1NBTTagCompound.setByte("Tile", (byte)this.blockID);
208            par1NBTTagCompound.setByte("Data", (byte)this.metadata);
209            par1NBTTagCompound.setByte("Time", (byte)this.fallTime);
210            par1NBTTagCompound.setBoolean("DropItem", this.shouldDropItem);
211            par1NBTTagCompound.setBoolean("HurtEntities", this.isAnvil);
212            par1NBTTagCompound.setFloat("FallHurtAmount", this.field_82158_h);
213            par1NBTTagCompound.setInteger("FallHurtMax", this.field_82156_g);
214        }
215    
216        /**
217         * (abstract) Protected helper method to read subclass entity data from NBT.
218         */
219        protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
220        {
221            this.blockID = par1NBTTagCompound.getByte("Tile") & 255;
222            this.metadata = par1NBTTagCompound.getByte("Data") & 255;
223            this.fallTime = par1NBTTagCompound.getByte("Time") & 255;
224    
225            if (par1NBTTagCompound.hasKey("HurtEntities"))
226            {
227                this.isAnvil = par1NBTTagCompound.getBoolean("HurtEntities");
228                this.field_82158_h = par1NBTTagCompound.getFloat("FallHurtAmount");
229                this.field_82156_g = par1NBTTagCompound.getInteger("FallHurtMax");
230            }
231            else if (this.blockID == Block.anvil.blockID)
232            {
233                this.isAnvil = true;
234            }
235    
236            if (par1NBTTagCompound.hasKey("DropItem"))
237            {
238                this.shouldDropItem = par1NBTTagCompound.getBoolean("DropItem");
239            }
240    
241            if (this.blockID == 0)
242            {
243                this.blockID = Block.sand.blockID;
244            }
245        }
246    
247        @SideOnly(Side.CLIENT)
248        public float getShadowSize()
249        {
250            return 0.0F;
251        }
252    
253        @SideOnly(Side.CLIENT)
254        public World getWorld()
255        {
256            return this.worldObj;
257        }
258    
259        public void setIsAnvil(boolean par1)
260        {
261            this.isAnvil = par1;
262        }
263    
264        @SideOnly(Side.CLIENT)
265        public boolean func_90999_ad()
266        {
267            return false;
268        }
269    }