package net.minecraft.entity.item; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.util.ArrayList; import java.util.Iterator; import net.minecraft.block.Block; import net.minecraft.block.BlockSand; import net.minecraft.crash.CrashReportCategory; import net.minecraft.entity.Entity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; import net.minecraft.world.World; public class EntityFallingSand extends Entity { public int blockID; public int metadata; /** How long the block has been falling for. */ public int fallTime; public boolean shouldDropItem; private boolean isBreakingAnvil; private boolean isAnvil; /** Maximum amount of damage dealt to entities hit by falling block */ private int fallHurtMax; /** Actual damage dealt to entities hit by falling block */ private float fallHurtAmount; public EntityFallingSand(World par1World) { super(par1World); this.fallTime = 0; this.shouldDropItem = true; this.isBreakingAnvil = false; this.isAnvil = false; this.fallHurtMax = 40; this.fallHurtAmount = 2.0F; } public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8) { this(par1World, par2, par4, par6, par8, 0); } public EntityFallingSand(World par1World, double par2, double par4, double par6, int par8, int par9) { super(par1World); this.fallTime = 0; this.shouldDropItem = true; this.isBreakingAnvil = false; this.isAnvil = false; this.fallHurtMax = 40; this.fallHurtAmount = 2.0F; this.blockID = par8; this.metadata = par9; this.preventEntitySpawning = true; this.setSize(0.98F, 0.98F); this.yOffset = this.height / 2.0F; this.setPosition(par2, par4, par6); this.motionX = 0.0D; this.motionY = 0.0D; this.motionZ = 0.0D; this.prevPosX = par2; this.prevPosY = par4; this.prevPosZ = par6; } /** * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to * prevent them from trampling crops */ protected boolean canTriggerWalking() { return false; } protected void entityInit() {} /** * Returns true if other Entities should be prevented from moving through this Entity. */ public boolean canBeCollidedWith() { return !this.isDead; } /** * Called to update the entity's position/logic. */ public void onUpdate() { if (this.blockID == 0) { this.setDead(); } else { this.prevPosX = this.posX; this.prevPosY = this.posY; this.prevPosZ = this.posZ; ++this.fallTime; this.motionY -= 0.03999999910593033D; this.moveEntity(this.motionX, this.motionY, this.motionZ); this.motionX *= 0.9800000190734863D; this.motionY *= 0.9800000190734863D; this.motionZ *= 0.9800000190734863D; if (!this.worldObj.isRemote) { int var1 = MathHelper.floor_double(this.posX); int var2 = MathHelper.floor_double(this.posY); int var3 = MathHelper.floor_double(this.posZ); if (this.fallTime == 1) { if (this.fallTime != 1 || this.worldObj.getBlockId(var1, var2, var3) != this.blockID) { this.setDead(); return; } this.worldObj.setBlockWithNotify(var1, var2, var3, 0); } if (this.onGround) { this.motionX *= 0.699999988079071D; this.motionZ *= 0.699999988079071D; this.motionY *= -0.5D; if (this.worldObj.getBlockId(var1, var2, var3) != Block.pistonMoving.blockID) { this.setDead(); 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)) { if (Block.blocksList[this.blockID] instanceof BlockSand) { ((BlockSand)Block.blocksList[this.blockID]).onFinishFalling(this.worldObj, var1, var2, var3, this.metadata); } } else if (this.shouldDropItem && !this.isBreakingAnvil) { this.entityDropItem(new ItemStack(this.blockID, 1, Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F); } } } else if (this.fallTime > 100 && !this.worldObj.isRemote && (var2 < 1 || var2 > 256) || this.fallTime > 600) { if (this.shouldDropItem) { this.entityDropItem(new ItemStack(this.blockID, 1, Block.blocksList[this.blockID].damageDropped(this.metadata)), 0.0F); } this.setDead(); } } } } /** * Called when the mob is falling. Calculates and applies fall damage. */ protected void fall(float par1) { if (this.isAnvil) { int var2 = MathHelper.ceiling_float_int(par1 - 1.0F); if (var2 > 0) { ArrayList var3 = new ArrayList(this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox)); DamageSource var4 = this.blockID == Block.anvil.blockID ? DamageSource.anvil : DamageSource.fallingBlock; Iterator var5 = var3.iterator(); while (var5.hasNext()) { Entity var6 = (Entity)var5.next(); var6.attackEntityFrom(var4, Math.min(MathHelper.floor_float((float)var2 * this.fallHurtAmount), this.fallHurtMax)); } if (this.blockID == Block.anvil.blockID && (double)this.rand.nextFloat() < 0.05000000074505806D + (double)var2 * 0.05D) { int var7 = this.metadata >> 2; int var8 = this.metadata & 3; ++var7; if (var7 > 2) { this.isBreakingAnvil = true; } else { this.metadata = var8 | var7 << 2; } } } } } /** * (abstract) Protected helper method to write subclass entity data to NBT. */ protected void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) { par1NBTTagCompound.setByte("Tile", (byte)this.blockID); par1NBTTagCompound.setByte("Data", (byte)this.metadata); par1NBTTagCompound.setByte("Time", (byte)this.fallTime); par1NBTTagCompound.setBoolean("DropItem", this.shouldDropItem); par1NBTTagCompound.setBoolean("HurtEntities", this.isAnvil); par1NBTTagCompound.setFloat("FallHurtAmount", this.fallHurtAmount); par1NBTTagCompound.setInteger("FallHurtMax", this.fallHurtMax); } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ protected void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) { this.blockID = par1NBTTagCompound.getByte("Tile") & 255; this.metadata = par1NBTTagCompound.getByte("Data") & 255; this.fallTime = par1NBTTagCompound.getByte("Time") & 255; if (par1NBTTagCompound.hasKey("HurtEntities")) { this.isAnvil = par1NBTTagCompound.getBoolean("HurtEntities"); this.fallHurtAmount = par1NBTTagCompound.getFloat("FallHurtAmount"); this.fallHurtMax = par1NBTTagCompound.getInteger("FallHurtMax"); } else if (this.blockID == Block.anvil.blockID) { this.isAnvil = true; } if (par1NBTTagCompound.hasKey("DropItem")) { this.shouldDropItem = par1NBTTagCompound.getBoolean("DropItem"); } if (this.blockID == 0) { this.blockID = Block.sand.blockID; } } @SideOnly(Side.CLIENT) public float getShadowSize() { return 0.0F; } @SideOnly(Side.CLIENT) public World getWorld() { return this.worldObj; } public void setIsAnvil(boolean par1) { this.isAnvil = par1; } @SideOnly(Side.CLIENT) /** * Return whether this entity should be rendered as on fire. */ public boolean canRenderOnFire() { return false; } public void func_85029_a(CrashReportCategory par1CrashReportCategory) { super.func_85029_a(par1CrashReportCategory); par1CrashReportCategory.addCrashSection("Immitating block ID", Integer.valueOf(this.blockID)); par1CrashReportCategory.addCrashSection("Immitating block data", Integer.valueOf(this.metadata)); } }