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 }