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