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