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