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 private int field_82156_g; 028 private float field_82158_h; 029 030 public EntityFallingSand(World par1World) 031 { 032 super(par1World); 033 this.fallTime = 0; 034 this.shouldDropItem = true; 035 this.isBreakingAnvil = false; 036 this.isAnvil = false; 037 this.field_82156_g = 40; 038 this.field_82158_h = 2.0F; 039 } 040 041 public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8) 042 { 043 this(par1World, par2, par4, par6, par8, 0); 044 } 045 046 public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8, int par9) 047 { 048 super(par1World); 049 this.fallTime = 0; 050 this.shouldDropItem = true; 051 this.isBreakingAnvil = false; 052 this.isAnvil = false; 053 this.field_82156_g = 40; 054 this.field_82158_h = 2.0F; 055 this.blockID = par8; 056 this.metadata = par9; 057 this.preventEntitySpawning = true; 058 this.setSize(0.98F, 0.98F); 059 this.yOffset = this.height / 2.0F; 060 this.setPosition(par2, par4, par6); 061 this.motionX = 0.0D; 062 this.motionY = 0.0D; 063 this.motionZ = 0.0D; 064 this.prevPosX = par2; 065 this.prevPosY = par4; 066 this.prevPosZ = par6; 067 } 068 069 /** 070 * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to 071 * prevent them from trampling crops 072 */ 073 protected boolean canTriggerWalking() 074 { 075 return false; 076 } 077 078 protected void entityInit() {} 079 080 /** 081 * Returns true if other Entities should be prevented from moving through this Entity. 082 */ 083 public boolean canBeCollidedWith() 084 { 085 return !this.isDead; 086 } 087 088 /** 089 * Called to update the entity's position/logic. 090 */ 091 public void onUpdate() 092 { 093 if (this.blockID == 0) 094 { 095 this.setDead(); 096 } 097 else 098 { 099 this.prevPosX = this.posX; 100 this.prevPosY = this.posY; 101 this.prevPosZ = this.posZ; 102 ++this.fallTime; 103 this.motionY -= 0.03999999910593033D; 104 this.moveEntity(this.motionX, this.motionY, this.motionZ); 105 this.motionX *= 0.9800000190734863D; 106 this.motionY *= 0.9800000190734863D; 107 this.motionZ *= 0.9800000190734863D; 108 109 if (!this.worldObj.isRemote) 110 { 111 int var1 = MathHelper.floor_double(this.posX); 112 int var2 = MathHelper.floor_double(this.posY); 113 int var3 = MathHelper.floor_double(this.posZ); 114 115 if (this.fallTime == 1) 116 { 117 if (this.fallTime != 1 || this.worldObj.getBlockId(var1, var2, var3) != this.blockID) 118 { 119 this.setDead(); 120 return; 121 } 122 123 this.worldObj.setBlockWithNotify(var1, var2, var3, 0); 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 266 /** 267 * Return whether this entity should be rendered as on fire. 268 */ 269 public boolean canRenderOnFire() 270 { 271 return false; 272 } 273 274 public void func_85029_a(CrashReportCategory par1CrashReportCategory) 275 { 276 super.func_85029_a(par1CrashReportCategory); 277 par1CrashReportCategory.addCrashSection("Immitating block ID", Integer.valueOf(this.blockID)); 278 par1CrashReportCategory.addCrashSection("Immitating block data", Integer.valueOf(this.metadata)); 279 } 280 }