001package net.minecraft.entity.item; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.ArrayList; 006import java.util.Iterator; 007import net.minecraft.block.Block; 008import net.minecraft.block.BlockSand; 009import net.minecraft.block.ITileEntityProvider; 010import net.minecraft.crash.CrashReportCategory; 011import net.minecraft.entity.Entity; 012import net.minecraft.item.ItemStack; 013import net.minecraft.nbt.NBTBase; 014import net.minecraft.nbt.NBTTagCompound; 015import net.minecraft.tileentity.TileEntity; 016import net.minecraft.util.DamageSource; 017import net.minecraft.util.MathHelper; 018import net.minecraft.world.World; 019 020public class EntityFallingSand extends Entity 021{ 022 public int blockID; 023 public int metadata; 024 025 /** How long the block has been falling for. */ 026 public int fallTime; 027 public boolean shouldDropItem; 028 private boolean isBreakingAnvil; 029 private boolean isAnvil; 030 031 /** Maximum amount of damage dealt to entities hit by falling block */ 032 private int fallHurtMax; 033 034 /** Actual damage dealt to entities hit by falling block */ 035 private float fallHurtAmount; 036 public NBTTagCompound field_98051_e; 037 038 public EntityFallingSand(World par1World) 039 { 040 super(par1World); 041 this.fallTime = 0; 042 this.shouldDropItem = true; 043 this.isBreakingAnvil = false; 044 this.isAnvil = false; 045 this.fallHurtMax = 40; 046 this.fallHurtAmount = 2.0F; 047 this.field_98051_e = null; 048 } 049 050 public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8) 051 { 052 this(par1World, par2, par4, par6, par8, 0); 053 } 054 055 public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8, int par9) 056 { 057 super(par1World); 058 this.fallTime = 0; 059 this.shouldDropItem = true; 060 this.isBreakingAnvil = false; 061 this.isAnvil = false; 062 this.fallHurtMax = 40; 063 this.fallHurtAmount = 2.0F; 064 this.field_98051_e = null; 065 this.blockID = par8; 066 this.metadata = par9; 067 this.preventEntitySpawning = true; 068 this.setSize(0.98F, 0.98F); 069 this.yOffset = this.height / 2.0F; 070 this.setPosition(par2, par4, par6); 071 this.motionX = 0.0D; 072 this.motionY = 0.0D; 073 this.motionZ = 0.0D; 074 this.prevPosX = par2; 075 this.prevPosY = par4; 076 this.prevPosZ = par6; 077 } 078 079 /** 080 * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to 081 * prevent them from trampling crops 082 */ 083 protected boolean canTriggerWalking() 084 { 085 return false; 086 } 087 088 protected void entityInit() {} 089 090 /** 091 * Returns true if other Entities should be prevented from moving through this Entity. 092 */ 093 public boolean canBeCollidedWith() 094 { 095 return !this.isDead; 096 } 097 098 /** 099 * Called to update the entity's position/logic. 100 */ 101 public void onUpdate() 102 { 103 if (this.blockID == 0) 104 { 105 this.setDead(); 106 } 107 else 108 { 109 this.prevPosX = this.posX; 110 this.prevPosY = this.posY; 111 this.prevPosZ = this.posZ; 112 ++this.fallTime; 113 this.motionY -= 0.03999999910593033D; 114 this.moveEntity(this.motionX, this.motionY, this.motionZ); 115 this.motionX *= 0.9800000190734863D; 116 this.motionY *= 0.9800000190734863D; 117 this.motionZ *= 0.9800000190734863D; 118 119 if (!this.worldObj.isRemote) 120 { 121 int i = MathHelper.floor_double(this.posX); 122 int j = MathHelper.floor_double(this.posY); 123 int k = MathHelper.floor_double(this.posZ); 124 125 if (this.fallTime == 1) 126 { 127 if (this.worldObj.getBlockId(i, j, k) != this.blockID) 128 { 129 this.setDead(); 130 return; 131 } 132 133 this.worldObj.func_94571_i(i, j, k); 134 } 135 136 if (this.onGround) 137 { 138 this.motionX *= 0.699999988079071D; 139 this.motionZ *= 0.699999988079071D; 140 this.motionY *= -0.5D; 141 142 if (this.worldObj.getBlockId(i, j, k) != Block.pistonMoving.blockID) 143 { 144 this.setDead(); 145 146 if (!this.isBreakingAnvil && this.worldObj.canPlaceEntityOnSide(this.blockID, i, j, k, true, 1, (Entity)null, (ItemStack)null) && !BlockSand.canFallBelow(this.worldObj, i, j - 1, k) && this.worldObj.setBlockAndMetadataWithNotify(i, j, k, this.blockID, this.metadata, 3)) 147 { 148 if (Block.blocksList[this.blockID] instanceof BlockSand) 149 { 150 ((BlockSand)Block.blocksList[this.blockID]).onFinishFalling(this.worldObj, i, j, k, this.metadata); 151 } 152 153 if (this.field_98051_e != null && Block.blocksList[this.blockID] instanceof ITileEntityProvider) 154 { 155 TileEntity tileentity = this.worldObj.getBlockTileEntity(i, j, k); 156 157 if (tileentity != null) 158 { 159 NBTTagCompound nbttagcompound = new NBTTagCompound(); 160 tileentity.writeToNBT(nbttagcompound); 161 Iterator iterator = this.field_98051_e.getTags().iterator(); 162 163 while (iterator.hasNext()) 164 { 165 NBTBase nbtbase = (NBTBase)iterator.next(); 166 167 if (!nbtbase.getName().equals("x") && !nbtbase.getName().equals("y") && !nbtbase.getName().equals("z")) 168 { 169 nbttagcompound.setTag(nbtbase.getName(), nbtbase.copy()); 170 } 171 } 172 173 tileentity.readFromNBT(nbttagcompound); 174 tileentity.onInventoryChanged(); 175 } 176 } 177 } 178 else if (this.shouldDropItem && !this.isBreakingAnvil) 179 { 180 this.entityDropItem(new ItemStack(this.blockID, 1, Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F); 181 } 182 } 183 } 184 else if (this.fallTime > 100 && !this.worldObj.isRemote && (j < 1 || j > 256) || this.fallTime > 600) 185 { 186 if (this.shouldDropItem) 187 { 188 this.entityDropItem(new ItemStack(this.blockID, 1, Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F); 189 } 190 191 this.setDead(); 192 } 193 } 194 } 195 } 196 197 /** 198 * Called when the mob is falling. Calculates and applies fall damage. 199 */ 200 protected void fall(float par1) 201 { 202 if (this.isAnvil) 203 { 204 int i = MathHelper.ceiling_float_int(par1 - 1.0F); 205 206 if (i > 0) 207 { 208 ArrayList arraylist = new ArrayList(this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox)); 209 DamageSource damagesource = this.blockID == Block.anvil.blockID ? DamageSource.anvil : DamageSource.fallingBlock; 210 Iterator iterator = arraylist.iterator(); 211 212 while (iterator.hasNext()) 213 { 214 Entity entity = (Entity)iterator.next(); 215 entity.attackEntityFrom(damagesource, Math.min(MathHelper.floor_float((float)i * this.fallHurtAmount), this.fallHurtMax)); 216 } 217 218 if (this.blockID == Block.anvil.blockID && (double)this.rand.nextFloat() < 0.05000000074505806D + (double)i * 0.05D) 219 { 220 int j = this.metadata >> 2; 221 int k = this.metadata & 3; 222 ++j; 223 224 if (j > 2) 225 { 226 this.isBreakingAnvil = true; 227 } 228 else 229 { 230 this.metadata = k | j << 2; 231 } 232 } 233 } 234 } 235 } 236 237 /** 238 * (abstract) Protected helper method to write subclass entity data to NBT. 239 */ 240 protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 241 { 242 par1NBTTagCompound.setByte("Tile", (byte)this.blockID); 243 par1NBTTagCompound.setInteger("TileID", this.blockID); 244 par1NBTTagCompound.setByte("Data", (byte)this.metadata); 245 par1NBTTagCompound.setByte("Time", (byte)this.fallTime); 246 par1NBTTagCompound.setBoolean("DropItem", this.shouldDropItem); 247 par1NBTTagCompound.setBoolean("HurtEntities", this.isAnvil); 248 par1NBTTagCompound.setFloat("FallHurtAmount", this.fallHurtAmount); 249 par1NBTTagCompound.setInteger("FallHurtMax", this.fallHurtMax); 250 251 if (this.field_98051_e != null) 252 { 253 par1NBTTagCompound.setCompoundTag("TileEntityData", this.field_98051_e); 254 } 255 } 256 257 /** 258 * (abstract) Protected helper method to read subclass entity data from NBT. 259 */ 260 protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 261 { 262 if (par1NBTTagCompound.hasKey("TileID")) 263 { 264 this.blockID = par1NBTTagCompound.getInteger("TileID"); 265 } 266 else 267 { 268 this.blockID = par1NBTTagCompound.getByte("Tile") & 255; 269 } 270 271 this.metadata = par1NBTTagCompound.getByte("Data") & 255; 272 this.fallTime = par1NBTTagCompound.getByte("Time") & 255; 273 274 if (par1NBTTagCompound.hasKey("HurtEntities")) 275 { 276 this.isAnvil = par1NBTTagCompound.getBoolean("HurtEntities"); 277 this.fallHurtAmount = par1NBTTagCompound.getFloat("FallHurtAmount"); 278 this.fallHurtMax = par1NBTTagCompound.getInteger("FallHurtMax"); 279 } 280 else if (this.blockID == Block.anvil.blockID) 281 { 282 this.isAnvil = true; 283 } 284 285 if (par1NBTTagCompound.hasKey("DropItem")) 286 { 287 this.shouldDropItem = par1NBTTagCompound.getBoolean("DropItem"); 288 } 289 290 if (par1NBTTagCompound.hasKey("TileEntityData")) 291 { 292 this.field_98051_e = par1NBTTagCompound.getCompoundTag("TileEntityData"); 293 } 294 295 if (this.blockID == 0) 296 { 297 this.blockID = Block.sand.blockID; 298 } 299 } 300 301 public void setIsAnvil(boolean par1) 302 { 303 this.isAnvil = par1; 304 } 305 306 public void func_85029_a(CrashReportCategory par1CrashReportCategory) 307 { 308 super.func_85029_a(par1CrashReportCategory); 309 par1CrashReportCategory.addCrashSection("Immitating block ID", Integer.valueOf(this.blockID)); 310 par1CrashReportCategory.addCrashSection("Immitating block data", Integer.valueOf(this.metadata)); 311 } 312 313 @SideOnly(Side.CLIENT) 314 public float getShadowSize() 315 { 316 return 0.0F; 317 } 318 319 @SideOnly(Side.CLIENT) 320 public World getWorld() 321 { 322 return this.worldObj; 323 } 324 325 @SideOnly(Side.CLIENT) 326 327 /** 328 * Return whether this entity should be rendered as on fire. 329 */ 330 public boolean canRenderOnFire() 331 { 332 return false; 333 } 334}