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