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