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