    001package net.minecraft.entity;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.Collection;
    006import java.util.HashMap;
    007import java.util.Iterator;
    008import java.util.List;
    009import java.util.Random;
    010import net.minecraft.block.Block;
    011import net.minecraft.block.StepSound;
    012import net.minecraft.block.material.Material;
    013import net.minecraft.enchantment.EnchantmentHelper;
    014import net.minecraft.entity.ai.EntityAITasks;
    015import net.minecraft.entity.ai.EntityJumpHelper;
    016import net.minecraft.entity.ai.EntityLookHelper;
    017import net.minecraft.entity.ai.EntityMoveHelper;
    018import net.minecraft.entity.ai.EntitySenses;
    019import net.minecraft.entity.item.EntityItem;
    020import net.minecraft.entity.item.EntityXPOrb;
    021import net.minecraft.entity.monster.EntityCreeper;
    022import net.minecraft.entity.monster.EntityGhast;
    023import net.minecraft.entity.passive.EntityPig;
    024import net.minecraft.entity.passive.EntityWolf;
    025import net.minecraft.entity.player.EntityPlayer;
    026import net.minecraft.entity.projectile.EntityArrow;
    027import net.minecraft.item.Item;
    028import net.minecraft.item.ItemArmor;
    029import net.minecraft.item.ItemStack;
    030import net.minecraft.item.ItemSword;
    031import net.minecraft.nbt.NBTTagCompound;
    032import net.minecraft.nbt.NBTTagFloat;
    033import net.minecraft.nbt.NBTTagList;
    034import net.minecraft.network.packet.Packet18Animation;
    035import net.minecraft.network.packet.Packet22Collect;
    036import net.minecraft.network.packet.Packet5PlayerInventory;
    037import net.minecraft.pathfinding.PathNavigate;
    038import net.minecraft.potion.Potion;
    039import net.minecraft.potion.PotionEffect;
    040import net.minecraft.potion.PotionHelper;
    041import net.minecraft.util.ChunkCoordinates;
    042import net.minecraft.util.CombatTracker;
    043import net.minecraft.util.DamageSource;
    044import net.minecraft.util.Icon;
    045import net.minecraft.util.MathHelper;
    046import net.minecraft.util.MovingObjectPosition;
    047import net.minecraft.util.Vec3;
    048import net.minecraft.world.World;
    049import net.minecraft.world.WorldServer;
    050
    051import net.minecraftforge.common.ForgeHooks;
    052import net.minecraftforge.common.MinecraftForge;
    053import net.minecraftforge.event.entity.living.*;
    054import static net.minecraftforge.event.entity.living.LivingEvent.*;
    055
    056public abstract class EntityLiving extends Entity
    057{
    058    /**
    059     * An array of probabilities that determines whether a random enchantment should be added to the held item. Indexed
    060     * by difficulty.
    061     */
    062    private static final float[] enchantmentProbability = new float[] {0.0F, 0.0F, 0.1F, 0.2F};
    063
    064    /** Probability to get enchanted armor */
    065    private static final float[] armorEnchantmentProbability = new float[] {0.0F, 0.0F, 0.25F, 0.5F};
    066
    067    /** Probability to get armor */
    068    private static final float[] armorProbability = new float[] {0.0F, 0.0F, 0.05F, 0.02F};
    069
    070    /** Probability to pick up loot */
    071    public static final float[] pickUpLootProability = new float[] {0.0F, 0.1F, 0.15F, 0.45F};
    072    public int maxHurtResistantTime = 20;
    073    public float field_70769_ao;
    074    public float field_70770_ap;
    075    public float renderYawOffset = 0.0F;
    076    public float prevRenderYawOffset = 0.0F;
    077
    078    /** Entity head rotation yaw */
    079    public float rotationYawHead = 0.0F;
    080
    081    /** Entity head rotation yaw at previous tick */
    082    public float prevRotationYawHead = 0.0F;
    083    protected float field_70768_au;
    084    protected float field_70766_av;
    085    protected float field_70764_aw;
    086    protected float field_70763_ax;
    087    protected boolean field_70753_ay = true;
    088
    089    /** the path for the texture of this entityLiving */
    090    protected String texture = "/mob/char.png";
    091    protected boolean field_70740_aA = true;
    092    protected float field_70741_aB = 0.0F;
    093
    094    /**
    095     * a string holding the type of entity it is currently only implemented in entityPlayer(as 'humanoid')
    096     */
    097    protected String entityType = null;
    098    protected float field_70743_aD = 1.0F;
    099
    100    /** The score value of the Mob, the amount of points the mob is worth. */
    101    protected int scoreValue = 0;
    102    protected float field_70745_aF = 0.0F;
    103
    104    /**
    105     * A factor used to determine how far this entity will move each tick if it is walking on land. Adjusted by speed,
    106     * and slipperiness of the current block.
    107     */
    108    public float landMovementFactor = 0.1F;
    109
    110    /**
    111     * A factor used to determine how far this entity will move each tick if it is jumping or falling.
    112     */
    113    public float jumpMovementFactor = 0.02F;
    114    public float prevSwingProgress;
    115    public float swingProgress;
    116    protected int health = this.getMaxHealth();
    117    public int prevHealth;
    118
    119    /**
    120     * in each step in the damage calculations, this is set to the 'carryover' that would result if someone was damaged
    121     * .25 hearts (for example), and added to the damage in the next step
    122     */
    123    public int carryoverDamage;
    124
    125    /** Number of ticks since this EntityLiving last produced its sound */
    126    public int livingSoundTime;
    127
    128    /**
    129     * The amount of time remaining this entity should act 'hurt'. (Visual appearance of red tint)
    130     */
    131    public int hurtTime;
    132
    133    /** What the hurt time was max set to last. */
    134    public int maxHurtTime;
    135
    136    /** The yaw at which this entity was last attacked from. */
    137    public float attackedAtYaw = 0.0F;
    138
    139    /**
    140     * The amount of time remaining this entity should act 'dead', i.e. have a corpse in the world.
    141     */
    142    public int deathTime = 0;
    143    public int attackTime = 0;
    144    public float prevCameraPitch;
    145    public float cameraPitch;
    146
    147    /**
    148     * This gets set on entity death, but never used. Looks like a duplicate of isDead
    149     */
    150    protected boolean dead = false;
    151
    152    /** The experience points the Entity gives. */
    153    public int experienceValue;
    154    public int field_70731_aW = -1;
    155    public float field_70730_aX = (float)(Math.random() * 0.8999999761581421D + 0.10000000149011612D);
    156    public float prevLimbYaw;
    157    public float limbYaw;
    158
    159    /**
    160     * Only relevant when legYaw is not 0(the entity is moving). Influences where in its swing legs and arms currently
    161     * are.
    162     */
    163    public float limbSwing;
    164
    165    /** The most recent player that has attacked this entity */
    166    protected EntityPlayer attackingPlayer = null;
    167
    168    /**
    169     * Set to 60 when hit by the player or the player's wolf, then decrements. Used to determine whether the entity
    170     * should drop items on death.
    171     */
    172    protected int recentlyHit = 0;
    173
    174    /** is only being set, has no uses as of MC 1.1 */
    175    private EntityLiving entityLivingToAttack = null;
    176    private int revengeTimer = 0;
    177    private EntityLiving lastAttackingEntity = null;
    178    public int arrowHitTimer = 0;
    179    protected HashMap activePotionsMap = new HashMap();
    180
    181    /** Whether the DataWatcher needs to be updated with the active potions */
    182    private boolean potionsNeedUpdate = true;
    183    private int field_70748_f;
    184    private EntityLookHelper lookHelper;
    185    private EntityMoveHelper moveHelper;
    186
    187    /** Entity jumping helper */
    188    private EntityJumpHelper jumpHelper;
    189    private EntityBodyHelper bodyHelper;
    190    private PathNavigate navigator;
    191    public final EntityAITasks tasks;
    192    protected final EntityAITasks targetTasks;
    193
    194    /** The active target the Task system uses for tracking */
    195    private EntityLiving attackTarget;
    196    private EntitySenses senses;
    197    private float AIMoveSpeed;
    198    private ChunkCoordinates homePosition = new ChunkCoordinates(0, 0, 0);
    199
    200    /** If -1 there is no maximum distance */
    201    private float maximumHomeDistance = -1.0F;
    202
    203    /** Equipment (armor and held item) for this entity. */
    204    private ItemStack[] equipment = new ItemStack[5];
    205
    206    /** Chances for each equipment piece from dropping when this entity dies. */
    207    protected float[] equipmentDropChances = new float[5];
    208    private ItemStack[] field_82180_bT = new ItemStack[5];
    209
    210    /** Whether an arm swing is currently in progress. */
    211    public boolean isSwingInProgress = false;
    212    public int swingProgressInt = 0;
    213
    214    /** Whether this entity can pick up items from the ground. */
    215    private boolean canPickUpLoot = false;
    216
    217    /** Whether this entity should NOT despawn. */
    218    private boolean persistenceRequired = false;
    219    protected final CombatTracker field_94063_bt = new CombatTracker(this);
    220
    221    /**
    222     * The number of updates over which the new position and rotation are to be applied to the entity.
    223     */
    224    protected int newPosRotationIncrements;
    225
    226    /** The new X position to be applied to the entity. */
    227    protected double newPosX;
    228
    229    /** The new Y position to be applied to the entity. */
    230    protected double newPosY;
    231
    232    /** The new Z position to be applied to the entity. */
    233    protected double newPosZ;
    234
    235    /** The new yaw rotation to be applied to the entity. */
    236    protected double newRotationYaw;
    237
    238    /** The new yaw rotation to be applied to the entity. */
    239    protected double newRotationPitch;
    240    float field_70706_bo = 0.0F;
    241
    242    /** Amount of damage taken in last hit, in half-hearts */
    243    protected int lastDamage = 0;
    244
    245    /** Holds the living entity age, used to control the despawn. */
    246    protected int entityAge = 0;
    247    protected float moveStrafing;
    248    protected float moveForward;
    249    protected float randomYawVelocity;
    250
    251    /** used to check whether entity is jumping. */
    252    public boolean isJumping = false;
    253    protected float defaultPitch = 0.0F;
    254    protected float moveSpeed = 0.7F;
    255
    256    /** Number of ticks since last jump */
    257    private int jumpTicks = 0;
    258
    259    /** This entity's current target. */
    260    private Entity currentTarget;
    261
    262    /** How long to keep a specific target entity */
    263    protected int numTicksToChaseTarget = 0;
    264
    265    public EntityLiving(World par1World)
    266    {
    267        super(par1World);
    268        this.preventEntitySpawning = true;
    269        this.tasks = new EntityAITasks(par1World != null && par1World.theProfiler != null ? par1World.theProfiler : null);
    270        this.targetTasks = new EntityAITasks(par1World != null && par1World.theProfiler != null ? par1World.theProfiler : null);
    271        this.lookHelper = new EntityLookHelper(this);
    272        this.moveHelper = new EntityMoveHelper(this);
    273        this.jumpHelper = new EntityJumpHelper(this);
    274        this.bodyHelper = new EntityBodyHelper(this);
    275        this.navigator = new PathNavigate(this, par1World, (float)this.func_96121_ay());
    276        this.senses = new EntitySenses(this);
    277        this.field_70770_ap = (float)(Math.random() + 1.0D) * 0.01F;
    278        this.setPosition(this.posX, this.posY, this.posZ);
    279        this.field_70769_ao = (float)Math.random() * 12398.0F;
    280        this.rotationYaw = (float)(Math.random() * Math.PI * 2.0D);
    281        this.rotationYawHead = this.rotationYaw;
    282
    283        for (int i = 0; i < this.equipmentDropChances.length; ++i)
    284        {
    285            this.equipmentDropChances[i] = 0.085F;
    286        }
    287
    288        this.stepHeight = 0.5F;
    289    }
    290
    291    protected int func_96121_ay()
    292    {
    293        return 16;
    294    }
    295
    296    public EntityLookHelper getLookHelper()
    297    {
    298        return this.lookHelper;
    299    }
    300
    301    public EntityMoveHelper getMoveHelper()
    302    {
    303        return this.moveHelper;
    304    }
    305
    306    public EntityJumpHelper getJumpHelper()
    307    {
    308        return this.jumpHelper;
    309    }
    310
    311    public PathNavigate getNavigator()
    312    {
    313        return this.navigator;
    314    }
    315
    316    /**
    317     * returns the EntitySenses Object for the EntityLiving
    318     */
    319    public EntitySenses getEntitySenses()
    320    {
    321        return this.senses;
    322    }
    323
    324    public Random getRNG()
    325    {
    326        return this.rand;
    327    }
    328
    329    public EntityLiving getAITarget()
    330    {
    331        return this.entityLivingToAttack;
    332    }
    333
    334    public EntityLiving getLastAttackingEntity()
    335    {
    336        return this.lastAttackingEntity;
    337    }
    338
    339    public void setLastAttackingEntity(Entity par1Entity)
    340    {
    341        if (par1Entity instanceof EntityLiving)
    342        {
    343            this.lastAttackingEntity = (EntityLiving)par1Entity;
    344        }
    345    }
    346
    347    public int getAge()
    348    {
    349        return this.entityAge;
    350    }
    351
    352    public float getRotationYawHead()
    353    {
    354        return this.rotationYawHead;
    355    }
    356
    357    @SideOnly(Side.CLIENT)
    358
    359    /**
    360     * Sets the head's yaw rotation of the entity.
    361     */
    362    public void setRotationYawHead(float par1)
    363    {
    364        this.rotationYawHead = par1;
    365    }
    366
    367    /**
    368     * the movespeed used for the new AI system
    369     */
    370    public float getAIMoveSpeed()
    371    {
    372        return this.AIMoveSpeed;
    373    }
    374
    375    /**
    376     * set the movespeed used for the new AI system
    377     */
    378    public void setAIMoveSpeed(float par1)
    379    {
    380        this.AIMoveSpeed = par1;
    381        this.setMoveForward(par1);
    382    }
    383
    384    public boolean attackEntityAsMob(Entity par1Entity)
    385    {
    386        this.setLastAttackingEntity(par1Entity);
    387        return false;
    388    }
    389
    390    /**
    391     * Gets the active target the Task system uses for tracking
    392     */
    393    public EntityLiving getAttackTarget()
    394    {
    395        return this.attackTarget;
    396    }
    397
    398    /**
    399     * Sets the active target the Task system uses for tracking
    400     */
    401    public void setAttackTarget(EntityLiving par1EntityLiving)
    402    {
    403        this.attackTarget = par1EntityLiving;
    404        ForgeHooks.onLivingSetAttackTarget(this, par1EntityLiving);
    405    }
    406
    407    /**
    408     * Returns true if this entity can attack entities of the specified class.
    409     */
    410    public boolean canAttackClass(Class par1Class)
    411    {
    412        return EntityCreeper.class != par1Class && EntityGhast.class != par1Class;
    413    }
    414
    415    /**
    416     * This function applies the benefits of growing back wool and faster growing up to the acting entity. (This
    417     * function is used in the AIEatGrass)
    418     */
    419    public void eatGrassBonus() {}
    420
    421    /**
    422     * Takes in the distance the entity has fallen this tick and whether its on the ground to update the fall distance
    423     * and deal fall damage if landing on the ground.  Args: distanceFallenThisTick, onGround
    424     */
    425    protected void updateFallState(double par1, boolean par3)
    426    {
    427        if (!this.isInWater())
    428        {
    429            this.handleWaterMovement();
    430        }
    431
    432        if (par3 && this.fallDistance > 0.0F)
    433        {
    434            int i = MathHelper.floor_double(this.posX);
    435            int j = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset);
    436            int k = MathHelper.floor_double(this.posZ);
    437            int l = this.worldObj.getBlockId(i, j, k);
    438
    439            if (l == 0)
    440            {
    441                int i1 = this.worldObj.blockGetRenderType(i, j - 1, k);
    442
    443                if (i1 == 11 || i1 == 32 || i1 == 21)
    444                {
    445                    l = this.worldObj.getBlockId(i, j - 1, k);
    446                }
    447            }
    448
    449            if (l > 0)
    450            {
    451                Block.blocksList[l].onFallenUpon(this.worldObj, i, j, k, this, this.fallDistance);
    452            }
    453        }
    454
    455        super.updateFallState(par1, par3);
    456    }
    457
    458    /**
    459     * Returns true if entity is within home distance from current position
    460     */
    461    public boolean isWithinHomeDistanceCurrentPosition()
    462    {
    463        return this.isWithinHomeDistance(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
    464    }
    465
    466    public boolean isWithinHomeDistance(int par1, int par2, int par3)
    467    {
    468        return this.maximumHomeDistance == -1.0F ? true : this.homePosition.getDistanceSquared(par1, par2, par3) < this.maximumHomeDistance * this.maximumHomeDistance;
    469    }
    470
    471    public void setHomeArea(int par1, int par2, int par3, int par4)
    472    {
    473        this.homePosition.set(par1, par2, par3);
    474        this.maximumHomeDistance = (float)par4;
    475    }
    476
    477    public ChunkCoordinates getHomePosition()
    478    {
    479        return this.homePosition;
    480    }
    481
    482    public float getMaximumHomeDistance()
    483    {
    484        return this.maximumHomeDistance;
    485    }
    486
    487    public void detachHome()
    488    {
    489        this.maximumHomeDistance = -1.0F;
    490    }
    491
    492    public boolean hasHome()
    493    {
    494        return this.maximumHomeDistance != -1.0F;
    495    }
    496
    497    public void setRevengeTarget(EntityLiving par1EntityLiving)
    498    {
    499        this.entityLivingToAttack = par1EntityLiving;
    500        this.revengeTimer = this.entityLivingToAttack != null ? 100 : 0;
    501        ForgeHooks.onLivingSetAttackTarget(this, par1EntityLiving);
    502    }
    503
    504    protected void entityInit()
    505    {
    506        this.dataWatcher.addObject(8, Integer.valueOf(this.field_70748_f));
    507        this.dataWatcher.addObject(9, Byte.valueOf((byte)0));
    508        this.dataWatcher.addObject(10, Byte.valueOf((byte)0));
    509        this.dataWatcher.addObject(6, Byte.valueOf((byte)0));
    510        this.dataWatcher.addObject(5, "");
    511    }
    512
    513    /**
    514     * returns true if the entity provided in the argument can be seen. (Raytrace)
    515     */
    516    public boolean canEntityBeSeen(Entity par1Entity)
    517    {
    518        return this.worldObj.rayTraceBlocks(this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ), this.worldObj.getWorldVec3Pool().getVecFromPool(par1Entity.posX, par1Entity.posY + (double)par1Entity.getEyeHeight(), par1Entity.posZ)) == null;
    519    }
    520
    521    @SideOnly(Side.CLIENT)
    522
    523    /**
    524     * Returns the texture's file path as a String.
    525     */
    526    public String getTexture()
    527    {
    528        return this.texture;
    529    }
    530
    531    /**
    532     * Returns true if other Entities should be prevented from moving through this Entity.
    533     */
    534    public boolean canBeCollidedWith()
    535    {
    536        return !this.isDead;
    537    }
    538
    539    /**
    540     * Returns true if this entity should push and be pushed by other entities when colliding.
    541     */
    542    public boolean canBePushed()
    543    {
    544        return !this.isDead;
    545    }
    546
    547    public float getEyeHeight()
    548    {
    549        return this.height * 0.85F;
    550    }
    551
    552    /**
    553     * Get number of ticks, at least during which the living entity will be silent.
    554     */
    555    public int getTalkInterval()
    556    {
    557        return 80;
    558    }
    559
    560    /**
    561     * Plays living's sound at its position
    562     */
    563    public void playLivingSound()
    564    {
    565        String s = this.getLivingSound();
    566
    567        if (s != null)
    568        {
    569            this.playSound(s, this.getSoundVolume(), this.getSoundPitch());
    570        }
    571    }
    572
    573    /**
    574     * Gets called every tick from main Entity class
    575     */
    576    public void onEntityUpdate()
    577    {
    578        this.prevSwingProgress = this.swingProgress;
    579        super.onEntityUpdate();
    580        this.worldObj.theProfiler.startSection("mobBaseTick");
    581
    582        if (this.isEntityAlive() && this.rand.nextInt(1000) < this.livingSoundTime++)
    583        {
    584            this.livingSoundTime = -this.getTalkInterval();
    585            this.playLivingSound();
    586        }
    587
    588        if (this.isEntityAlive() && this.isEntityInsideOpaqueBlock())
    589        {
    590            this.attackEntityFrom(DamageSource.inWall, 1);
    591        }
    592
    593        if (this.isImmuneToFire() || this.worldObj.isRemote)
    594        {
    595            this.extinguish();
    596        }
    597
    598        boolean flag = this instanceof EntityPlayer && ((EntityPlayer)this).capabilities.disableDamage;
    599
    600        if (this.isEntityAlive() && this.isInsideOfMaterial(Material.water) && !this.canBreatheUnderwater() && !this.activePotionsMap.containsKey(Integer.valueOf(Potion.waterBreathing.id)) && !flag)
    601        {
    602            this.setAir(this.decreaseAirSupply(this.getAir()));
    603
    604            if (this.getAir() == -20)
    605            {
    606                this.setAir(0);
    607
    608                for (int i = 0; i < 8; ++i)
    609                {
    610                    float f = this.rand.nextFloat() - this.rand.nextFloat();
    611                    float f1 = this.rand.nextFloat() - this.rand.nextFloat();
    612                    float f2 = this.rand.nextFloat() - this.rand.nextFloat();
    613                    this.worldObj.spawnParticle("bubble", this.posX + (double)f, this.posY + (double)f1, this.posZ + (double)f2, this.motionX, this.motionY, this.motionZ);
    614                }
    615
    616                this.attackEntityFrom(DamageSource.drown, 2);
    617            }
    618
    619            this.extinguish();
    620        }
    621        else
    622        {
    623            this.setAir(300);
    624        }
    625
    626        this.prevCameraPitch = this.cameraPitch;
    627
    628        if (this.attackTime > 0)
    629        {
    630            --this.attackTime;
    631        }
    632
    633        if (this.hurtTime > 0)
    634        {
    635            --this.hurtTime;
    636        }
    637
    638        if (this.hurtResistantTime > 0)
    639        {
    640            --this.hurtResistantTime;
    641        }
    642
    643        if (this.health <= 0)
    644        {
    645            this.onDeathUpdate();
    646        }
    647
    648        if (this.recentlyHit > 0)
    649        {
    650            --this.recentlyHit;
    651        }
    652        else
    653        {
    654            this.attackingPlayer = null;
    655        }
    656
    657        if (this.lastAttackingEntity != null && !this.lastAttackingEntity.isEntityAlive())
    658        {
    659            this.lastAttackingEntity = null;
    660        }
    661
    662        if (this.entityLivingToAttack != null)
    663        {
    664            if (!this.entityLivingToAttack.isEntityAlive())
    665            {
    666                this.setRevengeTarget((EntityLiving)null);
    667            }
    668            else if (this.revengeTimer > 0)
    669            {
    670                --this.revengeTimer;
    671            }
    672            else
    673            {
    674                this.setRevengeTarget((EntityLiving)null);
    675            }
    676        }
    677
    678        this.updatePotionEffects();
    679        this.field_70763_ax = this.field_70764_aw;
    680        this.prevRenderYawOffset = this.renderYawOffset;
    681        this.prevRotationYawHead = this.rotationYawHead;
    682        this.prevRotationYaw = this.rotationYaw;
    683        this.prevRotationPitch = this.rotationPitch;
    684        this.worldObj.theProfiler.endSection();
    685    }
    686
    687    /**
    688     * handles entity death timer, experience orb and particle creation
    689     */
    690    protected void onDeathUpdate()
    691    {
    692        ++this.deathTime;
    693
    694        if (this.deathTime == 20)
    695        {
    696            int i;
    697
    698            if (!this.worldObj.isRemote && (this.recentlyHit > 0 || this.isPlayer()) && !this.isChild() && this.worldObj.getGameRules().getGameRuleBooleanValue("doMobLoot"))
    699            {
    700                i = this.getExperiencePoints(this.attackingPlayer);
    701
    702                while (i > 0)
    703                {
    704                    int j = EntityXPOrb.getXPSplit(i);
    705                    i -= j;
    706                    this.worldObj.spawnEntityInWorld(new EntityXPOrb(this.worldObj, this.posX, this.posY, this.posZ, j));
    707                }
    708            }
    709
    710            this.setDead();
    711
    712            for (i = 0; i < 20; ++i)
    713            {
    714                double d0 = this.rand.nextGaussian() * 0.02D;
    715                double d1 = this.rand.nextGaussian() * 0.02D;
    716                double d2 = this.rand.nextGaussian() * 0.02D;
    717                this.worldObj.spawnParticle("explode", this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, this.posY + (double)(this.rand.nextFloat() * this.height), this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width, d0, d1, d2);
    718            }
    719        }
    720    }
    721
    722    /**
    723     * Decrements the entity's air supply when underwater
    724     */
    725    protected int decreaseAirSupply(int par1)
    726    {
    727        int j = EnchantmentHelper.getRespiration(this);
    728        return j > 0 && this.rand.nextInt(j + 1) > 0 ? par1 : par1 - 1;
    729    }
    730
    731    /**
    732     * Get the experience points the entity currently has.
    733     */
    734    protected int getExperiencePoints(EntityPlayer par1EntityPlayer)
    735    {
    736        if (this.experienceValue > 0)
    737        {
    738            int i = this.experienceValue;
    739            ItemStack[] aitemstack = this.getLastActiveItems();
    740
    741            for (int j = 0; j < aitemstack.length; ++j)
    742            {
    743                if (aitemstack[j] != null && this.equipmentDropChances[j] <= 1.0F)
    744                {
    745                    i += 1 + this.rand.nextInt(3);
    746                }
    747            }
    748
    749            return i;
    750        }
    751        else
    752        {
    753            return this.experienceValue;
    754        }
    755    }
    756
    757    /**
    758     * Only use is to identify if class is an instance of player for experience dropping
    759     */
    760    protected boolean isPlayer()
    761    {
    762        return false;
    763    }
    764
    765    /**
    766     * Spawns an explosion particle around the Entity's location
    767     */
    768    public void spawnExplosionParticle()
    769    {
    770        for (int i = 0; i < 20; ++i)
    771        {
    772            double d0 = this.rand.nextGaussian() * 0.02D;
    773            double d1 = this.rand.nextGaussian() * 0.02D;
    774            double d2 = this.rand.nextGaussian() * 0.02D;
    775            double d3 = 10.0D;
    776            this.worldObj.spawnParticle("explode", this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width - d0 * d3, this.posY + (double)(this.rand.nextFloat() * this.height) - d1 * d3, this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width - d2 * d3, d0, d1, d2);
    777        }
    778    }
    779
    780    /**
    781     * Handles updating while being ridden by an entity
    782     */
    783    public void updateRidden()
    784    {
    785        super.updateRidden();
    786        this.field_70768_au = this.field_70766_av;
    787        this.field_70766_av = 0.0F;
    788        this.fallDistance = 0.0F;
    789    }
    790
    791    @SideOnly(Side.CLIENT)
    792
    793    /**
    794     * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
    795     * posY, posZ, yaw, pitch
    796     */
    797    public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
    798    {
    799        this.yOffset = 0.0F;
    800        this.newPosX = par1;
    801        this.newPosY = par3;
    802        this.newPosZ = par5;
    803        this.newRotationYaw = (double)par7;
    804        this.newRotationPitch = (double)par8;
    805        this.newPosRotationIncrements = par9;
    806    }
    807
    808    /**
    809     * Called to update the entity's position/logic.
    810     */
    811    public void onUpdate()
    812    {
    813        if (ForgeHooks.onLivingUpdate(this))
    814        {
    815            return;
    816        }
    817
    818        super.onUpdate();
    819
    820        if (!this.worldObj.isRemote)
    821        {
    822            int i;
    823
    824            for (i = 0; i < 5; ++i)
    825            {
    826                ItemStack itemstack = this.getCurrentItemOrArmor(i);
    827
    828                if (!ItemStack.areItemStacksEqual(itemstack, this.field_82180_bT[i]))
    829                {
    830                    ((WorldServer)this.worldObj).getEntityTracker().sendPacketToAllPlayersTrackingEntity(this, new Packet5PlayerInventory(this.entityId, i, itemstack));
    831                    this.field_82180_bT[i] = itemstack == null ? null : itemstack.copy();
    832                }
    833            }
    834
    835            i = this.getArrowCountInEntity();
    836
    837            if (i > 0)
    838            {
    839                if (this.arrowHitTimer <= 0)
    840                {
    841                    this.arrowHitTimer = 20 * (30 - i);
    842                }
    843
    844                --this.arrowHitTimer;
    845
    846                if (this.arrowHitTimer <= 0)
    847                {
    848                    this.setArrowCountInEntity(i - 1);
    849                }
    850            }
    851        }
    852
    853        this.onLivingUpdate();
    854        double d0 = this.posX - this.prevPosX;
    855        double d1 = this.posZ - this.prevPosZ;
    856        float f = (float)(d0 * d0 + d1 * d1);
    857        float f1 = this.renderYawOffset;
    858        float f2 = 0.0F;
    859        this.field_70768_au = this.field_70766_av;
    860        float f3 = 0.0F;
    861
    862        if (f > 0.0025000002F)
    863        {
    864            f3 = 1.0F;
    865            f2 = (float)Math.sqrt((double)f) * 3.0F;
    866            f1 = (float)Math.atan2(d1, d0) * 180.0F / (float)Math.PI - 90.0F;
    867        }
    868
    869        if (this.swingProgress > 0.0F)
    870        {
    871            f1 = this.rotationYaw;
    872        }
    873
    874        if (!this.onGround)
    875        {
    876            f3 = 0.0F;
    877        }
    878
    879        this.field_70766_av += (f3 - this.field_70766_av) * 0.3F;
    880        this.worldObj.theProfiler.startSection("headTurn");
    881
    882        if (this.isAIEnabled())
    883        {
    884            this.bodyHelper.func_75664_a();
    885        }
    886        else
    887        {
    888            float f4 = MathHelper.wrapAngleTo180_float(f1 - this.renderYawOffset);
    889            this.renderYawOffset += f4 * 0.3F;
    890            float f5 = MathHelper.wrapAngleTo180_float(this.rotationYaw - this.renderYawOffset);
    891            boolean flag = f5 < -90.0F || f5 >= 90.0F;
    892
    893            if (f5 < -75.0F)
    894            {
    895                f5 = -75.0F;
    896            }
    897
    898            if (f5 >= 75.0F)
    899            {
    900                f5 = 75.0F;
    901            }
    902
    903            this.renderYawOffset = this.rotationYaw - f5;
    904
    905            if (f5 * f5 > 2500.0F)
    906            {
    907                this.renderYawOffset += f5 * 0.2F;
    908            }
    909
    910            if (flag)
    911            {
    912                f2 *= -1.0F;
    913            }
    914        }
    915
    916        this.worldObj.theProfiler.endSection();
    917        this.worldObj.theProfiler.startSection("rangeChecks");
    918
    919        while (this.rotationYaw - this.prevRotationYaw < -180.0F)
    920        {
    921            this.prevRotationYaw -= 360.0F;
    922        }
    923
    924        while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
    925        {
    926            this.prevRotationYaw += 360.0F;
    927        }
    928
    929        while (this.renderYawOffset - this.prevRenderYawOffset < -180.0F)
    930        {
    931            this.prevRenderYawOffset -= 360.0F;
    932        }
    933
    934        while (this.renderYawOffset - this.prevRenderYawOffset >= 180.0F)
    935        {
    936            this.prevRenderYawOffset += 360.0F;
    937        }
    938
    939        while (this.rotationPitch - this.prevRotationPitch < -180.0F)
    940        {
    941            this.prevRotationPitch -= 360.0F;
    942        }
    943
    944        while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
    945        {
    946            this.prevRotationPitch += 360.0F;
    947        }
    948
    949        while (this.rotationYawHead - this.prevRotationYawHead < -180.0F)
    950        {
    951            this.prevRotationYawHead -= 360.0F;
    952        }
    953
    954        while (this.rotationYawHead - this.prevRotationYawHead >= 180.0F)
    955        {
    956            this.prevRotationYawHead += 360.0F;
    957        }
    958
    959        this.worldObj.theProfiler.endSection();
    960        this.field_70764_aw += f2;
    961    }
    962
    963    /**
    964     * Heal living entity (param: amount of half-hearts)
    965     */
    966    public void heal(int par1)
    967    {
    968        if (this.health > 0)
    969        {
    970            this.setEntityHealth(this.getHealth() + par1);
    971
    972            if (this.health > this.getMaxHealth())
    973            {
    974                this.setEntityHealth(this.getMaxHealth());
    975            }
    976
    977            this.hurtResistantTime = this.maxHurtResistantTime / 2;
    978        }
    979    }
    980
    981    public abstract int getMaxHealth();
    982
    983    public int getHealth()
    984    {
    985        return this.health;
    986    }
    987
    988    public void setEntityHealth(int par1)
    989    {
    990        this.health = par1;
    991
    992        if (par1 > this.getMaxHealth())
    993        {
    994            par1 = this.getMaxHealth();
    995        }
    996    }
    997
    998    /**
    999     * Called when the entity is attacked.
    1000     */
    1001    public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    1002    {
    1003        if (ForgeHooks.onLivingAttack(this, par1DamageSource, par2))
    1004        {
    1005            return false;
    1006        }
    1007
    1008        if (this.isEntityInvulnerable())
    1009        {
    1010            return false;
    1011        }
    1012        else if (this.worldObj.isRemote)
    1013        {
    1014            return false;
    1015        }
    1016        else
    1017        {
    1018            this.entityAge = 0;
    1019
    1020            if (this.health <= 0)
    1021            {
    1022                return false;
    1023            }
    1024            else if (par1DamageSource.isFireDamage() && this.isPotionActive(Potion.fireResistance))
    1025            {
    1026                return false;
    1027            }
    1028            else
    1029            {
    1030                if ((par1DamageSource == DamageSource.anvil || par1DamageSource == DamageSource.fallingBlock) && this.getCurrentItemOrArmor(4) != null)
    1031                {
    1032                    this.getCurrentItemOrArmor(4).damageItem(par2 * 4 + this.rand.nextInt(par2 * 2), this);
    1033                    par2 = (int)((float)par2 * 0.75F);
    1034                }
    1035
    1036                this.limbYaw = 1.5F;
    1037                boolean flag = true;
    1038
    1039                if ((float)this.hurtResistantTime > (float)this.maxHurtResistantTime / 2.0F)
    1040                {
    1041                    if (par2 <= this.lastDamage)
    1042                    {
    1043                        return false;
    1044                    }
    1045
    1046                    this.damageEntity(par1DamageSource, par2 - this.lastDamage);
    1047                    this.lastDamage = par2;
    1048                    flag = false;
    1049                }
    1050                else
    1051                {
    1052                    this.lastDamage = par2;
    1053                    this.prevHealth = this.health;
    1054                    this.hurtResistantTime = this.maxHurtResistantTime;
    1055                    this.damageEntity(par1DamageSource, par2);
    1056                    this.hurtTime = this.maxHurtTime = 10;
    1057                }
    1058
    1059                this.attackedAtYaw = 0.0F;
    1060                Entity entity = par1DamageSource.getEntity();
    1061
    1062                if (entity != null)
    1063                {
    1064                    if (entity instanceof EntityLiving)
    1065                    {
    1066                        this.setRevengeTarget((EntityLiving)entity);
    1067                    }
    1068
    1069                    if (entity instanceof EntityPlayer)
    1070                    {
    1071                        this.recentlyHit = 100;
    1072                        this.attackingPlayer = (EntityPlayer)entity;
    1073                    }
    1074                    else if (entity instanceof EntityWolf)
    1075                    {
    1076                        EntityWolf entitywolf = (EntityWolf)entity;
    1077
    1078                        if (entitywolf.isTamed())
    1079                        {
    1080                            this.recentlyHit = 100;
    1081                            this.attackingPlayer = null;
    1082                        }
    1083                    }
    1084                }
    1085
    1086                if (flag)
    1087                {
    1088                    this.worldObj.setEntityState(this, (byte)2);
    1089
    1090                    if (par1DamageSource != DamageSource.drown)
    1091                    {
    1092                        this.setBeenAttacked();
    1093                    }
    1094
    1095                    if (entity != null)
    1096                    {
    1097                        double d0 = entity.posX - this.posX;
    1098                        double d1;
    1099
    1100                        for (d1 = entity.posZ - this.posZ; d0 * d0 + d1 * d1 < 1.0E-4D; d1 = (Math.random() - Math.random()) * 0.01D)
    1101                        {
    1102                            d0 = (Math.random() - Math.random()) * 0.01D;
    1103                        }
    1104
    1105                        this.attackedAtYaw = (float)(Math.atan2(d1, d0) * 180.0D / Math.PI) - this.rotationYaw;
    1106                        this.knockBack(entity, par2, d0, d1);
    1107                    }
    1108                    else
    1109                    {
    1110                        this.attackedAtYaw = (float)((int)(Math.random() * 2.0D) * 180);
    1111                    }
    1112                }
    1113
    1114                if (this.health <= 0)
    1115                {
    1116                    if (flag)
    1117                    {
    1118                        this.playSound(this.getDeathSound(), this.getSoundVolume(), this.getSoundPitch());
    1119                    }
    1120
    1121                    this.onDeath(par1DamageSource);
    1122                }
    1123                else if (flag)
    1124                {
    1125                    this.playSound(this.getHurtSound(), this.getSoundVolume(), this.getSoundPitch());
    1126                }
    1127
    1128                return true;
    1129            }
    1130        }
    1131    }
    1132
    1133    /**
    1134     * Gets the pitch of living sounds in living entities.
    1135     */
    1136    protected float getSoundPitch()
    1137    {
    1138        return this.isChild() ? (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.5F : (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F;
    1139    }
    1140
    1141    @SideOnly(Side.CLIENT)
    1142
    1143    /**
    1144     * Setups the entity to do the hurt animation. Only used by packets in multiplayer.
    1145     */
    1146    public void performHurtAnimation()
    1147    {
    1148        this.hurtTime = this.maxHurtTime = 10;
    1149        this.attackedAtYaw = 0.0F;
    1150    }
    1151
    1152    /**
    1153     * Returns the current armor value as determined by a call to InventoryPlayer.getTotalArmorValue
    1154     */
    1155    public int getTotalArmorValue()
    1156    {
    1157        int i = 0;
    1158        ItemStack[] aitemstack = this.getLastActiveItems();
    1159        int j = aitemstack.length;
    1160
    1161        for (int k = 0; k < j; ++k)
    1162        {
    1163            ItemStack itemstack = aitemstack[k];
    1164
    1165            if (itemstack != null && itemstack.getItem() instanceof ItemArmor)
    1166            {
    1167                int l = ((ItemArmor)itemstack.getItem()).damageReduceAmount;
    1168                i += l;
    1169            }
    1170        }
    1171
    1172        return i;
    1173    }
    1174
    1175    protected void damageArmor(int par1) {}
    1176
    1177    /**
    1178     * Reduces damage, depending on armor
    1179     */
    1180    protected int applyArmorCalculations(DamageSource par1DamageSource, int par2)
    1181    {
    1182        if (!par1DamageSource.isUnblockable())
    1183        {
    1184            int j = 25 - this.getTotalArmorValue();
    1185            int k = par2 * j + this.carryoverDamage;
    1186            this.damageArmor(par2);
    1187            par2 = k / 25;
    1188            this.carryoverDamage = k % 25;
    1189        }
    1190
    1191        return par2;
    1192    }
    1193
    1194    /**
    1195     * Reduces damage, depending on potions
    1196     */
    1197    protected int applyPotionDamageCalculations(DamageSource par1DamageSource, int par2)
    1198    {
    1199        int j;
    1200        int k;
    1201        int l;
    1202
    1203        if (this.isPotionActive(Potion.resistance))
    1204        {
    1205            j = (this.getActivePotionEffect(Potion.resistance).getAmplifier() + 1) * 5;
    1206            k = 25 - j;
    1207            l = par2 * k + this.carryoverDamage;
    1208            par2 = l / 25;
    1209            this.carryoverDamage = l % 25;
    1210        }
    1211
    1212        if (par2 <= 0)
    1213        {
    1214            return 0;
    1215        }
    1216        else
    1217        {
    1218            j = EnchantmentHelper.getEnchantmentModifierDamage(this.getLastActiveItems(), par1DamageSource);
    1219
    1220            if (j > 20)
    1221            {
    1222                j = 20;
    1223            }
    1224
    1225            if (j > 0 && j <= 20)
    1226            {
    1227                k = 25 - j;
    1228                l = par2 * k + this.carryoverDamage;
    1229                par2 = l / 25;
    1230                this.carryoverDamage = l % 25;
    1231            }
    1232
    1233            return par2;
    1234        }
    1235    }
    1236
    1237    /**
    1238     * Deals damage to the entity. If its a EntityPlayer then will take damage from the armor first and then health
    1239     * second with the reduced value. Args: damageAmount
    1240     */
    1241    protected void damageEntity(DamageSource par1DamageSource, int par2)
    1242    {
    1243        if (!this.isEntityInvulnerable())
    1244        {
    1245            par2 = ForgeHooks.onLivingHurt(this, par1DamageSource, par2);
    1246            if (par2 <= 0)
    1247            {
    1248                return;
    1249            }
    1250            par2 = this.applyArmorCalculations(par1DamageSource, par2);
    1251            par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
    1252            int j = this.getHealth();
    1253            this.health -= par2;
    1254            this.field_94063_bt.func_94547_a(par1DamageSource, j, par2);
    1255        }
    1256    }
    1257
    1258    /**
    1259     * Returns the volume for the sounds this mob makes.
    1260     */
    1261    protected float getSoundVolume()
    1262    {
    1263        return 1.0F;
    1264    }
    1265
    1266    /**
    1267     * Returns the sound this mob makes while it's alive.
    1268     */
    1269    protected String getLivingSound()
    1270    {
    1271        return null;
    1272    }
    1273
    1274    /**
    1275     * Returns the sound this mob makes when it is hurt.
    1276     */
    1277    protected String getHurtSound()
    1278    {
    1279        return "damage.hit";
    1280    }
    1281
    1282    /**
    1283     * Returns the sound this mob makes on death.
    1284     */
    1285    protected String getDeathSound()
    1286    {
    1287        return "damage.hit";
    1288    }
    1289
    1290    /**
    1291     * knocks back this entity
    1292     */
    1293    public void knockBack(Entity par1Entity, int par2, double par3, double par5)
    1294    {
    1295        this.isAirBorne = true;
    1296        float f = MathHelper.sqrt_double(par3 * par3 + par5 * par5);
    1297        float f1 = 0.4F;
    1298        this.motionX /= 2.0D;
    1299        this.motionY /= 2.0D;
    1300        this.motionZ /= 2.0D;
    1301        this.motionX -= par3 / (double)f * (double)f1;
    1302        this.motionY += (double)f1;
    1303        this.motionZ -= par5 / (double)f * (double)f1;
    1304
    1305        if (this.motionY > 0.4000000059604645D)
    1306        {
    1307            this.motionY = 0.4000000059604645D;
    1308        }
    1309    }
    1310
    1311    /**
    1312     * Called when the mob's health reaches 0.
    1313     */
    1314    public void onDeath(DamageSource par1DamageSource)
    1315    {
    1316        if (ForgeHooks.onLivingDeath(this, par1DamageSource))
    1317        {
    1318            return;
    1319        }
    1320
    1321        Entity entity = par1DamageSource.getEntity();
    1322        EntityLiving entityliving = this.func_94060_bK();
    1323
    1324        if (this.scoreValue >= 0 && entityliving != null)
    1325        {
    1326            entityliving.addToPlayerScore(this, this.scoreValue);
    1327        }
    1328
    1329        if (entity != null)
    1330        {
    1331            entity.onKillEntity(this);
    1332        }
    1333
    1334        this.dead = true;
    1335
    1336        if (!this.worldObj.isRemote)
    1337        {
    1338            int i = 0;
    1339
    1340            if (entity instanceof EntityPlayer)
    1341            {
    1342                i = EnchantmentHelper.getLootingModifier((EntityLiving)entity);
    1343            }
    1344
    1345            captureDrops = true;
    1346            capturedDrops.clear();
    1347            int j = 0;
    1348
    1349            if (!this.isChild() && this.worldObj.getGameRules().getGameRuleBooleanValue("doMobLoot"))
    1350            {
    1351                this.dropFewItems(this.recentlyHit > 0, i);
    1352                this.dropEquipment(this.recentlyHit > 0, i);
    1353
    1354                if (this.recentlyHit > 0)
    1355                {
    1356                    j = this.rand.nextInt(200) - i;
    1357
    1358                    if (j < 5)
    1359                    {
    1360                        this.dropRareDrop(j <= 0 ? 1 : 0);
    1361                    }
    1362                }
    1363            }
    1364
    1365            captureDrops = false;
    1366
    1367            if (!ForgeHooks.onLivingDrops(this, par1DamageSource, capturedDrops, i, recentlyHit > 0, j))
    1368            {
    1369                for (EntityItem item : capturedDrops)
    1370                {
    1371                    worldObj.spawnEntityInWorld(item);
    1372                }
    1373            }
    1374        }
    1375
    1376        this.worldObj.setEntityState(this, (byte)3);
    1377    }
    1378
    1379    protected void dropRareDrop(int par1) {}
    1380
    1381    /**
    1382     * Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param
    1383     * par2 - Level of Looting used to kill this mob.
    1384     */
    1385    protected void dropFewItems(boolean par1, int par2)
    1386    {
    1387        int j = this.getDropItemId();
    1388
    1389        if (j > 0)
    1390        {
    1391            int k = this.rand.nextInt(3);
    1392
    1393            if (par2 > 0)
    1394            {
    1395                k += this.rand.nextInt(par2 + 1);
    1396            }
    1397
    1398            for (int l = 0; l < k; ++l)
    1399            {
    1400                this.dropItem(j, 1);
    1401            }
    1402        }
    1403    }
    1404
    1405    /**
    1406     * Returns the item ID for the item the mob drops on death.
    1407     */
    1408    protected int getDropItemId()
    1409    {
    1410        return 0;
    1411    }
    1412
    1413    /**
    1414     * Called when the mob is falling. Calculates and applies fall damage.
    1415     */
    1416    protected void fall(float par1)
    1417    {
    1418        par1 = ForgeHooks.onLivingFall(this, par1);
    1419        if (par1 <= 0)
    1420        {
    1421            return;
    1422        }
    1423
    1424        super.fall(par1);
    1425        int i = MathHelper.ceiling_float_int(par1 - 3.0F);
    1426
    1427        if (i > 0)
    1428        {
    1429            if (i > 4)
    1430            {
    1431                this.playSound("damage.fallbig", 1.0F, 1.0F);
    1432            }
    1433            else
    1434            {
    1435                this.playSound("damage.fallsmall", 1.0F, 1.0F);
    1436            }
    1437
    1438            this.attackEntityFrom(DamageSource.fall, i);
    1439            int j = this.worldObj.getBlockId(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset), MathHelper.floor_double(this.posZ));
    1440
    1441            if (j > 0)
    1442            {
    1443                StepSound stepsound = Block.blocksList[j].stepSound;
    1444                this.playSound(stepsound.getStepSound(), stepsound.getVolume() * 0.5F, stepsound.getPitch() * 0.75F);
    1445            }
    1446        }
    1447    }
    1448
    1449    /**
    1450     * Moves the entity based on the specified heading.  Args: strafe, forward
    1451     */
    1452    public void moveEntityWithHeading(float par1, float par2)
    1453    {
    1454        double d0;
    1455
    1456        if (this.isInWater() && (!(this instanceof EntityPlayer) || !((EntityPlayer)this).capabilities.isFlying))
    1457        {
    1458            d0 = this.posY;
    1459            this.moveFlying(par1, par2, this.isAIEnabled() ? 0.04F : 0.02F);
    1460            this.moveEntity(this.motionX, this.motionY, this.motionZ);
    1461            this.motionX *= 0.800000011920929D;
    1462            this.motionY *= 0.800000011920929D;
    1463            this.motionZ *= 0.800000011920929D;
    1464            this.motionY -= 0.02D;
    1465
    1466            if (this.isCollidedHorizontally && this.isOffsetPositionInLiquid(this.motionX, this.motionY + 0.6000000238418579D - this.posY + d0, this.motionZ))
    1467            {
    1468                this.motionY = 0.30000001192092896D;
    1469            }
    1470        }
    1471        else if (this.handleLavaMovement() && (!(this instanceof EntityPlayer) || !((EntityPlayer)this).capabilities.isFlying))
    1472        {
    1473            d0 = this.posY;
    1474            this.moveFlying(par1, par2, 0.02F);
    1475            this.moveEntity(this.motionX, this.motionY, this.motionZ);
    1476            this.motionX *= 0.5D;
    1477            this.motionY *= 0.5D;
    1478            this.motionZ *= 0.5D;
    1479            this.motionY -= 0.02D;
    1480
    1481            if (this.isCollidedHorizontally && this.isOffsetPositionInLiquid(this.motionX, this.motionY + 0.6000000238418579D - this.posY + d0, this.motionZ))
    1482            {
    1483                this.motionY = 0.30000001192092896D;
    1484            }
    1485        }
    1486        else
    1487        {
    1488            float f2 = 0.91F;
    1489
    1490            if (this.onGround)
    1491            {
    1492                f2 = 0.54600006F;
    1493                int i = this.worldObj.getBlockId(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
    1494
    1495                if (i > 0)
    1496                {
    1497                    f2 = Block.blocksList[i].slipperiness * 0.91F;
    1498                }
    1499            }
    1500
    1501            float f3 = 0.16277136F / (f2 * f2 * f2);
    1502            float f4;
    1503
    1504            if (this.onGround)
    1505            {
    1506                if (this.isAIEnabled())
    1507                {
    1508                    f4 = this.getAIMoveSpeed();
    1509                }
    1510                else
    1511                {
    1512                    f4 = this.landMovementFactor;
    1513                }
    1514
    1515                f4 *= f3;
    1516            }
    1517            else
    1518            {
    1519                f4 = this.jumpMovementFactor;
    1520            }
    1521
    1522            this.moveFlying(par1, par2, f4);
    1523            f2 = 0.91F;
    1524
    1525            if (this.onGround)
    1526            {
    1527                f2 = 0.54600006F;
    1528                int j = this.worldObj.getBlockId(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
    1529
    1530                if (j > 0)
    1531                {
    1532                    f2 = Block.blocksList[j].slipperiness * 0.91F;
    1533                }
    1534            }
    1535
    1536            if (this.isOnLadder())
    1537            {
    1538                float f5 = 0.15F;
    1539
    1540                if (this.motionX < (double)(-f5))
    1541                {
    1542                    this.motionX = (double)(-f5);
    1543                }
    1544
    1545                if (this.motionX > (double)f5)
    1546                {
    1547                    this.motionX = (double)f5;
    1548                }
    1549
    1550                if (this.motionZ < (double)(-f5))
    1551                {
    1552                    this.motionZ = (double)(-f5);
    1553                }
    1554
    1555                if (this.motionZ > (double)f5)
    1556                {
    1557                    this.motionZ = (double)f5;
    1558                }
    1559
    1560                this.fallDistance = 0.0F;
    1561
    1562                if (this.motionY < -0.15D)
    1563                {
    1564                    this.motionY = -0.15D;
    1565                }
    1566
    1567                boolean flag = this.isSneaking() && this instanceof EntityPlayer;
    1568
    1569                if (flag && this.motionY < 0.0D)
    1570                {
    1571                    this.motionY = 0.0D;
    1572                }
    1573            }
    1574
    1575            this.moveEntity(this.motionX, this.motionY, this.motionZ);
    1576
    1577            if (this.isCollidedHorizontally && this.isOnLadder())
    1578            {
    1579                this.motionY = 0.2D;
    1580            }
    1581
    1582            if (this.worldObj.isRemote && (!this.worldObj.blockExists((int)this.posX, 0, (int)this.posZ) || !this.worldObj.getChunkFromBlockCoords((int)this.posX, (int)this.posZ).isChunkLoaded))
    1583            {
    1584                if (this.posY > 0.0D)
    1585                {
    1586                    this.motionY = -0.1D;
    1587                }
    1588                else
    1589                {
    1590                    this.motionY = 0.0D;
    1591                }
    1592            }
    1593            else
    1594            {
    1595                this.motionY -= 0.08D;
    1596            }
    1597
    1598            this.motionY *= 0.9800000190734863D;
    1599            this.motionX *= (double)f2;
    1600            this.motionZ *= (double)f2;
    1601        }
    1602
    1603        this.prevLimbYaw = this.limbYaw;
    1604        d0 = this.posX - this.prevPosX;
    1605        double d1 = this.posZ - this.prevPosZ;
    1606        float f6 = MathHelper.sqrt_double(d0 * d0 + d1 * d1) * 4.0F;
    1607
    1608        if (f6 > 1.0F)
    1609        {
    1610            f6 = 1.0F;
    1611        }
    1612
    1613        this.limbYaw += (f6 - this.limbYaw) * 0.4F;
    1614        this.limbSwing += this.limbYaw;
    1615    }
    1616
    1617    /**
    1618     * returns true if this entity is by a ladder, false otherwise
    1619     */
    1620    public boolean isOnLadder()
    1621    {
    1622        int i = MathHelper.floor_double(this.posX);
    1623        int j = MathHelper.floor_double(this.boundingBox.minY);
    1624        int k = MathHelper.floor_double(this.posZ);
    1625        int l = this.worldObj.getBlockId(i, j, k);
    1626        return ForgeHooks.isLivingOnLadder(Block.blocksList[l], worldObj, i, j, k);
    1627    }
    1628
    1629    /**
    1630     * (abstract) Protected helper method to write subclass entity data to NBT.
    1631     */
    1632    public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    1633    {
    1634        if (this.health < -32768)
    1635        {
    1636            this.health = -32768;
    1637        }
    1638
    1639        par1NBTTagCompound.setShort("Health", (short)this.health);
    1640        par1NBTTagCompound.setShort("HurtTime", (short)this.hurtTime);
    1641        par1NBTTagCompound.setShort("DeathTime", (short)this.deathTime);
    1642        par1NBTTagCompound.setShort("AttackTime", (short)this.attackTime);
    1643        par1NBTTagCompound.setBoolean("CanPickUpLoot", this.func_98052_bS());
    1644        par1NBTTagCompound.setBoolean("PersistenceRequired", this.persistenceRequired);
    1645        NBTTagList nbttaglist = new NBTTagList();
    1646
    1647        for (int i = 0; i < this.equipment.length; ++i)
    1648        {
    1649            NBTTagCompound nbttagcompound1 = new NBTTagCompound();
    1650
    1651            if (this.equipment[i] != null)
    1652            {
    1653                this.equipment[i].writeToNBT(nbttagcompound1);
    1654            }
    1655
    1656            nbttaglist.appendTag(nbttagcompound1);
    1657        }
    1658
    1659        par1NBTTagCompound.setTag("Equipment", nbttaglist);
    1660        NBTTagList nbttaglist1;
    1661
    1662        if (!this.activePotionsMap.isEmpty())
    1663        {
    1664            nbttaglist1 = new NBTTagList();
    1665            Iterator iterator = this.activePotionsMap.values().iterator();
    1666
    1667            while (iterator.hasNext())
    1668            {
    1669                PotionEffect potioneffect = (PotionEffect)iterator.next();
    1670                nbttaglist1.appendTag(potioneffect.writeCustomPotionEffectToNBT(new NBTTagCompound()));
    1671            }
    1672
    1673            par1NBTTagCompound.setTag("ActiveEffects", nbttaglist1);
    1674        }
    1675
    1676        nbttaglist1 = new NBTTagList();
    1677
    1678        for (int j = 0; j < this.equipmentDropChances.length; ++j)
    1679        {
    1680            nbttaglist1.appendTag(new NBTTagFloat(j + "", this.equipmentDropChances[j]));
    1681        }
    1682
    1683        par1NBTTagCompound.setTag("DropChances", nbttaglist1);
    1684        par1NBTTagCompound.setString("CustomName", this.func_94057_bL());
    1685        par1NBTTagCompound.setBoolean("CustomNameVisible", this.func_94062_bN());
    1686    }
    1687
    1688    /**
    1689     * (abstract) Protected helper method to read subclass entity data from NBT.
    1690     */
    1691    public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    1692    {
    1693        this.health = par1NBTTagCompound.getShort("Health");
    1694
    1695        if (!par1NBTTagCompound.hasKey("Health"))
    1696        {
    1697            this.health = this.getMaxHealth();
    1698        }
    1699
    1700        this.hurtTime = par1NBTTagCompound.getShort("HurtTime");
    1701        this.deathTime = par1NBTTagCompound.getShort("DeathTime");
    1702        this.attackTime = par1NBTTagCompound.getShort("AttackTime");
    1703        this.func_98053_h(par1NBTTagCompound.getBoolean("CanPickUpLoot"));
    1704        this.persistenceRequired = par1NBTTagCompound.getBoolean("PersistenceRequired");
    1705
    1706        if (par1NBTTagCompound.hasKey("CustomName") && par1NBTTagCompound.getString("CustomName").length() > 0)
    1707        {
    1708            this.func_94058_c(par1NBTTagCompound.getString("CustomName"));
    1709        }
    1710
    1711        this.func_94061_f(par1NBTTagCompound.getBoolean("CustomNameVisible"));
    1712        NBTTagList nbttaglist;
    1713        int i;
    1714
    1715        if (par1NBTTagCompound.hasKey("Equipment"))
    1716        {
    1717            nbttaglist = par1NBTTagCompound.getTagList("Equipment");
    1718
    1719            for (i = 0; i < this.equipment.length; ++i)
    1720            {
    1721                this.equipment[i] = ItemStack.loadItemStackFromNBT((NBTTagCompound)nbttaglist.tagAt(i));
    1722            }
    1723        }
    1724
    1725        if (par1NBTTagCompound.hasKey("ActiveEffects"))
    1726        {
    1727            nbttaglist = par1NBTTagCompound.getTagList("ActiveEffects");
    1728
    1729            for (i = 0; i < nbttaglist.tagCount(); ++i)
    1730            {
    1731                NBTTagCompound nbttagcompound1 = (NBTTagCompound)nbttaglist.tagAt(i);
    1732                PotionEffect potioneffect = PotionEffect.readCustomPotionEffectFromNBT(nbttagcompound1);
    1733                this.activePotionsMap.put(Integer.valueOf(potioneffect.getPotionID()), potioneffect);
    1734            }
    1735        }
    1736
    1737        if (par1NBTTagCompound.hasKey("DropChances"))
    1738        {
    1739            nbttaglist = par1NBTTagCompound.getTagList("DropChances");
    1740
    1741            for (i = 0; i < nbttaglist.tagCount(); ++i)
    1742            {
    1743                this.equipmentDropChances[i] = ((NBTTagFloat)nbttaglist.tagAt(i)).data;
    1744            }
    1745        }
    1746    }
    1747
    1748    /**
    1749     * Checks whether target entity is alive.
    1750     */
    1751    public boolean isEntityAlive()
    1752    {
    1753        return !this.isDead && this.health > 0;
    1754    }
    1755
    1756    public boolean canBreatheUnderwater()
    1757    {
    1758        return false;
    1759    }
    1760
    1761    public void setMoveForward(float par1)
    1762    {
    1763        this.moveForward = par1;
    1764    }
    1765
    1766    public void setJumping(boolean par1)
    1767    {
    1768        this.isJumping = par1;
    1769    }
    1770
    1771    /**
    1772     * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
    1773     * use this to react to sunlight and start to burn.
    1774     */
    1775    public void onLivingUpdate()
    1776    {
    1777        if (this.jumpTicks > 0)
    1778        {
    1779            --this.jumpTicks;
    1780        }
    1781
    1782        if (this.newPosRotationIncrements > 0)
    1783        {
    1784            double d0 = this.posX + (this.newPosX - this.posX) / (double)this.newPosRotationIncrements;
    1785            double d1 = this.posY + (this.newPosY - this.posY) / (double)this.newPosRotationIncrements;
    1786            double d2 = this.posZ + (this.newPosZ - this.posZ) / (double)this.newPosRotationIncrements;
    1787            double d3 = MathHelper.wrapAngleTo180_double(this.newRotationYaw - (double)this.rotationYaw);
    1788            this.rotationYaw = (float)((double)this.rotationYaw + d3 / (double)this.newPosRotationIncrements);
    1789            this.rotationPitch = (float)((double)this.rotationPitch + (this.newRotationPitch - (double)this.rotationPitch) / (double)this.newPosRotationIncrements);
    1790            --this.newPosRotationIncrements;
    1791            this.setPosition(d0, d1, d2);
    1792            this.setRotation(this.rotationYaw, this.rotationPitch);
    1793        }
    1794        else if (!this.isClientWorld())
    1795        {
    1796            this.motionX *= 0.98D;
    1797            this.motionY *= 0.98D;
    1798            this.motionZ *= 0.98D;
    1799        }
    1800
    1801        if (Math.abs(this.motionX) < 0.005D)
    1802        {
    1803            this.motionX = 0.0D;
    1804        }
    1805
    1806        if (Math.abs(this.motionY) < 0.005D)
    1807        {
    1808            this.motionY = 0.0D;
    1809        }
    1810
    1811        if (Math.abs(this.motionZ) < 0.005D)
    1812        {
    1813            this.motionZ = 0.0D;
    1814        }
    1815
    1816        this.worldObj.theProfiler.startSection("ai");
    1817
    1818        if (this.isMovementBlocked())
    1819        {
    1820            this.isJumping = false;
    1821            this.moveStrafing = 0.0F;
    1822            this.moveForward = 0.0F;
    1823            this.randomYawVelocity = 0.0F;
    1824        }
    1825        else if (this.isClientWorld())
    1826        {
    1827            if (this.isAIEnabled())
    1828            {
    1829                this.worldObj.theProfiler.startSection("newAi");
    1830                this.updateAITasks();
    1831                this.worldObj.theProfiler.endSection();
    1832            }
    1833            else
    1834            {
    1835                this.worldObj.theProfiler.startSection("oldAi");
    1836                this.updateEntityActionState();
    1837                this.worldObj.theProfiler.endSection();
    1838                this.rotationYawHead = this.rotationYaw;
    1839            }
    1840        }
    1841
    1842        this.worldObj.theProfiler.endSection();
    1843        this.worldObj.theProfiler.startSection("jump");
    1844
    1845        if (this.isJumping)
    1846        {
    1847            if (!this.isInWater() && !this.handleLavaMovement())
    1848            {
    1849                if (this.onGround && this.jumpTicks == 0)
    1850                {
    1851                    this.jump();
    1852                    this.jumpTicks = 10;
    1853                }
    1854            }
    1855            else
    1856            {
    1857                this.motionY += 0.03999999910593033D;
    1858            }
    1859        }
    1860        else
    1861        {
    1862            this.jumpTicks = 0;
    1863        }
    1864
    1865        this.worldObj.theProfiler.endSection();
    1866        this.worldObj.theProfiler.startSection("travel");
    1867        this.moveStrafing *= 0.98F;
    1868        this.moveForward *= 0.98F;
    1869        this.randomYawVelocity *= 0.9F;
    1870        float f = this.landMovementFactor;
    1871        this.landMovementFactor *= this.getSpeedModifier();
    1872        this.moveEntityWithHeading(this.moveStrafing, this.moveForward);
    1873        this.landMovementFactor = f;
    1874        this.worldObj.theProfiler.endSection();
    1875        this.worldObj.theProfiler.startSection("push");
    1876
    1877        if (!this.worldObj.isRemote)
    1878        {
    1879            this.func_85033_bc();
    1880        }
    1881
    1882        this.worldObj.theProfiler.endSection();
    1883        this.worldObj.theProfiler.startSection("looting");
    1884
    1885        if (!this.worldObj.isRemote && this.func_98052_bS() && !this.dead && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"))
    1886        {
    1887            List list = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(1.0D, 0.0D, 1.0D));
    1888            Iterator iterator = list.iterator();
    1889
    1890            while (iterator.hasNext())
    1891            {
    1892                EntityItem entityitem = (EntityItem)iterator.next();
    1893
    1894                if (!entityitem.isDead && entityitem.getEntityItem() != null)
    1895                {
    1896                    ItemStack itemstack = entityitem.getEntityItem();
    1897                    int i = func_82159_b(itemstack);
    1898
    1899                    if (i > -1)
    1900                    {
    1901                        boolean flag = true;
    1902                        ItemStack itemstack1 = this.getCurrentItemOrArmor(i);
    1903
    1904                        if (itemstack1 != null)
    1905                        {
    1906                            if (i == 0)
    1907                            {
    1908                                if (itemstack.getItem() instanceof ItemSword && !(itemstack1.getItem() instanceof ItemSword))
    1909                                {
    1910                                    flag = true;
    1911                                }
    1912                                else if (itemstack.getItem() instanceof ItemSword && itemstack1.getItem() instanceof ItemSword)
    1913                                {
    1914                                    ItemSword itemsword = (ItemSword)itemstack.getItem();
    1915                                    ItemSword itemsword1 = (ItemSword)itemstack1.getItem();
    1916
    1917                                    if (itemsword.func_82803_g() == itemsword1.func_82803_g())
    1918                                    {
    1919                                        flag = itemstack.getItemDamage() > itemstack1.getItemDamage() || itemstack.hasTagCompound() && !itemstack1.hasTagCompound();
    1920                                    }
    1921                                    else
    1922                                    {
    1923                                        flag = itemsword.func_82803_g() > itemsword1.func_82803_g();
    1924                                    }
    1925                                }
    1926                                else
    1927                                {
    1928                                    flag = false;
    1929                                }
    1930                            }
    1931                            else if (itemstack.getItem() instanceof ItemArmor && !(itemstack1.getItem() instanceof ItemArmor))
    1932                            {
    1933                                flag = true;
    1934                            }
    1935                            else if (itemstack.getItem() instanceof ItemArmor && itemstack1.getItem() instanceof ItemArmor)
    1936                            {
    1937                                ItemArmor itemarmor = (ItemArmor)itemstack.getItem();
    1938                                ItemArmor itemarmor1 = (ItemArmor)itemstack1.getItem();
    1939
    1940                                if (itemarmor.damageReduceAmount == itemarmor1.damageReduceAmount)
    1941                                {
    1942                                    flag = itemstack.getItemDamage() > itemstack1.getItemDamage() || itemstack.hasTagCompound() && !itemstack1.hasTagCompound();
    1943                                }
    1944                                else
    1945                                {
    1946                                    flag = itemarmor.damageReduceAmount > itemarmor1.damageReduceAmount;
    1947                                }
    1948                            }
    1949                            else
    1950                            {
    1951                                flag = false;
    1952                            }
    1953                        }
    1954
    1955                        if (flag)
    1956                        {
    1957                            if (itemstack1 != null && this.rand.nextFloat() - 0.1F < this.equipmentDropChances[i])
    1958                            {
    1959                                this.entityDropItem(itemstack1, 0.0F);
    1960                            }
    1961
    1962                            this.setCurrentItemOrArmor(i, itemstack);
    1963                            this.equipmentDropChances[i] = 2.0F;
    1964                            this.persistenceRequired = true;
    1965                            this.onItemPickup(entityitem, 1);
    1966                            entityitem.setDead();
    1967                        }
    1968                    }
    1969                }
    1970            }
    1971        }
    1972
    1973        this.worldObj.theProfiler.endSection();
    1974    }
    1975
    1976    protected void func_85033_bc()
    1977    {
    1978        List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
    1979
    1980        if (list != null && !list.isEmpty())
    1981        {
    1982            for (int i = 0; i < list.size(); ++i)
    1983            {
    1984                Entity entity = (Entity)list.get(i);
    1985
    1986                if (entity.canBePushed())
    1987                {
    1988                    this.collideWithEntity(entity);
    1989                }
    1990            }
    1991        }
    1992    }
    1993
    1994    protected void collideWithEntity(Entity par1Entity)
    1995    {
    1996        par1Entity.applyEntityCollision(this);
    1997    }
    1998
    1999    /**
    2000     * Returns true if the newer Entity AI code should be run
    2001     */
    2002    protected boolean isAIEnabled()
    2003    {
    2004        return false;
    2005    }
    2006
    2007    /**
    2008     * Returns whether the entity is in a local (client) world
    2009     */
    2010    protected boolean isClientWorld()
    2011    {
    2012        return !this.worldObj.isRemote;
    2013    }
    2014
    2015    /**
    2016     * Dead and sleeping entities cannot move
    2017     */
    2018    protected boolean isMovementBlocked()
    2019    {
    2020        return this.health <= 0;
    2021    }
    2022
    2023    public boolean isBlocking()
    2024    {
    2025        return false;
    2026    }
    2027
    2028    /**
    2029     * Causes this entity to do an upwards motion (jumping).
    2030     */
    2031    protected void jump()
    2032    {
    2033        this.motionY = 0.41999998688697815D;
    2034
    2035        if (this.isPotionActive(Potion.jump))
    2036        {
    2037            this.motionY += (double)((float)(this.getActivePotionEffect(Potion.jump).getAmplifier() + 1) * 0.1F);
    2038        }
    2039
    2040        if (this.isSprinting())
    2041        {
    2042            float f = this.rotationYaw * 0.017453292F;
    2043            this.motionX -= (double)(MathHelper.sin(f) * 0.2F);
    2044            this.motionZ += (double)(MathHelper.cos(f) * 0.2F);
    2045        }
    2046
    2047        this.isAirBorne = true;
    2048        ForgeHooks.onLivingJump(this);
    2049    }
    2050
    2051    /**
    2052     * Determines if an entity can be despawned, used on idle far away entities
    2053     */
    2054    protected boolean canDespawn()
    2055    {
    2056        return true;
    2057    }
    2058
    2059    /**
    2060     * Makes the entity despawn if requirements are reached
    2061     */
    2062    protected void despawnEntity()
    2063    {
    2064        if (!this.persistenceRequired)
    2065        {
    2066            EntityPlayer entityplayer = this.worldObj.getClosestPlayerToEntity(this, -1.0D);
    2067
    2068            if (entityplayer != null)
    2069            {
    2070                double d0 = entityplayer.posX - this.posX;
    2071                double d1 = entityplayer.posY - this.posY;
    2072                double d2 = entityplayer.posZ - this.posZ;
    2073                double d3 = d0 * d0 + d1 * d1 + d2 * d2;
    2074
    2075                if (this.canDespawn() && d3 > 16384.0D)
    2076                {
    2077                    this.setDead();
    2078                }
    2079
    2080                if (this.entityAge > 600 && this.rand.nextInt(800) == 0 && d3 > 1024.0D && this.canDespawn())
    2081                {
    2082                    this.setDead();
    2083                }
    2084                else if (d3 < 1024.0D)
    2085                {
    2086                    this.entityAge = 0;
    2087                }
    2088            }
    2089        }
    2090    }
    2091
    2092    protected void updateAITasks()
    2093    {
    2094        ++this.entityAge;
    2095        this.worldObj.theProfiler.startSection("checkDespawn");
    2096        this.despawnEntity();
    2097        this.worldObj.theProfiler.endSection();
    2098        this.worldObj.theProfiler.startSection("sensing");
    2099        this.senses.clearSensingCache();
    2100        this.worldObj.theProfiler.endSection();
    2101        this.worldObj.theProfiler.startSection("targetSelector");
    2102        this.targetTasks.onUpdateTasks();
    2103        this.worldObj.theProfiler.endSection();
    2104        this.worldObj.theProfiler.startSection("goalSelector");
    2105        this.tasks.onUpdateTasks();
    2106        this.worldObj.theProfiler.endSection();
    2107        this.worldObj.theProfiler.startSection("navigation");
    2108        this.navigator.onUpdateNavigation();
    2109        this.worldObj.theProfiler.endSection();
    2110        this.worldObj.theProfiler.startSection("mob tick");
    2111        this.updateAITick();
    2112        this.worldObj.theProfiler.endSection();
    2113        this.worldObj.theProfiler.startSection("controls");
    2114        this.worldObj.theProfiler.startSection("move");
    2115        this.moveHelper.onUpdateMoveHelper();
    2116        this.worldObj.theProfiler.endStartSection("look");
    2117        this.lookHelper.onUpdateLook();
    2118        this.worldObj.theProfiler.endStartSection("jump");
    2119        this.jumpHelper.doJump();
    2120        this.worldObj.theProfiler.endSection();
    2121        this.worldObj.theProfiler.endSection();
    2122    }
    2123
    2124    /**
    2125     * main AI tick function, replaces updateEntityActionState
    2126     */
    2127    protected void updateAITick() {}
    2128
    2129    protected void updateEntityActionState()
    2130    {
    2131        ++this.entityAge;
    2132        this.despawnEntity();
    2133        this.moveStrafing = 0.0F;
    2134        this.moveForward = 0.0F;
    2135        float f = 8.0F;
    2136
    2137        if (this.rand.nextFloat() < 0.02F)
    2138        {
    2139            EntityPlayer entityplayer = this.worldObj.getClosestPlayerToEntity(this, (double)f);
    2140
    2141            if (entityplayer != null)
    2142            {
    2143                this.currentTarget = entityplayer;
    2144                this.numTicksToChaseTarget = 10 + this.rand.nextInt(20);
    2145            }
    2146            else
    2147            {
    2148                this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F;
    2149            }
    2150        }
    2151
    2152        if (this.currentTarget != null)
    2153        {
    2154            this.faceEntity(this.currentTarget, 10.0F, (float)this.getVerticalFaceSpeed());
    2155
    2156            if (this.numTicksToChaseTarget-- <= 0 || this.currentTarget.isDead || this.currentTarget.getDistanceSqToEntity(this) > (double)(f * f))
    2157            {
    2158                this.currentTarget = null;
    2159            }
    2160        }
    2161        else
    2162        {
    2163            if (this.rand.nextFloat() < 0.05F)
    2164            {
    2165                this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F;
    2166            }
    2167
    2168            this.rotationYaw += this.randomYawVelocity;
    2169            this.rotationPitch = this.defaultPitch;
    2170        }
    2171
    2172        boolean flag = this.isInWater();
    2173        boolean flag1 = this.handleLavaMovement();
    2174
    2175        if (flag || flag1)
    2176        {
    2177            this.isJumping = this.rand.nextFloat() < 0.8F;
    2178        }
    2179    }
    2180
    2181    /**
    2182     * Updates the arm swing progress counters and animation progress
    2183     */
    2184    protected void updateArmSwingProgress()
    2185    {
    2186        int i = this.getArmSwingAnimationEnd();
    2187
    2188        if (this.isSwingInProgress)
    2189        {
    2190            ++this.swingProgressInt;
    2191
    2192            if (this.swingProgressInt >= i)
    2193            {
    2194                this.swingProgressInt = 0;
    2195                this.isSwingInProgress = false;
    2196            }
    2197        }
    2198        else
    2199        {
    2200            this.swingProgressInt = 0;
    2201        }
    2202
    2203        this.swingProgress = (float)this.swingProgressInt / (float)i;
    2204    }
    2205
    2206    /**
    2207     * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
    2208     * use in wolves.
    2209     */
    2210    public int getVerticalFaceSpeed()
    2211    {
    2212        return 40;
    2213    }
    2214
    2215    /**
    2216     * Changes pitch and yaw so that the entity calling the function is facing the entity provided as an argument.
    2217     */
    2218    public void faceEntity(Entity par1Entity, float par2, float par3)
    2219    {
    2220        double d0 = par1Entity.posX - this.posX;
    2221        double d1 = par1Entity.posZ - this.posZ;
    2222        double d2;
    2223
    2224        if (par1Entity instanceof EntityLiving)
    2225        {
    2226            EntityLiving entityliving = (EntityLiving)par1Entity;
    2227            d2 = entityliving.posY + (double)entityliving.getEyeHeight() - (this.posY + (double)this.getEyeHeight());
    2228        }
    2229        else
    2230        {
    2231            d2 = (par1Entity.boundingBox.minY + par1Entity.boundingBox.maxY) / 2.0D - (this.posY + (double)this.getEyeHeight());
    2232        }
    2233
    2234        double d3 = (double)MathHelper.sqrt_double(d0 * d0 + d1 * d1);
    2235        float f2 = (float)(Math.atan2(d1, d0) * 180.0D / Math.PI) - 90.0F;
    2236        float f3 = (float)(-(Math.atan2(d2, d3) * 180.0D / Math.PI));
    2237        this.rotationPitch = this.updateRotation(this.rotationPitch, f3, par3);
    2238        this.rotationYaw = this.updateRotation(this.rotationYaw, f2, par2);
    2239    }
    2240
    2241    /**
    2242     * Arguments: current rotation, intended rotation, max increment.
    2243     */
    2244    private float updateRotation(float par1, float par2, float par3)
    2245    {
    2246        float f3 = MathHelper.wrapAngleTo180_float(par2 - par1);
    2247
    2248        if (f3 > par3)
    2249        {
    2250            f3 = par3;
    2251        }
    2252
    2253        if (f3 < -par3)
    2254        {
    2255            f3 = -par3;
    2256        }
    2257
    2258        return par1 + f3;
    2259    }
    2260
    2261    /**
    2262     * Checks if the entity's current position is a valid location to spawn this entity.
    2263     */
    2264    public boolean getCanSpawnHere()
    2265    {
    2266        return this.worldObj.checkIfAABBIsClear(this.boundingBox) && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox);
    2267    }
    2268
    2269    /**
    2270     * sets the dead flag. Used when you fall off the bottom of the world.
    2271     */
    2272    protected void kill()
    2273    {
    2274        this.attackEntityFrom(DamageSource.outOfWorld, 4);
    2275    }
    2276
    2277    @SideOnly(Side.CLIENT)
    2278
    2279    /**
    2280     * Returns where in the swing animation the living entity is (from 0 to 1).  Args: partialTickTime
    2281     */
    2282    public float getSwingProgress(float par1)
    2283    {
    2284        float f1 = this.swingProgress - this.prevSwingProgress;
    2285
    2286        if (f1 < 0.0F)
    2287        {
    2288            ++f1;
    2289        }
    2290
    2291        return this.prevSwingProgress + f1 * par1;
    2292    }
    2293
    2294    @SideOnly(Side.CLIENT)
    2295
    2296    /**
    2297     * interpolated position vector
    2298     */
    2299    public Vec3 getPosition(float par1)
    2300    {
    2301        if (par1 == 1.0F)
    2302        {
    2303            return this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
    2304        }
    2305        else
    2306        {
    2307            double d0 = this.prevPosX + (this.posX - this.prevPosX) * (double)par1;
    2308            double d1 = this.prevPosY + (this.posY - this.prevPosY) * (double)par1;
    2309            double d2 = this.prevPosZ + (this.posZ - this.prevPosZ) * (double)par1;
    2310            return this.worldObj.getWorldVec3Pool().getVecFromPool(d0, d1, d2);
    2311        }
    2312    }
    2313
    2314    /**
    2315     * returns a (normalized) vector of where this entity is looking
    2316     */
    2317    public Vec3 getLookVec()
    2318    {
    2319        return this.getLook(1.0F);
    2320    }
    2321
    2322    /**
    2323     * interpolated look vector
    2324     */
    2325    public Vec3 getLook(float par1)
    2326    {
    2327        float f1;
    2328        float f2;
    2329        float f3;
    2330        float f4;
    2331
    2332        if (par1 == 1.0F)
    2333        {
    2334            f1 = MathHelper.cos(-this.rotationYaw * 0.017453292F - (float)Math.PI);
    2335            f2 = MathHelper.sin(-this.rotationYaw * 0.017453292F - (float)Math.PI);
    2336            f3 = -MathHelper.cos(-this.rotationPitch * 0.017453292F);
    2337            f4 = MathHelper.sin(-this.rotationPitch * 0.017453292F);
    2338            return this.worldObj.getWorldVec3Pool().getVecFromPool((double)(f2 * f3), (double)f4, (double)(f1 * f3));
    2339        }
    2340        else
    2341        {
    2342            f1 = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * par1;
    2343            f2 = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * par1;
    2344            f3 = MathHelper.cos(-f2 * 0.017453292F - (float)Math.PI);
    2345            f4 = MathHelper.sin(-f2 * 0.017453292F - (float)Math.PI);
    2346            float f5 = -MathHelper.cos(-f1 * 0.017453292F);
    2347            float f6 = MathHelper.sin(-f1 * 0.017453292F);
    2348            return this.worldObj.getWorldVec3Pool().getVecFromPool((double)(f4 * f5), (double)f6, (double)(f3 * f5));
    2349        }
    2350    }
    2351
    2352    @SideOnly(Side.CLIENT)
    2353
    2354    /**
    2355     * Returns render size modifier
    2356     */
    2357    public float getRenderSizeModifier()
    2358    {
    2359        return 1.0F;
    2360    }
    2361
    2362    @SideOnly(Side.CLIENT)
    2363
    2364    /**
    2365     * Performs a ray trace for the distance specified and using the partial tick time. Args: distance, partialTickTime
    2366     */
    2367    public MovingObjectPosition rayTrace(double par1, float par3)
    2368    {
    2369        Vec3 vec3 = this.getPosition(par3);
    2370        Vec3 vec31 = this.getLook(par3);
    2371        Vec3 vec32 = vec3.addVector(vec31.xCoord * par1, vec31.yCoord * par1, vec31.zCoord * par1);
    2372        return this.worldObj.rayTraceBlocks(vec3, vec32);
    2373    }
    2374
    2375    /**
    2376     * Will return how many at most can spawn in a chunk at once.
    2377     */
    2378    public int getMaxSpawnedInChunk()
    2379    {
    2380        return 4;
    2381    }
    2382
    2383    @SideOnly(Side.CLIENT)
    2384    public void handleHealthUpdate(byte par1)
    2385    {
    2386        if (par1 == 2)
    2387        {
    2388            this.limbYaw = 1.5F;
    2389            this.hurtResistantTime = this.maxHurtResistantTime;
    2390            this.hurtTime = this.maxHurtTime = 10;
    2391            this.attackedAtYaw = 0.0F;
    2392            this.playSound(this.getHurtSound(), this.getSoundVolume(), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
    2393            this.attackEntityFrom(DamageSource.generic, 0);
    2394        }
    2395        else if (par1 == 3)
    2396        {
    2397            this.playSound(this.getDeathSound(), this.getSoundVolume(), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
    2398            this.health = 0;
    2399            this.onDeath(DamageSource.generic);
    2400        }
    2401        else
    2402        {
    2403            super.handleHealthUpdate(par1);
    2404        }
    2405    }
    2406
    2407    /**
    2408     * Returns whether player is sleeping or not
    2409     */
    2410    public boolean isPlayerSleeping()
    2411    {
    2412        return false;
    2413    }
    2414
    2415    @SideOnly(Side.CLIENT)
    2416
    2417    /**
    2418     * Gets the Icon Index of the item currently held
    2419     */
    2420    public Icon getItemIcon(ItemStack par1ItemStack, int par2)
    2421    {
    2422        return par1ItemStack.getIconIndex();
    2423    }
    2424
    2425    protected void updatePotionEffects()
    2426    {
    2427        Iterator iterator = this.activePotionsMap.keySet().iterator();
    2428
    2429        while (iterator.hasNext())
    2430        {
    2431            Integer integer = (Integer)iterator.next();
    2432            PotionEffect potioneffect = (PotionEffect)this.activePotionsMap.get(integer);
    2433
    2434            if (!potioneffect.onUpdate(this))
    2435            {
    2436                if (!this.worldObj.isRemote)
    2437                {
    2438                    iterator.remove();
    2439                    this.onFinishedPotionEffect(potioneffect);
    2440                }
    2441            }
    2442            else if (potioneffect.getDuration() % 600 == 0)
    2443            {
    2444                this.onChangedPotionEffect(potioneffect);
    2445            }
    2446        }
    2447
    2448        int i;
    2449
    2450        if (this.potionsNeedUpdate)
    2451        {
    2452            if (!this.worldObj.isRemote)
    2453            {
    2454                if (this.activePotionsMap.isEmpty())
    2455                {
    2456                    this.dataWatcher.updateObject(9, Byte.valueOf((byte)0));
    2457                    this.dataWatcher.updateObject(8, Integer.valueOf(0));
    2458                    this.setHasActivePotion(false);
    2459                }
    2460                else
    2461                {
    2462                    i = PotionHelper.calcPotionLiquidColor(this.activePotionsMap.values());
    2463                    this.dataWatcher.updateObject(9, Byte.valueOf((byte)(PotionHelper.func_82817_b(this.activePotionsMap.values()) ? 1 : 0)));
    2464                    this.dataWatcher.updateObject(8, Integer.valueOf(i));
    2465                    this.setHasActivePotion(this.isPotionActive(Potion.invisibility.id));
    2466                }
    2467            }
    2468
    2469            this.potionsNeedUpdate = false;
    2470        }
    2471
    2472        i = this.dataWatcher.getWatchableObjectInt(8);
    2473        boolean flag = this.dataWatcher.getWatchableObjectByte(9) > 0;
    2474
    2475        if (i > 0)
    2476        {
    2477            boolean flag1 = false;
    2478
    2479            if (!this.getHasActivePotion())
    2480            {
    2481                flag1 = this.rand.nextBoolean();
    2482            }
    2483            else
    2484            {
    2485                flag1 = this.rand.nextInt(15) == 0;
    2486            }
    2487
    2488            if (flag)
    2489            {
    2490                flag1 &= this.rand.nextInt(5) == 0;
    2491            }
    2492
    2493            if (flag1 && i > 0)
    2494            {
    2495                double d0 = (double)(i >> 16 & 255) / 255.0D;
    2496                double d1 = (double)(i >> 8 & 255) / 255.0D;
    2497                double d2 = (double)(i >> 0 & 255) / 255.0D;
    2498                this.worldObj.spawnParticle(flag ? "mobSpellAmbient" : "mobSpell", this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height - (double)this.yOffset, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, d0, d1, d2);
    2499            }
    2500        }
    2501    }
    2502
    2503    public void clearActivePotions()
    2504    {
    2505        Iterator iterator = this.activePotionsMap.keySet().iterator();
    2506
    2507        while (iterator.hasNext())
    2508        {
    2509            Integer integer = (Integer)iterator.next();
    2510            PotionEffect potioneffect = (PotionEffect)this.activePotionsMap.get(integer);
    2511
    2512            if (!this.worldObj.isRemote)
    2513            {
    2514                iterator.remove();
    2515                this.onFinishedPotionEffect(potioneffect);
    2516            }
    2517        }
    2518    }
    2519
    2520    public Collection getActivePotionEffects()
    2521    {
    2522        return this.activePotionsMap.values();
    2523    }
    2524
    2525    public boolean isPotionActive(int par1)
    2526    {
    2527        return this.activePotionsMap.containsKey(Integer.valueOf(par1));
    2528    }
    2529
    2530    public boolean isPotionActive(Potion par1Potion)
    2531    {
    2532        return this.activePotionsMap.containsKey(Integer.valueOf(par1Potion.id));
    2533    }
    2534
    2535    /**
    2536     * returns the PotionEffect for the supplied Potion if it is active, null otherwise.
    2537     */
    2538    public PotionEffect getActivePotionEffect(Potion par1Potion)
    2539    {
    2540        return (PotionEffect)this.activePotionsMap.get(Integer.valueOf(par1Potion.id));
    2541    }
    2542
    2543    /**
    2544     * adds a PotionEffect to the entity
    2545     */
    2546    public void addPotionEffect(PotionEffect par1PotionEffect)
    2547    {
    2548        if (this.isPotionApplicable(par1PotionEffect))
    2549        {
    2550            if (this.activePotionsMap.containsKey(Integer.valueOf(par1PotionEffect.getPotionID())))
    2551            {
    2552                ((PotionEffect)this.activePotionsMap.get(Integer.valueOf(par1PotionEffect.getPotionID()))).combine(par1PotionEffect);
    2553                this.onChangedPotionEffect((PotionEffect)this.activePotionsMap.get(Integer.valueOf(par1PotionEffect.getPotionID())));
    2554            }
    2555            else
    2556            {
    2557                this.activePotionsMap.put(Integer.valueOf(par1PotionEffect.getPotionID()), par1PotionEffect);
    2558                this.onNewPotionEffect(par1PotionEffect);
    2559            }
    2560        }
    2561    }
    2562
    2563    public boolean isPotionApplicable(PotionEffect par1PotionEffect)
    2564    {
    2565        if (this.getCreatureAttribute() == EnumCreatureAttribute.UNDEAD)
    2566        {
    2567            int i = par1PotionEffect.getPotionID();
    2568
    2569            if (i == Potion.regeneration.id || i == Potion.poison.id)
    2570            {
    2571                return false;
    2572            }
    2573        }
    2574
    2575        return true;
    2576    }
    2577
    2578    /**
    2579     * Returns true if this entity is undead.
    2580     */
    2581    public boolean isEntityUndead()
    2582    {
    2583        return this.getCreatureAttribute() == EnumCreatureAttribute.UNDEAD;
    2584    }
    2585
    2586    /**
    2587     * Remove the speified potion effect from this entity.
    2588     */
    2589    public void removePotionEffectClient(int par1)
    2590    {
    2591        this.activePotionsMap.remove(Integer.valueOf(par1));
    2592    }
    2593
    2594    /**
    2595     * Remove the specified potion effect from this entity.
    2596     */
    2597    public void removePotionEffect(int par1)
    2598    {
    2599        PotionEffect potioneffect = (PotionEffect)this.activePotionsMap.remove(Integer.valueOf(par1));
    2600
    2601        if (potioneffect != null)
    2602        {
    2603            this.onFinishedPotionEffect(potioneffect);
    2604        }
    2605    }
    2606
    2607    protected void onNewPotionEffect(PotionEffect par1PotionEffect)
    2608    {
    2609        this.potionsNeedUpdate = true;
    2610    }
    2611
    2612    protected void onChangedPotionEffect(PotionEffect par1PotionEffect)
    2613    {
    2614        this.potionsNeedUpdate = true;
    2615    }
    2616
    2617    protected void onFinishedPotionEffect(PotionEffect par1PotionEffect)
    2618    {
    2619        this.potionsNeedUpdate = true;
    2620    }
    2621
    2622    /**
    2623     * This method returns a value to be applied directly to entity speed, this factor is less than 1 when a slowdown
    2624     * potion effect is applied, more than 1 when a haste potion effect is applied and 2 for fleeing entities.
    2625     */
    2626    public float getSpeedModifier()
    2627    {
    2628        float f = 1.0F;
    2629
    2630        if (this.isPotionActive(Potion.moveSpeed))
    2631        {
    2632            f *= 1.0F + 0.2F * (float)(this.getActivePotionEffect(Potion.moveSpeed).getAmplifier() + 1);
    2633        }
    2634
    2635        if (this.isPotionActive(Potion.moveSlowdown))
    2636        {
    2637            f *= 1.0F - 0.15F * (float)(this.getActivePotionEffect(Potion.moveSlowdown).getAmplifier() + 1);
    2638        }
    2639
    2640        if (f < 0.0F)
    2641        {
    2642            f = 0.0F;
    2643        }
    2644
    2645        return f;
    2646    }
    2647
    2648    /**
    2649     * Move the entity to the coordinates informed, but keep yaw/pitch values.
    2650     */
    2651    public void setPositionAndUpdate(double par1, double par3, double par5)
    2652    {
    2653        this.setLocationAndAngles(par1, par3, par5, this.rotationYaw, this.rotationPitch);
    2654    }
    2655
    2656    /**
    2657     * If Animal, checks if the age timer is negative
    2658     */
    2659    public boolean isChild()
    2660    {
    2661        return false;
    2662    }
    2663
    2664    /**
    2665     * Get this Entity's EnumCreatureAttribute
    2666     */
    2667    public EnumCreatureAttribute getCreatureAttribute()
    2668    {
    2669        return EnumCreatureAttribute.UNDEFINED;
    2670    }
    2671
    2672    /**
    2673     * Renders broken item particles using the given ItemStack
    2674     */
    2675    public void renderBrokenItemStack(ItemStack par1ItemStack)
    2676    {
    2677        this.playSound("random.break", 0.8F, 0.8F + this.worldObj.rand.nextFloat() * 0.4F);
    2678
    2679        for (int i = 0; i < 5; ++i)
    2680        {
    2681            Vec3 vec3 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
    2682            vec3.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
    2683            vec3.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
    2684            Vec3 vec31 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.3D, (double)(-this.rand.nextFloat()) * 0.6D - 0.3D, 0.6D);
    2685            vec31.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
    2686            vec31.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
    2687            vec31 = vec31.addVector(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);
    2688            this.worldObj.spawnParticle("iconcrack_" + par1ItemStack.getItem().itemID, vec31.xCoord, vec31.yCoord, vec31.zCoord, vec3.xCoord, vec3.yCoord + 0.05D, vec3.zCoord);
    2689        }
    2690    }
    2691
    2692    public int func_82143_as()
    2693    {
    2694        if (this.getAttackTarget() == null)
    2695        {
    2696            return 3;
    2697        }
    2698        else
    2699        {
    2700            int i = (int)((float)this.health - (float)this.getMaxHealth() * 0.33F);
    2701            i -= (3 - this.worldObj.difficultySetting) * 4;
    2702
    2703            if (i < 0)
    2704            {
    2705                i = 0;
    2706            }
    2707
    2708            return i + 3;
    2709        }
    2710    }
    2711
    2712    /**
    2713     * Returns the item that this EntityLiving is holding, if any.
    2714     */
    2715    public ItemStack getHeldItem()
    2716    {
    2717        return this.equipment[0];
    2718    }
    2719
    2720    /**
    2721     * 0 = item, 1-n is armor
    2722     */
    2723    public ItemStack getCurrentItemOrArmor(int par1)
    2724    {
    2725        return this.equipment[par1];
    2726    }
    2727
    2728    public ItemStack getCurrentArmor(int par1)
    2729    {
    2730        return this.equipment[par1 + 1];
    2731    }
    2732
    2733    /**
    2734     * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
    2735     */
    2736    public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
    2737    {
    2738        this.equipment[par1] = par2ItemStack;
    2739    }
    2740
    2741    public ItemStack[] getLastActiveItems()
    2742    {
    2743        return this.equipment;
    2744    }
    2745
    2746    /**
    2747     * Drop the equipment for this entity.
    2748     */
    2749    protected void dropEquipment(boolean par1, int par2)
    2750    {
    2751        for (int j = 0; j < this.getLastActiveItems().length; ++j)
    2752        {
    2753            ItemStack itemstack = this.getCurrentItemOrArmor(j);
    2754            boolean flag1 = this.equipmentDropChances[j] > 1.0F;
    2755
    2756            if (itemstack != null && (par1 || flag1) && this.rand.nextFloat() - (float)par2 * 0.01F < this.equipmentDropChances[j])
    2757            {
    2758                if (!flag1 && itemstack.isItemStackDamageable())
    2759                {
    2760                    int k = Math.max(itemstack.getMaxDamage() - 25, 1);
    2761                    int l = itemstack.getMaxDamage() - this.rand.nextInt(this.rand.nextInt(k) + 1);
    2762
    2763                    if (l > k)
    2764                    {
    2765                        l = k;
    2766                    }
    2767
    2768                    if (l < 1)
    2769                    {
    2770                        l = 1;
    2771                    }
    2772
    2773                    itemstack.setItemDamage(l);
    2774                }
    2775
    2776                this.entityDropItem(itemstack, 0.0F);
    2777            }
    2778        }
    2779    }
    2780
    2781    /**
    2782     * Makes entity wear random armor based on difficulty
    2783     */
    2784    protected void addRandomArmor()
    2785    {
    2786        if (this.rand.nextFloat() < armorProbability[this.worldObj.difficultySetting])
    2787        {
    2788            int i = this.rand.nextInt(2);
    2789            float f = this.worldObj.difficultySetting == 3 ? 0.1F : 0.25F;
    2790
    2791            if (this.rand.nextFloat() < 0.095F)
    2792            {
    2793                ++i;
    2794            }
    2795
    2796            if (this.rand.nextFloat() < 0.095F)
    2797            {
    2798                ++i;
    2799            }
    2800
    2801            if (this.rand.nextFloat() < 0.095F)
    2802            {
    2803                ++i;
    2804            }
    2805
    2806            for (int j = 3; j >= 0; --j)
    2807            {
    2808                ItemStack itemstack = this.getCurrentArmor(j);
    2809
    2810                if (j < 3 && this.rand.nextFloat() < f)
    2811                {
    2812                    break;
    2813                }
    2814
    2815                if (itemstack == null)
    2816                {
    2817                    Item item = getArmorItemForSlot(j + 1, i);
    2818
    2819                    if (item != null)
    2820                    {
    2821                        this.setCurrentItemOrArmor(j + 1, new ItemStack(item));
    2822                    }
    2823                }
    2824            }
    2825        }
    2826    }
    2827
    2828    /**
    2829     * Called whenever an item is picked up from walking over it. Args: pickedUpEntity, stackSize
    2830     */
    2831    public void onItemPickup(Entity par1Entity, int par2)
    2832    {
    2833        if (!par1Entity.isDead && !this.worldObj.isRemote)
    2834        {
    2835            EntityTracker entitytracker = ((WorldServer)this.worldObj).getEntityTracker();
    2836
    2837            if (par1Entity instanceof EntityItem)
    2838            {
    2839                entitytracker.sendPacketToAllPlayersTrackingEntity(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
    2840            }
    2841
    2842            if (par1Entity instanceof EntityArrow)
    2843            {
    2844                entitytracker.sendPacketToAllPlayersTrackingEntity(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
    2845            }
    2846
    2847            if (par1Entity instanceof EntityXPOrb)
    2848            {
    2849                entitytracker.sendPacketToAllPlayersTrackingEntity(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
    2850            }
    2851        }
    2852    }
    2853
    2854    public static int func_82159_b(ItemStack par0ItemStack)
    2855    {
    2856        if (par0ItemStack.itemID != Block.pumpkin.blockID && par0ItemStack.itemID != Item.skull.itemID)
    2857        {
    2858            if (par0ItemStack.getItem() instanceof ItemArmor)
    2859            {
    2860                switch (((ItemArmor)par0ItemStack.getItem()).armorType)
    2861                {
    2862                    case 0:
    2863                        return 4;
    2864                    case 1:
    2865                        return 3;
    2866                    case 2:
    2867                        return 2;
    2868                    case 3:
    2869                        return 1;
    2870                }
    2871            }
    2872
    2873            return 0;
    2874        }
    2875        else
    2876        {
    2877            return 4;
    2878        }
    2879    }
    2880
    2881    /**
    2882     * Params: Armor slot, Item tier
    2883     */
    2884    public static Item getArmorItemForSlot(int par0, int par1)
    2885    {
    2886        switch (par0)
    2887        {
    2888            case 4:
    2889                if (par1 == 0)
    2890                {
    2891                    return Item.helmetLeather;
    2892                }
    2893                else if (par1 == 1)
    2894                {
    2895                    return Item.helmetGold;
    2896                }
    2897                else if (par1 == 2)
    2898                {
    2899                    return Item.helmetChain;
    2900                }
    2901                else if (par1 == 3)
    2902                {
    2903                    return Item.helmetSteel;
    2904                }
    2905                else if (par1 == 4)
    2906                {
    2907                    return Item.helmetDiamond;
    2908                }
    2909            case 3:
    2910                if (par1 == 0)
    2911                {
    2912                    return Item.plateLeather;
    2913                }
    2914                else if (par1 == 1)
    2915                {
    2916                    return Item.plateGold;
    2917                }
    2918                else if (par1 == 2)
    2919                {
    2920                    return Item.plateChain;
    2921                }
    2922                else if (par1 == 3)
    2923                {
    2924                    return Item.plateSteel;
    2925                }
    2926                else if (par1 == 4)
    2927                {
    2928                    return Item.plateDiamond;
    2929                }
    2930            case 2:
    2931                if (par1 == 0)
    2932                {
    2933                    return Item.legsLeather;
    2934                }
    2935                else if (par1 == 1)
    2936                {
    2937                    return Item.legsGold;
    2938                }
    2939                else if (par1 == 2)
    2940                {
    2941                    return Item.legsChain;
    2942                }
    2943                else if (par1 == 3)
    2944                {
    2945                    return Item.legsSteel;
    2946                }
    2947                else if (par1 == 4)
    2948                {
    2949                    return Item.legsDiamond;
    2950                }
    2951            case 1:
    2952                if (par1 == 0)
    2953                {
    2954                    return Item.bootsLeather;
    2955                }
    2956                else if (par1 == 1)
    2957                {
    2958                    return Item.bootsGold;
    2959                }
    2960                else if (par1 == 2)
    2961                {
    2962                    return Item.bootsChain;
    2963                }
    2964                else if (par1 == 3)
    2965                {
    2966                    return Item.bootsSteel;
    2967                }
    2968                else if (par1 == 4)
    2969                {
    2970                    return Item.bootsDiamond;
    2971                }
    2972            default:
    2973                return null;
    2974        }
    2975    }
    2976
    2977    protected void func_82162_bC()
    2978    {
    2979        if (this.getHeldItem() != null && this.rand.nextFloat() < enchantmentProbability[this.worldObj.difficultySetting])
    2980        {
    2981            EnchantmentHelper.addRandomEnchantment(this.rand, this.getHeldItem(), 5 + this.worldObj.difficultySetting * this.rand.nextInt(6));
    2982        }
    2983
    2984        for (int i = 0; i < 4; ++i)
    2985        {
    2986            ItemStack itemstack = this.getCurrentArmor(i);
    2987
    2988            if (itemstack != null && this.rand.nextFloat() < armorEnchantmentProbability[this.worldObj.difficultySetting])
    2989            {
    2990                EnchantmentHelper.addRandomEnchantment(this.rand, itemstack, 5 + this.worldObj.difficultySetting * this.rand.nextInt(6));
    2991            }
    2992        }
    2993    }
    2994
    2995    /**
    2996     * Initialize this creature.
    2997     */
    2998    public void initCreature() {}
    2999
    3000    /**
    3001     * Returns an integer indicating the end point of the swing animation, used by {@link #swingProgress} to provide a
    3002     * progress indicator. Takes dig speed enchantments into account.
    3003     */
    3004    private int getArmSwingAnimationEnd()
    3005    {
    3006        return this.isPotionActive(Potion.digSpeed) ? 6 - (1 + this.getActivePotionEffect(Potion.digSpeed).getAmplifier()) * 1 : (this.isPotionActive(Potion.digSlowdown) ? 6 + (1 + this.getActivePotionEffect(Potion.digSlowdown).getAmplifier()) * 2 : 6);
    3007    }
    3008
    3009    /**
    3010     * Swings the item the player is holding.
    3011     */
    3012    public void swingItem()
    3013    {
    3014        if (!this.isSwingInProgress || this.swingProgressInt >= this.getArmSwingAnimationEnd() / 2 || this.swingProgressInt < 0)
    3015        {
    3016            this.swingProgressInt = -1;
    3017            this.isSwingInProgress = true;
    3018
    3019            if (this.worldObj instanceof WorldServer)
    3020            {
    3021                ((WorldServer)this.worldObj).getEntityTracker().sendPacketToAllPlayersTrackingEntity(this, new Packet18Animation(this, 1));
    3022            }
    3023        }
    3024    }
    3025
    3026    /**
    3027     * returns true if all the conditions for steering the entity are met. For pigs, this is true if it is being ridden
    3028     * by a player and the player is holding a carrot-on-a-stick
    3029     */
    3030    public boolean canBeSteered()
    3031    {
    3032        return false;
    3033    }
    3034
    3035    /**
    3036     * counts the amount of arrows stuck in the entity. getting hit by arrows increases this, used in rendering
    3037     */
    3038    public final int getArrowCountInEntity()
    3039    {
    3040        return this.dataWatcher.getWatchableObjectByte(10);
    3041    }
    3042
    3043    /**
    3044     * sets the amount of arrows stuck in the entity. used for rendering those
    3045     */
    3046    public final void setArrowCountInEntity(int par1)
    3047    {
    3048        this.dataWatcher.updateObject(10, Byte.valueOf((byte)par1));
    3049    }
    3050
    3051    public EntityLiving func_94060_bK()
    3052    {
    3053        return (EntityLiving)(this.field_94063_bt.func_94550_c() != null ? this.field_94063_bt.func_94550_c() : (this.attackingPlayer != null ? this.attackingPlayer : (this.entityLivingToAttack != null ? this.entityLivingToAttack : null)));
    3054    }
    3055
    3056    /**
    3057     * Gets the username of the entity.
    3058     */
    3059    public String getEntityName()
    3060    {
    3061        return this.func_94056_bM() ? this.func_94057_bL() : super.getEntityName();
    3062    }
    3063
    3064    public void func_94058_c(String par1Str)
    3065    {
    3066        this.dataWatcher.updateObject(5, par1Str);
    3067    }
    3068
    3069    public String func_94057_bL()
    3070    {
    3071        return this.dataWatcher.getWatchableObjectString(5);
    3072    }
    3073
    3074    public boolean func_94056_bM()
    3075    {
    3076        return this.dataWatcher.getWatchableObjectString(5).length() > 0;
    3077    }
    3078
    3079    public void func_94061_f(boolean par1)
    3080    {
    3081        this.dataWatcher.updateObject(6, Byte.valueOf((byte)(par1 ? 1 : 0)));
    3082    }
    3083
    3084    public boolean func_94062_bN()
    3085    {
    3086        return this.dataWatcher.getWatchableObjectByte(6) == 1;
    3087    }
    3088
    3089    @SideOnly(Side.CLIENT)
    3090    public boolean func_94059_bO()
    3091    {
    3092        return this.func_94062_bN();
    3093    }
    3094
    3095    public void func_96120_a(int par1, float par2)
    3096    {
    3097        this.equipmentDropChances[par1] = par2;
    3098    }
    3099
    3100    public boolean func_98052_bS()
    3101    {
    3102        return this.canPickUpLoot;
    3103    }
    3104
    3105    public void func_98053_h(boolean par1)
    3106    {
    3107        this.canPickUpLoot = par1;
    3108    }
    3109
    3110    /***
    3111     * Removes all potion effects that have curativeItem as a curative item for its effect
    3112     * @param curativeItem The itemstack we are using to cure potion effects
    3113     */
    3114    public void curePotionEffects(ItemStack curativeItem)
    3115    {
    3116        Iterator<Integer> potionKey = activePotionsMap.keySet().iterator();
    3117
    3118        if (worldObj.isRemote)
    3119        {
    3120            return;
    3121        }
    3122
    3123        while (potionKey.hasNext())
    3124        {
    3125            Integer key = potionKey.next();
    3126            PotionEffect effect = (PotionEffect)activePotionsMap.get(key);
    3127
    3128            if (effect.isCurativeItem(curativeItem))
    3129            {
    3130                potionKey.remove();
    3131                onFinishedPotionEffect(effect);
    3132            }
    3133        }
    3134    }
    3135
    3136    /**
    3137     * Returns true if the entity's rider (EntityPlayer) should face forward when mounted.
    3138     * currently only used in vanilla code by pigs.
    3139     *
    3140     * @param player The player who is riding the entity.
    3141     * @return If the player should orient the same direction as this entity.
    3142     */
    3143    public boolean shouldRiderFaceForward(EntityPlayer player)
    3144    {
    3145        return this instanceof EntityPig;
    3146    }
    3147}