001    package net.minecraft.entity.item;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.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.crash.CrashReportCategory;
010    import net.minecraft.entity.Entity;
011    import net.minecraft.item.ItemStack;
012    import net.minecraft.nbt.NBTTagCompound;
013    import net.minecraft.util.DamageSource;
014    import net.minecraft.util.MathHelper;
015    import net.minecraft.world.World;
016    
017    public class EntityFallingSand extends Entity
018    {
019        public int blockID;
020        public int metadata;
021    
022        /** How long the block has been falling for. */
023        public int fallTime;
024        public boolean shouldDropItem;
025        private boolean isBreakingAnvil;
026        private boolean isAnvil;
027        private int field_82156_g;
028        private float field_82158_h;
029    
030        public EntityFallingSand(World par1World)
031        {
032            super(par1World);
033            this.fallTime = 0;
034            this.shouldDropItem = true;
035            this.isBreakingAnvil = false;
036            this.isAnvil = false;
037            this.field_82156_g = 40;
038            this.field_82158_h = 2.0F;
039        }
040    
041        public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8)
042        {
043            this(par1World, par2, par4, par6, par8, 0);
044        }
045    
046        public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8, int par9)
047        {
048            super(par1World);
049            this.fallTime = 0;
050            this.shouldDropItem = true;
051            this.isBreakingAnvil = false;
052            this.isAnvil = false;
053            this.field_82156_g = 40;
054            this.field_82158_h = 2.0F;
055            this.blockID = par8;
056            this.metadata = par9;
057            this.preventEntitySpawning = true;
058            this.setSize(0.98F, 0.98F);
059            this.yOffset = this.height / 2.0F;
060            this.setPosition(par2, par4, par6);
061            this.motionX = 0.0D;
062            this.motionY = 0.0D;
063            this.motionZ = 0.0D;
064            this.prevPosX = par2;
065            this.prevPosY = par4;
066            this.prevPosZ = par6;
067        }
068    
069        /**
070         * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
071         * prevent them from trampling crops
072         */
073        protected boolean canTriggerWalking()
074        {
075            return false;
076        }
077    
078        protected void entityInit() {}
079    
080        /**
081         * Returns true if other Entities should be prevented from moving through this Entity.
082         */
083        public boolean canBeCollidedWith()
084        {
085            return !this.isDead;
086        }
087    
088        /**
089         * Called to update the entity's position/logic.
090         */
091        public void onUpdate()
092        {
093            if (this.blockID == 0)
094            {
095                this.setDead();
096            }
097            else
098            {
099                this.prevPosX = this.posX;
100                this.prevPosY = this.posY;
101                this.prevPosZ = this.posZ;
102                ++this.fallTime;
103                this.motionY -= 0.03999999910593033D;
104                this.moveEntity(this.motionX, this.motionY, this.motionZ);
105                this.motionX *= 0.9800000190734863D;
106                this.motionY *= 0.9800000190734863D;
107                this.motionZ *= 0.9800000190734863D;
108    
109                if (!this.worldObj.isRemote)
110                {
111                    int var1 = MathHelper.floor_double(this.posX);
112                    int var2 = MathHelper.floor_double(this.posY);
113                    int var3 = MathHelper.floor_double(this.posZ);
114    
115                    if (this.fallTime == 1)
116                    {
117                        if (this.fallTime != 1 || this.worldObj.getBlockId(var1, var2, var3) != this.blockID)
118                        {
119                            this.setDead();
120                            return;
121                        }
122    
123                        this.worldObj.setBlockWithNotify(var1, var2, var3, 0);
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    
266        /**
267         * Return whether this entity should be rendered as on fire.
268         */
269        public boolean canRenderOnFire()
270        {
271            return false;
272        }
273    
274        public void func_85029_a(CrashReportCategory par1CrashReportCategory)
275        {
276            super.func_85029_a(par1CrashReportCategory);
277            par1CrashReportCategory.addCrashSection("Immitating block ID", Integer.valueOf(this.blockID));
278            par1CrashReportCategory.addCrashSection("Immitating block data", Integer.valueOf(this.metadata));
279        }
280    }