    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.crash.CrashReportCategory;
    010import net.minecraft.entity.Entity;
    011import net.minecraft.item.ItemStack;
    012import net.minecraft.nbt.NBTTagCompound;
    013import net.minecraft.util.DamageSource;
    014import net.minecraft.util.MathHelper;
    015import net.minecraft.world.World;
    016
    017public 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}