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