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 }