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