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 }