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