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