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