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