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 }