    001package net.minecraft.entity;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005
    006import java.util.ArrayList;
    007import java.util.List;
    008import java.util.Random;
    009import java.util.UUID;
    010
    011import net.minecraft.block.Block;
    012import net.minecraft.block.BlockFluid;
    013import net.minecraft.block.StepSound;
    014import net.minecraft.block.material.Material;
    015import net.minecraft.crash.CrashReport;
    016import net.minecraft.crash.CrashReportCategory;
    017import net.minecraft.enchantment.EnchantmentProtection;
    018import net.minecraft.entity.effect.EntityLightningBolt;
    019import net.minecraft.entity.item.EntityBoat;
    020import net.minecraft.entity.item.EntityItem;
    021import net.minecraft.entity.item.EntityItemFrame;
    022import net.minecraft.entity.item.EntityMinecart;
    023import net.minecraft.entity.item.EntityPainting;
    024import net.minecraft.entity.player.EntityPlayer;
    025import net.minecraft.item.Item;
    026import net.minecraft.item.ItemStack;
    027import net.minecraft.nbt.NBTTagCompound;
    028import net.minecraft.nbt.NBTTagDouble;
    029import net.minecraft.nbt.NBTTagFloat;
    030import net.minecraft.nbt.NBTTagList;
    031import net.minecraft.server.MinecraftServer;
    032import net.minecraft.util.AxisAlignedBB;
    033import net.minecraft.util.DamageSource;
    034import net.minecraft.util.Direction;
    035import net.minecraft.util.MathHelper;
    036import net.minecraft.util.MovingObjectPosition;
    037import net.minecraft.util.ReportedException;
    038import net.minecraft.util.StatCollector;
    039import net.minecraft.util.Vec3;
    040import net.minecraft.world.Explosion;
    041import net.minecraft.world.World;
    042import net.minecraft.world.WorldServer;
    043
    044public abstract class Entity
    045{
    046    private static int nextEntityID = 0;
    047    public int entityId;
    048    public double renderDistanceWeight;
    049
    050    /**
    051     * Blocks entities from spawning when they do their AABB check to make sure the spot is clear of entities that can
    052     * prevent spawning.
    053     */
    054    public boolean preventEntitySpawning;
    055
    056    /** The entity that is riding this entity */
    057    public Entity riddenByEntity;
    058
    059    /** The entity we are currently riding */
    060    public Entity ridingEntity;
    061
    062    /** Reference to the World object. */
    063    public World worldObj;
    064    public double prevPosX;
    065    public double prevPosY;
    066    public double prevPosZ;
    067
    068    /** Entity position X */
    069    public double posX;
    070
    071    /** Entity position Y */
    072    public double posY;
    073
    074    /** Entity position Z */
    075    public double posZ;
    076
    077    /** Entity motion X */
    078    public double motionX;
    079
    080    /** Entity motion Y */
    081    public double motionY;
    082
    083    /** Entity motion Z */
    084    public double motionZ;
    085
    086    /** Entity rotation Yaw */
    087    public float rotationYaw;
    088
    089    /** Entity rotation Pitch */
    090    public float rotationPitch;
    091    public float prevRotationYaw;
    092    public float prevRotationPitch;
    093
    094    /** Axis aligned bounding box. */
    095    public final AxisAlignedBB boundingBox;
    096    public boolean onGround;
    097
    098    /**
    099     * True if after a move this entity has collided with something on X- or Z-axis
    100     */
    101    public boolean isCollidedHorizontally;
    102
    103    /**
    104     * True if after a move this entity has collided with something on Y-axis
    105     */
    106    public boolean isCollidedVertically;
    107
    108    /**
    109     * True if after a move this entity has collided with something either vertically or horizontally
    110     */
    111    public boolean isCollided;
    112    public boolean velocityChanged;
    113    protected boolean isInWeb;
    114    public boolean field_70135_K;
    115
    116    /**
    117     * Gets set by setDead, so this must be the flag whether an Entity is dead (inactive may be better term)
    118     */
    119    public boolean isDead;
    120    public float yOffset;
    121
    122    /** How wide this entity is considered to be */
    123    public float width;
    124
    125    /** How high this entity is considered to be */
    126    public float height;
    127
    128    /** The previous ticks distance walked multiplied by 0.6 */
    129    public float prevDistanceWalkedModified;
    130
    131    /** The distance walked multiplied by 0.6 */
    132    public float distanceWalkedModified;
    133    public float field_82151_R;
    134    public float fallDistance;
    135
    136    /**
    137     * The distance that has to be exceeded in order to triger a new step sound and an onEntityWalking event on a block
    138     */
    139    private int nextStepDistance;
    140
    141    /**
    142     * The entity's X coordinate at the previous tick, used to calculate position during rendering routines
    143     */
    144    public double lastTickPosX;
    145
    146    /**
    147     * The entity's Y coordinate at the previous tick, used to calculate position during rendering routines
    148     */
    149    public double lastTickPosY;
    150
    151    /**
    152     * The entity's Z coordinate at the previous tick, used to calculate position during rendering routines
    153     */
    154    public double lastTickPosZ;
    155    public float ySize;
    156
    157    /**
    158     * How high this entity can step up when running into a block to try to get over it (currently make note the entity
    159     * will always step up this amount and not just the amount needed)
    160     */
    161    public float stepHeight;
    162
    163    /**
    164     * Whether this entity won't clip with collision or not (make note it won't disable gravity)
    165     */
    166    public boolean noClip;
    167
    168    /**
    169     * Reduces the velocity applied by entity collisions by the specified percent.
    170     */
    171    public float entityCollisionReduction;
    172    protected Random rand;
    173
    174    /** How many ticks has this entity had ran since being alive */
    175    public int ticksExisted;
    176
    177    /**
    178     * The amount of ticks you have to stand inside of fire before be set on fire
    179     */
    180    public int fireResistance;
    181    private int fire;
    182
    183    /**
    184     * Whether this entity is currently inside of water (if it handles water movement that is)
    185     */
    186    protected boolean inWater;
    187
    188    /**
    189     * Remaining time an entity will be "immune" to further damage after being hurt.
    190     */
    191    public int hurtResistantTime;
    192    private boolean firstUpdate;
    193    @SideOnly(Side.CLIENT)
    194
    195    /** downloadable location of player's skin */
    196    public String skinUrl;
    197    @SideOnly(Side.CLIENT)
    198
    199    /** downloadable location of player's cloak */
    200    public String cloakUrl;
    201    protected boolean isImmuneToFire;
    202    protected DataWatcher dataWatcher;
    203    private double entityRiderPitchDelta;
    204    private double entityRiderYawDelta;
    205
    206    /** Has this entity been added to the chunk its within */
    207    public boolean addedToChunk;
    208    public int chunkCoordX;
    209    public int chunkCoordY;
    210    public int chunkCoordZ;
    211    @SideOnly(Side.CLIENT)
    212    public int serverPosX;
    213    @SideOnly(Side.CLIENT)
    214    public int serverPosY;
    215    @SideOnly(Side.CLIENT)
    216    public int serverPosZ;
    217
    218    /**
    219     * Render entity even if it is outside the camera frustum. Only true in EntityFish for now. Used in RenderGlobal:
    220     * render if ignoreFrustumCheck or in frustum.
    221     */
    222    public boolean ignoreFrustumCheck;
    223    public boolean isAirBorne;
    224    public int timeUntilPortal;
    225
    226    /** Whether the entity is inside a Portal */
    227    protected boolean inPortal;
    228    protected int timeInPortal;
    229
    230    /** Which dimension the player is in (-1 = the Nether, 0 = normal world) */
    231    public int dimension;
    232    protected int field_82152_aq;
    233    private boolean invulnerable;
    234    public EnumEntitySize myEntitySize;
    235    /** Forge: Used to store custom data for each entity. */
    236    private NBTTagCompound customEntityData;
    237    public boolean captureDrops = false;
    238    public ArrayList<EntityItem> capturedDrops = new ArrayList<EntityItem>();
    239    private UUID persistentID;
    240
    241    public Entity(World par1World)
    242    {
    243        this.entityId = nextEntityID++;
    244        this.renderDistanceWeight = 1.0D;
    245        this.preventEntitySpawning = false;
    246        this.boundingBox = AxisAlignedBB.getBoundingBox(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
    247        this.onGround = false;
    248        this.isCollided = false;
    249        this.velocityChanged = false;
    250        this.field_70135_K = true;
    251        this.isDead = false;
    252        this.yOffset = 0.0F;
    253        this.width = 0.6F;
    254        this.height = 1.8F;
    255        this.prevDistanceWalkedModified = 0.0F;
    256        this.distanceWalkedModified = 0.0F;
    257        this.field_82151_R = 0.0F;
    258        this.fallDistance = 0.0F;
    259        this.nextStepDistance = 1;
    260        this.ySize = 0.0F;
    261        this.stepHeight = 0.0F;
    262        this.noClip = false;
    263        this.entityCollisionReduction = 0.0F;
    264        this.rand = new Random();
    265        this.ticksExisted = 0;
    266        this.fireResistance = 1;
    267        this.fire = 0;
    268        this.inWater = false;
    269        this.hurtResistantTime = 0;
    270        this.firstUpdate = true;
    271        this.isImmuneToFire = false;
    272        this.dataWatcher = new DataWatcher();
    273        this.addedToChunk = false;
    274        this.field_82152_aq = 0;
    275        this.invulnerable = false;
    276        this.myEntitySize = EnumEntitySize.SIZE_2;
    277        this.worldObj = par1World;
    278        this.setPosition(0.0D, 0.0D, 0.0D);
    279
    280        if (par1World != null)
    281        {
    282            this.dimension = par1World.provider.dimensionId;
    283        }
    284
    285        this.dataWatcher.addObject(0, Byte.valueOf((byte)0));
    286        this.dataWatcher.addObject(1, Short.valueOf((short)300));
    287        this.entityInit();
    288    }
    289
    290    protected abstract void entityInit();
    291
    292    public DataWatcher getDataWatcher()
    293    {
    294        return this.dataWatcher;
    295    }
    296
    297    public boolean equals(Object par1Obj)
    298    {
    299        return par1Obj instanceof Entity ? ((Entity)par1Obj).entityId == this.entityId : false;
    300    }
    301
    302    public int hashCode()
    303    {
    304        return this.entityId;
    305    }
    306
    307    @SideOnly(Side.CLIENT)
    308
    309    /**
    310     * Keeps moving the entity up so it isn't colliding with blocks and other requirements for this entity to be spawned
    311     * (only actually used on players though its also on Entity)
    312     */
    313    protected void preparePlayerToSpawn()
    314    {
    315        if (this.worldObj != null)
    316        {
    317            while (this.posY > 0.0D)
    318            {
    319                this.setPosition(this.posX, this.posY, this.posZ);
    320
    321                if (this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty())
    322                {
    323                    break;
    324                }
    325
    326                ++this.posY;
    327            }
    328
    329            this.motionX = this.motionY = this.motionZ = 0.0D;
    330            this.rotationPitch = 0.0F;
    331        }
    332    }
    333
    334    /**
    335     * Will get destroyed next tick.
    336     */
    337    public void setDead()
    338    {
    339        this.isDead = true;
    340    }
    341
    342    /**
    343     * Sets the width and height of the entity. Args: width, height
    344     */
    345    protected void setSize(float par1, float par2)
    346    {
    347        this.width = par1;
    348        this.height = par2;
    349        float var3 = par1 % 2.0F;
    350
    351        if ((double)var3 < 0.375D)
    352        {
    353            this.myEntitySize = EnumEntitySize.SIZE_1;
    354        }
    355        else if ((double)var3 < 0.75D)
    356        {
    357            this.myEntitySize = EnumEntitySize.SIZE_2;
    358        }
    359        else if ((double)var3 < 1.0D)
    360        {
    361            this.myEntitySize = EnumEntitySize.SIZE_3;
    362        }
    363        else if ((double)var3 < 1.375D)
    364        {
    365            this.myEntitySize = EnumEntitySize.SIZE_4;
    366        }
    367        else if ((double)var3 < 1.75D)
    368        {
    369            this.myEntitySize = EnumEntitySize.SIZE_5;
    370        }
    371        else
    372        {
    373            this.myEntitySize = EnumEntitySize.SIZE_6;
    374        }
    375    }
    376
    377    /**
    378     * Sets the rotation of the entity
    379     */
    380    protected void setRotation(float par1, float par2)
    381    {
    382        this.rotationYaw = par1 % 360.0F;
    383        this.rotationPitch = par2 % 360.0F;
    384    }
    385
    386    /**
    387     * Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box.
    388     */
    389    public void setPosition(double par1, double par3, double par5)
    390    {
    391        this.posX = par1;
    392        this.posY = par3;
    393        this.posZ = par5;
    394        float var7 = this.width / 2.0F;
    395        float var8 = this.height;
    396        this.boundingBox.setBounds(par1 - (double)var7, par3 - (double)this.yOffset + (double)this.ySize, par5 - (double)var7, par1 + (double)var7, par3 - (double)this.yOffset + (double)this.ySize + (double)var8, par5 + (double)var7);
    397    }
    398
    399    @SideOnly(Side.CLIENT)
    400
    401    /**
    402     * Adds par1*0.15 to the entity's yaw, and *subtracts* par2*0.15 from the pitch. Clamps pitch from -90 to 90. Both
    403     * arguments in degrees.
    404     */
    405    public void setAngles(float par1, float par2)
    406    {
    407        float var3 = this.rotationPitch;
    408        float var4 = this.rotationYaw;
    409        this.rotationYaw = (float)((double)this.rotationYaw + (double)par1 * 0.15D);
    410        this.rotationPitch = (float)((double)this.rotationPitch - (double)par2 * 0.15D);
    411
    412        if (this.rotationPitch < -90.0F)
    413        {
    414            this.rotationPitch = -90.0F;
    415        }
    416
    417        if (this.rotationPitch > 90.0F)
    418        {
    419            this.rotationPitch = 90.0F;
    420        }
    421
    422        this.prevRotationPitch += this.rotationPitch - var3;
    423        this.prevRotationYaw += this.rotationYaw - var4;
    424    }
    425
    426    /**
    427     * Called to update the entity's position/logic.
    428     */
    429    public void onUpdate()
    430    {
    431        this.onEntityUpdate();
    432    }
    433
    434    /**
    435     * Gets called every tick from main Entity class
    436     */
    437    public void onEntityUpdate()
    438    {
    439        this.worldObj.theProfiler.startSection("entityBaseTick");
    440
    441        if (this.ridingEntity != null && this.ridingEntity.isDead)
    442        {
    443            this.ridingEntity = null;
    444        }
    445
    446        this.prevDistanceWalkedModified = this.distanceWalkedModified;
    447        this.prevPosX = this.posX;
    448        this.prevPosY = this.posY;
    449        this.prevPosZ = this.posZ;
    450        this.prevRotationPitch = this.rotationPitch;
    451        this.prevRotationYaw = this.rotationYaw;
    452        int var2;
    453
    454        if (!this.worldObj.isRemote && this.worldObj instanceof WorldServer)
    455        {
    456            this.worldObj.theProfiler.startSection("portal");
    457            MinecraftServer var1 = ((WorldServer)this.worldObj).getMinecraftServer();
    458            var2 = this.getMaxInPortalTime();
    459
    460            if (this.inPortal)
    461            {
    462                if (var1.getAllowNether())
    463                {
    464                    if (this.ridingEntity == null && this.timeInPortal++ >= var2)
    465                    {
    466                        this.timeInPortal = var2;
    467                        this.timeUntilPortal = this.getPortalCooldown();
    468                        byte var3;
    469
    470                        if (this.worldObj.provider.dimensionId == -1)
    471                        {
    472                            var3 = 0;
    473                        }
    474                        else
    475                        {
    476                            var3 = -1;
    477                        }
    478
    479                        this.travelToDimension(var3);
    480                    }
    481
    482                    this.inPortal = false;
    483                }
    484            }
    485            else
    486            {
    487                if (this.timeInPortal > 0)
    488                {
    489                    this.timeInPortal -= 4;
    490                }
    491
    492                if (this.timeInPortal < 0)
    493                {
    494                    this.timeInPortal = 0;
    495                }
    496            }
    497
    498            if (this.timeUntilPortal > 0)
    499            {
    500                --this.timeUntilPortal;
    501            }
    502
    503            this.worldObj.theProfiler.endSection();
    504        }
    505
    506        if (this.isSprinting() && !this.isInWater())
    507        {
    508            int var5 = MathHelper.floor_double(this.posX);
    509            var2 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset);
    510            int var6 = MathHelper.floor_double(this.posZ);
    511            int var4 = this.worldObj.getBlockId(var5, var2, var6);
    512
    513            if (var4 > 0)
    514            {
    515                this.worldObj.spawnParticle("tilecrack_" + var4 + "_" + this.worldObj.getBlockMetadata(var5, var2, var6), this.posX + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, this.boundingBox.minY + 0.1D, this.posZ + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, -this.motionX * 4.0D, 1.5D, -this.motionZ * 4.0D);
    516            }
    517        }
    518
    519        this.handleWaterMovement();
    520
    521        if (this.worldObj.isRemote)
    522        {
    523            this.fire = 0;
    524        }
    525        else if (this.fire > 0)
    526        {
    527            if (this.isImmuneToFire)
    528            {
    529                this.fire -= 4;
    530
    531                if (this.fire < 0)
    532                {
    533                    this.fire = 0;
    534                }
    535            }
    536            else
    537            {
    538                if (this.fire % 20 == 0)
    539                {
    540                    this.attackEntityFrom(DamageSource.onFire, 1);
    541                }
    542
    543                --this.fire;
    544            }
    545        }
    546
    547        if (this.handleLavaMovement())
    548        {
    549            this.setOnFireFromLava();
    550            this.fallDistance *= 0.5F;
    551        }
    552
    553        if (this.posY < -64.0D)
    554        {
    555            this.kill();
    556        }
    557
    558        if (!this.worldObj.isRemote)
    559        {
    560            this.setFlag(0, this.fire > 0);
    561            this.setFlag(2, this.ridingEntity != null && ridingEntity.shouldRiderSit());
    562        }
    563
    564        this.firstUpdate = false;
    565        this.worldObj.theProfiler.endSection();
    566    }
    567
    568    /**
    569     * Return the amount of time this entity should stay in a portal before being transported.
    570     */
    571    public int getMaxInPortalTime()
    572    {
    573        return 0;
    574    }
    575
    576    /**
    577     * Called whenever the entity is walking inside of lava.
    578     */
    579    protected void setOnFireFromLava()
    580    {
    581        if (!this.isImmuneToFire)
    582        {
    583            this.attackEntityFrom(DamageSource.lava, 4);
    584            this.setFire(15);
    585        }
    586    }
    587
    588    /**
    589     * Sets entity to burn for x amount of seconds, cannot lower amount of existing fire.
    590     */
    591    public void setFire(int par1)
    592    {
    593        int var2 = par1 * 20;
    594        var2 = EnchantmentProtection.func_92093_a(this, var2);
    595
    596        if (this.fire < var2)
    597        {
    598            this.fire = var2;
    599        }
    600    }
    601
    602    /**
    603     * Removes fire from entity.
    604     */
    605    public void extinguish()
    606    {
    607        this.fire = 0;
    608    }
    609
    610    /**
    611     * sets the dead flag. Used when you fall off the bottom of the world.
    612     */
    613    protected void kill()
    614    {
    615        this.setDead();
    616    }
    617
    618    /**
    619     * Checks if the offset position from the entity's current position is inside of liquid. Args: x, y, z
    620     */
    621    public boolean isOffsetPositionInLiquid(double par1, double par3, double par5)
    622    {
    623        AxisAlignedBB var7 = this.boundingBox.getOffsetBoundingBox(par1, par3, par5);
    624        List var8 = this.worldObj.getCollidingBoundingBoxes(this, var7);
    625        return !var8.isEmpty() ? false : !this.worldObj.isAnyLiquid(var7);
    626    }
    627
    628    /**
    629     * Tries to moves the entity by the passed in displacement. Args: x, y, z
    630     */
    631    public void moveEntity(double par1, double par3, double par5)
    632    {
    633        if (this.noClip)
    634        {
    635            this.boundingBox.offset(par1, par3, par5);
    636            this.posX = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0D;
    637            this.posY = this.boundingBox.minY + (double)this.yOffset - (double)this.ySize;
    638            this.posZ = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0D;
    639        }
    640        else
    641        {
    642            this.worldObj.theProfiler.startSection("move");
    643            this.ySize *= 0.4F;
    644            double var7 = this.posX;
    645            double var9 = this.posY;
    646            double var11 = this.posZ;
    647
    648            if (this.isInWeb)
    649            {
    650                this.isInWeb = false;
    651                par1 *= 0.25D;
    652                par3 *= 0.05000000074505806D;
    653                par5 *= 0.25D;
    654                this.motionX = 0.0D;
    655                this.motionY = 0.0D;
    656                this.motionZ = 0.0D;
    657            }
    658
    659            double var13 = par1;
    660            double var15 = par3;
    661            double var17 = par5;
    662            AxisAlignedBB var19 = this.boundingBox.copy();
    663            boolean var20 = this.onGround && this.isSneaking() && this instanceof EntityPlayer;
    664
    665            if (var20)
    666            {
    667                double var21;
    668
    669                for (var21 = 0.05D; par1 != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(par1, -1.0D, 0.0D)).isEmpty(); var13 = par1)
    670                {
    671                    if (par1 < var21 && par1 >= -var21)
    672                    {
    673                        par1 = 0.0D;
    674                    }
    675                    else if (par1 > 0.0D)
    676                    {
    677                        par1 -= var21;
    678                    }
    679                    else
    680                    {
    681                        par1 += var21;
    682                    }
    683                }
    684
    685                for (; par5 != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(0.0D, -1.0D, par5)).isEmpty(); var17 = par5)
    686                {
    687                    if (par5 < var21 && par5 >= -var21)
    688                    {
    689                        par5 = 0.0D;
    690                    }
    691                    else if (par5 > 0.0D)
    692                    {
    693                        par5 -= var21;
    694                    }
    695                    else
    696                    {
    697                        par5 += var21;
    698                    }
    699                }
    700
    701                while (par1 != 0.0D && par5 != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(par1, -1.0D, par5)).isEmpty())
    702                {
    703                    if (par1 < var21 && par1 >= -var21)
    704                    {
    705                        par1 = 0.0D;
    706                    }
    707                    else if (par1 > 0.0D)
    708                    {
    709                        par1 -= var21;
    710                    }
    711                    else
    712                    {
    713                        par1 += var21;
    714                    }
    715
    716                    if (par5 < var21 && par5 >= -var21)
    717                    {
    718                        par5 = 0.0D;
    719                    }
    720                    else if (par5 > 0.0D)
    721                    {
    722                        par5 -= var21;
    723                    }
    724                    else
    725                    {
    726                        par5 += var21;
    727                    }
    728
    729                    var13 = par1;
    730                    var17 = par5;
    731                }
    732            }
    733
    734            List var35 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.addCoord(par1, par3, par5));
    735
    736            for (int var22 = 0; var22 < var35.size(); ++var22)
    737            {
    738                par3 = ((AxisAlignedBB)var35.get(var22)).calculateYOffset(this.boundingBox, par3);
    739            }
    740
    741            this.boundingBox.offset(0.0D, par3, 0.0D);
    742
    743            if (!this.field_70135_K && var15 != par3)
    744            {
    745                par5 = 0.0D;
    746                par3 = 0.0D;
    747                par1 = 0.0D;
    748            }
    749
    750            boolean var34 = this.onGround || var15 != par3 && var15 < 0.0D;
    751            int var23;
    752
    753            for (var23 = 0; var23 < var35.size(); ++var23)
    754            {
    755                par1 = ((AxisAlignedBB)var35.get(var23)).calculateXOffset(this.boundingBox, par1);
    756            }
    757
    758            this.boundingBox.offset(par1, 0.0D, 0.0D);
    759
    760            if (!this.field_70135_K && var13 != par1)
    761            {
    762                par5 = 0.0D;
    763                par3 = 0.0D;
    764                par1 = 0.0D;
    765            }
    766
    767            for (var23 = 0; var23 < var35.size(); ++var23)
    768            {
    769                par5 = ((AxisAlignedBB)var35.get(var23)).calculateZOffset(this.boundingBox, par5);
    770            }
    771
    772            this.boundingBox.offset(0.0D, 0.0D, par5);
    773
    774            if (!this.field_70135_K && var17 != par5)
    775            {
    776                par5 = 0.0D;
    777                par3 = 0.0D;
    778                par1 = 0.0D;
    779            }
    780
    781            double var25;
    782            double var27;
    783            int var30;
    784            double var36;
    785
    786            if (this.stepHeight > 0.0F && var34 && (var20 || this.ySize < 0.05F) && (var13 != par1 || var17 != par5))
    787            {
    788                var36 = par1;
    789                var25 = par3;
    790                var27 = par5;
    791                par1 = var13;
    792                par3 = (double)this.stepHeight;
    793                par5 = var17;
    794                AxisAlignedBB var29 = this.boundingBox.copy();
    795                this.boundingBox.setBB(var19);
    796                var35 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.addCoord(var13, par3, var17));
    797
    798                for (var30 = 0; var30 < var35.size(); ++var30)
    799                {
    800                    par3 = ((AxisAlignedBB)var35.get(var30)).calculateYOffset(this.boundingBox, par3);
    801                }
    802
    803                this.boundingBox.offset(0.0D, par3, 0.0D);
    804
    805                if (!this.field_70135_K && var15 != par3)
    806                {
    807                    par5 = 0.0D;
    808                    par3 = 0.0D;
    809                    par1 = 0.0D;
    810                }
    811
    812                for (var30 = 0; var30 < var35.size(); ++var30)
    813                {
    814                    par1 = ((AxisAlignedBB)var35.get(var30)).calculateXOffset(this.boundingBox, par1);
    815                }
    816
    817                this.boundingBox.offset(par1, 0.0D, 0.0D);
    818
    819                if (!this.field_70135_K && var13 != par1)
    820                {
    821                    par5 = 0.0D;
    822                    par3 = 0.0D;
    823                    par1 = 0.0D;
    824                }
    825
    826                for (var30 = 0; var30 < var35.size(); ++var30)
    827                {
    828                    par5 = ((AxisAlignedBB)var35.get(var30)).calculateZOffset(this.boundingBox, par5);
    829                }
    830
    831                this.boundingBox.offset(0.0D, 0.0D, par5);
    832
    833                if (!this.field_70135_K && var17 != par5)
    834                {
    835                    par5 = 0.0D;
    836                    par3 = 0.0D;
    837                    par1 = 0.0D;
    838                }
    839
    840                if (!this.field_70135_K && var15 != par3)
    841                {
    842                    par5 = 0.0D;
    843                    par3 = 0.0D;
    844                    par1 = 0.0D;
    845                }
    846                else
    847                {
    848                    par3 = (double)(-this.stepHeight);
    849
    850                    for (var30 = 0; var30 < var35.size(); ++var30)
    851                    {
    852                        par3 = ((AxisAlignedBB)var35.get(var30)).calculateYOffset(this.boundingBox, par3);
    853                    }
    854
    855                    this.boundingBox.offset(0.0D, par3, 0.0D);
    856                }
    857
    858                if (var36 * var36 + var27 * var27 >= par1 * par1 + par5 * par5)
    859                {
    860                    par1 = var36;
    861                    par3 = var25;
    862                    par5 = var27;
    863                    this.boundingBox.setBB(var29);
    864                }
    865                /* Fixes a vanilla bug where the player view would dip when stepping between certain blocks
    866                 * https://mojang.atlassian.net/browse/MC-1594
    867                else
    868                {
    869                    double var40 = this.boundingBox.minY - (double)((int)this.boundingBox.minY);
    870
    871                    if (var40 > 0.0D)
    872                    {
    873                        this.ySize = (float)((double)this.ySize + var40 + 0.01D);
    874                    }
    875                }
    876                */
    877            }
    878
    879            this.worldObj.theProfiler.endSection();
    880            this.worldObj.theProfiler.startSection("rest");
    881            this.posX = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0D;
    882            this.posY = this.boundingBox.minY + (double)this.yOffset - (double)this.ySize;
    883            this.posZ = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0D;
    884            this.isCollidedHorizontally = var13 != par1 || var17 != par5;
    885            this.isCollidedVertically = var15 != par3;
    886            this.onGround = var15 != par3 && var15 < 0.0D;
    887            this.isCollided = this.isCollidedHorizontally || this.isCollidedVertically;
    888            this.updateFallState(par3, this.onGround);
    889
    890            if (var13 != par1)
    891            {
    892                this.motionX = 0.0D;
    893            }
    894
    895            if (var15 != par3)
    896            {
    897                this.motionY = 0.0D;
    898            }
    899
    900            if (var17 != par5)
    901            {
    902                this.motionZ = 0.0D;
    903            }
    904
    905            var36 = this.posX - var7;
    906            var25 = this.posY - var9;
    907            var27 = this.posZ - var11;
    908
    909            if (this.canTriggerWalking() && !var20 && this.ridingEntity == null)
    910            {
    911                int var37 = MathHelper.floor_double(this.posX);
    912                var30 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset);
    913                int var31 = MathHelper.floor_double(this.posZ);
    914                int var32 = this.worldObj.getBlockId(var37, var30, var31);
    915
    916                if (var32 == 0)
    917                {
    918                    int var33 = this.worldObj.blockGetRenderType(var37, var30 - 1, var31);
    919
    920                    if (var33 == 11 || var33 == 32 || var33 == 21)
    921                    {
    922                        var32 = this.worldObj.getBlockId(var37, var30 - 1, var31);
    923                    }
    924                }
    925
    926                if (var32 != Block.ladder.blockID)
    927                {
    928                    var25 = 0.0D;
    929                }
    930
    931                this.distanceWalkedModified = (float)((double)this.distanceWalkedModified + (double)MathHelper.sqrt_double(var36 * var36 + var27 * var27) * 0.6D);
    932                this.field_82151_R = (float)((double)this.field_82151_R + (double)MathHelper.sqrt_double(var36 * var36 + var25 * var25 + var27 * var27) * 0.6D);
    933
    934                if (this.field_82151_R > (float)this.nextStepDistance && var32 > 0)
    935                {
    936                    this.nextStepDistance = (int)this.field_82151_R + 1;
    937
    938                    if (this.isInWater())
    939                    {
    940                        float var39 = MathHelper.sqrt_double(this.motionX * this.motionX * 0.20000000298023224D + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D) * 0.35F;
    941
    942                        if (var39 > 1.0F)
    943                        {
    944                            var39 = 1.0F;
    945                        }
    946
    947                        this.playSound("liquid.swim", var39, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
    948                    }
    949
    950                    this.playStepSound(var37, var30, var31, var32);
    951                    Block.blocksList[var32].onEntityWalking(this.worldObj, var37, var30, var31, this);
    952                }
    953            }
    954
    955            this.doBlockCollisions();
    956            boolean var38 = this.isWet();
    957
    958            if (this.worldObj.isBoundingBoxBurning(this.boundingBox.contract(0.001D, 0.001D, 0.001D)))
    959            {
    960                this.dealFireDamage(1);
    961
    962                if (!var38)
    963                {
    964                    ++this.fire;
    965
    966                    if (this.fire == 0)
    967                    {
    968                        this.setFire(8);
    969                    }
    970                }
    971            }
    972            else if (this.fire <= 0)
    973            {
    974                this.fire = -this.fireResistance;
    975            }
    976
    977            if (var38 && this.fire > 0)
    978            {
    979                this.playSound("random.fizz", 0.7F, 1.6F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
    980                this.fire = -this.fireResistance;
    981            }
    982
    983            this.worldObj.theProfiler.endSection();
    984        }
    985    }
    986
    987    /**
    988     * Checks for block collisions, and calls the associated onBlockCollided method for the collided block.
    989     */
    990    protected void doBlockCollisions()
    991    {
    992        int var1 = MathHelper.floor_double(this.boundingBox.minX + 0.001D);
    993        int var2 = MathHelper.floor_double(this.boundingBox.minY + 0.001D);
    994        int var3 = MathHelper.floor_double(this.boundingBox.minZ + 0.001D);
    995        int var4 = MathHelper.floor_double(this.boundingBox.maxX - 0.001D);
    996        int var5 = MathHelper.floor_double(this.boundingBox.maxY - 0.001D);
    997        int var6 = MathHelper.floor_double(this.boundingBox.maxZ - 0.001D);
    998
    999        if (this.worldObj.checkChunksExist(var1, var2, var3, var4, var5, var6))
    1000        {
    1001            for (int var7 = var1; var7 <= var4; ++var7)
    1002            {
    1003                for (int var8 = var2; var8 <= var5; ++var8)
    1004                {
    1005                    for (int var9 = var3; var9 <= var6; ++var9)
    1006                    {
    1007                        int var10 = this.worldObj.getBlockId(var7, var8, var9);
    1008
    1009                        if (var10 > 0)
    1010                        {
    1011                            Block.blocksList[var10].onEntityCollidedWithBlock(this.worldObj, var7, var8, var9, this);
    1012                        }
    1013                    }
    1014                }
    1015            }
    1016        }
    1017    }
    1018
    1019    /**
    1020     * Plays step sound at given x, y, z for the entity
    1021     */
    1022    protected void playStepSound(int par1, int par2, int par3, int par4)
    1023    {
    1024        StepSound var5 = Block.blocksList[par4].stepSound;
    1025
    1026        if (this.worldObj.getBlockId(par1, par2 + 1, par3) == Block.snow.blockID)
    1027        {
    1028            var5 = Block.snow.stepSound;
    1029            this.playSound(var5.getStepSound(), var5.getVolume() * 0.15F, var5.getPitch());
    1030        }
    1031        else if (!Block.blocksList[par4].blockMaterial.isLiquid())
    1032        {
    1033            this.playSound(var5.getStepSound(), var5.getVolume() * 0.15F, var5.getPitch());
    1034        }
    1035    }
    1036
    1037    public void playSound(String par1Str, float par2, float par3)
    1038    {
    1039        this.worldObj.playSoundAtEntity(this, par1Str, par2, par3);
    1040    }
    1041
    1042    /**
    1043     * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
    1044     * prevent them from trampling crops
    1045     */
    1046    protected boolean canTriggerWalking()
    1047    {
    1048        return true;
    1049    }
    1050
    1051    /**
    1052     * Takes in the distance the entity has fallen this tick and whether its on the ground to update the fall distance
    1053     * and deal fall damage if landing on the ground.  Args: distanceFallenThisTick, onGround
    1054     */
    1055    protected void updateFallState(double par1, boolean par3)
    1056    {
    1057        if (par3)
    1058        {
    1059            if (this.fallDistance > 0.0F)
    1060            {
    1061                this.fall(this.fallDistance);
    1062                this.fallDistance = 0.0F;
    1063            }
    1064        }
    1065        else if (par1 < 0.0D)
    1066        {
    1067            this.fallDistance = (float)((double)this.fallDistance - par1);
    1068        }
    1069    }
    1070
    1071    /**
    1072     * returns the bounding box for this entity
    1073     */
    1074    public AxisAlignedBB getBoundingBox()
    1075    {
    1076        return null;
    1077    }
    1078
    1079    /**
    1080     * Will deal the specified amount of damage to the entity if the entity isn't immune to fire damage. Args:
    1081     * amountDamage
    1082     */
    1083    protected void dealFireDamage(int par1)
    1084    {
    1085        if (!this.isImmuneToFire)
    1086        {
    1087            this.attackEntityFrom(DamageSource.inFire, par1);
    1088        }
    1089    }
    1090
    1091    public final boolean isImmuneToFire()
    1092    {
    1093        return this.isImmuneToFire;
    1094    }
    1095
    1096    /**
    1097     * Called when the mob is falling. Calculates and applies fall damage.
    1098     */
    1099    protected void fall(float par1)
    1100    {
    1101        if (this.riddenByEntity != null)
    1102        {
    1103            this.riddenByEntity.fall(par1);
    1104        }
    1105    }
    1106
    1107    /**
    1108     * Checks if this entity is either in water or on an open air block in rain (used in wolves).
    1109     */
    1110    public boolean isWet()
    1111    {
    1112        return this.inWater || this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) || this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY + (double)this.height), MathHelper.floor_double(this.posZ));
    1113    }
    1114
    1115    /**
    1116     * Checks if this entity is inside water (if inWater field is true as a result of handleWaterMovement() returning
    1117     * true)
    1118     */
    1119    public boolean isInWater()
    1120    {
    1121        return this.inWater;
    1122    }
    1123
    1124    /**
    1125     * Returns if this entity is in water and will end up adding the waters velocity to the entity
    1126     */
    1127    public boolean handleWaterMovement()
    1128    {
    1129        if (this.worldObj.handleMaterialAcceleration(this.boundingBox.expand(0.0D, -0.4000000059604645D, 0.0D).contract(0.001D, 0.001D, 0.001D), Material.water, this))
    1130        {
    1131            if (!this.inWater && !this.firstUpdate)
    1132            {
    1133                float var1 = MathHelper.sqrt_double(this.motionX * this.motionX * 0.20000000298023224D + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D) * 0.2F;
    1134
    1135                if (var1 > 1.0F)
    1136                {
    1137                    var1 = 1.0F;
    1138                }
    1139
    1140                this.playSound("liquid.splash", var1, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
    1141                float var2 = (float)MathHelper.floor_double(this.boundingBox.minY);
    1142                int var3;
    1143                float var4;
    1144                float var5;
    1145
    1146                for (var3 = 0; (float)var3 < 1.0F + this.width * 20.0F; ++var3)
    1147                {
    1148                    var4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    1149                    var5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    1150                    this.worldObj.spawnParticle("bubble", this.posX + (double)var4, (double)(var2 + 1.0F), this.posZ + (double)var5, this.motionX, this.motionY - (double)(this.rand.nextFloat() * 0.2F), this.motionZ);
    1151                }
    1152
    1153                for (var3 = 0; (float)var3 < 1.0F + this.width * 20.0F; ++var3)
    1154                {
    1155                    var4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    1156                    var5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    1157                    this.worldObj.spawnParticle("splash", this.posX + (double)var4, (double)(var2 + 1.0F), this.posZ + (double)var5, this.motionX, this.motionY, this.motionZ);
    1158                }
    1159            }
    1160
    1161            this.fallDistance = 0.0F;
    1162            this.inWater = true;
    1163            this.fire = 0;
    1164        }
    1165        else
    1166        {
    1167            this.inWater = false;
    1168        }
    1169
    1170        return this.inWater;
    1171    }
    1172
    1173    /**
    1174     * Checks if the current block the entity is within of the specified material type
    1175     */
    1176    public boolean isInsideOfMaterial(Material par1Material)
    1177    {
    1178        double var2 = this.posY + (double)this.getEyeHeight();
    1179        int var4 = MathHelper.floor_double(this.posX);
    1180        int var5 = MathHelper.floor_float((float)MathHelper.floor_double(var2));
    1181        int var6 = MathHelper.floor_double(this.posZ);
    1182        int var7 = this.worldObj.getBlockId(var4, var5, var6);
    1183
    1184        if (var7 != 0 && Block.blocksList[var7].blockMaterial == par1Material)
    1185        {
    1186            float var8 = BlockFluid.getFluidHeightPercent(this.worldObj.getBlockMetadata(var4, var5, var6)) - 0.11111111F;
    1187            float var9 = (float)(var5 + 1) - var8;
    1188            return var2 < (double)var9;
    1189        }
    1190        else
    1191        {
    1192            return false;
    1193        }
    1194    }
    1195
    1196    public float getEyeHeight()
    1197    {
    1198        return 0.0F;
    1199    }
    1200
    1201    /**
    1202     * Whether or not the current entity is in lava
    1203     */
    1204    public boolean handleLavaMovement()
    1205    {
    1206        return this.worldObj.isMaterialInBB(this.boundingBox.expand(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), Material.lava);
    1207    }
    1208
    1209    /**
    1210     * Used in both water and by flying objects
    1211     */
    1212    public void moveFlying(float par1, float par2, float par3)
    1213    {
    1214        float var4 = par1 * par1 + par2 * par2;
    1215
    1216        if (var4 >= 1.0E-4F)
    1217        {
    1218            var4 = MathHelper.sqrt_float(var4);
    1219
    1220            if (var4 < 1.0F)
    1221            {
    1222                var4 = 1.0F;
    1223            }
    1224
    1225            var4 = par3 / var4;
    1226            par1 *= var4;
    1227            par2 *= var4;
    1228            float var5 = MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F);
    1229            float var6 = MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F);
    1230            this.motionX += (double)(par1 * var6 - par2 * var5);
    1231            this.motionZ += (double)(par2 * var6 + par1 * var5);
    1232        }
    1233    }
    1234
    1235    @SideOnly(Side.CLIENT)
    1236    public int getBrightnessForRender(float par1)
    1237    {
    1238        int var2 = MathHelper.floor_double(this.posX);
    1239        int var3 = MathHelper.floor_double(this.posZ);
    1240
    1241        if (this.worldObj.blockExists(var2, 0, var3))
    1242        {
    1243            double var4 = (this.boundingBox.maxY - this.boundingBox.minY) * 0.66D;
    1244            int var6 = MathHelper.floor_double(this.posY - (double)this.yOffset + var4);
    1245            return this.worldObj.getLightBrightnessForSkyBlocks(var2, var6, var3, 0);
    1246        }
    1247        else
    1248        {
    1249            return 0;
    1250        }
    1251    }
    1252
    1253    /**
    1254     * Gets how bright this entity is.
    1255     */
    1256    public float getBrightness(float par1)
    1257    {
    1258        int var2 = MathHelper.floor_double(this.posX);
    1259        int var3 = MathHelper.floor_double(this.posZ);
    1260
    1261        if (this.worldObj.blockExists(var2, 0, var3))
    1262        {
    1263            double var4 = (this.boundingBox.maxY - this.boundingBox.minY) * 0.66D;
    1264            int var6 = MathHelper.floor_double(this.posY - (double)this.yOffset + var4);
    1265            return this.worldObj.getLightBrightness(var2, var6, var3);
    1266        }
    1267        else
    1268        {
    1269            return 0.0F;
    1270        }
    1271    }
    1272
    1273    /**
    1274     * Sets the reference to the World object.
    1275     */
    1276    public void setWorld(World par1World)
    1277    {
    1278        this.worldObj = par1World;
    1279    }
    1280
    1281    /**
    1282     * Sets the entity's position and rotation. Args: posX, posY, posZ, yaw, pitch
    1283     */
    1284    public void setPositionAndRotation(double par1, double par3, double par5, float par7, float par8)
    1285    {
    1286        this.prevPosX = this.posX = par1;
    1287        this.prevPosY = this.posY = par3;
    1288        this.prevPosZ = this.posZ = par5;
    1289        this.prevRotationYaw = this.rotationYaw = par7;
    1290        this.prevRotationPitch = this.rotationPitch = par8;
    1291        this.ySize = 0.0F;
    1292        double var9 = (double)(this.prevRotationYaw - par7);
    1293
    1294        if (var9 < -180.0D)
    1295        {
    1296            this.prevRotationYaw += 360.0F;
    1297        }
    1298
    1299        if (var9 >= 180.0D)
    1300        {
    1301            this.prevRotationYaw -= 360.0F;
    1302        }
    1303
    1304        this.setPosition(this.posX, this.posY, this.posZ);
    1305        this.setRotation(par7, par8);
    1306    }
    1307
    1308    /**
    1309     * Sets the location and Yaw/Pitch of an entity in the world
    1310     */
    1311    public void setLocationAndAngles(double par1, double par3, double par5, float par7, float par8)
    1312    {
    1313        this.lastTickPosX = this.prevPosX = this.posX = par1;
    1314        this.lastTickPosY = this.prevPosY = this.posY = par3 + (double)this.yOffset;
    1315        this.lastTickPosZ = this.prevPosZ = this.posZ = par5;
    1316        this.rotationYaw = par7;
    1317        this.rotationPitch = par8;
    1318        this.setPosition(this.posX, this.posY, this.posZ);
    1319    }
    1320
    1321    /**
    1322     * Returns the distance to the entity. Args: entity
    1323     */
    1324    public float getDistanceToEntity(Entity par1Entity)
    1325    {
    1326        float var2 = (float)(this.posX - par1Entity.posX);
    1327        float var3 = (float)(this.posY - par1Entity.posY);
    1328        float var4 = (float)(this.posZ - par1Entity.posZ);
    1329        return MathHelper.sqrt_float(var2 * var2 + var3 * var3 + var4 * var4);
    1330    }
    1331
    1332    /**
    1333     * Gets the squared distance to the position. Args: x, y, z
    1334     */
    1335    public double getDistanceSq(double par1, double par3, double par5)
    1336    {
    1337        double var7 = this.posX - par1;
    1338        double var9 = this.posY - par3;
    1339        double var11 = this.posZ - par5;
    1340        return var7 * var7 + var9 * var9 + var11 * var11;
    1341    }
    1342
    1343    /**
    1344     * Gets the distance to the position. Args: x, y, z
    1345     */
    1346    public double getDistance(double par1, double par3, double par5)
    1347    {
    1348        double var7 = this.posX - par1;
    1349        double var9 = this.posY - par3;
    1350        double var11 = this.posZ - par5;
    1351        return (double)MathHelper.sqrt_double(var7 * var7 + var9 * var9 + var11 * var11);
    1352    }
    1353
    1354    /**
    1355     * Returns the squared distance to the entity. Args: entity
    1356     */
    1357    public double getDistanceSqToEntity(Entity par1Entity)
    1358    {
    1359        double var2 = this.posX - par1Entity.posX;
    1360        double var4 = this.posY - par1Entity.posY;
    1361        double var6 = this.posZ - par1Entity.posZ;
    1362        return var2 * var2 + var4 * var4 + var6 * var6;
    1363    }
    1364
    1365    /**
    1366     * Called by a player entity when they collide with an entity
    1367     */
    1368    public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {}
    1369
    1370    /**
    1371     * Applies a velocity to each of the entities pushing them away from each other. Args: entity
    1372     */
    1373    public void applyEntityCollision(Entity par1Entity)
    1374    {
    1375        if (par1Entity.riddenByEntity != this && par1Entity.ridingEntity != this)
    1376        {
    1377            double var2 = par1Entity.posX - this.posX;
    1378            double var4 = par1Entity.posZ - this.posZ;
    1379            double var6 = MathHelper.abs_max(var2, var4);
    1380
    1381            if (var6 >= 0.009999999776482582D)
    1382            {
    1383                var6 = (double)MathHelper.sqrt_double(var6);
    1384                var2 /= var6;
    1385                var4 /= var6;
    1386                double var8 = 1.0D / var6;
    1387
    1388                if (var8 > 1.0D)
    1389                {
    1390                    var8 = 1.0D;
    1391                }
    1392
    1393                var2 *= var8;
    1394                var4 *= var8;
    1395                var2 *= 0.05000000074505806D;
    1396                var4 *= 0.05000000074505806D;
    1397                var2 *= (double)(1.0F - this.entityCollisionReduction);
    1398                var4 *= (double)(1.0F - this.entityCollisionReduction);
    1399                this.addVelocity(-var2, 0.0D, -var4);
    1400                par1Entity.addVelocity(var2, 0.0D, var4);
    1401            }
    1402        }
    1403    }
    1404
    1405    /**
    1406     * Adds to the current velocity of the entity. Args: x, y, z
    1407     */
    1408    public void addVelocity(double par1, double par3, double par5)
    1409    {
    1410        this.motionX += par1;
    1411        this.motionY += par3;
    1412        this.motionZ += par5;
    1413        this.isAirBorne = true;
    1414    }
    1415
    1416    /**
    1417     * Sets that this entity has been attacked.
    1418     */
    1419    protected void setBeenAttacked()
    1420    {
    1421        this.velocityChanged = true;
    1422    }
    1423
    1424    /**
    1425     * Called when the entity is attacked.
    1426     */
    1427    public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    1428    {
    1429        if (this.isEntityInvulnerable())
    1430        {
    1431            return false;
    1432        }
    1433        else
    1434        {
    1435            this.setBeenAttacked();
    1436            return false;
    1437        }
    1438    }
    1439
    1440    /**
    1441     * Returns true if other Entities should be prevented from moving through this Entity.
    1442     */
    1443    public boolean canBeCollidedWith()
    1444    {
    1445        return false;
    1446    }
    1447
    1448    /**
    1449     * Returns true if this entity should push and be pushed by other entities when colliding.
    1450     */
    1451    public boolean canBePushed()
    1452    {
    1453        return false;
    1454    }
    1455
    1456    /**
    1457     * Adds a value to the player score. Currently not actually used and the entity passed in does nothing. Args:
    1458     * entity, scoreToAdd
    1459     */
    1460    public void addToPlayerScore(Entity par1Entity, int par2) {}
    1461
    1462    /**
    1463     * adds the ID of this entity to the NBT given
    1464     */
    1465    public boolean addEntityID(NBTTagCompound par1NBTTagCompound)
    1466    {
    1467        String var2 = this.getEntityString();
    1468
    1469        if (!this.isDead && var2 != null)
    1470        {
    1471            par1NBTTagCompound.setString("id", var2);
    1472            this.writeToNBT(par1NBTTagCompound);
    1473            return true;
    1474        }
    1475        else
    1476        {
    1477            return false;
    1478        }
    1479    }
    1480
    1481    @SideOnly(Side.CLIENT)
    1482
    1483    /**
    1484     * Checks using a Vec3d to determine if this entity is within range of that vector to be rendered. Args: vec3D
    1485     */
    1486    public boolean isInRangeToRenderVec3D(Vec3 par1Vec3)
    1487    {
    1488        double var2 = this.posX - par1Vec3.xCoord;
    1489        double var4 = this.posY - par1Vec3.yCoord;
    1490        double var6 = this.posZ - par1Vec3.zCoord;
    1491        double var8 = var2 * var2 + var4 * var4 + var6 * var6;
    1492        return this.isInRangeToRenderDist(var8);
    1493    }
    1494
    1495    @SideOnly(Side.CLIENT)
    1496
    1497    /**
    1498     * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge
    1499     * length * 64 * renderDistanceWeight Args: distance
    1500     */
    1501    public boolean isInRangeToRenderDist(double par1)
    1502    {
    1503        double var3 = this.boundingBox.getAverageEdgeLength();
    1504        var3 *= 64.0D * this.renderDistanceWeight;
    1505        return par1 < var3 * var3;
    1506    }
    1507
    1508    @SideOnly(Side.CLIENT)
    1509
    1510    /**
    1511     * Returns the texture's file path as a String.
    1512     */
    1513    public String getTexture()
    1514    {
    1515        return null;
    1516    }
    1517
    1518    /**
    1519     * Save the entity to NBT (calls an abstract helper method to write extra data)
    1520     */
    1521    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    1522    {
    1523        try
    1524        {
    1525            par1NBTTagCompound.setTag("Pos", this.newDoubleNBTList(new double[] {this.posX, this.posY + (double)this.ySize, this.posZ}));
    1526            par1NBTTagCompound.setTag("Motion", this.newDoubleNBTList(new double[] {this.motionX, this.motionY, this.motionZ}));
    1527            par1NBTTagCompound.setTag("Rotation", this.newFloatNBTList(new float[] {this.rotationYaw, this.rotationPitch}));
    1528            par1NBTTagCompound.setFloat("FallDistance", this.fallDistance);
    1529            par1NBTTagCompound.setShort("Fire", (short)this.fire);
    1530            par1NBTTagCompound.setShort("Air", (short)this.getAir());
    1531            par1NBTTagCompound.setBoolean("OnGround", this.onGround);
    1532            par1NBTTagCompound.setInteger("Dimension", this.dimension);
    1533            par1NBTTagCompound.setBoolean("Invulnerable", this.invulnerable);
    1534            par1NBTTagCompound.setInteger("PortalCooldown", this.timeUntilPortal);
    1535            if (persistentID != null)
    1536            {
    1537                par1NBTTagCompound.setLong("PersistentIDMSB", persistentID.getMostSignificantBits());
    1538                par1NBTTagCompound.setLong("PersistentIDLSB", persistentID.getLeastSignificantBits());
    1539            }
    1540            if (customEntityData != null)
    1541            {
    1542                par1NBTTagCompound.setCompoundTag("ForgeData", customEntityData);
    1543            }
    1544            this.writeEntityToNBT(par1NBTTagCompound);
    1545        }
    1546        catch (Throwable var5)
    1547        {
    1548            CrashReport var3 = CrashReport.makeCrashReport(var5, "Saving entity NBT");
    1549            CrashReportCategory var4 = var3.makeCategory("Entity being saved");
    1550            this.func_85029_a(var4);
    1551            throw new ReportedException(var3);
    1552        }
    1553    }
    1554
    1555    /**
    1556     * Reads the entity from NBT (calls an abstract helper method to read specialized data)
    1557     */
    1558    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    1559    {
    1560        try
    1561        {
    1562            NBTTagList var2 = par1NBTTagCompound.getTagList("Pos");
    1563            NBTTagList var6 = par1NBTTagCompound.getTagList("Motion");
    1564            NBTTagList var7 = par1NBTTagCompound.getTagList("Rotation");
    1565            this.motionX = ((NBTTagDouble)var6.tagAt(0)).data;
    1566            this.motionY = ((NBTTagDouble)var6.tagAt(1)).data;
    1567            this.motionZ = ((NBTTagDouble)var6.tagAt(2)).data;
    1568
    1569            if (Math.abs(this.motionX) > 10.0D)
    1570            {
    1571                this.motionX = 0.0D;
    1572            }
    1573
    1574            if (Math.abs(this.motionY) > 10.0D)
    1575            {
    1576                this.motionY = 0.0D;
    1577            }
    1578
    1579            if (Math.abs(this.motionZ) > 10.0D)
    1580            {
    1581                this.motionZ = 0.0D;
    1582            }
    1583
    1584            this.prevPosX = this.lastTickPosX = this.posX = ((NBTTagDouble)var2.tagAt(0)).data;
    1585            this.prevPosY = this.lastTickPosY = this.posY = ((NBTTagDouble)var2.tagAt(1)).data;
    1586            this.prevPosZ = this.lastTickPosZ = this.posZ = ((NBTTagDouble)var2.tagAt(2)).data;
    1587            this.prevRotationYaw = this.rotationYaw = ((NBTTagFloat)var7.tagAt(0)).data;
    1588            this.prevRotationPitch = this.rotationPitch = ((NBTTagFloat)var7.tagAt(1)).data;
    1589            this.fallDistance = par1NBTTagCompound.getFloat("FallDistance");
    1590            this.fire = par1NBTTagCompound.getShort("Fire");
    1591            this.setAir(par1NBTTagCompound.getShort("Air"));
    1592            this.onGround = par1NBTTagCompound.getBoolean("OnGround");
    1593            this.dimension = par1NBTTagCompound.getInteger("Dimension");
    1594            this.invulnerable = par1NBTTagCompound.getBoolean("Invulnerable");
    1595            this.timeUntilPortal = par1NBTTagCompound.getInteger("PortalCooldown");
    1596            this.setPosition(this.posX, this.posY, this.posZ);
    1597            this.setRotation(this.rotationYaw, this.rotationPitch);
    1598            if (par1NBTTagCompound.hasKey("ForgeData"))
    1599            {
    1600                customEntityData = par1NBTTagCompound.getCompoundTag("ForgeData");
    1601            }
    1602            if (par1NBTTagCompound.hasKey("PersistentIDMSB") && par1NBTTagCompound.hasKey("PersistentIDLSB"))
    1603            {
    1604                persistentID = new UUID(par1NBTTagCompound.getLong("PersistentIDMSB"), par1NBTTagCompound.getLong("PersistentIDLSB"));
    1605            }
    1606            this.readEntityFromNBT(par1NBTTagCompound);
    1607        }
    1608        catch (Throwable var5)
    1609        {
    1610            CrashReport var3 = CrashReport.makeCrashReport(var5, "Loading entity NBT");
    1611            CrashReportCategory var4 = var3.makeCategory("Entity being loaded");
    1612            this.func_85029_a(var4);
    1613            throw new ReportedException(var3);
    1614        }
    1615    }
    1616
    1617    /**
    1618     * Returns the string that identifies this Entity's class
    1619     */
    1620    protected final String getEntityString()
    1621    {
    1622        return EntityList.getEntityString(this);
    1623    }
    1624
    1625    /**
    1626     * (abstract) Protected helper method to read subclass entity data from NBT.
    1627     */
    1628    protected abstract void readEntityFromNBT(NBTTagCompound var1);
    1629
    1630    /**
    1631     * (abstract) Protected helper method to write subclass entity data to NBT.
    1632     */
    1633    protected abstract void writeEntityToNBT(NBTTagCompound var1);
    1634
    1635    /**
    1636     * creates a NBT list from the array of doubles passed to this function
    1637     */
    1638    protected NBTTagList newDoubleNBTList(double ... par1ArrayOfDouble)
    1639    {
    1640        NBTTagList var2 = new NBTTagList();
    1641        double[] var3 = par1ArrayOfDouble;
    1642        int var4 = par1ArrayOfDouble.length;
    1643
    1644        for (int var5 = 0; var5 < var4; ++var5)
    1645        {
    1646            double var6 = var3[var5];
    1647            var2.appendTag(new NBTTagDouble((String)null, var6));
    1648        }
    1649
    1650        return var2;
    1651    }
    1652
    1653    /**
    1654     * Returns a new NBTTagList filled with the specified floats
    1655     */
    1656    protected NBTTagList newFloatNBTList(float ... par1ArrayOfFloat)
    1657    {
    1658        NBTTagList var2 = new NBTTagList();
    1659        float[] var3 = par1ArrayOfFloat;
    1660        int var4 = par1ArrayOfFloat.length;
    1661
    1662        for (int var5 = 0; var5 < var4; ++var5)
    1663        {
    1664            float var6 = var3[var5];
    1665            var2.appendTag(new NBTTagFloat((String)null, var6));
    1666        }
    1667
    1668        return var2;
    1669    }
    1670
    1671    @SideOnly(Side.CLIENT)
    1672    public float getShadowSize()
    1673    {
    1674        return this.height / 2.0F;
    1675    }
    1676
    1677    /**
    1678     * Drops an item stack at the entity's position. Args: itemID, count
    1679     */
    1680    public EntityItem dropItem(int par1, int par2)
    1681    {
    1682        return this.dropItemWithOffset(par1, par2, 0.0F);
    1683    }
    1684
    1685    /**
    1686     * Drops an item stack with a specified y offset. Args: itemID, count, yOffset
    1687     */
    1688    public EntityItem dropItemWithOffset(int par1, int par2, float par3)
    1689    {
    1690        return this.entityDropItem(new ItemStack(par1, par2, 0), par3);
    1691    }
    1692
    1693    /**
    1694     * Drops an item at the position of the entity.
    1695     */
    1696    public EntityItem entityDropItem(ItemStack par1ItemStack, float par2)
    1697    {
    1698        EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY + (double)par2, this.posZ, par1ItemStack);
    1699        var3.delayBeforeCanPickup = 10;
    1700        if (captureDrops)
    1701        {
    1702            capturedDrops.add(var3);
    1703        }
    1704        else
    1705        {
    1706            this.worldObj.spawnEntityInWorld(var3);
    1707        }
    1708        return var3;
    1709    }
    1710
    1711    /**
    1712     * Checks whether target entity is alive.
    1713     */
    1714    public boolean isEntityAlive()
    1715    {
    1716        return !this.isDead;
    1717    }
    1718
    1719    /**
    1720     * Checks if this entity is inside of an opaque block
    1721     */
    1722    public boolean isEntityInsideOpaqueBlock()
    1723    {
    1724        for (int var1 = 0; var1 < 8; ++var1)
    1725        {
    1726            float var2 = ((float)((var1 >> 0) % 2) - 0.5F) * this.width * 0.8F;
    1727            float var3 = ((float)((var1 >> 1) % 2) - 0.5F) * 0.1F;
    1728            float var4 = ((float)((var1 >> 2) % 2) - 0.5F) * this.width * 0.8F;
    1729            int var5 = MathHelper.floor_double(this.posX + (double)var2);
    1730            int var6 = MathHelper.floor_double(this.posY + (double)this.getEyeHeight() + (double)var3);
    1731            int var7 = MathHelper.floor_double(this.posZ + (double)var4);
    1732
    1733            if (this.worldObj.isBlockNormalCube(var5, var6, var7))
    1734            {
    1735                return true;
    1736            }
    1737        }
    1738
    1739        return false;
    1740    }
    1741
    1742    /**
    1743     * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
    1744     */
    1745    public boolean interact(EntityPlayer par1EntityPlayer)
    1746    {
    1747        return false;
    1748    }
    1749
    1750    /**
    1751     * Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be
    1752     * pushable on contact, like boats or minecarts.
    1753     */
    1754    public AxisAlignedBB getCollisionBox(Entity par1Entity)
    1755    {
    1756        return null;
    1757    }
    1758
    1759    /**
    1760     * Handles updating while being ridden by an entity
    1761     */
    1762    public void updateRidden()
    1763    {
    1764        if (this.ridingEntity.isDead)
    1765        {
    1766            this.ridingEntity = null;
    1767        }
    1768        else
    1769        {
    1770            this.motionX = 0.0D;
    1771            this.motionY = 0.0D;
    1772            this.motionZ = 0.0D;
    1773            this.onUpdate();
    1774
    1775            if (this.ridingEntity != null)
    1776            {
    1777                this.ridingEntity.updateRiderPosition();
    1778                this.entityRiderYawDelta += (double)(this.ridingEntity.rotationYaw - this.ridingEntity.prevRotationYaw);
    1779
    1780                for (this.entityRiderPitchDelta += (double)(this.ridingEntity.rotationPitch - this.ridingEntity.prevRotationPitch); this.entityRiderYawDelta >= 180.0D; this.entityRiderYawDelta -= 360.0D)
    1781                {
    1782                    ;
    1783                }
    1784
    1785                while (this.entityRiderYawDelta < -180.0D)
    1786                {
    1787                    this.entityRiderYawDelta += 360.0D;
    1788                }
    1789
    1790                while (this.entityRiderPitchDelta >= 180.0D)
    1791                {
    1792                    this.entityRiderPitchDelta -= 360.0D;
    1793                }
    1794
    1795                while (this.entityRiderPitchDelta < -180.0D)
    1796                {
    1797                    this.entityRiderPitchDelta += 360.0D;
    1798                }
    1799
    1800                double var1 = this.entityRiderYawDelta * 0.5D;
    1801                double var3 = this.entityRiderPitchDelta * 0.5D;
    1802                float var5 = 10.0F;
    1803
    1804                if (var1 > (double)var5)
    1805                {
    1806                    var1 = (double)var5;
    1807                }
    1808
    1809                if (var1 < (double)(-var5))
    1810                {
    1811                    var1 = (double)(-var5);
    1812                }
    1813
    1814                if (var3 > (double)var5)
    1815                {
    1816                    var3 = (double)var5;
    1817                }
    1818
    1819                if (var3 < (double)(-var5))
    1820                {
    1821                    var3 = (double)(-var5);
    1822                }
    1823
    1824                this.entityRiderYawDelta -= var1;
    1825                this.entityRiderPitchDelta -= var3;
    1826                this.rotationYaw = (float)((double)this.rotationYaw + var1);
    1827                this.rotationPitch = (float)((double)this.rotationPitch + var3);
    1828            }
    1829        }
    1830    }
    1831
    1832    public void updateRiderPosition()
    1833    {
    1834        if (!(this.riddenByEntity instanceof EntityPlayer) || !((EntityPlayer)this.riddenByEntity).func_71066_bF())
    1835        {
    1836            this.riddenByEntity.lastTickPosX = this.lastTickPosX;
    1837            this.riddenByEntity.lastTickPosY = this.lastTickPosY + this.getMountedYOffset() + this.riddenByEntity.getYOffset();
    1838            this.riddenByEntity.lastTickPosZ = this.lastTickPosZ;
    1839        }
    1840
    1841        this.riddenByEntity.setPosition(this.posX, this.posY + this.getMountedYOffset() + this.riddenByEntity.getYOffset(), this.posZ);
    1842    }
    1843
    1844    /**
    1845     * Returns the Y Offset of this entity.
    1846     */
    1847    public double getYOffset()
    1848    {
    1849        return (double)this.yOffset;
    1850    }
    1851
    1852    /**
    1853     * Returns the Y offset from the entity's position for any entity riding this one.
    1854     */
    1855    public double getMountedYOffset()
    1856    {
    1857        return (double)this.height * 0.75D;
    1858    }
    1859
    1860    /**
    1861     * Called when a player mounts an entity. e.g. mounts a pig, mounts a boat.
    1862     */
    1863    public void mountEntity(Entity par1Entity)
    1864    {
    1865        this.entityRiderPitchDelta = 0.0D;
    1866        this.entityRiderYawDelta = 0.0D;
    1867
    1868        if (par1Entity == null)
    1869        {
    1870            if (this.ridingEntity != null)
    1871            {
    1872                this.setLocationAndAngles(this.ridingEntity.posX, this.ridingEntity.boundingBox.minY + (double)this.ridingEntity.height, this.ridingEntity.posZ, this.rotationYaw, this.rotationPitch);
    1873                this.ridingEntity.riddenByEntity = null;
    1874            }
    1875
    1876            this.ridingEntity = null;
    1877        }
    1878        else if (this.ridingEntity == par1Entity)
    1879        {
    1880            this.unmountEntity(par1Entity);
    1881            this.ridingEntity.riddenByEntity = null;
    1882            this.ridingEntity = null;
    1883        }
    1884        else
    1885        {
    1886            if (this.ridingEntity != null)
    1887            {
    1888                this.ridingEntity.riddenByEntity = null;
    1889            }
    1890
    1891            if (par1Entity.riddenByEntity != null)
    1892            {
    1893                par1Entity.riddenByEntity.ridingEntity = null;
    1894            }
    1895
    1896            this.ridingEntity = par1Entity;
    1897            par1Entity.riddenByEntity = this;
    1898        }
    1899    }
    1900
    1901    /**
    1902     * Called when a player unounts an entity.
    1903     */
    1904    public void unmountEntity(Entity par1Entity)
    1905    {
    1906        double var3 = par1Entity.posX;
    1907        double var5 = par1Entity.boundingBox.minY + (double)par1Entity.height;
    1908        double var7 = par1Entity.posZ;
    1909
    1910        for (double var9 = -1.5D; var9 < 2.0D; ++var9)
    1911        {
    1912            for (double var11 = -1.5D; var11 < 2.0D; ++var11)
    1913            {
    1914                if (var9 != 0.0D || var11 != 0.0D)
    1915                {
    1916                    int var13 = (int)(this.posX + var9);
    1917                    int var14 = (int)(this.posZ + var11);
    1918                    AxisAlignedBB var2 = this.boundingBox.getOffsetBoundingBox(var9, 1.0D, var11);
    1919
    1920                    if (this.worldObj.getAllCollidingBoundingBoxes(var2).isEmpty())
    1921                    {
    1922                        if (this.worldObj.doesBlockHaveSolidTopSurface(var13, (int)this.posY, var14))
    1923                        {
    1924                            this.setLocationAndAngles(this.posX + var9, this.posY + 1.0D, this.posZ + var11, this.rotationYaw, this.rotationPitch);
    1925                            return;
    1926                        }
    1927
    1928                        if (this.worldObj.doesBlockHaveSolidTopSurface(var13, (int)this.posY - 1, var14) || this.worldObj.getBlockMaterial(var13, (int)this.posY - 1, var14) == Material.water)
    1929                        {
    1930                            var3 = this.posX + var9;
    1931                            var5 = this.posY + 1.0D;
    1932                            var7 = this.posZ + var11;
    1933                        }
    1934                    }
    1935                }
    1936            }
    1937        }
    1938
    1939        this.setLocationAndAngles(var3, var5, var7, this.rotationYaw, this.rotationPitch);
    1940    }
    1941
    1942    @SideOnly(Side.CLIENT)
    1943
    1944    /**
    1945     * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
    1946     * posY, posZ, yaw, pitch
    1947     */
    1948    public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
    1949    {
    1950        this.setPosition(par1, par3, par5);
    1951        this.setRotation(par7, par8);
    1952        List var10 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.contract(0.03125D, 0.0D, 0.03125D));
    1953
    1954        if (!var10.isEmpty())
    1955        {
    1956            double var11 = 0.0D;
    1957
    1958            for (int var13 = 0; var13 < var10.size(); ++var13)
    1959            {
    1960                AxisAlignedBB var14 = (AxisAlignedBB)var10.get(var13);
    1961
    1962                if (var14.maxY > var11)
    1963                {
    1964                    var11 = var14.maxY;
    1965                }
    1966            }
    1967
    1968            par3 += var11 - this.boundingBox.minY;
    1969            this.setPosition(par1, par3, par5);
    1970        }
    1971    }
    1972
    1973    public float getCollisionBorderSize()
    1974    {
    1975        return 0.1F;
    1976    }
    1977
    1978    /**
    1979     * returns a (normalized) vector of where this entity is looking
    1980     */
    1981    public Vec3 getLookVec()
    1982    {
    1983        return null;
    1984    }
    1985
    1986    /**
    1987     * Called by portal blocks when an entity is within it.
    1988     */
    1989    public void setInPortal()
    1990    {
    1991        if (this.timeUntilPortal > 0)
    1992        {
    1993            this.timeUntilPortal = this.getPortalCooldown();
    1994        }
    1995        else
    1996        {
    1997            double var1 = this.prevPosX - this.posX;
    1998            double var3 = this.prevPosZ - this.posZ;
    1999
    2000            if (!this.worldObj.isRemote && !this.inPortal)
    2001            {
    2002                this.field_82152_aq = Direction.getMovementDirection(var1, var3);
    2003            }
    2004
    2005            this.inPortal = true;
    2006        }
    2007    }
    2008
    2009    /**
    2010     * Return the amount of cooldown before this entity can use a portal again.
    2011     */
    2012    public int getPortalCooldown()
    2013    {
    2014        return 900;
    2015    }
    2016
    2017    @SideOnly(Side.CLIENT)
    2018
    2019    /**
    2020     * Sets the velocity to the args. Args: x, y, z
    2021     */
    2022    public void setVelocity(double par1, double par3, double par5)
    2023    {
    2024        this.motionX = par1;
    2025        this.motionY = par3;
    2026        this.motionZ = par5;
    2027    }
    2028
    2029    @SideOnly(Side.CLIENT)
    2030    public void handleHealthUpdate(byte par1) {}
    2031
    2032    @SideOnly(Side.CLIENT)
    2033
    2034    /**
    2035     * Setups the entity to do the hurt animation. Only used by packets in multiplayer.
    2036     */
    2037    public void performHurtAnimation() {}
    2038
    2039    @SideOnly(Side.CLIENT)
    2040    public void updateCloak() {}
    2041
    2042    public ItemStack[] getLastActiveItems()
    2043    {
    2044        return null;
    2045    }
    2046
    2047    /**
    2048     * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
    2049     */
    2050    public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack) {}
    2051
    2052    /**
    2053     * Returns true if the entity is on fire. Used by render to add the fire effect on rendering.
    2054     */
    2055    public boolean isBurning()
    2056    {
    2057        return this.fire > 0 || this.getFlag(0);
    2058    }
    2059
    2060    /**
    2061     * Returns true if the entity is riding another entity, used by render to rotate the legs to be in 'sit' position
    2062     * for players.
    2063     */
    2064    public boolean isRiding()
    2065    {
    2066        return (this.ridingEntity != null && ridingEntity.shouldRiderSit()) || this.getFlag(2);
    2067    }
    2068
    2069    /**
    2070     * Returns if this entity is sneaking.
    2071     */
    2072    public boolean isSneaking()
    2073    {
    2074        return this.getFlag(1);
    2075    }
    2076
    2077    /**
    2078     * Sets the sneaking flag.
    2079     */
    2080    public void setSneaking(boolean par1)
    2081    {
    2082        this.setFlag(1, par1);
    2083    }
    2084
    2085    /**
    2086     * Get if the Entity is sprinting.
    2087     */
    2088    public boolean isSprinting()
    2089    {
    2090        return this.getFlag(3);
    2091    }
    2092
    2093    /**
    2094     * Set sprinting switch for Entity.
    2095     */
    2096    public void setSprinting(boolean par1)
    2097    {
    2098        this.setFlag(3, par1);
    2099    }
    2100
    2101    public boolean getHasActivePotion()
    2102    {
    2103        return this.getFlag(5);
    2104    }
    2105
    2106    public void setHasActivePotion(boolean par1)
    2107    {
    2108        this.setFlag(5, par1);
    2109    }
    2110
    2111    @SideOnly(Side.CLIENT)
    2112    public boolean isEating()
    2113    {
    2114        return this.getFlag(4);
    2115    }
    2116
    2117    public void setEating(boolean par1)
    2118    {
    2119        this.setFlag(4, par1);
    2120    }
    2121
    2122    /**
    2123     * Returns true if the flag is active for the entity. Known flags: 0) is burning; 1) is sneaking; 2) is riding
    2124     * something; 3) is sprinting; 4) is eating
    2125     */
    2126    protected boolean getFlag(int par1)
    2127    {
    2128        return (this.dataWatcher.getWatchableObjectByte(0) & 1 << par1) != 0;
    2129    }
    2130
    2131    /**
    2132     * Enable or disable a entity flag, see getEntityFlag to read the know flags.
    2133     */
    2134    protected void setFlag(int par1, boolean par2)
    2135    {
    2136        byte var3 = this.dataWatcher.getWatchableObjectByte(0);
    2137
    2138        if (par2)
    2139        {
    2140            this.dataWatcher.updateObject(0, Byte.valueOf((byte)(var3 | 1 << par1)));
    2141        }
    2142        else
    2143        {
    2144            this.dataWatcher.updateObject(0, Byte.valueOf((byte)(var3 & ~(1 << par1))));
    2145        }
    2146    }
    2147
    2148    public int getAir()
    2149    {
    2150        return this.dataWatcher.getWatchableObjectShort(1);
    2151    }
    2152
    2153    public void setAir(int par1)
    2154    {
    2155        this.dataWatcher.updateObject(1, Short.valueOf((short)par1));
    2156    }
    2157
    2158    /**
    2159     * Called when a lightning bolt hits the entity.
    2160     */
    2161    public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt)
    2162    {
    2163        this.dealFireDamage(5);
    2164        ++this.fire;
    2165
    2166        if (this.fire == 0)
    2167        {
    2168            this.setFire(8);
    2169        }
    2170    }
    2171
    2172    /**
    2173     * This method gets called when the entity kills another one.
    2174     */
    2175    public void onKillEntity(EntityLiving par1EntityLiving) {}
    2176
    2177    /**
    2178     * Adds velocity to push the entity out of blocks at the specified x, y, z position Args: x, y, z
    2179     */
    2180    protected boolean pushOutOfBlocks(double par1, double par3, double par5)
    2181    {
    2182        int var7 = MathHelper.floor_double(par1);
    2183        int var8 = MathHelper.floor_double(par3);
    2184        int var9 = MathHelper.floor_double(par5);
    2185        double var10 = par1 - (double)var7;
    2186        double var12 = par3 - (double)var8;
    2187        double var14 = par5 - (double)var9;
    2188        List var16 = this.worldObj.getAllCollidingBoundingBoxes(this.boundingBox);
    2189
    2190        if (var16.isEmpty() && !this.worldObj.func_85174_u(var7, var8, var9))
    2191        {
    2192            return false;
    2193        }
    2194        else
    2195        {
    2196            boolean var17 = !this.worldObj.func_85174_u(var7 - 1, var8, var9);
    2197            boolean var18 = !this.worldObj.func_85174_u(var7 + 1, var8, var9);
    2198            boolean var19 = !this.worldObj.func_85174_u(var7, var8 - 1, var9);
    2199            boolean var20 = !this.worldObj.func_85174_u(var7, var8 + 1, var9);
    2200            boolean var21 = !this.worldObj.func_85174_u(var7, var8, var9 - 1);
    2201            boolean var22 = !this.worldObj.func_85174_u(var7, var8, var9 + 1);
    2202            byte var23 = 3;
    2203            double var24 = 9999.0D;
    2204
    2205            if (var17 && var10 < var24)
    2206            {
    2207                var24 = var10;
    2208                var23 = 0;
    2209            }
    2210
    2211            if (var18 && 1.0D - var10 < var24)
    2212            {
    2213                var24 = 1.0D - var10;
    2214                var23 = 1;
    2215            }
    2216
    2217            if (var20 && 1.0D - var12 < var24)
    2218            {
    2219                var24 = 1.0D - var12;
    2220                var23 = 3;
    2221            }
    2222
    2223            if (var21 && var14 < var24)
    2224            {
    2225                var24 = var14;
    2226                var23 = 4;
    2227            }
    2228
    2229            if (var22 && 1.0D - var14 < var24)
    2230            {
    2231                var24 = 1.0D - var14;
    2232                var23 = 5;
    2233            }
    2234
    2235            float var26 = this.rand.nextFloat() * 0.2F + 0.1F;
    2236
    2237            if (var23 == 0)
    2238            {
    2239                this.motionX = (double)(-var26);
    2240            }
    2241
    2242            if (var23 == 1)
    2243            {
    2244                this.motionX = (double)var26;
    2245            }
    2246
    2247            if (var23 == 2)
    2248            {
    2249                this.motionY = (double)(-var26);
    2250            }
    2251
    2252            if (var23 == 3)
    2253            {
    2254                this.motionY = (double)var26;
    2255            }
    2256
    2257            if (var23 == 4)
    2258            {
    2259                this.motionZ = (double)(-var26);
    2260            }
    2261
    2262            if (var23 == 5)
    2263            {
    2264                this.motionZ = (double)var26;
    2265            }
    2266
    2267            return true;
    2268        }
    2269    }
    2270
    2271    /**
    2272     * Sets the Entity inside a web block.
    2273     */
    2274    public void setInWeb()
    2275    {
    2276        this.isInWeb = true;
    2277        this.fallDistance = 0.0F;
    2278    }
    2279
    2280    /**
    2281     * Gets the username of the entity.
    2282     */
    2283    public String getEntityName()
    2284    {
    2285        String var1 = EntityList.getEntityString(this);
    2286
    2287        if (var1 == null)
    2288        {
    2289            var1 = "generic";
    2290        }
    2291
    2292        return StatCollector.translateToLocal("entity." + var1 + ".name");
    2293    }
    2294
    2295    /**
    2296     * Return the Entity parts making up this Entity (currently only for dragons)
    2297     */
    2298    public Entity[] getParts()
    2299    {
    2300        return null;
    2301    }
    2302
    2303    /**
    2304     * Returns true if Entity argument is equal to this Entity
    2305     */
    2306    public boolean isEntityEqual(Entity par1Entity)
    2307    {
    2308        return this == par1Entity;
    2309    }
    2310
    2311    public float setRotationYawHead()
    2312    {
    2313        return 0.0F;
    2314    }
    2315
    2316    @SideOnly(Side.CLIENT)
    2317
    2318    /**
    2319     * Sets the head's yaw rotation of the entity.
    2320     */
    2321    public void setHeadRotationYaw(float par1) {}
    2322
    2323    /**
    2324     * If returns false, the item will not inflict any damage against entities.
    2325     */
    2326    public boolean canAttackWithItem()
    2327    {
    2328        return true;
    2329    }
    2330
    2331    public boolean func_85031_j(Entity par1Entity)
    2332    {
    2333        return false;
    2334    }
    2335
    2336    public String toString()
    2337    {
    2338        return String.format("%s[\'%s\'/%d, l=\'%s\', x=%.2f, y=%.2f, z=%.2f]", new Object[] {this.getClass().getSimpleName(), this.getEntityName(), Integer.valueOf(this.entityId), this.worldObj == null ? "~NULL~" : this.worldObj.getWorldInfo().getWorldName(), Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ)});
    2339    }
    2340
    2341    /**
    2342     * Return whether this entity is invulnerable to damage.
    2343     */
    2344    public boolean isEntityInvulnerable()
    2345    {
    2346        return this.invulnerable;
    2347    }
    2348
    2349    public void func_82149_j(Entity par1Entity)
    2350    {
    2351        this.setLocationAndAngles(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par1Entity.rotationYaw, par1Entity.rotationPitch);
    2352    }
    2353
    2354    /**
    2355     * Copies important data from another entity to this entity. Used when teleporting entities between worlds, as this
    2356     * actually deletes the teleporting entity and re-creates it on the other side. Params: Entity to copy from, unused
    2357     * (always true)
    2358     */
    2359    public void copyDataFrom(Entity par1Entity, boolean par2)
    2360    {
    2361        NBTTagCompound var3 = new NBTTagCompound();
    2362        par1Entity.writeToNBT(var3);
    2363        this.readFromNBT(var3);
    2364        this.timeUntilPortal = par1Entity.timeUntilPortal;
    2365        this.field_82152_aq = par1Entity.field_82152_aq;
    2366    }
    2367
    2368    /**
    2369     * Teleports the entity to another dimension. Params: Dimension number to teleport to
    2370     */
    2371    public void travelToDimension(int par1)
    2372    {
    2373        if (!this.worldObj.isRemote && !this.isDead)
    2374        {
    2375            this.worldObj.theProfiler.startSection("changeDimension");
    2376            MinecraftServer var2 = MinecraftServer.getServer();
    2377            int var3 = this.dimension;
    2378            WorldServer var4 = var2.worldServerForDimension(var3);
    2379            WorldServer var5 = var2.worldServerForDimension(par1);
    2380            this.dimension = par1;
    2381            this.worldObj.removeEntity(this);
    2382            this.isDead = false;
    2383            this.worldObj.theProfiler.startSection("reposition");
    2384            var2.getConfigurationManager().transferEntityToWorld(this, var3, var4, var5);
    2385            this.worldObj.theProfiler.endStartSection("reloading");
    2386            Entity var6 = EntityList.createEntityByName(EntityList.getEntityString(this), var5);
    2387
    2388            if (var6 != null)
    2389            {
    2390                var6.copyDataFrom(this, true);
    2391                var5.spawnEntityInWorld(var6);
    2392            }
    2393
    2394            this.isDead = true;
    2395            this.worldObj.theProfiler.endSection();
    2396            var4.resetUpdateEntityTick();
    2397            var5.resetUpdateEntityTick();
    2398            this.worldObj.theProfiler.endSection();
    2399        }
    2400    }
    2401
    2402    public float func_82146_a(Explosion par1Explosion, Block par2Block, int par3, int par4, int par5)
    2403    {
    2404        return par2Block.getExplosionResistance(this, worldObj, par3, par4, par5, posX, posY + (double)getEyeHeight(), posZ);
    2405    }
    2406
    2407    public int func_82143_as()
    2408    {
    2409        return 3;
    2410    }
    2411
    2412    public int func_82148_at()
    2413    {
    2414        return this.field_82152_aq;
    2415    }
    2416
    2417    /**
    2418     * Return whether this entity should NOT trigger a pressure plate or a tripwire.
    2419     */
    2420    public boolean doesEntityNotTriggerPressurePlate()
    2421    {
    2422        return false;
    2423    }
    2424
    2425    public void func_85029_a(CrashReportCategory par1CrashReportCategory)
    2426    {
    2427        par1CrashReportCategory.addCrashSectionCallable("Entity Type", new CallableEntityType(this));
    2428        par1CrashReportCategory.addCrashSection("Entity ID", Integer.valueOf(this.entityId));
    2429        par1CrashReportCategory.addCrashSection("Name", this.getEntityName());
    2430        par1CrashReportCategory.addCrashSection("Exact location", String.format("%.2f, %.2f, %.2f", new Object[] {Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ)}));
    2431        par1CrashReportCategory.addCrashSection("Block location", CrashReportCategory.func_85071_a(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)));
    2432        par1CrashReportCategory.addCrashSection("Momentum", String.format("%.2f, %.2f, %.2f", new Object[] {Double.valueOf(this.motionX), Double.valueOf(this.motionY), Double.valueOf(this.motionZ)}));
    2433    }
    2434
    2435    @SideOnly(Side.CLIENT)
    2436
    2437    /**
    2438     * Return whether this entity should be rendered as on fire.
    2439     */
    2440    public boolean canRenderOnFire()
    2441    {
    2442        return this.isBurning();
    2443    }
    2444
    2445    /* ================================== Forge Start =====================================*/
    2446    /**
    2447     * Returns a NBTTagCompound that can be used to store custom data for this entity.
    2448     * It will be written, and read from disc, so it persists over world saves.
    2449     * @return A NBTTagCompound
    2450     */
    2451    public NBTTagCompound getEntityData()
    2452    {
    2453        if (customEntityData == null)
    2454        {
    2455            customEntityData = new NBTTagCompound();
    2456        }
    2457        return customEntityData;
    2458    }
    2459
    2460    /**
    2461     * Used in model rendering to determine if the entity riding this entity should be in the 'sitting' position.
    2462     * @return false to prevent an entity that is mounted to this entity from displaying the 'sitting' animation.
    2463     */
    2464    public boolean shouldRiderSit()
    2465    {
    2466        return true;
    2467    }
    2468
    2469    /**
    2470     * Called when a user uses the creative pick block button on this entity.
    2471     *
    2472     * @param target The full target the player is looking at
    2473     * @return A ItemStack to add to the player's inventory, Null if nothing should be added.
    2474     */
    2475    public ItemStack getPickedResult(MovingObjectPosition target)
    2476    {
    2477        if (this instanceof EntityPainting)
    2478        {
    2479            return new ItemStack(Item.painting);
    2480        }
    2481        else if (this instanceof EntityMinecart)
    2482        {
    2483            return ((EntityMinecart)this).getCartItem();
    2484        }
    2485        else if (this instanceof EntityBoat)
    2486        {
    2487            return new ItemStack(Item.boat);
    2488        }
    2489        else if (this instanceof EntityItemFrame)
    2490        {
    2491            ItemStack held = ((EntityItemFrame)this).getDisplayedItem();
    2492            if (held == null)
    2493            {
    2494                return new ItemStack(Item.itemFrame);
    2495            }
    2496            else
    2497            {
    2498                return held.copy();
    2499            }
    2500        }
    2501        else
    2502        {
    2503            int id = EntityList.getEntityID(this);
    2504            if (id > 0 && EntityList.entityEggs.containsKey(id))
    2505            {
    2506                return new ItemStack(Item.monsterPlacer, 1, id);
    2507            }
    2508        }
    2509        return null;
    2510    }
    2511
    2512    public UUID getPersistentID()
    2513    {
    2514        return persistentID;
    2515    }
    2516
    2517    public synchronized void generatePersistentID()
    2518    {
    2519        if (persistentID == null)
    2520        {
    2521            persistentID = UUID.randomUUID();
    2522        }
    2523    }
    2524
    2525    /**
    2526     * Reset the entity ID to a new value. Not to be used from Mod code
    2527     */
    2528    public final void resetEntityId()
    2529    {
    2530        this.entityId = nextEntityID++;
    2531    }
    2532
    2533    public boolean shouldRenderInPass(int pass)
    2534    {
    2535        return pass == 0;
    2536    }
    2537}