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.func_85030_a(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.func_85032_ar())
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.field_76375_l)
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.func_85030_a(this.getDeathSound(), this.getSoundVolume(), this.getSoundPitch());
1109                        }
1110    
1111                        this.onDeath(par1DamageSource);
1112                    }
1113                    else if (var3)
1114                    {
1115                        this.func_85030_a(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.func_85032_ar())
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
1344         */
1345        protected void dropFewItems(boolean par1, int par2)
1346        {
1347            int var3 = this.getDropItemId();
1348    
1349            if (var3 > 0)
1350            {
1351                int var4 = this.rand.nextInt(3);
1352    
1353                if (par2 > 0)
1354                {
1355                    var4 += this.rand.nextInt(par2 + 1);
1356                }
1357    
1358                for (int var5 = 0; var5 < var4; ++var5)
1359                {
1360                    this.dropItem(var3, 1);
1361                }
1362            }
1363        }
1364    
1365        /**
1366         * Returns the item ID for the item the mob drops on death.
1367         */
1368        protected int getDropItemId()
1369        {
1370            return 0;
1371        }
1372    
1373        /**
1374         * Called when the mob is falling. Calculates and applies fall damage.
1375         */
1376        protected void fall(float par1)
1377        {
1378            par1 = ForgeHooks.onLivingFall(this, par1);
1379            if (par1 <= 0)
1380            {
1381                return;
1382            }
1383    
1384            super.fall(par1);
1385            int var2 = MathHelper.ceiling_float_int(par1 - 3.0F);
1386    
1387            if (var2 > 0)
1388            {
1389                if (var2 > 4)
1390                {
1391                    this.func_85030_a("damage.fallbig", 1.0F, 1.0F);
1392                }
1393                else
1394                {
1395                    this.func_85030_a("damage.fallsmall", 1.0F, 1.0F);
1396                }
1397    
1398                this.attackEntityFrom(DamageSource.fall, var2);
1399                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));
1400    
1401                if (var3 > 0)
1402                {
1403                    StepSound var4 = Block.blocksList[var3].stepSound;
1404                    this.func_85030_a(var4.getStepSound(), var4.getVolume() * 0.5F, var4.getPitch() * 0.75F);
1405                }
1406            }
1407        }
1408    
1409        /**
1410         * Moves the entity based on the specified heading.  Args: strafe, forward
1411         */
1412        public void moveEntityWithHeading(float par1, float par2)
1413        {
1414            double var9;
1415    
1416            if (this.isInWater() && (!(this instanceof EntityPlayer) || !((EntityPlayer)this).capabilities.isFlying))
1417            {
1418                var9 = this.posY;
1419                this.moveFlying(par1, par2, this.isAIEnabled() ? 0.04F : 0.02F);
1420                this.moveEntity(this.motionX, this.motionY, this.motionZ);
1421                this.motionX *= 0.800000011920929D;
1422                this.motionY *= 0.800000011920929D;
1423                this.motionZ *= 0.800000011920929D;
1424                this.motionY -= 0.02D;
1425    
1426                if (this.isCollidedHorizontally && this.isOffsetPositionInLiquid(this.motionX, this.motionY + 0.6000000238418579D - this.posY + var9, this.motionZ))
1427                {
1428                    this.motionY = 0.30000001192092896D;
1429                }
1430            }
1431            else if (this.handleLavaMovement() && (!(this instanceof EntityPlayer) || !((EntityPlayer)this).capabilities.isFlying))
1432            {
1433                var9 = this.posY;
1434                this.moveFlying(par1, par2, 0.02F);
1435                this.moveEntity(this.motionX, this.motionY, this.motionZ);
1436                this.motionX *= 0.5D;
1437                this.motionY *= 0.5D;
1438                this.motionZ *= 0.5D;
1439                this.motionY -= 0.02D;
1440    
1441                if (this.isCollidedHorizontally && this.isOffsetPositionInLiquid(this.motionX, this.motionY + 0.6000000238418579D - this.posY + var9, this.motionZ))
1442                {
1443                    this.motionY = 0.30000001192092896D;
1444                }
1445            }
1446            else
1447            {
1448                float var3 = 0.91F;
1449    
1450                if (this.onGround)
1451                {
1452                    var3 = 0.54600006F;
1453                    int var4 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
1454    
1455                    if (var4 > 0)
1456                    {
1457                        var3 = Block.blocksList[var4].slipperiness * 0.91F;
1458                    }
1459                }
1460    
1461                float var8 = 0.16277136F / (var3 * var3 * var3);
1462                float var5;
1463    
1464                if (this.onGround)
1465                {
1466                    if (this.isAIEnabled())
1467                    {
1468                        var5 = this.getAIMoveSpeed();
1469                    }
1470                    else
1471                    {
1472                        var5 = this.landMovementFactor;
1473                    }
1474    
1475                    var5 *= var8;
1476                }
1477                else
1478                {
1479                    var5 = this.jumpMovementFactor;
1480                }
1481    
1482                this.moveFlying(par1, par2, var5);
1483                var3 = 0.91F;
1484    
1485                if (this.onGround)
1486                {
1487                    var3 = 0.54600006F;
1488                    int var6 = this.worldObj.getBlockId(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.boundingBox.minY) - 1, MathHelper.floor_double(this.posZ));
1489    
1490                    if (var6 > 0)
1491                    {
1492                        var3 = Block.blocksList[var6].slipperiness * 0.91F;
1493                    }
1494                }
1495    
1496                if (this.isOnLadder())
1497                {
1498                    float var10 = 0.15F;
1499    
1500                    if (this.motionX < (double)(-var10))
1501                    {
1502                        this.motionX = (double)(-var10);
1503                    }
1504    
1505                    if (this.motionX > (double)var10)
1506                    {
1507                        this.motionX = (double)var10;
1508                    }
1509    
1510                    if (this.motionZ < (double)(-var10))
1511                    {
1512                        this.motionZ = (double)(-var10);
1513                    }
1514    
1515                    if (this.motionZ > (double)var10)
1516                    {
1517                        this.motionZ = (double)var10;
1518                    }
1519    
1520                    this.fallDistance = 0.0F;
1521    
1522                    if (this.motionY < -0.15D)
1523                    {
1524                        this.motionY = -0.15D;
1525                    }
1526    
1527                    boolean var7 = this.isSneaking() && this instanceof EntityPlayer;
1528    
1529                    if (var7 && this.motionY < 0.0D)
1530                    {
1531                        this.motionY = 0.0D;
1532                    }
1533                }
1534    
1535                this.moveEntity(this.motionX, this.motionY, this.motionZ);
1536    
1537                if (this.isCollidedHorizontally && this.isOnLadder())
1538                {
1539                    this.motionY = 0.2D;
1540                }
1541    
1542                if (this.worldObj.isRemote && (!this.worldObj.blockExists((int)this.posX, 0, (int)this.posZ) || !this.worldObj.getChunkFromBlockCoords((int)this.posX, (int)this.posZ).isChunkLoaded))
1543                {
1544                    if (this.posY > 0.0D)
1545                    {
1546                        this.motionY = -0.1D;
1547                    }
1548                    else
1549                    {
1550                        this.motionY = 0.0D;
1551                    }
1552                }
1553                else
1554                {
1555                    this.motionY -= 0.08D;
1556                }
1557    
1558                this.motionY *= 0.9800000190734863D;
1559                this.motionX *= (double)var3;
1560                this.motionZ *= (double)var3;
1561            }
1562    
1563            this.prevLegYaw = this.legYaw;
1564            var9 = this.posX - this.prevPosX;
1565            double var12 = this.posZ - this.prevPosZ;
1566            float var11 = MathHelper.sqrt_double(var9 * var9 + var12 * var12) * 4.0F;
1567    
1568            if (var11 > 1.0F)
1569            {
1570                var11 = 1.0F;
1571            }
1572    
1573            this.legYaw += (var11 - this.legYaw) * 0.4F;
1574            this.legSwing += this.legYaw;
1575        }
1576    
1577        /**
1578         * returns true if this entity is by a ladder, false otherwise
1579         */
1580        public boolean isOnLadder()
1581        {
1582            int var1 = MathHelper.floor_double(this.posX);
1583            int var2 = MathHelper.floor_double(this.boundingBox.minY);
1584            int var3 = MathHelper.floor_double(this.posZ);
1585            int var4 = this.worldObj.getBlockId(var1, var2, var3);
1586            return ForgeHooks.isLivingOnLadder(Block.blocksList[var4], worldObj, var1, var2, var3);
1587        }
1588    
1589        /**
1590         * (abstract) Protected helper method to write subclass entity data to NBT.
1591         */
1592        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
1593        {
1594            if (this.health < -32768)
1595            {
1596                this.health = -32768;
1597            }
1598    
1599            par1NBTTagCompound.setShort("Health", (short)this.health);
1600            par1NBTTagCompound.setShort("HurtTime", (short)this.hurtTime);
1601            par1NBTTagCompound.setShort("DeathTime", (short)this.deathTime);
1602            par1NBTTagCompound.setShort("AttackTime", (short)this.attackTime);
1603            par1NBTTagCompound.setBoolean("CanPickUpLoot", this.canPickUpLoot);
1604            par1NBTTagCompound.setBoolean("PersistenceRequired", this.persistenceRequired);
1605            NBTTagList var2 = new NBTTagList();
1606    
1607            for (int var3 = 0; var3 < this.equipment.length; ++var3)
1608            {
1609                NBTTagCompound var4 = new NBTTagCompound();
1610    
1611                if (this.equipment[var3] != null)
1612                {
1613                    this.equipment[var3].writeToNBT(var4);
1614                }
1615    
1616                var2.appendTag(var4);
1617            }
1618    
1619            par1NBTTagCompound.setTag("Equipment", var2);
1620            NBTTagList var6;
1621    
1622            if (!this.activePotionsMap.isEmpty())
1623            {
1624                var6 = new NBTTagList();
1625                Iterator var7 = this.activePotionsMap.values().iterator();
1626    
1627                while (var7.hasNext())
1628                {
1629                    PotionEffect var5 = (PotionEffect)var7.next();
1630                    var6.appendTag(var5.writeCustomPotionEffectToNBT(new NBTTagCompound()));
1631                }
1632    
1633                par1NBTTagCompound.setTag("ActiveEffects", var6);
1634            }
1635    
1636            var6 = new NBTTagList();
1637    
1638            for (int var8 = 0; var8 < this.equipmentDropChances.length; ++var8)
1639            {
1640                var6.appendTag(new NBTTagFloat(var8 + "", this.equipmentDropChances[var8]));
1641            }
1642    
1643            par1NBTTagCompound.setTag("DropChances", var6);
1644        }
1645    
1646        /**
1647         * (abstract) Protected helper method to read subclass entity data from NBT.
1648         */
1649        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
1650        {
1651            this.health = par1NBTTagCompound.getShort("Health");
1652    
1653            if (!par1NBTTagCompound.hasKey("Health"))
1654            {
1655                this.health = this.getMaxHealth();
1656            }
1657    
1658            this.hurtTime = par1NBTTagCompound.getShort("HurtTime");
1659            this.deathTime = par1NBTTagCompound.getShort("DeathTime");
1660            this.attackTime = par1NBTTagCompound.getShort("AttackTime");
1661            this.canPickUpLoot = par1NBTTagCompound.getBoolean("CanPickUpLoot");
1662            this.persistenceRequired = par1NBTTagCompound.getBoolean("PersistenceRequired");
1663            NBTTagList var2;
1664            int var3;
1665    
1666            if (par1NBTTagCompound.hasKey("Equipment"))
1667            {
1668                var2 = par1NBTTagCompound.getTagList("Equipment");
1669    
1670                for (var3 = 0; var3 < this.equipment.length; ++var3)
1671                {
1672                    this.equipment[var3] = ItemStack.loadItemStackFromNBT((NBTTagCompound)var2.tagAt(var3));
1673                }
1674            }
1675    
1676            if (par1NBTTagCompound.hasKey("ActiveEffects"))
1677            {
1678                var2 = par1NBTTagCompound.getTagList("ActiveEffects");
1679    
1680                for (var3 = 0; var3 < var2.tagCount(); ++var3)
1681                {
1682                    NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3);
1683                    PotionEffect var5 = PotionEffect.readCustomPotionEffectFromNBT(var4);
1684                    this.activePotionsMap.put(Integer.valueOf(var5.getPotionID()), var5);
1685                }
1686            }
1687    
1688            if (par1NBTTagCompound.hasKey("DropChances"))
1689            {
1690                var2 = par1NBTTagCompound.getTagList("DropChances");
1691    
1692                for (var3 = 0; var3 < var2.tagCount(); ++var3)
1693                {
1694                    this.equipmentDropChances[var3] = ((NBTTagFloat)var2.tagAt(var3)).data;
1695                }
1696            }
1697        }
1698    
1699        /**
1700         * Checks whether target entity is alive.
1701         */
1702        public boolean isEntityAlive()
1703        {
1704            return !this.isDead && this.health > 0;
1705        }
1706    
1707        public boolean canBreatheUnderwater()
1708        {
1709            return false;
1710        }
1711    
1712        public void setMoveForward(float par1)
1713        {
1714            this.moveForward = par1;
1715        }
1716    
1717        public void setJumping(boolean par1)
1718        {
1719            this.isJumping = par1;
1720        }
1721    
1722        /**
1723         * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
1724         * use this to react to sunlight and start to burn.
1725         */
1726        public void onLivingUpdate()
1727        {
1728            if (this.jumpTicks > 0)
1729            {
1730                --this.jumpTicks;
1731            }
1732    
1733            if (this.newPosRotationIncrements > 0)
1734            {
1735                double var1 = this.posX + (this.newPosX - this.posX) / (double)this.newPosRotationIncrements;
1736                double var3 = this.posY + (this.newPosY - this.posY) / (double)this.newPosRotationIncrements;
1737                double var5 = this.posZ + (this.newPosZ - this.posZ) / (double)this.newPosRotationIncrements;
1738                double var7 = MathHelper.wrapAngleTo180_double(this.newRotationYaw - (double)this.rotationYaw);
1739                this.rotationYaw = (float)((double)this.rotationYaw + var7 / (double)this.newPosRotationIncrements);
1740                this.rotationPitch = (float)((double)this.rotationPitch + (this.newRotationPitch - (double)this.rotationPitch) / (double)this.newPosRotationIncrements);
1741                --this.newPosRotationIncrements;
1742                this.setPosition(var1, var3, var5);
1743                this.setRotation(this.rotationYaw, this.rotationPitch);
1744            }
1745            else if (!this.isClientWorld())
1746            {
1747                this.motionX *= 0.98D;
1748                this.motionY *= 0.98D;
1749                this.motionZ *= 0.98D;
1750            }
1751    
1752            if (Math.abs(this.motionX) < 0.005D)
1753            {
1754                this.motionX = 0.0D;
1755            }
1756    
1757            if (Math.abs(this.motionY) < 0.005D)
1758            {
1759                this.motionY = 0.0D;
1760            }
1761    
1762            if (Math.abs(this.motionZ) < 0.005D)
1763            {
1764                this.motionZ = 0.0D;
1765            }
1766    
1767            this.worldObj.theProfiler.startSection("ai");
1768    
1769            if (this.isMovementBlocked())
1770            {
1771                this.isJumping = false;
1772                this.moveStrafing = 0.0F;
1773                this.moveForward = 0.0F;
1774                this.randomYawVelocity = 0.0F;
1775            }
1776            else if (this.isClientWorld())
1777            {
1778                if (this.isAIEnabled())
1779                {
1780                    this.worldObj.theProfiler.startSection("newAi");
1781                    this.updateAITasks();
1782                    this.worldObj.theProfiler.endSection();
1783                }
1784                else
1785                {
1786                    this.worldObj.theProfiler.startSection("oldAi");
1787                    this.updateEntityActionState();
1788                    this.worldObj.theProfiler.endSection();
1789                    this.rotationYawHead = this.rotationYaw;
1790                }
1791            }
1792    
1793            this.worldObj.theProfiler.endSection();
1794            this.worldObj.theProfiler.startSection("jump");
1795    
1796            if (this.isJumping)
1797            {
1798                if (!this.isInWater() && !this.handleLavaMovement())
1799                {
1800                    if (this.onGround && this.jumpTicks == 0)
1801                    {
1802                        this.jump();
1803                        this.jumpTicks = 10;
1804                    }
1805                }
1806                else
1807                {
1808                    this.motionY += 0.03999999910593033D;
1809                }
1810            }
1811            else
1812            {
1813                this.jumpTicks = 0;
1814            }
1815    
1816            this.worldObj.theProfiler.endSection();
1817            this.worldObj.theProfiler.startSection("travel");
1818            this.moveStrafing *= 0.98F;
1819            this.moveForward *= 0.98F;
1820            this.randomYawVelocity *= 0.9F;
1821            float var11 = this.landMovementFactor;
1822            this.landMovementFactor *= this.getSpeedModifier();
1823            this.moveEntityWithHeading(this.moveStrafing, this.moveForward);
1824            this.landMovementFactor = var11;
1825            this.worldObj.theProfiler.endSection();
1826            this.worldObj.theProfiler.startSection("push");
1827    
1828            if (!this.worldObj.isRemote)
1829            {
1830                this.func_85033_bc();
1831            }
1832    
1833            this.worldObj.theProfiler.endSection();
1834            this.worldObj.theProfiler.startSection("looting");
1835    
1836            if (!this.worldObj.isRemote && this.canPickUpLoot && !this.dead && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"))
1837            {
1838                List var2 = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(1.0D, 0.0D, 1.0D));
1839                Iterator var12 = var2.iterator();
1840    
1841                while (var12.hasNext())
1842                {
1843                    EntityItem var4 = (EntityItem)var12.next();
1844    
1845                    if (!var4.isDead && var4.func_92014_d() != null)
1846                    {
1847                        ItemStack var13 = var4.func_92014_d();
1848                        int var6 = func_82159_b(var13);
1849    
1850                        if (var6 > -1)
1851                        {
1852                            boolean var14 = true;
1853                            ItemStack var8 = this.getCurrentItemOrArmor(var6);
1854    
1855                            if (var8 != null)
1856                            {
1857                                if (var6 == 0)
1858                                {
1859                                    if (var13.getItem() instanceof ItemSword && !(var8.getItem() instanceof ItemSword))
1860                                    {
1861                                        var14 = true;
1862                                    }
1863                                    else if (var13.getItem() instanceof ItemSword && var8.getItem() instanceof ItemSword)
1864                                    {
1865                                        ItemSword var9 = (ItemSword)var13.getItem();
1866                                        ItemSword var10 = (ItemSword)var8.getItem();
1867    
1868                                        if (var9.func_82803_g() == var10.func_82803_g())
1869                                        {
1870                                            var14 = var13.getItemDamage() > var8.getItemDamage() || var13.hasTagCompound() && !var8.hasTagCompound();
1871                                        }
1872                                        else
1873                                        {
1874                                            var14 = var9.func_82803_g() > var10.func_82803_g();
1875                                        }
1876                                    }
1877                                    else
1878                                    {
1879                                        var14 = false;
1880                                    }
1881                                }
1882                                else if (var13.getItem() instanceof ItemArmor && !(var8.getItem() instanceof ItemArmor))
1883                                {
1884                                    var14 = true;
1885                                }
1886                                else if (var13.getItem() instanceof ItemArmor && var8.getItem() instanceof ItemArmor)
1887                                {
1888                                    ItemArmor var15 = (ItemArmor)var13.getItem();
1889                                    ItemArmor var16 = (ItemArmor)var8.getItem();
1890    
1891                                    if (var15.damageReduceAmount == var16.damageReduceAmount)
1892                                    {
1893                                        var14 = var13.getItemDamage() > var8.getItemDamage() || var13.hasTagCompound() && !var8.hasTagCompound();
1894                                    }
1895                                    else
1896                                    {
1897                                        var14 = var15.damageReduceAmount > var16.damageReduceAmount;
1898                                    }
1899                                }
1900                                else
1901                                {
1902                                    var14 = false;
1903                                }
1904                            }
1905    
1906                            if (var14)
1907                            {
1908                                if (var8 != null && this.rand.nextFloat() - 0.1F < this.equipmentDropChances[var6])
1909                                {
1910                                    this.entityDropItem(var8, 0.0F);
1911                                }
1912    
1913                                this.setCurrentItemOrArmor(var6, var13);
1914                                this.equipmentDropChances[var6] = 2.0F;
1915                                this.persistenceRequired = true;
1916                                this.onItemPickup(var4, 1);
1917                                var4.setDead();
1918                            }
1919                        }
1920                    }
1921                }
1922            }
1923    
1924            this.worldObj.theProfiler.endSection();
1925        }
1926    
1927        protected void func_85033_bc()
1928        {
1929            List var1 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(0.20000000298023224D, 0.0D, 0.20000000298023224D));
1930    
1931            if (var1 != null && !var1.isEmpty())
1932            {
1933                for (int var2 = 0; var2 < var1.size(); ++var2)
1934                {
1935                    Entity var3 = (Entity)var1.get(var2);
1936    
1937                    if (var3.canBePushed())
1938                    {
1939                        this.collideWithEntity(var3);
1940                    }
1941                }
1942            }
1943        }
1944    
1945        protected void collideWithEntity(Entity par1Entity)
1946        {
1947            par1Entity.applyEntityCollision(this);
1948        }
1949    
1950        /**
1951         * Returns true if the newer Entity AI code should be run
1952         */
1953        protected boolean isAIEnabled()
1954        {
1955            return false;
1956        }
1957    
1958        /**
1959         * Returns whether the entity is in a local (client) world
1960         */
1961        protected boolean isClientWorld()
1962        {
1963            return !this.worldObj.isRemote;
1964        }
1965    
1966        /**
1967         * Dead and sleeping entities cannot move
1968         */
1969        protected boolean isMovementBlocked()
1970        {
1971            return this.health <= 0;
1972        }
1973    
1974        public boolean isBlocking()
1975        {
1976            return false;
1977        }
1978    
1979        /**
1980         * Causes this entity to do an upwards motion (jumping).
1981         */
1982        protected void jump()
1983        {
1984            this.motionY = 0.41999998688697815D;
1985    
1986            if (this.isPotionActive(Potion.jump))
1987            {
1988                this.motionY += (double)((float)(this.getActivePotionEffect(Potion.jump).getAmplifier() + 1) * 0.1F);
1989            }
1990    
1991            if (this.isSprinting())
1992            {
1993                float var1 = this.rotationYaw * 0.017453292F;
1994                this.motionX -= (double)(MathHelper.sin(var1) * 0.2F);
1995                this.motionZ += (double)(MathHelper.cos(var1) * 0.2F);
1996            }
1997    
1998            this.isAirBorne = true;
1999            ForgeHooks.onLivingJump(this);
2000        }
2001    
2002        /**
2003         * Determines if an entity can be despawned, used on idle far away entities
2004         */
2005        protected boolean canDespawn()
2006        {
2007            return true;
2008        }
2009    
2010        /**
2011         * Makes the entity despawn if requirements are reached
2012         */
2013        protected void despawnEntity()
2014        {
2015            if (!this.persistenceRequired)
2016            {
2017                EntityPlayer var1 = this.worldObj.getClosestPlayerToEntity(this, -1.0D);
2018    
2019                if (var1 != null)
2020                {
2021                    double var2 = var1.posX - this.posX;
2022                    double var4 = var1.posY - this.posY;
2023                    double var6 = var1.posZ - this.posZ;
2024                    double var8 = var2 * var2 + var4 * var4 + var6 * var6;
2025    
2026                    if (this.canDespawn() && var8 > 16384.0D)
2027                    {
2028                        this.setDead();
2029                    }
2030    
2031                    if (this.entityAge > 600 && this.rand.nextInt(800) == 0 && var8 > 1024.0D && this.canDespawn())
2032                    {
2033                        this.setDead();
2034                    }
2035                    else if (var8 < 1024.0D)
2036                    {
2037                        this.entityAge = 0;
2038                    }
2039                }
2040            }
2041        }
2042    
2043        protected void updateAITasks()
2044        {
2045            ++this.entityAge;
2046            this.worldObj.theProfiler.startSection("checkDespawn");
2047            this.despawnEntity();
2048            this.worldObj.theProfiler.endSection();
2049            this.worldObj.theProfiler.startSection("sensing");
2050            this.senses.clearSensingCache();
2051            this.worldObj.theProfiler.endSection();
2052            this.worldObj.theProfiler.startSection("targetSelector");
2053            this.targetTasks.onUpdateTasks();
2054            this.worldObj.theProfiler.endSection();
2055            this.worldObj.theProfiler.startSection("goalSelector");
2056            this.tasks.onUpdateTasks();
2057            this.worldObj.theProfiler.endSection();
2058            this.worldObj.theProfiler.startSection("navigation");
2059            this.navigator.onUpdateNavigation();
2060            this.worldObj.theProfiler.endSection();
2061            this.worldObj.theProfiler.startSection("mob tick");
2062            this.updateAITick();
2063            this.worldObj.theProfiler.endSection();
2064            this.worldObj.theProfiler.startSection("controls");
2065            this.worldObj.theProfiler.startSection("move");
2066            this.moveHelper.onUpdateMoveHelper();
2067            this.worldObj.theProfiler.endStartSection("look");
2068            this.lookHelper.onUpdateLook();
2069            this.worldObj.theProfiler.endStartSection("jump");
2070            this.jumpHelper.doJump();
2071            this.worldObj.theProfiler.endSection();
2072            this.worldObj.theProfiler.endSection();
2073        }
2074    
2075        /**
2076         * main AI tick function, replaces updateEntityActionState
2077         */
2078        protected void updateAITick() {}
2079    
2080        protected void updateEntityActionState()
2081        {
2082            ++this.entityAge;
2083            this.despawnEntity();
2084            this.moveStrafing = 0.0F;
2085            this.moveForward = 0.0F;
2086            float var1 = 8.0F;
2087    
2088            if (this.rand.nextFloat() < 0.02F)
2089            {
2090                EntityPlayer var2 = this.worldObj.getClosestPlayerToEntity(this, (double)var1);
2091    
2092                if (var2 != null)
2093                {
2094                    this.currentTarget = var2;
2095                    this.numTicksToChaseTarget = 10 + this.rand.nextInt(20);
2096                }
2097                else
2098                {
2099                    this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F;
2100                }
2101            }
2102    
2103            if (this.currentTarget != null)
2104            {
2105                this.faceEntity(this.currentTarget, 10.0F, (float)this.getVerticalFaceSpeed());
2106    
2107                if (this.numTicksToChaseTarget-- <= 0 || this.currentTarget.isDead || this.currentTarget.getDistanceSqToEntity(this) > (double)(var1 * var1))
2108                {
2109                    this.currentTarget = null;
2110                }
2111            }
2112            else
2113            {
2114                if (this.rand.nextFloat() < 0.05F)
2115                {
2116                    this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F;
2117                }
2118    
2119                this.rotationYaw += this.randomYawVelocity;
2120                this.rotationPitch = this.defaultPitch;
2121            }
2122    
2123            boolean var4 = this.isInWater();
2124            boolean var3 = this.handleLavaMovement();
2125    
2126            if (var4 || var3)
2127            {
2128                this.isJumping = this.rand.nextFloat() < 0.8F;
2129            }
2130        }
2131    
2132        /**
2133         * Updates the arm swing progress counters and animation progress
2134         */
2135        protected void updateArmSwingProgress()
2136        {
2137            int var1 = this.getArmSwingAnimationEnd();
2138    
2139            if (this.isSwingInProgress)
2140            {
2141                ++this.swingProgressInt;
2142    
2143                if (this.swingProgressInt >= var1)
2144                {
2145                    this.swingProgressInt = 0;
2146                    this.isSwingInProgress = false;
2147                }
2148            }
2149            else
2150            {
2151                this.swingProgressInt = 0;
2152            }
2153    
2154            this.swingProgress = (float)this.swingProgressInt / (float)var1;
2155        }
2156    
2157        /**
2158         * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
2159         * use in wolves.
2160         */
2161        public int getVerticalFaceSpeed()
2162        {
2163            return 40;
2164        }
2165    
2166        /**
2167         * Changes pitch and yaw so that the entity calling the function is facing the entity provided as an argument.
2168         */
2169        public void faceEntity(Entity par1Entity, float par2, float par3)
2170        {
2171            double var4 = par1Entity.posX - this.posX;
2172            double var8 = par1Entity.posZ - this.posZ;
2173            double var6;
2174    
2175            if (par1Entity instanceof EntityLiving)
2176            {
2177                EntityLiving var10 = (EntityLiving)par1Entity;
2178                var6 = this.posY + (double)this.getEyeHeight() - (var10.posY + (double)var10.getEyeHeight());
2179            }
2180            else
2181            {
2182                var6 = (par1Entity.boundingBox.minY + par1Entity.boundingBox.maxY) / 2.0D - (this.posY + (double)this.getEyeHeight());
2183            }
2184    
2185            double var14 = (double)MathHelper.sqrt_double(var4 * var4 + var8 * var8);
2186            float var12 = (float)(Math.atan2(var8, var4) * 180.0D / Math.PI) - 90.0F;
2187            float var13 = (float)(-(Math.atan2(var6, var14) * 180.0D / Math.PI));
2188            this.rotationPitch = -this.updateRotation(this.rotationPitch, var13, par3);
2189            this.rotationYaw = this.updateRotation(this.rotationYaw, var12, par2);
2190        }
2191    
2192        /**
2193         * Arguments: current rotation, intended rotation, max increment.
2194         */
2195        private float updateRotation(float par1, float par2, float par3)
2196        {
2197            float var4 = MathHelper.wrapAngleTo180_float(par2 - par1);
2198    
2199            if (var4 > par3)
2200            {
2201                var4 = par3;
2202            }
2203    
2204            if (var4 < -par3)
2205            {
2206                var4 = -par3;
2207            }
2208    
2209            return par1 + var4;
2210        }
2211    
2212        /**
2213         * Checks if the entity's current position is a valid location to spawn this entity.
2214         */
2215        public boolean getCanSpawnHere()
2216        {
2217            return this.worldObj.checkIfAABBIsClear(this.boundingBox) && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox);
2218        }
2219    
2220        /**
2221         * sets the dead flag. Used when you fall off the bottom of the world.
2222         */
2223        protected void kill()
2224        {
2225            this.attackEntityFrom(DamageSource.outOfWorld, 4);
2226        }
2227    
2228        @SideOnly(Side.CLIENT)
2229    
2230        /**
2231         * Returns where in the swing animation the living entity is (from 0 to 1).  Args: partialTickTime
2232         */
2233        public float getSwingProgress(float par1)
2234        {
2235            float var2 = this.swingProgress - this.prevSwingProgress;
2236    
2237            if (var2 < 0.0F)
2238            {
2239                ++var2;
2240            }
2241    
2242            return this.prevSwingProgress + var2 * par1;
2243        }
2244    
2245        @SideOnly(Side.CLIENT)
2246    
2247        /**
2248         * interpolated position vector
2249         */
2250        public Vec3 getPosition(float par1)
2251        {
2252            if (par1 == 1.0F)
2253            {
2254                return this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
2255            }
2256            else
2257            {
2258                double var2 = this.prevPosX + (this.posX - this.prevPosX) * (double)par1;
2259                double var4 = this.prevPosY + (this.posY - this.prevPosY) * (double)par1;
2260                double var6 = this.prevPosZ + (this.posZ - this.prevPosZ) * (double)par1;
2261                return this.worldObj.getWorldVec3Pool().getVecFromPool(var2, var4, var6);
2262            }
2263        }
2264    
2265        /**
2266         * returns a (normalized) vector of where this entity is looking
2267         */
2268        public Vec3 getLookVec()
2269        {
2270            return this.getLook(1.0F);
2271        }
2272    
2273        /**
2274         * interpolated look vector
2275         */
2276        public Vec3 getLook(float par1)
2277        {
2278            float var2;
2279            float var3;
2280            float var4;
2281            float var5;
2282    
2283            if (par1 == 1.0F)
2284            {
2285                var2 = MathHelper.cos(-this.rotationYaw * 0.017453292F - (float)Math.PI);
2286                var3 = MathHelper.sin(-this.rotationYaw * 0.017453292F - (float)Math.PI);
2287                var4 = -MathHelper.cos(-this.rotationPitch * 0.017453292F);
2288                var5 = MathHelper.sin(-this.rotationPitch * 0.017453292F);
2289                return this.worldObj.getWorldVec3Pool().getVecFromPool((double)(var3 * var4), (double)var5, (double)(var2 * var4));
2290            }
2291            else
2292            {
2293                var2 = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * par1;
2294                var3 = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * par1;
2295                var4 = MathHelper.cos(-var3 * 0.017453292F - (float)Math.PI);
2296                var5 = MathHelper.sin(-var3 * 0.017453292F - (float)Math.PI);
2297                float var6 = -MathHelper.cos(-var2 * 0.017453292F);
2298                float var7 = MathHelper.sin(-var2 * 0.017453292F);
2299                return this.worldObj.getWorldVec3Pool().getVecFromPool((double)(var5 * var6), (double)var7, (double)(var4 * var6));
2300            }
2301        }
2302    
2303        @SideOnly(Side.CLIENT)
2304    
2305        /**
2306         * Returns render size modifier
2307         */
2308        public float getRenderSizeModifier()
2309        {
2310            return 1.0F;
2311        }
2312    
2313        @SideOnly(Side.CLIENT)
2314    
2315        /**
2316         * Performs a ray trace for the distance specified and using the partial tick time. Args: distance, partialTickTime
2317         */
2318        public MovingObjectPosition rayTrace(double par1, float par3)
2319        {
2320            Vec3 var4 = this.getPosition(par3);
2321            Vec3 var5 = this.getLook(par3);
2322            Vec3 var6 = var4.addVector(var5.xCoord * par1, var5.yCoord * par1, var5.zCoord * par1);
2323            return this.worldObj.rayTraceBlocks(var4, var6);
2324        }
2325    
2326        /**
2327         * Will return how many at most can spawn in a chunk at once.
2328         */
2329        public int getMaxSpawnedInChunk()
2330        {
2331            return 4;
2332        }
2333    
2334        @SideOnly(Side.CLIENT)
2335        public void handleHealthUpdate(byte par1)
2336        {
2337            if (par1 == 2)
2338            {
2339                this.legYaw = 1.5F;
2340                this.hurtResistantTime = this.maxHurtResistantTime;
2341                this.hurtTime = this.maxHurtTime = 10;
2342                this.attackedAtYaw = 0.0F;
2343                this.func_85030_a(this.getHurtSound(), this.getSoundVolume(), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
2344                this.attackEntityFrom(DamageSource.generic, 0);
2345            }
2346            else if (par1 == 3)
2347            {
2348                this.func_85030_a(this.getDeathSound(), this.getSoundVolume(), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
2349                this.health = 0;
2350                this.onDeath(DamageSource.generic);
2351            }
2352            else
2353            {
2354                super.handleHealthUpdate(par1);
2355            }
2356        }
2357    
2358        /**
2359         * Returns whether player is sleeping or not
2360         */
2361        public boolean isPlayerSleeping()
2362        {
2363            return false;
2364        }
2365    
2366        @SideOnly(Side.CLIENT)
2367    
2368        /**
2369         * Gets the Icon Index of the item currently held
2370         */
2371        public int getItemIcon(ItemStack par1ItemStack, int par2)
2372        {
2373            return par1ItemStack.getIconIndex();
2374        }
2375    
2376        protected void updatePotionEffects()
2377        {
2378            Iterator var1 = this.activePotionsMap.keySet().iterator();
2379    
2380            while (var1.hasNext())
2381            {
2382                Integer var2 = (Integer)var1.next();
2383                PotionEffect var3 = (PotionEffect)this.activePotionsMap.get(var2);
2384    
2385                if (!var3.onUpdate(this))
2386                {
2387                    if (!this.worldObj.isRemote)
2388                    {
2389                        var1.remove();
2390                        this.onFinishedPotionEffect(var3);
2391                    }
2392                }
2393                else if (var3.getDuration() % 600 == 0)
2394                {
2395                    this.onChangedPotionEffect(var3);
2396                }
2397            }
2398    
2399            int var11;
2400    
2401            if (this.potionsNeedUpdate)
2402            {
2403                if (!this.worldObj.isRemote)
2404                {
2405                    if (this.activePotionsMap.isEmpty())
2406                    {
2407                        this.dataWatcher.updateObject(9, Byte.valueOf((byte)0));
2408                        this.dataWatcher.updateObject(8, Integer.valueOf(0));
2409                        this.setHasActivePotion(false);
2410                    }
2411                    else
2412                    {
2413                        var11 = PotionHelper.calcPotionLiquidColor(this.activePotionsMap.values());
2414                        this.dataWatcher.updateObject(9, Byte.valueOf((byte)(PotionHelper.func_82817_b(this.activePotionsMap.values()) ? 1 : 0)));
2415                        this.dataWatcher.updateObject(8, Integer.valueOf(var11));
2416                        this.setHasActivePotion(this.isPotionActive(Potion.invisibility.id));
2417                    }
2418                }
2419    
2420                this.potionsNeedUpdate = false;
2421            }
2422    
2423            var11 = this.dataWatcher.getWatchableObjectInt(8);
2424            boolean var12 = this.dataWatcher.getWatchableObjectByte(9) > 0;
2425    
2426            if (var11 > 0)
2427            {
2428                boolean var4 = false;
2429    
2430                if (!this.getHasActivePotion())
2431                {
2432                    var4 = this.rand.nextBoolean();
2433                }
2434                else
2435                {
2436                    var4 = this.rand.nextInt(15) == 0;
2437                }
2438    
2439                if (var12)
2440                {
2441                    var4 &= this.rand.nextInt(5) == 0;
2442                }
2443    
2444                if (var4 && var11 > 0)
2445                {
2446                    double var5 = (double)(var11 >> 16 & 255) / 255.0D;
2447                    double var7 = (double)(var11 >> 8 & 255) / 255.0D;
2448                    double var9 = (double)(var11 >> 0 & 255) / 255.0D;
2449                    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);
2450                }
2451            }
2452        }
2453    
2454        public void clearActivePotions()
2455        {
2456            Iterator var1 = this.activePotionsMap.keySet().iterator();
2457    
2458            while (var1.hasNext())
2459            {
2460                Integer var2 = (Integer)var1.next();
2461                PotionEffect var3 = (PotionEffect)this.activePotionsMap.get(var2);
2462    
2463                if (!this.worldObj.isRemote)
2464                {
2465                    var1.remove();
2466                    this.onFinishedPotionEffect(var3);
2467                }
2468            }
2469        }
2470    
2471        public Collection getActivePotionEffects()
2472        {
2473            return this.activePotionsMap.values();
2474        }
2475    
2476        public boolean isPotionActive(int par1)
2477        {
2478            return this.activePotionsMap.containsKey(Integer.valueOf(par1));
2479        }
2480    
2481        public boolean isPotionActive(Potion par1Potion)
2482        {
2483            return this.activePotionsMap.containsKey(Integer.valueOf(par1Potion.id));
2484        }
2485    
2486        /**
2487         * returns the PotionEffect for the supplied Potion if it is active, null otherwise.
2488         */
2489        public PotionEffect getActivePotionEffect(Potion par1Potion)
2490        {
2491            return (PotionEffect)this.activePotionsMap.get(Integer.valueOf(par1Potion.id));
2492        }
2493    
2494        /**
2495         * adds a PotionEffect to the entity
2496         */
2497        public void addPotionEffect(PotionEffect par1PotionEffect)
2498        {
2499            if (this.isPotionApplicable(par1PotionEffect))
2500            {
2501                if (this.activePotionsMap.containsKey(Integer.valueOf(par1PotionEffect.getPotionID())))
2502                {
2503                    ((PotionEffect)this.activePotionsMap.get(Integer.valueOf(par1PotionEffect.getPotionID()))).combine(par1PotionEffect);
2504                    this.onChangedPotionEffect((PotionEffect)this.activePotionsMap.get(Integer.valueOf(par1PotionEffect.getPotionID())));
2505                }
2506                else
2507                {
2508                    this.activePotionsMap.put(Integer.valueOf(par1PotionEffect.getPotionID()), par1PotionEffect);
2509                    this.onNewPotionEffect(par1PotionEffect);
2510                }
2511            }
2512        }
2513    
2514        public boolean isPotionApplicable(PotionEffect par1PotionEffect)
2515        {
2516            if (this.getCreatureAttribute() == EnumCreatureAttribute.UNDEAD)
2517            {
2518                int var2 = par1PotionEffect.getPotionID();
2519    
2520                if (var2 == Potion.regeneration.id || var2 == Potion.poison.id)
2521                {
2522                    return false;
2523                }
2524            }
2525    
2526            return true;
2527        }
2528    
2529        /**
2530         * Returns true if this entity is undead.
2531         */
2532        public boolean isEntityUndead()
2533        {
2534            return this.getCreatureAttribute() == EnumCreatureAttribute.UNDEAD;
2535        }
2536    
2537        /**
2538         * Remove the speified potion effect from this entity.
2539         */
2540        public void removePotionEffectClient(int par1)
2541        {
2542            this.activePotionsMap.remove(Integer.valueOf(par1));
2543        }
2544    
2545        /**
2546         * Remove the specified potion effect from this entity.
2547         */
2548        public void removePotionEffect(int par1)
2549        {
2550            PotionEffect var2 = (PotionEffect)this.activePotionsMap.remove(Integer.valueOf(par1));
2551    
2552            if (var2 != null)
2553            {
2554                this.onFinishedPotionEffect(var2);
2555            }
2556        }
2557    
2558        protected void onNewPotionEffect(PotionEffect par1PotionEffect)
2559        {
2560            this.potionsNeedUpdate = true;
2561        }
2562    
2563        protected void onChangedPotionEffect(PotionEffect par1PotionEffect)
2564        {
2565            this.potionsNeedUpdate = true;
2566        }
2567    
2568        protected void onFinishedPotionEffect(PotionEffect par1PotionEffect)
2569        {
2570            this.potionsNeedUpdate = true;
2571        }
2572    
2573        /**
2574         * This method returns a value to be applied directly to entity speed, this factor is less than 1 when a slowdown
2575         * potion effect is applied, more than 1 when a haste potion effect is applied and 2 for fleeing entities.
2576         */
2577        public float getSpeedModifier()
2578        {
2579            float var1 = 1.0F;
2580    
2581            if (this.isPotionActive(Potion.moveSpeed))
2582            {
2583                var1 *= 1.0F + 0.2F * (float)(this.getActivePotionEffect(Potion.moveSpeed).getAmplifier() + 1);
2584            }
2585    
2586            if (this.isPotionActive(Potion.moveSlowdown))
2587            {
2588                var1 *= 1.0F - 0.15F * (float)(this.getActivePotionEffect(Potion.moveSlowdown).getAmplifier() + 1);
2589            }
2590    
2591            return var1;
2592        }
2593    
2594        /**
2595         * Move the entity to the coordinates informed, but keep yaw/pitch values.
2596         */
2597        public void setPositionAndUpdate(double par1, double par3, double par5)
2598        {
2599            this.setLocationAndAngles(par1, par3, par5, this.rotationYaw, this.rotationPitch);
2600        }
2601    
2602        /**
2603         * If Animal, checks if the age timer is negative
2604         */
2605        public boolean isChild()
2606        {
2607            return false;
2608        }
2609    
2610        /**
2611         * Get this Entity's EnumCreatureAttribute
2612         */
2613        public EnumCreatureAttribute getCreatureAttribute()
2614        {
2615            return EnumCreatureAttribute.UNDEFINED;
2616        }
2617    
2618        /**
2619         * Renders broken item particles using the given ItemStack
2620         */
2621        public void renderBrokenItemStack(ItemStack par1ItemStack)
2622        {
2623            this.func_85030_a("random.break", 0.8F, 0.8F + this.worldObj.rand.nextFloat() * 0.4F);
2624    
2625            for (int var2 = 0; var2 < 5; ++var2)
2626            {
2627                Vec3 var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
2628                var3.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
2629                var3.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
2630                Vec3 var4 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.3D, (double)(-this.rand.nextFloat()) * 0.6D - 0.3D, 0.6D);
2631                var4.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
2632                var4.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
2633                var4 = var4.addVector(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);
2634                this.worldObj.spawnParticle("iconcrack_" + par1ItemStack.getItem().shiftedIndex, var4.xCoord, var4.yCoord, var4.zCoord, var3.xCoord, var3.yCoord + 0.05D, var3.zCoord);
2635            }
2636        }
2637    
2638        public int func_82143_as()
2639        {
2640            if (this.getAttackTarget() == null)
2641            {
2642                return 3;
2643            }
2644            else
2645            {
2646                int var1 = (int)((float)this.health - (float)this.getMaxHealth() * 0.33F);
2647                var1 -= (3 - this.worldObj.difficultySetting) * 4;
2648    
2649                if (var1 < 0)
2650                {
2651                    var1 = 0;
2652                }
2653    
2654                return var1 + 3;
2655            }
2656        }
2657    
2658        /**
2659         * Returns the item that this EntityLiving is holding, if any.
2660         */
2661        public ItemStack getHeldItem()
2662        {
2663            return this.equipment[0];
2664        }
2665    
2666        /**
2667         * 0 = item, 1-n is armor
2668         */
2669        public ItemStack getCurrentItemOrArmor(int par1)
2670        {
2671            return this.equipment[par1];
2672        }
2673    
2674        public ItemStack getCurrentArmor(int par1)
2675        {
2676            return this.equipment[par1 + 1];
2677        }
2678    
2679        /**
2680         * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
2681         */
2682        public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
2683        {
2684            this.equipment[par1] = par2ItemStack;
2685        }
2686    
2687        public ItemStack[] getLastActiveItems()
2688        {
2689            return this.equipment;
2690        }
2691    
2692        /**
2693         * Drop the equipment for this entity.
2694         */
2695        protected void dropEquipment(boolean par1, int par2)
2696        {
2697            for (int var3 = 0; var3 < this.getLastActiveItems().length; ++var3)
2698            {
2699                ItemStack var4 = this.getCurrentItemOrArmor(var3);
2700                boolean var5 = this.equipmentDropChances[var3] > 1.0F;
2701    
2702                if (var4 != null && (par1 || var5) && this.rand.nextFloat() - (float)par2 * 0.01F < this.equipmentDropChances[var3])
2703                {
2704                    if (!var5 && var4.isItemStackDamageable())
2705                    {
2706                        int var6 = Math.max(var4.getMaxDamage() - 25, 1);
2707                        int var7 = var4.getMaxDamage() - this.rand.nextInt(this.rand.nextInt(var6) + 1);
2708    
2709                        if (var7 > var6)
2710                        {
2711                            var7 = var6;
2712                        }
2713    
2714                        if (var7 < 1)
2715                        {
2716                            var7 = 1;
2717                        }
2718    
2719                        var4.setItemDamage(var7);
2720                    }
2721    
2722                    this.entityDropItem(var4, 0.0F);
2723                }
2724            }
2725        }
2726    
2727        protected void func_82164_bB()
2728        {
2729            if (this.rand.nextFloat() < armorProbability[this.worldObj.difficultySetting])
2730            {
2731                int var1 = this.rand.nextInt(2);
2732                float var2 = this.worldObj.difficultySetting == 3 ? 0.1F : 0.25F;
2733    
2734                if (this.rand.nextFloat() < 0.1F)
2735                {
2736                    ++var1;
2737                }
2738    
2739                if (this.rand.nextFloat() < 0.1F)
2740                {
2741                    ++var1;
2742                }
2743    
2744                if (this.rand.nextFloat() < 0.1F)
2745                {
2746                    ++var1;
2747                }
2748    
2749                for (int var3 = 3; var3 >= 0; --var3)
2750                {
2751                    ItemStack var4 = this.getCurrentArmor(var3);
2752    
2753                    if (var3 < 3 && this.rand.nextFloat() < var2)
2754                    {
2755                        break;
2756                    }
2757    
2758                    if (var4 == null)
2759                    {
2760                        Item var5 = getArmorItemForSlot(var3 + 1, var1);
2761    
2762                        if (var5 != null)
2763                        {
2764                            this.setCurrentItemOrArmor(var3 + 1, new ItemStack(var5));
2765                        }
2766                    }
2767                }
2768            }
2769        }
2770    
2771        /**
2772         * Called whenever an item is picked up from walking over it. Args: pickedUpEntity, stackSize
2773         */
2774        public void onItemPickup(Entity par1Entity, int par2)
2775        {
2776            if (!par1Entity.isDead && !this.worldObj.isRemote)
2777            {
2778                EntityTracker var3 = ((WorldServer)this.worldObj).getEntityTracker();
2779    
2780                if (par1Entity instanceof EntityItem)
2781                {
2782                    var3.sendPacketToAllPlayersTrackingEntity(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
2783                }
2784    
2785                if (par1Entity instanceof EntityArrow)
2786                {
2787                    var3.sendPacketToAllPlayersTrackingEntity(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
2788                }
2789    
2790                if (par1Entity instanceof EntityXPOrb)
2791                {
2792                    var3.sendPacketToAllPlayersTrackingEntity(par1Entity, new Packet22Collect(par1Entity.entityId, this.entityId));
2793                }
2794            }
2795        }
2796    
2797        public static int func_82159_b(ItemStack par0ItemStack)
2798        {
2799            if (par0ItemStack.itemID != Block.pumpkin.blockID && par0ItemStack.itemID != Item.skull.shiftedIndex)
2800            {
2801                if (par0ItemStack.getItem() instanceof ItemArmor)
2802                {
2803                    switch (((ItemArmor)par0ItemStack.getItem()).armorType)
2804                    {
2805                        case 0:
2806                            return 4;
2807                        case 1:
2808                            return 3;
2809                        case 2:
2810                            return 2;
2811                        case 3:
2812                            return 1;
2813                    }
2814                }
2815    
2816                return 0;
2817            }
2818            else
2819            {
2820                return 4;
2821            }
2822        }
2823    
2824        /**
2825         * Params: Armor slot, Item tier
2826         */
2827        public static Item getArmorItemForSlot(int par0, int par1)
2828        {
2829            switch (par0)
2830            {
2831                case 4:
2832                    if (par1 == 0)
2833                    {
2834                        return Item.helmetLeather;
2835                    }
2836                    else if (par1 == 1)
2837                    {
2838                        return Item.helmetGold;
2839                    }
2840                    else if (par1 == 2)
2841                    {
2842                        return Item.helmetChain;
2843                    }
2844                    else if (par1 == 3)
2845                    {
2846                        return Item.helmetSteel;
2847                    }
2848                    else if (par1 == 4)
2849                    {
2850                        return Item.helmetDiamond;
2851                    }
2852                case 3:
2853                    if (par1 == 0)
2854                    {
2855                        return Item.plateLeather;
2856                    }
2857                    else if (par1 == 1)
2858                    {
2859                        return Item.plateGold;
2860                    }
2861                    else if (par1 == 2)
2862                    {
2863                        return Item.plateChain;
2864                    }
2865                    else if (par1 == 3)
2866                    {
2867                        return Item.plateSteel;
2868                    }
2869                    else if (par1 == 4)
2870                    {
2871                        return Item.plateDiamond;
2872                    }
2873                case 2:
2874                    if (par1 == 0)
2875                    {
2876                        return Item.legsLeather;
2877                    }
2878                    else if (par1 == 1)
2879                    {
2880                        return Item.legsGold;
2881                    }
2882                    else if (par1 == 2)
2883                    {
2884                        return Item.legsChain;
2885                    }
2886                    else if (par1 == 3)
2887                    {
2888                        return Item.legsSteel;
2889                    }
2890                    else if (par1 == 4)
2891                    {
2892                        return Item.legsDiamond;
2893                    }
2894                case 1:
2895                    if (par1 == 0)
2896                    {
2897                        return Item.bootsLeather;
2898                    }
2899                    else if (par1 == 1)
2900                    {
2901                        return Item.bootsGold;
2902                    }
2903                    else if (par1 == 2)
2904                    {
2905                        return Item.bootsChain;
2906                    }
2907                    else if (par1 == 3)
2908                    {
2909                        return Item.bootsSteel;
2910                    }
2911                    else if (par1 == 4)
2912                    {
2913                        return Item.bootsDiamond;
2914                    }
2915                default:
2916                    return null;
2917            }
2918        }
2919    
2920        protected void func_82162_bC()
2921        {
2922            if (this.getHeldItem() != null && this.rand.nextFloat() < enchantmentProbability[this.worldObj.difficultySetting])
2923            {
2924                EnchantmentHelper.addRandomEnchantment(this.rand, this.getHeldItem(), 5 + this.worldObj.difficultySetting * this.rand.nextInt(6));
2925            }
2926    
2927            for (int var1 = 0; var1 < 4; ++var1)
2928            {
2929                ItemStack var2 = this.getCurrentArmor(var1);
2930    
2931                if (var2 != null && this.rand.nextFloat() < armorEnchantmentProbability[this.worldObj.difficultySetting])
2932                {
2933                    EnchantmentHelper.addRandomEnchantment(this.rand, var2, 5 + this.worldObj.difficultySetting * this.rand.nextInt(6));
2934                }
2935            }
2936        }
2937    
2938        /**
2939         * Initialize this creature.
2940         */
2941        public void initCreature() {}
2942    
2943        /**
2944         * Returns an integer indicating the end point of the swing animation, used by {@link #swingProgress} to provide a
2945         * progress indicator. Takes dig speed enchantments into account.
2946         */
2947        private int getArmSwingAnimationEnd()
2948        {
2949            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);
2950        }
2951    
2952        /**
2953         * Swings the item the player is holding.
2954         */
2955        public void swingItem()
2956        {
2957            if (!this.isSwingInProgress || this.swingProgressInt >= this.getArmSwingAnimationEnd() / 2 || this.swingProgressInt < 0)
2958            {
2959                this.swingProgressInt = -1;
2960                this.isSwingInProgress = true;
2961    
2962                if (this.worldObj instanceof WorldServer)
2963                {
2964                    ((WorldServer)this.worldObj).getEntityTracker().sendPacketToAllPlayersTrackingEntity(this, new Packet18Animation(this, 1));
2965                }
2966            }
2967        }
2968    
2969        /**
2970         * returns true if all the conditions for steering the entity are met. For pigs, this is true if it is being ridden
2971         * by a player and the player is holding a carrot-on-a-stick
2972         */
2973        public boolean canBeSteered()
2974        {
2975            return false;
2976        }
2977    
2978        /**
2979         * counts the amount of arrows stuck in the entity. getting hit by arrows increases this, used in rendering
2980         */
2981        public final int getArrowCountInEntity()
2982        {
2983            return this.dataWatcher.getWatchableObjectByte(10);
2984        }
2985    
2986        /**
2987         * sets the amount of arrows stuck in the entity. used for rendering those
2988         */
2989        public final void setArrowCountInEntity(int par1)
2990        {
2991            this.dataWatcher.updateObject(10, Byte.valueOf((byte)par1));
2992        }
2993    
2994        /***
2995         * Removes all potion effects that have curativeItem as a curative item for its effect
2996         * @param curativeItem The itemstack we are using to cure potion effects
2997         */
2998        public void curePotionEffects(ItemStack curativeItem)
2999        {
3000            Iterator<Integer> potionKey = activePotionsMap.keySet().iterator();
3001    
3002            if (worldObj.isRemote)
3003            {
3004                return;
3005            }
3006    
3007            while (potionKey.hasNext())
3008            {
3009                Integer key = potionKey.next();
3010                PotionEffect effect = (PotionEffect)activePotionsMap.get(key);
3011    
3012                if (effect.isCurativeItem(curativeItem))
3013                {
3014                    potionKey.remove();
3015                    onFinishedPotionEffect(effect);
3016                }
3017            }
3018        }
3019    
3020        /** 
3021         * Returns true if the entity's rider (EntityPlayer) should face forward when mounted.
3022         * currently only used in vanilla code by pigs.
3023         * 
3024         * @param player The player who is riding the entity.
3025         * @return If the player should orient the same direction as this entity.
3026         */
3027        public boolean shouldRiderFaceForward(EntityPlayer player)
3028        {
3029            return this instanceof EntityPig;
3030        }
3031    }