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