001package net.minecraft.entity.player;
002
003import cpw.mods.fml.common.FMLCommonHandler;
004import cpw.mods.fml.common.network.FMLNetworkHandler;
005import cpw.mods.fml.relauncher.Side;
006import cpw.mods.fml.relauncher.SideOnly;
007import java.util.Iterator;
008import java.util.List;
009import net.minecraft.block.Block;
010import net.minecraft.block.BlockBed;
011import net.minecraft.block.material.Material;
012import net.minecraft.command.ICommandSender;
013import net.minecraft.enchantment.EnchantmentHelper;
014import net.minecraft.enchantment.EnchantmentThorns;
015import net.minecraft.entity.Entity;
016import net.minecraft.entity.EntityLiving;
017import net.minecraft.entity.IMerchant;
018import net.minecraft.entity.item.EntityBoat;
019import net.minecraft.entity.item.EntityItem;
020import net.minecraft.entity.item.EntityMinecart;
021import net.minecraft.entity.monster.EntityCreeper;
022import net.minecraft.entity.monster.EntityGhast;
023import net.minecraft.entity.monster.EntityMob;
024import net.minecraft.entity.monster.IMob;
025import net.minecraft.entity.passive.EntityPig;
026import net.minecraft.entity.passive.EntityWolf;
027import net.minecraft.entity.projectile.EntityArrow;
028import net.minecraft.entity.projectile.EntityFishHook;
029import net.minecraft.inventory.Container;
030import net.minecraft.inventory.ContainerPlayer;
031import net.minecraft.inventory.IInventory;
032import net.minecraft.inventory.InventoryEnderChest;
033import net.minecraft.item.EnumAction;
034import net.minecraft.item.Item;
035import net.minecraft.item.ItemStack;
036import net.minecraft.nbt.NBTTagCompound;
037import net.minecraft.nbt.NBTTagList;
038import net.minecraft.potion.Potion;
039import net.minecraft.stats.AchievementList;
040import net.minecraft.stats.StatBase;
041import net.minecraft.stats.StatList;
042import net.minecraft.tileentity.TileEntity;
043import net.minecraft.tileentity.TileEntityBeacon;
044import net.minecraft.tileentity.TileEntityBrewingStand;
045import net.minecraft.tileentity.TileEntityDispenser;
046import net.minecraft.tileentity.TileEntityFurnace;
047import net.minecraft.util.AxisAlignedBB;
048import net.minecraft.util.ChunkCoordinates;
049import net.minecraft.util.DamageSource;
050import net.minecraft.util.FoodStats;
051import net.minecraft.util.MathHelper;
052import net.minecraft.util.StringTranslate;
053import net.minecraft.util.Vec3;
054import net.minecraft.world.EnumGameType;
055import net.minecraft.world.World;
056import net.minecraft.world.chunk.IChunkProvider;
057
058import net.minecraftforge.common.ForgeHooks;
059import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
060import net.minecraftforge.common.MinecraftForge;
061import net.minecraftforge.event.ForgeEventFactory;
062import net.minecraftforge.event.entity.living.LivingHurtEvent;
063import net.minecraftforge.event.entity.player.AttackEntityEvent;
064import net.minecraftforge.event.entity.player.EntityInteractEvent;
065import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
066import net.minecraftforge.event.entity.player.PlayerDropsEvent;
067import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
068
069public abstract class EntityPlayer extends EntityLiving implements ICommandSender
070{
071    public static final String PERSISTED_NBT_TAG = "PlayerPersisted";
072
073    /** Inventory of the player */
074    public InventoryPlayer inventory = new InventoryPlayer(this);
075    private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest();
076
077    /**
078     * The Container for the player's inventory (which opens when they press E)
079     */
080    public Container inventoryContainer;
081
082    /** The Container the player has open. */
083    public Container openContainer;
084
085    /** The player's food stats. (See class FoodStats) */
086    protected FoodStats foodStats = new FoodStats();
087
088    /**
089     * Used to tell if the player pressed jump twice. If this is at 0 and it's pressed (And they are allowed to fly, as
090     * defined in the player's movementInput) it sets this to 7. If it's pressed and it's greater than 0 enable fly.
091     */
092    protected int flyToggleTimer = 0;
093    public byte field_71098_bD = 0;
094    public float prevCameraYaw;
095    public float cameraYaw;
096    public String username;
097    @SideOnly(Side.CLIENT)
098    public String playerCloakUrl;
099
100    /**
101     * Used by EntityPlayer to prevent too many xp orbs from getting absorbed at once.
102     */
103    public int xpCooldown = 0;
104    public double field_71091_bM;
105    public double field_71096_bN;
106    public double field_71097_bO;
107    public double field_71094_bP;
108    public double field_71095_bQ;
109    public double field_71085_bR;
110
111    /** Boolean value indicating weather a player is sleeping or not */
112    protected boolean sleeping;
113
114    /**
115     * The chunk coordinates of the bed the player is in (null if player isn't in a bed).
116     */
117    public ChunkCoordinates playerLocation;
118    private int sleepTimer;
119    public float field_71079_bU;
120    @SideOnly(Side.CLIENT)
121    public float field_71082_cx;
122    public float field_71089_bV;
123
124    /**
125     * Holds the last coordinate to spawn based on last bed that the player sleep.
126     */
127    private ChunkCoordinates spawnChunk;
128
129    /**
130     * Whether this player's spawn point is forced, preventing execution of bed checks.
131     */
132    private boolean spawnForced;
133
134    /** Holds the coordinate of the player when enter a minecraft to ride. */
135    private ChunkCoordinates startMinecartRidingCoordinate;
136
137    /** The player's capabilities. (See class PlayerCapabilities) */
138    public PlayerCapabilities capabilities = new PlayerCapabilities();
139
140    /** The current experience level the player is on. */
141    public int experienceLevel;
142
143    /**
144     * The total amount of experience the player has. This also includes the amount of experience within their
145     * Experience Bar.
146     */
147    public int experienceTotal;
148
149    /**
150     * The current amount of experience the player has within their Experience Bar.
151     */
152    public float experience;
153
154    /**
155     * This is the item that is in use when the player is holding down the useItemButton (e.g., bow, food, sword)
156     */
157    private ItemStack itemInUse;
158
159    /**
160     * This field starts off equal to getMaxItemUseDuration and is decremented on each tick
161     */
162    private int itemInUseCount;
163    protected float speedOnGround = 0.1F;
164    protected float speedInAir = 0.02F;
165    private int field_82249_h = 0;
166
167    /**
168     * An instance of a fishing rod's hook. If this isn't null, the icon image of the fishing rod is slightly different
169     */
170    public EntityFishHook fishEntity = null;
171
172    public EntityPlayer(World par1World)
173    {
174        super(par1World);
175        this.inventoryContainer = new ContainerPlayer(this.inventory, !par1World.isRemote, this);
176        this.openContainer = this.inventoryContainer;
177        this.yOffset = 1.62F;
178        ChunkCoordinates var2 = par1World.getSpawnPoint();
179        this.setLocationAndAngles((double)var2.posX + 0.5D, (double)(var2.posY + 1), (double)var2.posZ + 0.5D, 0.0F, 0.0F);
180        this.entityType = "humanoid";
181        this.field_70741_aB = 180.0F;
182        this.fireResistance = 20;
183        this.texture = "/mob/char.png";
184    }
185
186    public int getMaxHealth()
187    {
188        return 20;
189    }
190
191    protected void entityInit()
192    {
193        super.entityInit();
194        this.dataWatcher.addObject(16, Byte.valueOf((byte)0));
195        this.dataWatcher.addObject(17, Byte.valueOf((byte)0));
196        this.dataWatcher.addObject(18, Integer.valueOf(0));
197    }
198
199    @SideOnly(Side.CLIENT)
200
201    /**
202     * returns the ItemStack containing the itemInUse
203     */
204    public ItemStack getItemInUse()
205    {
206        return this.itemInUse;
207    }
208
209    @SideOnly(Side.CLIENT)
210
211    /**
212     * Returns the item in use count
213     */
214    public int getItemInUseCount()
215    {
216        return this.itemInUseCount;
217    }
218
219    /**
220     * Checks if the entity is currently using an item (e.g., bow, food, sword) by holding down the useItemButton
221     */
222    public boolean isUsingItem()
223    {
224        return this.itemInUse != null;
225    }
226
227    @SideOnly(Side.CLIENT)
228
229    /**
230     * gets the duration for how long the current itemInUse has been in use
231     */
232    public int getItemInUseDuration()
233    {
234        return this.isUsingItem() ? this.itemInUse.getMaxItemUseDuration() - this.itemInUseCount : 0;
235    }
236
237    public void stopUsingItem()
238    {
239        if (this.itemInUse != null)
240        {
241            this.itemInUse.onPlayerStoppedUsing(this.worldObj, this, this.itemInUseCount);
242        }
243
244        this.clearItemInUse();
245    }
246
247    public void clearItemInUse()
248    {
249        this.itemInUse = null;
250        this.itemInUseCount = 0;
251
252        if (!this.worldObj.isRemote)
253        {
254            this.setEating(false);
255        }
256    }
257
258    public boolean isBlocking()
259    {
260        return this.isUsingItem() && Item.itemsList[this.itemInUse.itemID].getItemUseAction(this.itemInUse) == EnumAction.block;
261    }
262
263    /**
264     * Called to update the entity's position/logic.
265     */
266    public void onUpdate()
267    {
268        FMLCommonHandler.instance().onPlayerPreTick(this);
269        if (this.itemInUse != null)
270        {
271            ItemStack var1 = this.inventory.getCurrentItem();
272
273            if (var1 == this.itemInUse)
274            {
275                itemInUse.getItem().onUsingItemTick(itemInUse, this, itemInUseCount);
276                if (this.itemInUseCount <= 25 && this.itemInUseCount % 4 == 0)
277                {
278                    this.updateItemUse(var1, 5);
279                }
280
281                if (--this.itemInUseCount == 0 && !this.worldObj.isRemote)
282                {
283                    this.onItemUseFinish();
284                }
285            }
286            else
287            {
288                this.clearItemInUse();
289            }
290        }
291
292        if (this.xpCooldown > 0)
293        {
294            --this.xpCooldown;
295        }
296
297        if (this.isPlayerSleeping())
298        {
299            ++this.sleepTimer;
300
301            if (this.sleepTimer > 100)
302            {
303                this.sleepTimer = 100;
304            }
305
306            if (!this.worldObj.isRemote)
307            {
308                if (!this.isInBed())
309                {
310                    this.wakeUpPlayer(true, true, false);
311                }
312                else if (this.worldObj.isDaytime())
313                {
314                    this.wakeUpPlayer(false, true, true);
315                }
316            }
317        }
318        else if (this.sleepTimer > 0)
319        {
320            ++this.sleepTimer;
321
322            if (this.sleepTimer >= 110)
323            {
324                this.sleepTimer = 0;
325            }
326        }
327
328        super.onUpdate();
329
330        if (!this.worldObj.isRemote && this.openContainer != null && !this.openContainer.canInteractWith(this))
331        {
332            this.closeScreen();
333            this.openContainer = this.inventoryContainer;
334        }
335
336        if (this.isBurning() && this.capabilities.disableDamage)
337        {
338            this.extinguish();
339        }
340
341        this.field_71091_bM = this.field_71094_bP;
342        this.field_71096_bN = this.field_71095_bQ;
343        this.field_71097_bO = this.field_71085_bR;
344        double var9 = this.posX - this.field_71094_bP;
345        double var3 = this.posY - this.field_71095_bQ;
346        double var5 = this.posZ - this.field_71085_bR;
347        double var7 = 10.0D;
348
349        if (var9 > var7)
350        {
351            this.field_71091_bM = this.field_71094_bP = this.posX;
352        }
353
354        if (var5 > var7)
355        {
356            this.field_71097_bO = this.field_71085_bR = this.posZ;
357        }
358
359        if (var3 > var7)
360        {
361            this.field_71096_bN = this.field_71095_bQ = this.posY;
362        }
363
364        if (var9 < -var7)
365        {
366            this.field_71091_bM = this.field_71094_bP = this.posX;
367        }
368
369        if (var5 < -var7)
370        {
371            this.field_71097_bO = this.field_71085_bR = this.posZ;
372        }
373
374        if (var3 < -var7)
375        {
376            this.field_71096_bN = this.field_71095_bQ = this.posY;
377        }
378
379        this.field_71094_bP += var9 * 0.25D;
380        this.field_71085_bR += var5 * 0.25D;
381        this.field_71095_bQ += var3 * 0.25D;
382        this.addStat(StatList.minutesPlayedStat, 1);
383
384        if (this.ridingEntity == null)
385        {
386            this.startMinecartRidingCoordinate = null;
387        }
388
389        if (!this.worldObj.isRemote)
390        {
391            this.foodStats.onUpdate(this);
392        }
393        FMLCommonHandler.instance().onPlayerPostTick(this);
394    }
395
396    /**
397     * Return the amount of time this entity should stay in a portal before being transported.
398     */
399    public int getMaxInPortalTime()
400    {
401        return this.capabilities.disableDamage ? 0 : 80;
402    }
403
404    /**
405     * Return the amount of cooldown before this entity can use a portal again.
406     */
407    public int getPortalCooldown()
408    {
409        return 10;
410    }
411
412    public void playSound(String par1Str, float par2, float par3)
413    {
414        this.worldObj.playSoundToNearExcept(this, par1Str, par2, par3);
415    }
416
417    /**
418     * Plays sounds and makes particles for item in use state
419     */
420    protected void updateItemUse(ItemStack par1ItemStack, int par2)
421    {
422        if (par1ItemStack.getItemUseAction() == EnumAction.drink)
423        {
424            this.playSound("random.drink", 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F);
425        }
426
427        if (par1ItemStack.getItemUseAction() == EnumAction.eat)
428        {
429            for (int var3 = 0; var3 < par2; ++var3)
430            {
431                Vec3 var4 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D);
432                var4.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
433                var4.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
434                Vec3 var5 = this.worldObj.getWorldVec3Pool().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.3D, (double)(-this.rand.nextFloat()) * 0.6D - 0.3D, 0.6D);
435                var5.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F);
436                var5.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F);
437                var5 = var5.addVector(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ);
438                this.worldObj.spawnParticle("iconcrack_" + par1ItemStack.getItem().itemID, var5.xCoord, var5.yCoord, var5.zCoord, var4.xCoord, var4.yCoord + 0.05D, var4.zCoord);
439            }
440
441            this.playSound("random.eat", 0.5F + 0.5F * (float)this.rand.nextInt(2), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
442        }
443    }
444
445    /**
446     * Used for when item use count runs out, ie: eating completed
447     */
448    protected void onItemUseFinish()
449    {
450        if (this.itemInUse != null)
451        {
452            this.updateItemUse(this.itemInUse, 16);
453            int var1 = this.itemInUse.stackSize;
454            ItemStack var2 = this.itemInUse.onFoodEaten(this.worldObj, this);
455
456            if (var2 != this.itemInUse || var2 != null && var2.stackSize != var1)
457            {
458                this.inventory.mainInventory[this.inventory.currentItem] = var2;
459
460                if (var2.stackSize == 0)
461                {
462                    this.inventory.mainInventory[this.inventory.currentItem] = null;
463                }
464            }
465
466            this.clearItemInUse();
467        }
468    }
469
470    @SideOnly(Side.CLIENT)
471    public void handleHealthUpdate(byte par1)
472    {
473        if (par1 == 9)
474        {
475            this.onItemUseFinish();
476        }
477        else
478        {
479            super.handleHealthUpdate(par1);
480        }
481    }
482
483    /**
484     * Dead and sleeping entities cannot move
485     */
486    protected boolean isMovementBlocked()
487    {
488        return this.getHealth() <= 0 || this.isPlayerSleeping();
489    }
490
491    /**
492     * sets current screen to null (used on escape buttons of GUIs)
493     */
494    public void closeScreen()
495    {
496        this.openContainer = this.inventoryContainer;
497    }
498
499    /**
500     * Handles updating while being ridden by an entity
501     */
502    public void updateRidden()
503    {
504        double var1 = this.posX;
505        double var3 = this.posY;
506        double var5 = this.posZ;
507        float var7 = this.rotationYaw;
508        float var8 = this.rotationPitch;
509        super.updateRidden();
510        this.prevCameraYaw = this.cameraYaw;
511        this.cameraYaw = 0.0F;
512        this.addMountedMovementStat(this.posX - var1, this.posY - var3, this.posZ - var5);
513
514        if (this.ridingEntity instanceof EntityLiving && ((EntityLiving)ridingEntity).shouldRiderFaceForward(this))
515        {
516            this.rotationPitch = var8;
517            this.rotationYaw = var7;
518            this.renderYawOffset = ((EntityLiving)this.ridingEntity).renderYawOffset;
519        }
520    }
521
522    @SideOnly(Side.CLIENT)
523
524    /**
525     * Keeps moving the entity up so it isn't colliding with blocks and other requirements for this entity to be spawned
526     * (only actually used on players though its also on Entity)
527     */
528    public void preparePlayerToSpawn()
529    {
530        this.yOffset = 1.62F;
531        this.setSize(0.6F, 1.8F);
532        super.preparePlayerToSpawn();
533        this.setEntityHealth(this.getMaxHealth());
534        this.deathTime = 0;
535    }
536
537    protected void updateEntityActionState()
538    {
539        this.updateArmSwingProgress();
540    }
541
542    /**
543     * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
544     * use this to react to sunlight and start to burn.
545     */
546    public void onLivingUpdate()
547    {
548        if (this.flyToggleTimer > 0)
549        {
550            --this.flyToggleTimer;
551        }
552
553        if (this.worldObj.difficultySetting == 0 && this.getHealth() < this.getMaxHealth() && this.ticksExisted % 20 * 12 == 0)
554        {
555            this.heal(1);
556        }
557
558        this.inventory.decrementAnimations();
559        this.prevCameraYaw = this.cameraYaw;
560        super.onLivingUpdate();
561        this.landMovementFactor = this.capabilities.getWalkSpeed();
562        this.jumpMovementFactor = this.speedInAir;
563
564        if (this.isSprinting())
565        {
566            this.landMovementFactor = (float)((double)this.landMovementFactor + (double)this.capabilities.getWalkSpeed() * 0.3D);
567            this.jumpMovementFactor = (float)((double)this.jumpMovementFactor + (double)this.speedInAir * 0.3D);
568        }
569
570        float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
571        float var2 = (float)Math.atan(-this.motionY * 0.20000000298023224D) * 15.0F;
572
573        if (var1 > 0.1F)
574        {
575            var1 = 0.1F;
576        }
577
578        if (!this.onGround || this.getHealth() <= 0)
579        {
580            var1 = 0.0F;
581        }
582
583        if (this.onGround || this.getHealth() <= 0)
584        {
585            var2 = 0.0F;
586        }
587
588        this.cameraYaw += (var1 - this.cameraYaw) * 0.4F;
589        this.cameraPitch += (var2 - this.cameraPitch) * 0.8F;
590
591        if (this.getHealth() > 0)
592        {
593            List var3 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(1.0D, 0.5D, 1.0D));
594
595            if (var3 != null)
596            {
597                for (int var4 = 0; var4 < var3.size(); ++var4)
598                {
599                    Entity var5 = (Entity)var3.get(var4);
600
601                    if (!var5.isDead)
602                    {
603                        this.collideWithPlayer(var5);
604                    }
605                }
606            }
607        }
608    }
609
610    private void collideWithPlayer(Entity par1Entity)
611    {
612        par1Entity.onCollideWithPlayer(this);
613    }
614
615    public int getScore()
616    {
617        return this.dataWatcher.getWatchableObjectInt(18);
618    }
619
620    /**
621     * Set player's score
622     */
623    public void setScore(int par1)
624    {
625        this.dataWatcher.updateObject(18, Integer.valueOf(par1));
626    }
627
628    /**
629     * Add to player's score
630     */
631    public void addScore(int par1)
632    {
633        int var2 = this.getScore();
634        this.dataWatcher.updateObject(18, Integer.valueOf(var2 + par1));
635    }
636
637    /**
638     * Called when the mob's health reaches 0.
639     */
640    public void onDeath(DamageSource par1DamageSource)
641    {
642        super.onDeath(par1DamageSource);
643        this.setSize(0.2F, 0.2F);
644        this.setPosition(this.posX, this.posY, this.posZ);
645        this.motionY = 0.10000000149011612D;
646
647        captureDrops = true;
648        capturedDrops.clear();
649
650        if (this.username.equals("Notch"))
651        {
652            this.dropPlayerItemWithRandomChoice(new ItemStack(Item.appleRed, 1), true);
653        }
654
655        if (!this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
656        {
657            this.inventory.dropAllItems();
658        }
659
660        captureDrops = false;
661
662        if (!worldObj.isRemote)
663        {
664            PlayerDropsEvent event = new PlayerDropsEvent(this, par1DamageSource, capturedDrops, recentlyHit > 0);
665            if (!MinecraftForge.EVENT_BUS.post(event))
666            {
667                for (EntityItem item : capturedDrops)
668                {
669                    joinEntityItemWithWorld(item);
670                }
671            }
672        }
673
674        if (par1DamageSource != null)
675        {
676            this.motionX = (double)(-MathHelper.cos((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F);
677            this.motionZ = (double)(-MathHelper.sin((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F);
678        }
679        else
680        {
681            this.motionX = this.motionZ = 0.0D;
682        }
683
684        this.yOffset = 0.1F;
685        this.addStat(StatList.deathsStat, 1);
686    }
687
688    /**
689     * Adds a value to the player score. Currently not actually used and the entity passed in does nothing. Args:
690     * entity, scoreToAdd
691     */
692    public void addToPlayerScore(Entity par1Entity, int par2)
693    {
694        this.addScore(par2);
695
696        if (par1Entity instanceof EntityPlayer)
697        {
698            this.addStat(StatList.playerKillsStat, 1);
699        }
700        else
701        {
702            this.addStat(StatList.mobKillsStat, 1);
703        }
704    }
705
706    /**
707     * Called when player presses the drop item key
708     */
709    public EntityItem dropOneItem(boolean par1)
710    {
711        ItemStack stack = inventory.getCurrentItem();
712
713        if (stack == null)
714        {
715            return null;
716        }
717
718        if (stack.getItem().onDroppedByPlayer(stack, this))
719        {
720            int count = par1 && this.inventory.getCurrentItem() != null ? this.inventory.getCurrentItem().stackSize : 1;
721            return ForgeHooks.onPlayerTossEvent(this, inventory.decrStackSize(inventory.currentItem, count));
722        }
723
724        return null;
725    }
726
727    /**
728     * Args: itemstack - called when player drops an item stack that's not in his inventory (like items still placed in
729     * a workbench while the workbench'es GUI gets closed)
730     */
731    public EntityItem dropPlayerItem(ItemStack par1ItemStack)
732    {
733        return ForgeHooks.onPlayerTossEvent(this, par1ItemStack);
734    }
735
736    /**
737     * Args: itemstack, flag
738     */
739    public EntityItem dropPlayerItemWithRandomChoice(ItemStack par1ItemStack, boolean par2)
740    {
741        if (par1ItemStack == null)
742        {
743            return null;
744        }
745        else
746        {
747            EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY - 0.30000001192092896D + (double)this.getEyeHeight(), this.posZ, par1ItemStack);
748            var3.delayBeforeCanPickup = 40;
749            float var4 = 0.1F;
750            float var5;
751
752            if (par2)
753            {
754                var5 = this.rand.nextFloat() * 0.5F;
755                float var6 = this.rand.nextFloat() * (float)Math.PI * 2.0F;
756                var3.motionX = (double)(-MathHelper.sin(var6) * var5);
757                var3.motionZ = (double)(MathHelper.cos(var6) * var5);
758                var3.motionY = 0.20000000298023224D;
759            }
760            else
761            {
762                var4 = 0.3F;
763                var3.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4);
764                var3.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4);
765                var3.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI) * var4 + 0.1F);
766                var4 = 0.02F;
767                var5 = this.rand.nextFloat() * (float)Math.PI * 2.0F;
768                var4 *= this.rand.nextFloat();
769                var3.motionX += Math.cos((double)var5) * (double)var4;
770                var3.motionY += (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F);
771                var3.motionZ += Math.sin((double)var5) * (double)var4;
772            }
773
774            this.joinEntityItemWithWorld(var3);
775            this.addStat(StatList.dropStat, 1);
776            return var3;
777        }
778    }
779
780    /**
781     * Joins the passed in entity item with the world. Args: entityItem
782     */
783    public void joinEntityItemWithWorld(EntityItem par1EntityItem)
784    {
785        if (captureDrops)
786        {
787            capturedDrops.add(par1EntityItem);
788        }
789        else
790        {
791            this.worldObj.spawnEntityInWorld(par1EntityItem);
792        }
793    }
794
795    /**
796     * Returns how strong the player is against the specified block at this moment
797     * Deprecated in favor of the more sensitive version
798     */
799    @Deprecated
800    public float getCurrentPlayerStrVsBlock(Block par1Block)
801    {
802        return getCurrentPlayerStrVsBlock(par1Block, 0);
803    }
804
805    public float getCurrentPlayerStrVsBlock(Block par1Block, int meta)
806    {
807        ItemStack stack = inventory.getCurrentItem();
808        float var2 = (stack == null ? 1.0F : stack.getItem().getStrVsBlock(stack, par1Block, meta));
809        int var3 = EnchantmentHelper.getEfficiencyModifier(this);
810        ItemStack var4 = this.inventory.getCurrentItem();
811
812        if (var3 > 0 && var4 != null)
813        {
814            float var5 = (float)(var3 * var3 + 1);
815            boolean canHarvest = ForgeHooks.canToolHarvestBlock(par1Block, meta, var4);
816
817            if (!canHarvest && var2 <= 1.0F)
818            {
819                var2 += var5 * 0.08F;
820            }
821            else
822            {
823                var2 += var5;
824            }
825        }
826
827        if (this.isPotionActive(Potion.digSpeed))
828        {
829            var2 *= 1.0F + (float)(this.getActivePotionEffect(Potion.digSpeed).getAmplifier() + 1) * 0.2F;
830        }
831
832        if (this.isPotionActive(Potion.digSlowdown))
833        {
834            var2 *= 1.0F - (float)(this.getActivePotionEffect(Potion.digSlowdown).getAmplifier() + 1) * 0.2F;
835        }
836
837        if (this.isInsideOfMaterial(Material.water) && !EnchantmentHelper.getAquaAffinityModifier(this))
838        {
839            var2 /= 5.0F;
840        }
841
842        if (!this.onGround)
843        {
844            var2 /= 5.0F;
845        }
846
847        var2 = ForgeEventFactory.getBreakSpeed(this, par1Block, meta, var2);
848        return (var2 < 0 ? 0 : var2);
849    }
850
851    /**
852     * Checks if the player has the ability to harvest a block (checks current inventory item for a tool if necessary)
853     */
854    public boolean canHarvestBlock(Block par1Block)
855    {
856        return ForgeEventFactory.doPlayerHarvestCheck(this, par1Block, inventory.canHarvestBlock(par1Block));
857    }
858
859    /**
860     * (abstract) Protected helper method to read subclass entity data from NBT.
861     */
862    public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
863    {
864        super.readEntityFromNBT(par1NBTTagCompound);
865        NBTTagList var2 = par1NBTTagCompound.getTagList("Inventory");
866        this.inventory.readFromNBT(var2);
867        this.inventory.currentItem = par1NBTTagCompound.getInteger("SelectedItemSlot");
868        this.sleeping = par1NBTTagCompound.getBoolean("Sleeping");
869        this.sleepTimer = par1NBTTagCompound.getShort("SleepTimer");
870        this.experience = par1NBTTagCompound.getFloat("XpP");
871        this.experienceLevel = par1NBTTagCompound.getInteger("XpLevel");
872        this.experienceTotal = par1NBTTagCompound.getInteger("XpTotal");
873        this.setScore(par1NBTTagCompound.getInteger("Score"));
874
875        if (this.sleeping)
876        {
877            this.playerLocation = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
878            this.wakeUpPlayer(true, true, false);
879        }
880
881        if (par1NBTTagCompound.hasKey("SpawnX") && par1NBTTagCompound.hasKey("SpawnY") && par1NBTTagCompound.hasKey("SpawnZ"))
882        {
883            this.spawnChunk = new ChunkCoordinates(par1NBTTagCompound.getInteger("SpawnX"), par1NBTTagCompound.getInteger("SpawnY"), par1NBTTagCompound.getInteger("SpawnZ"));
884            this.spawnForced = par1NBTTagCompound.getBoolean("SpawnForced");
885        }
886
887        this.foodStats.readNBT(par1NBTTagCompound);
888        this.capabilities.readCapabilitiesFromNBT(par1NBTTagCompound);
889
890        if (par1NBTTagCompound.hasKey("EnderItems"))
891        {
892            NBTTagList var3 = par1NBTTagCompound.getTagList("EnderItems");
893            this.theInventoryEnderChest.loadInventoryFromNBT(var3);
894        }
895    }
896
897    /**
898     * (abstract) Protected helper method to write subclass entity data to NBT.
899     */
900    public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
901    {
902        super.writeEntityToNBT(par1NBTTagCompound);
903        par1NBTTagCompound.setTag("Inventory", this.inventory.writeToNBT(new NBTTagList()));
904        par1NBTTagCompound.setInteger("SelectedItemSlot", this.inventory.currentItem);
905        par1NBTTagCompound.setBoolean("Sleeping", this.sleeping);
906        par1NBTTagCompound.setShort("SleepTimer", (short)this.sleepTimer);
907        par1NBTTagCompound.setFloat("XpP", this.experience);
908        par1NBTTagCompound.setInteger("XpLevel", this.experienceLevel);
909        par1NBTTagCompound.setInteger("XpTotal", this.experienceTotal);
910        par1NBTTagCompound.setInteger("Score", this.getScore());
911
912        if (this.spawnChunk != null)
913        {
914            par1NBTTagCompound.setInteger("SpawnX", this.spawnChunk.posX);
915            par1NBTTagCompound.setInteger("SpawnY", this.spawnChunk.posY);
916            par1NBTTagCompound.setInteger("SpawnZ", this.spawnChunk.posZ);
917            par1NBTTagCompound.setBoolean("SpawnForced", this.spawnForced);
918        }
919
920        this.foodStats.writeNBT(par1NBTTagCompound);
921        this.capabilities.writeCapabilitiesToNBT(par1NBTTagCompound);
922        par1NBTTagCompound.setTag("EnderItems", this.theInventoryEnderChest.saveInventoryToNBT());
923    }
924
925    /**
926     * Displays the GUI for interacting with a chest inventory. Args: chestInventory
927     */
928    public void displayGUIChest(IInventory par1IInventory) {}
929
930    public void displayGUIEnchantment(int par1, int par2, int par3) {}
931
932    /**
933     * Displays the GUI for interacting with an anvil.
934     */
935    public void displayGUIAnvil(int par1, int par2, int par3) {}
936
937    /**
938     * Displays the crafting GUI for a workbench.
939     */
940    public void displayGUIWorkbench(int par1, int par2, int par3) {}
941
942    public float getEyeHeight()
943    {
944        return 0.12F;
945    }
946
947    /**
948     * sets the players height back to normal after doing things like sleeping and dieing
949     */
950    protected void resetHeight()
951    {
952        this.yOffset = 1.62F;
953    }
954
955    /**
956     * Called when the entity is attacked.
957     */
958    public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
959    {
960        if (this.isEntityInvulnerable())
961        {
962            return false;
963        }
964        else if (this.capabilities.disableDamage && !par1DamageSource.canHarmInCreative())
965        {
966            return false;
967        }
968        else
969        {
970            this.entityAge = 0;
971
972            if (this.getHealth() <= 0)
973            {
974                return false;
975            }
976            else
977            {
978                if (this.isPlayerSleeping() && !this.worldObj.isRemote)
979                {
980                    this.wakeUpPlayer(true, true, false);
981                }
982
983                if (par1DamageSource.isDifficultyScaled())
984                {
985                    if (this.worldObj.difficultySetting == 0)
986                    {
987                        par2 = 0;
988                    }
989
990                    if (this.worldObj.difficultySetting == 1)
991                    {
992                        par2 = par2 / 2 + 1;
993                    }
994
995                    if (this.worldObj.difficultySetting == 3)
996                    {
997                        par2 = par2 * 3 / 2;
998                    }
999                }
1000
1001                if (par2 == 0)
1002                {
1003                    return false;
1004                }
1005                else
1006                {
1007                    Entity var3 = par1DamageSource.getEntity();
1008
1009                    if (var3 instanceof EntityArrow && ((EntityArrow)var3).shootingEntity != null)
1010                    {
1011                        var3 = ((EntityArrow)var3).shootingEntity;
1012                    }
1013
1014                    if (var3 instanceof EntityLiving)
1015                    {
1016                        this.alertWolves((EntityLiving)var3, false);
1017                    }
1018
1019                    this.addStat(StatList.damageTakenStat, par2);
1020                    return super.attackEntityFrom(par1DamageSource, par2);
1021                }
1022            }
1023        }
1024    }
1025
1026    /**
1027     * Reduces damage, depending on potions
1028     */
1029    protected int applyPotionDamageCalculations(DamageSource par1DamageSource, int par2)
1030    {
1031        int var3 = super.applyPotionDamageCalculations(par1DamageSource, par2);
1032
1033        if (var3 <= 0)
1034        {
1035            return 0;
1036        }
1037        else
1038        {
1039            int var4 = EnchantmentHelper.getEnchantmentModifierDamage(this.inventory.armorInventory, par1DamageSource);
1040
1041            if (var4 > 20)
1042            {
1043                var4 = 20;
1044            }
1045
1046            if (var4 > 0 && var4 <= 20)
1047            {
1048                int var5 = 25 - var4;
1049                int var6 = var3 * var5 + this.carryoverDamage;
1050                var3 = var6 / 25;
1051                this.carryoverDamage = var6 % 25;
1052            }
1053
1054            return var3;
1055        }
1056    }
1057
1058    /**
1059     * returns if pvp is enabled or not
1060     */
1061    protected boolean isPVPEnabled()
1062    {
1063        return false;
1064    }
1065
1066    /**
1067     * Called when the player attack or gets attacked, it's alert all wolves in the area that are owned by the player to
1068     * join the attack or defend the player.
1069     */
1070    protected void alertWolves(EntityLiving par1EntityLiving, boolean par2)
1071    {
1072        if (!(par1EntityLiving instanceof EntityCreeper) && !(par1EntityLiving instanceof EntityGhast))
1073        {
1074            if (par1EntityLiving instanceof EntityWolf)
1075            {
1076                EntityWolf var3 = (EntityWolf)par1EntityLiving;
1077
1078                if (var3.isTamed() && this.username.equals(var3.getOwnerName()))
1079                {
1080                    return;
1081                }
1082            }
1083
1084            if (!(par1EntityLiving instanceof EntityPlayer) || this.isPVPEnabled())
1085            {
1086                List var6 = this.worldObj.getEntitiesWithinAABB(EntityWolf.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(this.posX, this.posY, this.posZ, this.posX + 1.0D, this.posY + 1.0D, this.posZ + 1.0D).expand(16.0D, 4.0D, 16.0D));
1087                Iterator var4 = var6.iterator();
1088
1089                while (var4.hasNext())
1090                {
1091                    EntityWolf var5 = (EntityWolf)var4.next();
1092
1093                    if (var5.isTamed() && var5.getEntityToAttack() == null && this.username.equals(var5.getOwnerName()) && (!par2 || !var5.isSitting()))
1094                    {
1095                        var5.setSitting(false);
1096                        var5.setTarget(par1EntityLiving);
1097                    }
1098                }
1099            }
1100        }
1101    }
1102
1103    protected void damageArmor(int par1)
1104    {
1105        this.inventory.damageArmor(par1);
1106    }
1107
1108    /**
1109     * Returns the current armor value as determined by a call to InventoryPlayer.getTotalArmorValue
1110     */
1111    public int getTotalArmorValue()
1112    {
1113        return this.inventory.getTotalArmorValue();
1114    }
1115
1116    public float func_82243_bO()
1117    {
1118        int var1 = 0;
1119        ItemStack[] var2 = this.inventory.armorInventory;
1120        int var3 = var2.length;
1121
1122        for (int var4 = 0; var4 < var3; ++var4)
1123        {
1124            ItemStack var5 = var2[var4];
1125
1126            if (var5 != null)
1127            {
1128                ++var1;
1129            }
1130        }
1131
1132        return (float)var1 / (float)this.inventory.armorInventory.length;
1133    }
1134
1135    /**
1136     * Deals damage to the entity. If its a EntityPlayer then will take damage from the armor first and then health
1137     * second with the reduced value. Args: damageAmount
1138     */
1139    protected void damageEntity(DamageSource par1DamageSource, int par2)
1140    {
1141        if (!this.isEntityInvulnerable())
1142        {
1143            par2 = ForgeHooks.onLivingHurt(this, par1DamageSource, par2);
1144            if (par2 <= 0)
1145            {
1146                return;
1147            }
1148
1149            if (!par1DamageSource.isUnblockable() && this.isBlocking())
1150            {
1151                par2 = 1 + par2 >> 1;
1152            }
1153
1154            par2 = ArmorProperties.ApplyArmor(this, inventory.armorInventory, par1DamageSource, par2);
1155            if (par2 <= 0)
1156            {
1157                return;
1158            }
1159            par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
1160            this.addExhaustion(par1DamageSource.getHungerDamage());
1161            this.health -= par2;
1162        }
1163    }
1164
1165    /**
1166     * Displays the furnace GUI for the passed in furnace entity. Args: tileEntityFurnace
1167     */
1168    public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace) {}
1169
1170    /**
1171     * Displays the dipsenser GUI for the passed in dispenser entity. Args: TileEntityDispenser
1172     */
1173    public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser) {}
1174
1175    /**
1176     * Displays the GUI for editing a sign. Args: tileEntitySign
1177     */
1178    public void displayGUIEditSign(TileEntity par1TileEntity) {}
1179
1180    /**
1181     * Displays the GUI for interacting with a brewing stand.
1182     */
1183    public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand) {}
1184
1185    /**
1186     * Displays the GUI for interacting with a beacon.
1187     */
1188    public void displayGUIBeacon(TileEntityBeacon par1TileEntityBeacon) {}
1189
1190    public void displayGUIMerchant(IMerchant par1IMerchant) {}
1191
1192    /**
1193     * Displays the GUI for interacting with a book.
1194     */
1195    public void displayGUIBook(ItemStack par1ItemStack) {}
1196
1197    public boolean interactWith(Entity par1Entity)
1198    {
1199        if (MinecraftForge.EVENT_BUS.post(new EntityInteractEvent(this, par1Entity)))
1200        {
1201            return false;
1202        }
1203        if (par1Entity.interact(this))
1204        {
1205            return true;
1206        }
1207        else
1208        {
1209            ItemStack var2 = this.getCurrentEquippedItem();
1210
1211            if (var2 != null && par1Entity instanceof EntityLiving)
1212            {
1213                if (this.capabilities.isCreativeMode)
1214                {
1215                    var2 = var2.copy();
1216                }
1217
1218                if (var2.interactWith((EntityLiving)par1Entity))
1219                {
1220                    if (var2.stackSize <= 0 && !this.capabilities.isCreativeMode)
1221                    {
1222                        this.destroyCurrentEquippedItem();
1223                    }
1224
1225                    return true;
1226                }
1227            }
1228
1229            return false;
1230        }
1231    }
1232
1233    /**
1234     * Returns the currently being used item by the player.
1235     */
1236    public ItemStack getCurrentEquippedItem()
1237    {
1238        return this.inventory.getCurrentItem();
1239    }
1240
1241    /**
1242     * Destroys the currently equipped item from the player's inventory.
1243     */
1244    public void destroyCurrentEquippedItem()
1245    {
1246        ItemStack orig = getCurrentEquippedItem();
1247        this.inventory.setInventorySlotContents(this.inventory.currentItem, (ItemStack)null);
1248        MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(this, orig));
1249    }
1250
1251    /**
1252     * Returns the Y Offset of this entity.
1253     */
1254    public double getYOffset()
1255    {
1256        return (double)(this.yOffset - 0.5F);
1257    }
1258
1259    /**
1260     * Attacks for the player the targeted entity with the currently equipped item.  The equipped item has hitEntity
1261     * called on it. Args: targetEntity
1262     */
1263    public void attackTargetEntityWithCurrentItem(Entity par1Entity)
1264    {
1265        if (MinecraftForge.EVENT_BUS.post(new AttackEntityEvent(this, par1Entity)))
1266        {
1267            return;
1268        }
1269        ItemStack stack = getCurrentEquippedItem();
1270        if (stack != null && stack.getItem().onLeftClickEntity(stack, this, par1Entity))
1271        {
1272            return;
1273        }
1274        if (par1Entity.canAttackWithItem())
1275        {
1276            if (!par1Entity.func_85031_j(this))
1277            {
1278                int var2 = this.inventory.getDamageVsEntity(par1Entity);
1279
1280                if (this.isPotionActive(Potion.damageBoost))
1281                {
1282                    var2 += 3 << this.getActivePotionEffect(Potion.damageBoost).getAmplifier();
1283                }
1284
1285                if (this.isPotionActive(Potion.weakness))
1286                {
1287                    var2 -= 2 << this.getActivePotionEffect(Potion.weakness).getAmplifier();
1288                }
1289
1290                int var3 = 0;
1291                int var4 = 0;
1292
1293                if (par1Entity instanceof EntityLiving)
1294                {
1295                    var4 = EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLiving)par1Entity);
1296                    var3 += EnchantmentHelper.getKnockbackModifier(this, (EntityLiving)par1Entity);
1297                }
1298
1299                if (this.isSprinting())
1300                {
1301                    ++var3;
1302                }
1303
1304                if (var2 > 0 || var4 > 0)
1305                {
1306                    boolean var5 = this.fallDistance > 0.0F && !this.onGround && !this.isOnLadder() && !this.isInWater() && !this.isPotionActive(Potion.blindness) && this.ridingEntity == null && par1Entity instanceof EntityLiving;
1307
1308                    if (var5)
1309                    {
1310                        var2 += this.rand.nextInt(var2 / 2 + 2);
1311                    }
1312
1313                    var2 += var4;
1314                    boolean var6 = false;
1315                    int var7 = EnchantmentHelper.getFireAspectModifier(this);
1316
1317                    if (par1Entity instanceof EntityLiving && var7 > 0 && !par1Entity.isBurning())
1318                    {
1319                        var6 = true;
1320                        par1Entity.setFire(1);
1321                    }
1322
1323                    boolean var8 = par1Entity.attackEntityFrom(DamageSource.causePlayerDamage(this), var2);
1324
1325                    if (var8)
1326                    {
1327                        if (var3 > 0)
1328                        {
1329                            par1Entity.addVelocity((double)(-MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F) * (float)var3 * 0.5F), 0.1D, (double)(MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F) * (float)var3 * 0.5F));
1330                            this.motionX *= 0.6D;
1331                            this.motionZ *= 0.6D;
1332                            this.setSprinting(false);
1333                        }
1334
1335                        if (var5)
1336                        {
1337                            this.onCriticalHit(par1Entity);
1338                        }
1339
1340                        if (var4 > 0)
1341                        {
1342                            this.onEnchantmentCritical(par1Entity);
1343                        }
1344
1345                        if (var2 >= 18)
1346                        {
1347                            this.triggerAchievement(AchievementList.overkill);
1348                        }
1349
1350                        this.setLastAttackingEntity(par1Entity);
1351
1352                        if (par1Entity instanceof EntityLiving)
1353                        {
1354                            EnchantmentThorns.func_92096_a(this, (EntityLiving)par1Entity, this.rand);
1355                        }
1356                    }
1357
1358                    ItemStack var9 = this.getCurrentEquippedItem();
1359
1360                    if (var9 != null && par1Entity instanceof EntityLiving)
1361                    {
1362                        var9.hitEntity((EntityLiving)par1Entity, this);
1363
1364                        if (var9.stackSize <= 0)
1365                        {
1366                            this.destroyCurrentEquippedItem();
1367                        }
1368                    }
1369
1370                    if (par1Entity instanceof EntityLiving)
1371                    {
1372                        if (par1Entity.isEntityAlive())
1373                        {
1374                            this.alertWolves((EntityLiving)par1Entity, true);
1375                        }
1376
1377                        this.addStat(StatList.damageDealtStat, var2);
1378
1379                        if (var7 > 0 && var8)
1380                        {
1381                            par1Entity.setFire(var7 * 4);
1382                        }
1383                        else if (var6)
1384                        {
1385                            par1Entity.extinguish();
1386                        }
1387                    }
1388
1389                    this.addExhaustion(0.3F);
1390                }
1391            }
1392        }
1393    }
1394
1395    /**
1396     * Called when the player performs a critical hit on the Entity. Args: entity that was hit critically
1397     */
1398    public void onCriticalHit(Entity par1Entity) {}
1399
1400    public void onEnchantmentCritical(Entity par1Entity) {}
1401
1402    @SideOnly(Side.CLIENT)
1403    public void respawnPlayer() {}
1404
1405    /**
1406     * Will get destroyed next tick.
1407     */
1408    public void setDead()
1409    {
1410        super.setDead();
1411        this.inventoryContainer.onCraftGuiClosed(this);
1412
1413        if (this.openContainer != null)
1414        {
1415            this.openContainer.onCraftGuiClosed(this);
1416        }
1417    }
1418
1419    /**
1420     * Checks if this entity is inside of an opaque block
1421     */
1422    public boolean isEntityInsideOpaqueBlock()
1423    {
1424        return !this.sleeping && super.isEntityInsideOpaqueBlock();
1425    }
1426
1427    public boolean func_71066_bF()
1428    {
1429        return false;
1430    }
1431
1432    /**
1433     * Attempts to have the player sleep in a bed at the specified location.
1434     */
1435    public EnumStatus sleepInBedAt(int par1, int par2, int par3)
1436    {
1437        PlayerSleepInBedEvent event = new PlayerSleepInBedEvent(this, par1, par2, par3);
1438        MinecraftForge.EVENT_BUS.post(event);
1439        if (event.result != null)
1440        {
1441            return event.result;
1442        }
1443        if (!this.worldObj.isRemote)
1444        {
1445            if (this.isPlayerSleeping() || !this.isEntityAlive())
1446            {
1447                return EnumStatus.OTHER_PROBLEM;
1448            }
1449
1450            if (!this.worldObj.provider.isSurfaceWorld())
1451            {
1452                return EnumStatus.NOT_POSSIBLE_HERE;
1453            }
1454
1455            if (this.worldObj.isDaytime())
1456            {
1457                return EnumStatus.NOT_POSSIBLE_NOW;
1458            }
1459
1460            if (Math.abs(this.posX - (double)par1) > 3.0D || Math.abs(this.posY - (double)par2) > 2.0D || Math.abs(this.posZ - (double)par3) > 3.0D)
1461            {
1462                return EnumStatus.TOO_FAR_AWAY;
1463            }
1464
1465            double var4 = 8.0D;
1466            double var6 = 5.0D;
1467            List var8 = this.worldObj.getEntitiesWithinAABB(EntityMob.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)par1 - var4, (double)par2 - var6, (double)par3 - var4, (double)par1 + var4, (double)par2 + var6, (double)par3 + var4));
1468
1469            if (!var8.isEmpty())
1470            {
1471                return EnumStatus.NOT_SAFE;
1472            }
1473        }
1474
1475        this.setSize(0.2F, 0.2F);
1476        this.yOffset = 0.2F;
1477
1478        if (this.worldObj.blockExists(par1, par2, par3))
1479        {
1480            int var9 = this.worldObj.getBlockMetadata(par1, par2, par3);
1481            int var5 = BlockBed.getDirection(var9);
1482            Block block = Block.blocksList[worldObj.getBlockId(par1, par2, par3)];
1483            if (block != null)
1484            {
1485                var5 = block.getBedDirection(worldObj, par1, par2, par3);
1486            }
1487            float var10 = 0.5F;
1488            float var7 = 0.5F;
1489
1490            switch (var5)
1491            {
1492                case 0:
1493                    var7 = 0.9F;
1494                    break;
1495                case 1:
1496                    var10 = 0.1F;
1497                    break;
1498                case 2:
1499                    var7 = 0.1F;
1500                    break;
1501                case 3:
1502                    var10 = 0.9F;
1503            }
1504
1505            this.func_71013_b(var5);
1506            this.setPosition((double)((float)par1 + var10), (double)((float)par2 + 0.9375F), (double)((float)par3 + var7));
1507        }
1508        else
1509        {
1510            this.setPosition((double)((float)par1 + 0.5F), (double)((float)par2 + 0.9375F), (double)((float)par3 + 0.5F));
1511        }
1512
1513        this.sleeping = true;
1514        this.sleepTimer = 0;
1515        this.playerLocation = new ChunkCoordinates(par1, par2, par3);
1516        this.motionX = this.motionZ = this.motionY = 0.0D;
1517
1518        if (!this.worldObj.isRemote)
1519        {
1520            this.worldObj.updateAllPlayersSleepingFlag();
1521        }
1522
1523        return EnumStatus.OK;
1524    }
1525
1526    private void func_71013_b(int par1)
1527    {
1528        this.field_71079_bU = 0.0F;
1529        this.field_71089_bV = 0.0F;
1530
1531        switch (par1)
1532        {
1533            case 0:
1534                this.field_71089_bV = -1.8F;
1535                break;
1536            case 1:
1537                this.field_71079_bU = 1.8F;
1538                break;
1539            case 2:
1540                this.field_71089_bV = 1.8F;
1541                break;
1542            case 3:
1543                this.field_71079_bU = -1.8F;
1544        }
1545    }
1546
1547    /**
1548     * Wake up the player if they're sleeping.
1549     */
1550    public void wakeUpPlayer(boolean par1, boolean par2, boolean par3)
1551    {
1552        this.setSize(0.6F, 1.8F);
1553        this.resetHeight();
1554        ChunkCoordinates var4 = this.playerLocation;
1555        ChunkCoordinates var5 = this.playerLocation;
1556
1557        Block block = (var4 == null ? null : Block.blocksList[worldObj.getBlockId(var4.posX, var4.posY, var4.posZ)]);
1558
1559        if (var4 != null && block != null && block.isBed(worldObj, var4.posX, var4.posY, var4.posZ, this))
1560        {
1561            block.setBedOccupied(this.worldObj, var4.posX, var4.posY, var4.posZ, this, false);
1562            var5 = block.getBedSpawnPosition(worldObj, var4.posX, var4.posY, var4.posZ, this);
1563
1564            if (var5 == null)
1565            {
1566                var5 = new ChunkCoordinates(var4.posX, var4.posY + 1, var4.posZ);
1567            }
1568
1569            this.setPosition((double)((float)var5.posX + 0.5F), (double)((float)var5.posY + this.yOffset + 0.1F), (double)((float)var5.posZ + 0.5F));
1570        }
1571
1572        this.sleeping = false;
1573
1574        if (!this.worldObj.isRemote && par2)
1575        {
1576            this.worldObj.updateAllPlayersSleepingFlag();
1577        }
1578
1579        if (par1)
1580        {
1581            this.sleepTimer = 0;
1582        }
1583        else
1584        {
1585            this.sleepTimer = 100;
1586        }
1587
1588        if (par3)
1589        {
1590            this.setSpawnChunk(this.playerLocation, false);
1591        }
1592    }
1593
1594    /**
1595     * Checks if the player is currently in a bed
1596     */
1597    private boolean isInBed()
1598    {
1599        ChunkCoordinates c = playerLocation;
1600        int blockID = worldObj.getBlockId(c.posX, c.posY, c.posZ);
1601        return Block.blocksList[blockID] != null && Block.blocksList[blockID].isBed(worldObj, c.posX, c.posY, c.posZ, this);
1602    }
1603
1604    /**
1605     * Ensure that a block enabling respawning exists at the specified coordinates and find an empty space nearby to
1606     * spawn.
1607     */
1608    public static ChunkCoordinates verifyRespawnCoordinates(World par0World, ChunkCoordinates par1ChunkCoordinates, boolean par2)
1609    {
1610        IChunkProvider var3 = par0World.getChunkProvider();
1611        var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
1612        var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
1613        var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
1614        var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
1615
1616        ChunkCoordinates c = par1ChunkCoordinates;
1617        Block block = Block.blocksList[par0World.getBlockId(c.posX, c.posY, c.posZ)];
1618
1619        if (block != null && block.isBed(par0World, c.posX, c.posY, c.posZ, null))
1620        {
1621            ChunkCoordinates var8 = block.getBedSpawnPosition(par0World, c.posX, c.posY, c.posZ, null);
1622            return var8;
1623        }
1624        else
1625        {
1626            Material var4 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY, par1ChunkCoordinates.posZ);
1627            Material var5 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY + 1, par1ChunkCoordinates.posZ);
1628            boolean var6 = !var4.isSolid() && !var4.isLiquid();
1629            boolean var7 = !var5.isSolid() && !var5.isLiquid();
1630            return par2 && var6 && var7 ? par1ChunkCoordinates : null;
1631        }
1632    }
1633
1634    @SideOnly(Side.CLIENT)
1635
1636    /**
1637     * Returns the orientation of the bed in degrees.
1638     */
1639    public float getBedOrientationInDegrees()
1640    {
1641        if (this.playerLocation != null)
1642        {
1643            int x = playerLocation.posX;
1644            int y = playerLocation.posY;
1645            int z = playerLocation.posZ;
1646            Block block = Block.blocksList[worldObj.getBlockId(x, y, z)];
1647            int var2 = (block == null ? 0 : block.getBedDirection(worldObj, x, y, z));
1648
1649            switch (var2)
1650            {
1651                case 0:
1652                    return 90.0F;
1653                case 1:
1654                    return 0.0F;
1655                case 2:
1656                    return 270.0F;
1657                case 3:
1658                    return 180.0F;
1659            }
1660        }
1661
1662        return 0.0F;
1663    }
1664
1665    /**
1666     * Returns whether player is sleeping or not
1667     */
1668    public boolean isPlayerSleeping()
1669    {
1670        return this.sleeping;
1671    }
1672
1673    /**
1674     * Returns whether or not the player is asleep and the screen has fully faded.
1675     */
1676    public boolean isPlayerFullyAsleep()
1677    {
1678        return this.sleeping && this.sleepTimer >= 100;
1679    }
1680
1681    @SideOnly(Side.CLIENT)
1682    public int getSleepTimer()
1683    {
1684        return this.sleepTimer;
1685    }
1686
1687    @SideOnly(Side.CLIENT)
1688    protected boolean getHideCape(int par1)
1689    {
1690        return (this.dataWatcher.getWatchableObjectByte(16) & 1 << par1) != 0;
1691    }
1692
1693    protected void setHideCape(int par1, boolean par2)
1694    {
1695        byte var3 = this.dataWatcher.getWatchableObjectByte(16);
1696
1697        if (par2)
1698        {
1699            this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 | 1 << par1)));
1700        }
1701        else
1702        {
1703            this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 & ~(1 << par1))));
1704        }
1705    }
1706
1707    /**
1708     * Add a chat message to the player
1709     */
1710    public void addChatMessage(String par1Str) {}
1711
1712    /**
1713     * Returns the location of the bed the player will respawn at, or null if the player has not slept in a bed.
1714     */
1715    public ChunkCoordinates getBedLocation()
1716    {
1717        return this.spawnChunk;
1718    }
1719
1720    public boolean isSpawnForced()
1721    {
1722        return this.spawnForced;
1723    }
1724
1725    /**
1726     * Defines a spawn coordinate to player spawn. Used by bed after the player sleep on it.
1727     */
1728    public void setSpawnChunk(ChunkCoordinates par1ChunkCoordinates, boolean par2)
1729    {
1730        if (par1ChunkCoordinates != null)
1731        {
1732            this.spawnChunk = new ChunkCoordinates(par1ChunkCoordinates);
1733            this.spawnForced = par2;
1734        }
1735        else
1736        {
1737            this.spawnChunk = null;
1738            this.spawnForced = false;
1739        }
1740    }
1741
1742    /**
1743     * Will trigger the specified trigger.
1744     */
1745    public void triggerAchievement(StatBase par1StatBase)
1746    {
1747        this.addStat(par1StatBase, 1);
1748    }
1749
1750    /**
1751     * Adds a value to a statistic field.
1752     */
1753    public void addStat(StatBase par1StatBase, int par2) {}
1754
1755    /**
1756     * Causes this entity to do an upwards motion (jumping).
1757     */
1758    protected void jump()
1759    {
1760        super.jump();
1761        this.addStat(StatList.jumpStat, 1);
1762
1763        if (this.isSprinting())
1764        {
1765            this.addExhaustion(0.8F);
1766        }
1767        else
1768        {
1769            this.addExhaustion(0.2F);
1770        }
1771    }
1772
1773    /**
1774     * Moves the entity based on the specified heading.  Args: strafe, forward
1775     */
1776    public void moveEntityWithHeading(float par1, float par2)
1777    {
1778        double var3 = this.posX;
1779        double var5 = this.posY;
1780        double var7 = this.posZ;
1781
1782        if (this.capabilities.isFlying && this.ridingEntity == null)
1783        {
1784            double var9 = this.motionY;
1785            float var11 = this.jumpMovementFactor;
1786            this.jumpMovementFactor = this.capabilities.getFlySpeed();
1787            super.moveEntityWithHeading(par1, par2);
1788            this.motionY = var9 * 0.6D;
1789            this.jumpMovementFactor = var11;
1790        }
1791        else
1792        {
1793            super.moveEntityWithHeading(par1, par2);
1794        }
1795
1796        this.addMovementStat(this.posX - var3, this.posY - var5, this.posZ - var7);
1797    }
1798
1799    /**
1800     * Adds a value to a movement statistic field - like run, walk, swin or climb.
1801     */
1802    public void addMovementStat(double par1, double par3, double par5)
1803    {
1804        if (this.ridingEntity == null)
1805        {
1806            int var7;
1807
1808            if (this.isInsideOfMaterial(Material.water))
1809            {
1810                var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
1811
1812                if (var7 > 0)
1813                {
1814                    this.addStat(StatList.distanceDoveStat, var7);
1815                    this.addExhaustion(0.015F * (float)var7 * 0.01F);
1816                }
1817            }
1818            else if (this.isInWater())
1819            {
1820                var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
1821
1822                if (var7 > 0)
1823                {
1824                    this.addStat(StatList.distanceSwumStat, var7);
1825                    this.addExhaustion(0.015F * (float)var7 * 0.01F);
1826                }
1827            }
1828            else if (this.isOnLadder())
1829            {
1830                if (par3 > 0.0D)
1831                {
1832                    this.addStat(StatList.distanceClimbedStat, (int)Math.round(par3 * 100.0D));
1833                }
1834            }
1835            else if (this.onGround)
1836            {
1837                var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
1838
1839                if (var7 > 0)
1840                {
1841                    this.addStat(StatList.distanceWalkedStat, var7);
1842
1843                    if (this.isSprinting())
1844                    {
1845                        this.addExhaustion(0.099999994F * (float)var7 * 0.01F);
1846                    }
1847                    else
1848                    {
1849                        this.addExhaustion(0.01F * (float)var7 * 0.01F);
1850                    }
1851                }
1852            }
1853            else
1854            {
1855                var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
1856
1857                if (var7 > 25)
1858                {
1859                    this.addStat(StatList.distanceFlownStat, var7);
1860                }
1861            }
1862        }
1863    }
1864
1865    /**
1866     * Adds a value to a mounted movement statistic field - by minecart, boat, or pig.
1867     */
1868    private void addMountedMovementStat(double par1, double par3, double par5)
1869    {
1870        if (this.ridingEntity != null)
1871        {
1872            int var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
1873
1874            if (var7 > 0)
1875            {
1876                if (this.ridingEntity instanceof EntityMinecart)
1877                {
1878                    this.addStat(StatList.distanceByMinecartStat, var7);
1879
1880                    if (this.startMinecartRidingCoordinate == null)
1881                    {
1882                        this.startMinecartRidingCoordinate = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
1883                    }
1884                    else if ((double)this.startMinecartRidingCoordinate.getDistanceSquared(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) >= 1000000.0D)
1885                    {
1886                        this.addStat(AchievementList.onARail, 1);
1887                    }
1888                }
1889                else if (this.ridingEntity instanceof EntityBoat)
1890                {
1891                    this.addStat(StatList.distanceByBoatStat, var7);
1892                }
1893                else if (this.ridingEntity instanceof EntityPig)
1894                {
1895                    this.addStat(StatList.distanceByPigStat, var7);
1896                }
1897            }
1898        }
1899    }
1900
1901    /**
1902     * Called when the mob is falling. Calculates and applies fall damage.
1903     */
1904    protected void fall(float par1)
1905    {
1906        if (!this.capabilities.allowFlying)
1907        {
1908            if (par1 >= 2.0F)
1909            {
1910                this.addStat(StatList.distanceFallenStat, (int)Math.round((double)par1 * 100.0D));
1911            }
1912
1913            super.fall(par1);
1914        }
1915    }
1916
1917    /**
1918     * This method gets called when the entity kills another one.
1919     */
1920    public void onKillEntity(EntityLiving par1EntityLiving)
1921    {
1922        if (par1EntityLiving instanceof IMob)
1923        {
1924            this.triggerAchievement(AchievementList.killEnemy);
1925        }
1926    }
1927
1928    /**
1929     * Sets the Entity inside a web block.
1930     */
1931    public void setInWeb()
1932    {
1933        if (!this.capabilities.isFlying)
1934        {
1935            super.setInWeb();
1936        }
1937    }
1938
1939    @SideOnly(Side.CLIENT)
1940
1941    /**
1942     * Gets the Icon Index of the item currently held
1943     */
1944    public int getItemIcon(ItemStack par1ItemStack, int par2)
1945    {
1946        int var3 = super.getItemIcon(par1ItemStack, par2);
1947
1948        if (par1ItemStack.itemID == Item.fishingRod.itemID && this.fishEntity != null)
1949        {
1950            var3 = par1ItemStack.getIconIndex() + 16;
1951        }
1952        else
1953        {
1954            if (par1ItemStack.getItem().requiresMultipleRenderPasses())
1955            {
1956                return par1ItemStack.getItem().getIconIndex(par1ItemStack, par2);
1957            }
1958
1959            if (this.itemInUse != null && par1ItemStack.itemID == Item.bow.itemID)
1960            {
1961                int var4 = par1ItemStack.getMaxItemUseDuration() - this.itemInUseCount;
1962
1963                if (var4 >= 18)
1964                {
1965                    return 133;
1966                }
1967
1968                if (var4 > 13)
1969                {
1970                    return 117;
1971                }
1972
1973                if (var4 > 0)
1974                {
1975                    return 101;
1976                }
1977            }
1978            var3 = par1ItemStack.getItem().getIconIndex(par1ItemStack, par2, this, itemInUse, itemInUseCount);
1979        }
1980
1981        return var3;
1982    }
1983
1984    public ItemStack getCurrentArmor(int par1)
1985    {
1986        return this.inventory.armorItemInSlot(par1);
1987    }
1988
1989    protected void func_82164_bB() {}
1990
1991    protected void func_82162_bC() {}
1992
1993    /**
1994     * This method increases the player's current amount of experience.
1995     */
1996    public void addExperience(int par1)
1997    {
1998        this.addScore(par1);
1999        int var2 = Integer.MAX_VALUE - this.experienceTotal;
2000
2001        if (par1 > var2)
2002        {
2003            par1 = var2;
2004        }
2005
2006        this.experience += (float)par1 / (float)this.xpBarCap();
2007
2008        for (this.experienceTotal += par1; this.experience >= 1.0F; this.experience /= (float)this.xpBarCap())
2009        {
2010            this.experience = (this.experience - 1.0F) * (float)this.xpBarCap();
2011            this.addExperienceLevel(1);
2012        }
2013    }
2014
2015    /**
2016     * Add experience levels to this player.
2017     */
2018    public void addExperienceLevel(int par1)
2019    {
2020        this.experienceLevel += par1;
2021
2022        if (this.experienceLevel < 0)
2023        {
2024            this.experienceLevel = 0;
2025            this.experience = 0.0F;
2026            this.experienceTotal = 0;
2027        }
2028
2029        if (par1 > 0 && this.experienceLevel % 5 == 0 && (float)this.field_82249_h < (float)this.ticksExisted - 100.0F)
2030        {
2031            float var2 = this.experienceLevel > 30 ? 1.0F : (float)this.experienceLevel / 30.0F;
2032            this.worldObj.playSoundAtEntity(this, "random.levelup", var2 * 0.75F, 1.0F);
2033            this.field_82249_h = this.ticksExisted;
2034        }
2035    }
2036
2037    /**
2038     * This method returns the cap amount of experience that the experience bar can hold. With each level, the
2039     * experience cap on the player's experience bar is raised by 10.
2040     */
2041    public int xpBarCap()
2042    {
2043        return this.experienceLevel >= 30 ? 62 + (this.experienceLevel - 30) * 7 : (this.experienceLevel >= 15 ? 17 + (this.experienceLevel - 15) * 3 : 17);
2044    }
2045
2046    /**
2047     * increases exhaustion level by supplied amount
2048     */
2049    public void addExhaustion(float par1)
2050    {
2051        if (!this.capabilities.disableDamage)
2052        {
2053            if (!this.worldObj.isRemote)
2054            {
2055                this.foodStats.addExhaustion(par1);
2056            }
2057        }
2058    }
2059
2060    /**
2061     * Returns the player's FoodStats object.
2062     */
2063    public FoodStats getFoodStats()
2064    {
2065        return this.foodStats;
2066    }
2067
2068    public boolean canEat(boolean par1)
2069    {
2070        return (par1 || this.foodStats.needFood()) && !this.capabilities.disableDamage;
2071    }
2072
2073    /**
2074     * Checks if the player's health is not full and not zero.
2075     */
2076    public boolean shouldHeal()
2077    {
2078        return this.getHealth() > 0 && this.getHealth() < this.getMaxHealth();
2079    }
2080
2081    /**
2082     * sets the itemInUse when the use item button is clicked. Args: itemstack, int maxItemUseDuration
2083     */
2084    public void setItemInUse(ItemStack par1ItemStack, int par2)
2085    {
2086        if (par1ItemStack != this.itemInUse)
2087        {
2088            this.itemInUse = par1ItemStack;
2089            this.itemInUseCount = par2;
2090
2091            if (!this.worldObj.isRemote)
2092            {
2093                this.setEating(true);
2094            }
2095        }
2096    }
2097
2098    /**
2099     * Returns true if the item the player is holding can harvest the block at the given coords. Args: x, y, z.
2100     */
2101    public boolean canCurrentToolHarvestBlock(int par1, int par2, int par3)
2102    {
2103        if (this.capabilities.allowEdit)
2104        {
2105            return true;
2106        }
2107        else
2108        {
2109            int var4 = this.worldObj.getBlockId(par1, par2, par3);
2110
2111            if (var4 > 0)
2112            {
2113                Block var5 = Block.blocksList[var4];
2114
2115                if (var5.blockMaterial.func_85157_q())
2116                {
2117                    return true;
2118                }
2119
2120                if (this.getCurrentEquippedItem() != null)
2121                {
2122                    ItemStack var6 = this.getCurrentEquippedItem();
2123
2124                    if (var6.canHarvestBlock(var5) || var6.getStrVsBlock(var5) > 1.0F)
2125                    {
2126                        return true;
2127                    }
2128                }
2129            }
2130
2131            return false;
2132        }
2133    }
2134
2135    public boolean canPlayerEdit(int par1, int par2, int par3, int par4, ItemStack par5ItemStack)
2136    {
2137        return this.capabilities.allowEdit ? true : (par5ItemStack != null ? par5ItemStack.func_82835_x() : false);
2138    }
2139
2140    /**
2141     * Get the experience points the entity currently has.
2142     */
2143    protected int getExperiencePoints(EntityPlayer par1EntityPlayer)
2144    {
2145        if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
2146        {
2147            return 0;
2148        }
2149        else
2150        {
2151            int var2 = this.experienceLevel * 7;
2152            return var2 > 100 ? 100 : var2;
2153        }
2154    }
2155
2156    /**
2157     * Only use is to identify if class is an instance of player for experience dropping
2158     */
2159    protected boolean isPlayer()
2160    {
2161        return true;
2162    }
2163
2164    /**
2165     * Gets the username of the entity.
2166     */
2167    public String getEntityName()
2168    {
2169        return this.username;
2170    }
2171
2172    /**
2173     * Copies the values from the given player into this player if boolean par2 is true. Always clones Ender Chest
2174     * Inventory.
2175     */
2176    public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2)
2177    {
2178        if (par2)
2179        {
2180            this.inventory.copyInventory(par1EntityPlayer.inventory);
2181            this.health = par1EntityPlayer.health;
2182            this.foodStats = par1EntityPlayer.foodStats;
2183            this.experienceLevel = par1EntityPlayer.experienceLevel;
2184            this.experienceTotal = par1EntityPlayer.experienceTotal;
2185            this.experience = par1EntityPlayer.experience;
2186            this.setScore(par1EntityPlayer.getScore());
2187            this.field_82152_aq = par1EntityPlayer.field_82152_aq;
2188        }
2189        else if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
2190        {
2191            this.inventory.copyInventory(par1EntityPlayer.inventory);
2192            this.experienceLevel = par1EntityPlayer.experienceLevel;
2193            this.experienceTotal = par1EntityPlayer.experienceTotal;
2194            this.experience = par1EntityPlayer.experience;
2195            this.setScore(par1EntityPlayer.getScore());
2196        }
2197
2198        this.theInventoryEnderChest = par1EntityPlayer.theInventoryEnderChest;
2199
2200        //Copy over a section of the Entity Data from the old player.
2201        //Allows mods to specify data that persists after players respawn.
2202        NBTTagCompound old = par1EntityPlayer.getEntityData();
2203        if (old.hasKey(PERSISTED_NBT_TAG))
2204        {
2205            getEntityData().setCompoundTag(PERSISTED_NBT_TAG, old.getCompoundTag(PERSISTED_NBT_TAG));
2206        }
2207    }
2208
2209    /**
2210     * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
2211     * prevent them from trampling crops
2212     */
2213    protected boolean canTriggerWalking()
2214    {
2215        return !this.capabilities.isFlying;
2216    }
2217
2218    /**
2219     * Sends the player's abilities to the server (if there is one).
2220     */
2221    public void sendPlayerAbilities() {}
2222
2223    /**
2224     * Sets the player's game mode and sends it to them.
2225     */
2226    public void setGameType(EnumGameType par1EnumGameType) {}
2227
2228    /**
2229     * Gets the name of this command sender (usually username, but possibly "Rcon")
2230     */
2231    public String getCommandSenderName()
2232    {
2233        return this.username;
2234    }
2235
2236    public StringTranslate getTranslator()
2237    {
2238        return StringTranslate.getInstance();
2239    }
2240
2241    /**
2242     * Translates and formats the given string key with the given arguments.
2243     */
2244    public String translateString(String par1Str, Object ... par2ArrayOfObj)
2245    {
2246        return this.getTranslator().translateKeyFormat(par1Str, par2ArrayOfObj);
2247    }
2248
2249    /**
2250     * Returns the InventoryEnderChest of this player.
2251     */
2252    public InventoryEnderChest getInventoryEnderChest()
2253    {
2254        return this.theInventoryEnderChest;
2255    }
2256
2257    /**
2258     * 0 = item, 1-n is armor
2259     */
2260    public ItemStack getCurrentItemOrArmor(int par1)
2261    {
2262        return par1 == 0 ? this.inventory.getCurrentItem() : this.inventory.armorInventory[par1 - 1];
2263    }
2264
2265    /**
2266     * Returns the item that this EntityLiving is holding, if any.
2267     */
2268    public ItemStack getHeldItem()
2269    {
2270        return this.inventory.getCurrentItem();
2271    }
2272
2273    /**
2274     * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
2275     */
2276    public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
2277    {
2278        this.inventory.armorInventory[par1] = par2ItemStack;
2279    }
2280
2281    public ItemStack[] getLastActiveItems()
2282    {
2283        return this.inventory.armorInventory;
2284    }
2285
2286    @SideOnly(Side.CLIENT)
2287    public boolean getHideCape()
2288    {
2289        return this.getHideCape(1);
2290    }
2291
2292    public void openGui(Object mod, int modGuiId, World world, int x, int y, int z)
2293    {
2294        FMLNetworkHandler.openGui(this, mod, modGuiId, world, x, y, z);
2295    }
2296}