    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    }