    001    package net.minecraft.entity.player;
    002
    003    import cpw.mods.fml.common.FMLCommonHandler;
    004    import cpw.mods.fml.common.network.FMLNetworkHandler;
    005    import cpw.mods.fml.relauncher.Side;
    006    import cpw.mods.fml.relauncher.SideOnly;
    007    import java.util.Iterator;
    008    import java.util.List;
    009    import net.minecraft.block.Block;
    010    import net.minecraft.block.BlockBed;
    011    import net.minecraft.block.material.Material;
    012    import net.minecraft.command.ICommandSender;
    013    import net.minecraft.enchantment.EnchantmentHelper;
    014    import net.minecraft.enchantment.EnchantmentThorns;
    015    import net.minecraft.entity.Entity;
    016    import net.minecraft.entity.EntityLiving;
    017    import net.minecraft.entity.IMerchant;
    018    import net.minecraft.entity.item.EntityBoat;
    019    import net.minecraft.entity.item.EntityItem;
    020    import net.minecraft.entity.item.EntityMinecart;
    021    import net.minecraft.entity.monster.EntityCreeper;
    022    import net.minecraft.entity.monster.EntityGhast;
    023    import net.minecraft.entity.monster.EntityMob;
    024    import net.minecraft.entity.monster.IMob;
    025    import net.minecraft.entity.passive.EntityPig;
    026    import net.minecraft.entity.passive.EntityWolf;
    027    import net.minecraft.entity.projectile.EntityArrow;
    028    import net.minecraft.entity.projectile.EntityFishHook;
    029    import net.minecraft.inventory.Container;
    030    import net.minecraft.inventory.ContainerPlayer;
    031    import net.minecraft.inventory.IInventory;
    032    import net.minecraft.inventory.InventoryEnderChest;
    033    import net.minecraft.item.EnumAction;
    034    import net.minecraft.item.Item;
    035    import net.minecraft.item.ItemStack;
    036    import net.minecraft.nbt.NBTTagCompound;
    037    import net.minecraft.nbt.NBTTagList;
    038    import net.minecraft.potion.Potion;
    039    import net.minecraft.stats.AchievementList;
    040    import net.minecraft.stats.StatBase;
    041    import net.minecraft.stats.StatList;
    042    import net.minecraft.tileentity.TileEntity;
    043    import net.minecraft.tileentity.TileEntityBeacon;
    044    import net.minecraft.tileentity.TileEntityBrewingStand;
    045    import net.minecraft.tileentity.TileEntityDispenser;
    046    import net.minecraft.tileentity.TileEntityFurnace;
    047    import net.minecraft.util.AxisAlignedBB;
    048    import net.minecraft.util.ChunkCoordinates;
    049    import net.minecraft.util.DamageSource;
    050    import net.minecraft.util.FoodStats;
    051    import net.minecraft.util.MathHelper;
    052    import net.minecraft.util.StringTranslate;
    053    import net.minecraft.util.Vec3;
    054    import net.minecraft.world.EnumGameType;
    055    import net.minecraft.world.World;
    056    import net.minecraft.world.chunk.IChunkProvider;
    057
    058    import net.minecraftforge.common.ForgeHooks;
    059    import net.minecraftforge.common.ISpecialArmor.ArmorProperties;
    060    import net.minecraftforge.common.MinecraftForge;
    061    import net.minecraftforge.event.ForgeEventFactory;
    062    import net.minecraftforge.event.entity.living.LivingHurtEvent;
    063    import net.minecraftforge.event.entity.player.AttackEntityEvent;
    064    import net.minecraftforge.event.entity.player.EntityInteractEvent;
    065    import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
    066    import net.minecraftforge.event.entity.player.PlayerDropsEvent;
    067    import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent;
    068
    069    public 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 func_85030_a(String par1Str, float par2, float par3)
    413        {
    414            this.worldObj.func_85173_a(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.func_85030_a("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().shiftedIndex, var5.xCoord, var5.yCoord, var5.zCoord, var4.xCoord, var4.yCoord + 0.05D, var4.zCoord);
    439                }
    440
    441                this.func_85030_a("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        public void func_85040_s(int par1)
    621        {
    622            this.dataWatcher.updateObject(18, Integer.valueOf(par1));
    623        }
    624
    625        public void func_85039_t(int par1)
    626        {
    627            int var2 = this.getScore();
    628            this.dataWatcher.updateObject(18, Integer.valueOf(var2 + par1));
    629        }
    630
    631        /**
    632         * Called when the mob's health reaches 0.
    633         */
    634        public void onDeath(DamageSource par1DamageSource)
    635        {
    636            super.onDeath(par1DamageSource);
    637            this.setSize(0.2F, 0.2F);
    638            this.setPosition(this.posX, this.posY, this.posZ);
    639            this.motionY = 0.10000000149011612D;
    640
    641            captureDrops = true;
    642            capturedDrops.clear();
    643
    644            if (this.username.equals("Notch"))
    645            {
    646                this.dropPlayerItemWithRandomChoice(new ItemStack(Item.appleRed, 1), true);
    647            }
    648
    649            if (!this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
    650            {
    651                this.inventory.dropAllItems();
    652            }
    653
    654            captureDrops = false;
    655
    656            if (!worldObj.isRemote)
    657            {
    658                PlayerDropsEvent event = new PlayerDropsEvent(this, par1DamageSource, capturedDrops, recentlyHit > 0);
    659                if (!MinecraftForge.EVENT_BUS.post(event))
    660                {
    661                    for (EntityItem item : capturedDrops)
    662                    {
    663                        joinEntityItemWithWorld(item);
    664                    }
    665                }
    666            }
    667
    668            if (par1DamageSource != null)
    669            {
    670                this.motionX = (double)(-MathHelper.cos((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F);
    671                this.motionZ = (double)(-MathHelper.sin((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F);
    672            }
    673            else
    674            {
    675                this.motionX = this.motionZ = 0.0D;
    676            }
    677
    678            this.yOffset = 0.1F;
    679            this.addStat(StatList.deathsStat, 1);
    680        }
    681
    682        /**
    683         * Adds a value to the player score. Currently not actually used and the entity passed in does nothing. Args:
    684         * entity, scoreToAdd
    685         */
    686        public void addToPlayerScore(Entity par1Entity, int par2)
    687        {
    688            this.func_85039_t(par2);
    689
    690            if (par1Entity instanceof EntityPlayer)
    691            {
    692                this.addStat(StatList.playerKillsStat, 1);
    693            }
    694            else
    695            {
    696                this.addStat(StatList.mobKillsStat, 1);
    697            }
    698        }
    699
    700        /**
    701         * Called when player presses the drop item key
    702         */
    703        public EntityItem dropOneItem(boolean par1)
    704        {
    705            ItemStack stack = inventory.getCurrentItem();
    706
    707            if (stack == null)
    708            {
    709                return null;
    710            }
    711
    712            if (stack.getItem().onDroppedByPlayer(stack, this))
    713            {
    714                int count = par1 && this.inventory.getCurrentItem() != null ? this.inventory.getCurrentItem().stackSize : 1;
    715                return ForgeHooks.onPlayerTossEvent(this, inventory.decrStackSize(inventory.currentItem, count));
    716            }
    717
    718            return null;
    719        }
    720
    721        /**
    722         * Args: itemstack - called when player drops an item stack that's not in his inventory (like items still placed in
    723         * a workbench while the workbench'es GUI gets closed)
    724         */
    725        public EntityItem dropPlayerItem(ItemStack par1ItemStack)
    726        {
    727            return ForgeHooks.onPlayerTossEvent(this, par1ItemStack);
    728        }
    729
    730        /**
    731         * Args: itemstack, flag
    732         */
    733        public EntityItem dropPlayerItemWithRandomChoice(ItemStack par1ItemStack, boolean par2)
    734        {
    735            if (par1ItemStack == null)
    736            {
    737                return null;
    738            }
    739            else
    740            {
    741                EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY - 0.30000001192092896D + (double)this.getEyeHeight(), this.posZ, par1ItemStack);
    742                var3.delayBeforeCanPickup = 40;
    743                float var4 = 0.1F;
    744                float var5;
    745
    746                if (par2)
    747                {
    748                    var5 = this.rand.nextFloat() * 0.5F;
    749                    float var6 = this.rand.nextFloat() * (float)Math.PI * 2.0F;
    750                    var3.motionX = (double)(-MathHelper.sin(var6) * var5);
    751                    var3.motionZ = (double)(MathHelper.cos(var6) * var5);
    752                    var3.motionY = 0.20000000298023224D;
    753                }
    754                else
    755                {
    756                    var4 = 0.3F;
    757                    var3.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4);
    758                    var3.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4);
    759                    var3.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI) * var4 + 0.1F);
    760                    var4 = 0.02F;
    761                    var5 = this.rand.nextFloat() * (float)Math.PI * 2.0F;
    762                    var4 *= this.rand.nextFloat();
    763                    var3.motionX += Math.cos((double)var5) * (double)var4;
    764                    var3.motionY += (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F);
    765                    var3.motionZ += Math.sin((double)var5) * (double)var4;
    766                }
    767
    768                this.joinEntityItemWithWorld(var3);
    769                this.addStat(StatList.dropStat, 1);
    770                return var3;
    771            }
    772        }
    773
    774        /**
    775         * Joins the passed in entity item with the world. Args: entityItem
    776         */
    777        public void joinEntityItemWithWorld(EntityItem par1EntityItem)
    778        {
    779            if (captureDrops)
    780            {
    781                capturedDrops.add(par1EntityItem);
    782            }
    783            else
    784            {
    785                this.worldObj.spawnEntityInWorld(par1EntityItem);
    786            }
    787        }
    788
    789        /**
    790         * Returns how strong the player is against the specified block at this moment
    791         * Deprecated in favor of the more sensitive version
    792         */
    793        @Deprecated
    794        public float getCurrentPlayerStrVsBlock(Block par1Block)
    795        {
    796            return getCurrentPlayerStrVsBlock(par1Block, 0);
    797        }
    798
    799        public float getCurrentPlayerStrVsBlock(Block par1Block, int meta)
    800        {
    801            ItemStack stack = inventory.getCurrentItem();
    802            float var2 = (stack == null ? 1.0F : stack.getItem().getStrVsBlock(stack, par1Block, meta));
    803            int var3 = EnchantmentHelper.getEfficiencyModifier(this);
    804            ItemStack var4 = this.inventory.getCurrentItem();
    805
    806            if (var3 > 0 && var4 != null)
    807            {
    808                float var5 = (float)(var3 * var3 + 1);
    809                boolean canHarvest = ForgeHooks.canToolHarvestBlock(par1Block, meta, var4);
    810
    811                if (!canHarvest && var2 <= 1.0F)
    812                {
    813                    var2 += var5 * 0.08F;
    814                }
    815                else
    816                {
    817                    var2 += var5;
    818                }
    819            }
    820
    821            if (this.isPotionActive(Potion.digSpeed))
    822            {
    823                var2 *= 1.0F + (float)(this.getActivePotionEffect(Potion.digSpeed).getAmplifier() + 1) * 0.2F;
    824            }
    825
    826            if (this.isPotionActive(Potion.digSlowdown))
    827            {
    828                var2 *= 1.0F - (float)(this.getActivePotionEffect(Potion.digSlowdown).getAmplifier() + 1) * 0.2F;
    829            }
    830
    831            if (this.isInsideOfMaterial(Material.water) && !EnchantmentHelper.getAquaAffinityModifier(this))
    832            {
    833                var2 /= 5.0F;
    834            }
    835
    836            if (!this.onGround)
    837            {
    838                var2 /= 5.0F;
    839            }
    840
    841            var2 = ForgeEventFactory.getBreakSpeed(this, par1Block, meta, var2);
    842            return (var2 < 0 ? 0 : var2);
    843        }
    844
    845        /**
    846         * Checks if the player has the ability to harvest a block (checks current inventory item for a tool if necessary)
    847         */
    848        public boolean canHarvestBlock(Block par1Block)
    849        {
    850            return ForgeEventFactory.doPlayerHarvestCheck(this, par1Block, inventory.canHarvestBlock(par1Block));
    851        }
    852
    853        /**
    854         * (abstract) Protected helper method to read subclass entity data from NBT.
    855         */
    856        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    857        {
    858            super.readEntityFromNBT(par1NBTTagCompound);
    859            NBTTagList var2 = par1NBTTagCompound.getTagList("Inventory");
    860            this.inventory.readFromNBT(var2);
    861            this.inventory.currentItem = par1NBTTagCompound.getInteger("SelectedItemSlot");
    862            this.sleeping = par1NBTTagCompound.getBoolean("Sleeping");
    863            this.sleepTimer = par1NBTTagCompound.getShort("SleepTimer");
    864            this.experience = par1NBTTagCompound.getFloat("XpP");
    865            this.experienceLevel = par1NBTTagCompound.getInteger("XpLevel");
    866            this.experienceTotal = par1NBTTagCompound.getInteger("XpTotal");
    867            this.func_85040_s(par1NBTTagCompound.getInteger("Score"));
    868
    869            if (this.sleeping)
    870            {
    871                this.playerLocation = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
    872                this.wakeUpPlayer(true, true, false);
    873            }
    874
    875            if (par1NBTTagCompound.hasKey("SpawnX") && par1NBTTagCompound.hasKey("SpawnY") && par1NBTTagCompound.hasKey("SpawnZ"))
    876            {
    877                this.spawnChunk = new ChunkCoordinates(par1NBTTagCompound.getInteger("SpawnX"), par1NBTTagCompound.getInteger("SpawnY"), par1NBTTagCompound.getInteger("SpawnZ"));
    878                this.spawnForced = par1NBTTagCompound.getBoolean("SpawnForced");
    879            }
    880
    881            this.foodStats.readNBT(par1NBTTagCompound);
    882            this.capabilities.readCapabilitiesFromNBT(par1NBTTagCompound);
    883
    884            if (par1NBTTagCompound.hasKey("EnderItems"))
    885            {
    886                NBTTagList var3 = par1NBTTagCompound.getTagList("EnderItems");
    887                this.theInventoryEnderChest.loadInventoryFromNBT(var3);
    888            }
    889        }
    890
    891        /**
    892         * (abstract) Protected helper method to write subclass entity data to NBT.
    893         */
    894        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    895        {
    896            super.writeEntityToNBT(par1NBTTagCompound);
    897            par1NBTTagCompound.setTag("Inventory", this.inventory.writeToNBT(new NBTTagList()));
    898            par1NBTTagCompound.setInteger("SelectedItemSlot", this.inventory.currentItem);
    899            par1NBTTagCompound.setBoolean("Sleeping", this.sleeping);
    900            par1NBTTagCompound.setShort("SleepTimer", (short)this.sleepTimer);
    901            par1NBTTagCompound.setFloat("XpP", this.experience);
    902            par1NBTTagCompound.setInteger("XpLevel", this.experienceLevel);
    903            par1NBTTagCompound.setInteger("XpTotal", this.experienceTotal);
    904            par1NBTTagCompound.setInteger("Score", this.getScore());
    905
    906            if (this.spawnChunk != null)
    907            {
    908                par1NBTTagCompound.setInteger("SpawnX", this.spawnChunk.posX);
    909                par1NBTTagCompound.setInteger("SpawnY", this.spawnChunk.posY);
    910                par1NBTTagCompound.setInteger("SpawnZ", this.spawnChunk.posZ);
    911                par1NBTTagCompound.setBoolean("SpawnForced", this.spawnForced);
    912            }
    913
    914            this.foodStats.writeNBT(par1NBTTagCompound);
    915            this.capabilities.writeCapabilitiesToNBT(par1NBTTagCompound);
    916            par1NBTTagCompound.setTag("EnderItems", this.theInventoryEnderChest.saveInventoryToNBT());
    917        }
    918
    919        /**
    920         * Displays the GUI for interacting with a chest inventory. Args: chestInventory
    921         */
    922        public void displayGUIChest(IInventory par1IInventory) {}
    923
    924        public void displayGUIEnchantment(int par1, int par2, int par3) {}
    925
    926        /**
    927         * Displays the GUI for interacting with an anvil.
    928         */
    929        public void displayGUIAnvil(int par1, int par2, int par3) {}
    930
    931        /**
    932         * Displays the crafting GUI for a workbench.
    933         */
    934        public void displayGUIWorkbench(int par1, int par2, int par3) {}
    935
    936        public float getEyeHeight()
    937        {
    938            return 0.12F;
    939        }
    940
    941        /**
    942         * sets the players height back to normal after doing things like sleeping and dieing
    943         */
    944        protected void resetHeight()
    945        {
    946            this.yOffset = 1.62F;
    947        }
    948
    949        /**
    950         * Called when the entity is attacked.
    951         */
    952        public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    953        {
    954            if (this.func_85032_ar())
    955            {
    956                return false;
    957            }
    958            else if (this.capabilities.disableDamage && !par1DamageSource.canHarmInCreative())
    959            {
    960                return false;
    961            }
    962            else
    963            {
    964                this.entityAge = 0;
    965
    966                if (this.getHealth() <= 0)
    967                {
    968                    return false;
    969                }
    970                else
    971                {
    972                    if (this.isPlayerSleeping() && !this.worldObj.isRemote)
    973                    {
    974                        this.wakeUpPlayer(true, true, false);
    975                    }
    976
    977                    if (par1DamageSource.func_76350_n())
    978                    {
    979                        if (this.worldObj.difficultySetting == 0)
    980                        {
    981                            par2 = 0;
    982                        }
    983
    984                        if (this.worldObj.difficultySetting == 1)
    985                        {
    986                            par2 = par2 / 2 + 1;
    987                        }
    988
    989                        if (this.worldObj.difficultySetting == 3)
    990                        {
    991                            par2 = par2 * 3 / 2;
    992                        }
    993                    }
    994
    995                    if (par2 == 0)
    996                    {
    997                        return false;
    998                    }
    999                    else
    1000                    {
    1001                        Entity var3 = par1DamageSource.getEntity();
    1002
    1003                        if (var3 instanceof EntityArrow && ((EntityArrow)var3).shootingEntity != null)
    1004                        {
    1005                            var3 = ((EntityArrow)var3).shootingEntity;
    1006                        }
    1007
    1008                        if (var3 instanceof EntityLiving)
    1009                        {
    1010                            this.alertWolves((EntityLiving)var3, false);
    1011                        }
    1012
    1013                        this.addStat(StatList.damageTakenStat, par2);
    1014                        return super.attackEntityFrom(par1DamageSource, par2);
    1015                    }
    1016                }
    1017            }
    1018        }
    1019
    1020        /**
    1021         * Reduces damage, depending on potions
    1022         */
    1023        protected int applyPotionDamageCalculations(DamageSource par1DamageSource, int par2)
    1024        {
    1025            int var3 = super.applyPotionDamageCalculations(par1DamageSource, par2);
    1026
    1027            if (var3 <= 0)
    1028            {
    1029                return 0;
    1030            }
    1031            else
    1032            {
    1033                int var4 = EnchantmentHelper.getEnchantmentModifierDamage(this.inventory.armorInventory, par1DamageSource);
    1034
    1035                if (var4 > 20)
    1036                {
    1037                    var4 = 20;
    1038                }
    1039
    1040                if (var4 > 0 && var4 <= 20)
    1041                {
    1042                    int var5 = 25 - var4;
    1043                    int var6 = var3 * var5 + this.carryoverDamage;
    1044                    var3 = var6 / 25;
    1045                    this.carryoverDamage = var6 % 25;
    1046                }
    1047
    1048                return var3;
    1049            }
    1050        }
    1051
    1052        /**
    1053         * returns if pvp is enabled or not
    1054         */
    1055        protected boolean isPVPEnabled()
    1056        {
    1057            return false;
    1058        }
    1059
    1060        /**
    1061         * Called when the player attack or gets attacked, it's alert all wolves in the area that are owned by the player to
    1062         * join the attack or defend the player.
    1063         */
    1064        protected void alertWolves(EntityLiving par1EntityLiving, boolean par2)
    1065        {
    1066            if (!(par1EntityLiving instanceof EntityCreeper) && !(par1EntityLiving instanceof EntityGhast))
    1067            {
    1068                if (par1EntityLiving instanceof EntityWolf)
    1069                {
    1070                    EntityWolf var3 = (EntityWolf)par1EntityLiving;
    1071
    1072                    if (var3.isTamed() && this.username.equals(var3.getOwnerName()))
    1073                    {
    1074                        return;
    1075                    }
    1076                }
    1077
    1078                if (!(par1EntityLiving instanceof EntityPlayer) || this.isPVPEnabled())
    1079                {
    1080                    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));
    1081                    Iterator var4 = var6.iterator();
    1082
    1083                    while (var4.hasNext())
    1084                    {
    1085                        EntityWolf var5 = (EntityWolf)var4.next();
    1086
    1087                        if (var5.isTamed() && var5.getEntityToAttack() == null && this.username.equals(var5.getOwnerName()) && (!par2 || !var5.isSitting()))
    1088                        {
    1089                            var5.setSitting(false);
    1090                            var5.setTarget(par1EntityLiving);
    1091                        }
    1092                    }
    1093                }
    1094            }
    1095        }
    1096
    1097        protected void damageArmor(int par1)
    1098        {
    1099            this.inventory.damageArmor(par1);
    1100        }
    1101
    1102        /**
    1103         * Returns the current armor value as determined by a call to InventoryPlayer.getTotalArmorValue
    1104         */
    1105        public int getTotalArmorValue()
    1106        {
    1107            return this.inventory.getTotalArmorValue();
    1108        }
    1109
    1110        public float func_82243_bO()
    1111        {
    1112            int var1 = 0;
    1113            ItemStack[] var2 = this.inventory.armorInventory;
    1114            int var3 = var2.length;
    1115
    1116            for (int var4 = 0; var4 < var3; ++var4)
    1117            {
    1118                ItemStack var5 = var2[var4];
    1119
    1120                if (var5 != null)
    1121                {
    1122                    ++var1;
    1123                }
    1124            }
    1125
    1126            return (float)var1 / (float)this.inventory.armorInventory.length;
    1127        }
    1128
    1129        /**
    1130         * Deals damage to the entity. If its a EntityPlayer then will take damage from the armor first and then health
    1131         * second with the reduced value. Args: damageAmount
    1132         */
    1133        protected void damageEntity(DamageSource par1DamageSource, int par2)
    1134        {
    1135            if (!this.func_85032_ar())
    1136            {
    1137                par2 = ForgeHooks.onLivingHurt(this, par1DamageSource, par2);
    1138                if (par2 <= 0)
    1139                {
    1140                    return;
    1141                }
    1142
    1143                if (!par1DamageSource.isUnblockable() && this.isBlocking())
    1144                {
    1145                    par2 = 1 + par2 >> 1;
    1146                }
    1147
    1148                par2 = ArmorProperties.ApplyArmor(this, inventory.armorInventory, par1DamageSource, par2);
    1149                if (par2 <= 0)
    1150                {
    1151                    return;
    1152                }
    1153                par2 = this.applyPotionDamageCalculations(par1DamageSource, par2);
    1154                this.addExhaustion(par1DamageSource.getHungerDamage());
    1155                this.health -= par2;
    1156            }
    1157        }
    1158
    1159        /**
    1160         * Displays the furnace GUI for the passed in furnace entity. Args: tileEntityFurnace
    1161         */
    1162        public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace) {}
    1163
    1164        /**
    1165         * Displays the dipsenser GUI for the passed in dispenser entity. Args: TileEntityDispenser
    1166         */
    1167        public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser) {}
    1168
    1169        /**
    1170         * Displays the GUI for editing a sign. Args: tileEntitySign
    1171         */
    1172        public void displayGUIEditSign(TileEntity par1TileEntity) {}
    1173
    1174        /**
    1175         * Displays the GUI for interacting with a brewing stand.
    1176         */
    1177        public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand) {}
    1178
    1179        /**
    1180         * Displays the GUI for interacting with a beacon.
    1181         */
    1182        public void displayGUIBeacon(TileEntityBeacon par1TileEntityBeacon) {}
    1183
    1184        public void displayGUIMerchant(IMerchant par1IMerchant) {}
    1185
    1186        /**
    1187         * Displays the GUI for interacting with a book.
    1188         */
    1189        public void displayGUIBook(ItemStack par1ItemStack) {}
    1190
    1191        public boolean interactWith(Entity par1Entity)
    1192        {
    1193            if (MinecraftForge.EVENT_BUS.post(new EntityInteractEvent(this, par1Entity)))
    1194            {
    1195                return false;
    1196            }
    1197            if (par1Entity.interact(this))
    1198            {
    1199                return true;
    1200            }
    1201            else
    1202            {
    1203                ItemStack var2 = this.getCurrentEquippedItem();
    1204
    1205                if (var2 != null && par1Entity instanceof EntityLiving)
    1206                {
    1207                    if (this.capabilities.isCreativeMode)
    1208                    {
    1209                        var2 = var2.copy();
    1210                    }
    1211
    1212                    if (var2.interactWith((EntityLiving)par1Entity))
    1213                    {
    1214                        if (var2.stackSize <= 0 && !this.capabilities.isCreativeMode)
    1215                        {
    1216                            this.destroyCurrentEquippedItem();
    1217                        }
    1218
    1219                        return true;
    1220                    }
    1221                }
    1222
    1223                return false;
    1224            }
    1225        }
    1226
    1227        /**
    1228         * Returns the currently being used item by the player.
    1229         */
    1230        public ItemStack getCurrentEquippedItem()
    1231        {
    1232            return this.inventory.getCurrentItem();
    1233        }
    1234
    1235        /**
    1236         * Destroys the currently equipped item from the player's inventory.
    1237         */
    1238        public void destroyCurrentEquippedItem()
    1239        {
    1240            ItemStack orig = getCurrentEquippedItem();
    1241            this.inventory.setInventorySlotContents(this.inventory.currentItem, (ItemStack)null);
    1242            MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(this, orig));
    1243        }
    1244
    1245        /**
    1246         * Returns the Y Offset of this entity.
    1247         */
    1248        public double getYOffset()
    1249        {
    1250            return (double)(this.yOffset - 0.5F);
    1251        }
    1252
    1253        /**
    1254         * Attacks for the player the targeted entity with the currently equipped item.  The equipped item has hitEntity
    1255         * called on it. Args: targetEntity
    1256         */
    1257        public void attackTargetEntityWithCurrentItem(Entity par1Entity)
    1258        {
    1259            if (MinecraftForge.EVENT_BUS.post(new AttackEntityEvent(this, par1Entity)))
    1260            {
    1261                return;
    1262            }
    1263            ItemStack stack = getCurrentEquippedItem();
    1264            if (stack != null && stack.getItem().onLeftClickEntity(stack, this, par1Entity))
    1265            {
    1266                return;
    1267            }
    1268            if (par1Entity.canAttackWithItem())
    1269            {
    1270                if (!par1Entity.func_85031_j(this))
    1271                {
    1272                    int var2 = this.inventory.getDamageVsEntity(par1Entity);
    1273
    1274                    if (this.isPotionActive(Potion.damageBoost))
    1275                    {
    1276                        var2 += 3 << this.getActivePotionEffect(Potion.damageBoost).getAmplifier();
    1277                    }
    1278
    1279                    if (this.isPotionActive(Potion.weakness))
    1280                    {
    1281                        var2 -= 2 << this.getActivePotionEffect(Potion.weakness).getAmplifier();
    1282                    }
    1283
    1284                    int var3 = 0;
    1285                    int var4 = 0;
    1286
    1287                    if (par1Entity instanceof EntityLiving)
    1288                    {
    1289                        var4 = EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLiving)par1Entity);
    1290                        var3 += EnchantmentHelper.getKnockbackModifier(this, (EntityLiving)par1Entity);
    1291                    }
    1292
    1293                    if (this.isSprinting())
    1294                    {
    1295                        ++var3;
    1296                    }
    1297
    1298                    if (var2 > 0 || var4 > 0)
    1299                    {
    1300                        boolean var5 = this.fallDistance > 0.0F && !this.onGround && !this.isOnLadder() && !this.isInWater() && !this.isPotionActive(Potion.blindness) && this.ridingEntity == null && par1Entity instanceof EntityLiving;
    1301
    1302                        if (var5)
    1303                        {
    1304                            var2 += this.rand.nextInt(var2 / 2 + 2);
    1305                        }
    1306
    1307                        var2 += var4;
    1308                        boolean var6 = false;
    1309                        int var7 = EnchantmentHelper.getFireAspectModifier(this);
    1310
    1311                        if (par1Entity instanceof EntityLiving && var7 > 0 && !par1Entity.isBurning())
    1312                        {
    1313                            var6 = true;
    1314                            par1Entity.setFire(1);
    1315                        }
    1316
    1317                        boolean var8 = par1Entity.attackEntityFrom(DamageSource.causePlayerDamage(this), var2);
    1318
    1319                        if (var8)
    1320                        {
    1321                            if (var3 > 0)
    1322                            {
    1323                                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));
    1324                                this.motionX *= 0.6D;
    1325                                this.motionZ *= 0.6D;
    1326                                this.setSprinting(false);
    1327                            }
    1328
    1329                            if (var5)
    1330                            {
    1331                                this.onCriticalHit(par1Entity);
    1332                            }
    1333
    1334                            if (var4 > 0)
    1335                            {
    1336                                this.onEnchantmentCritical(par1Entity);
    1337                            }
    1338
    1339                            if (var2 >= 18)
    1340                            {
    1341                                this.triggerAchievement(AchievementList.overkill);
    1342                            }
    1343
    1344                            this.setLastAttackingEntity(par1Entity);
    1345
    1346                            if (par1Entity instanceof EntityLiving)
    1347                            {
    1348                                EnchantmentThorns.func_92044_a(this, (EntityLiving)par1Entity, this.rand);
    1349                            }
    1350                        }
    1351
    1352                        ItemStack var9 = this.getCurrentEquippedItem();
    1353
    1354                        if (var9 != null && par1Entity instanceof EntityLiving)
    1355                        {
    1356                            var9.hitEntity((EntityLiving)par1Entity, this);
    1357
    1358                            if (var9.stackSize <= 0)
    1359                            {
    1360                                this.destroyCurrentEquippedItem();
    1361                            }
    1362                        }
    1363
    1364                        if (par1Entity instanceof EntityLiving)
    1365                        {
    1366                            if (par1Entity.isEntityAlive())
    1367                            {
    1368                                this.alertWolves((EntityLiving)par1Entity, true);
    1369                            }
    1370
    1371                            this.addStat(StatList.damageDealtStat, var2);
    1372
    1373                            if (var7 > 0 && var8)
    1374                            {
    1375                                par1Entity.setFire(var7 * 4);
    1376                            }
    1377                            else if (var6)
    1378                            {
    1379                                par1Entity.extinguish();
    1380                            }
    1381                        }
    1382
    1383                        this.addExhaustion(0.3F);
    1384                    }
    1385                }
    1386            }
    1387        }
    1388
    1389        /**
    1390         * Called when the player performs a critical hit on the Entity. Args: entity that was hit critically
    1391         */
    1392        public void onCriticalHit(Entity par1Entity) {}
    1393
    1394        public void onEnchantmentCritical(Entity par1Entity) {}
    1395
    1396        @SideOnly(Side.CLIENT)
    1397        public void respawnPlayer() {}
    1398
    1399        /**
    1400         * Will get destroyed next tick.
    1401         */
    1402        public void setDead()
    1403        {
    1404            super.setDead();
    1405            this.inventoryContainer.onCraftGuiClosed(this);
    1406
    1407            if (this.openContainer != null)
    1408            {
    1409                this.openContainer.onCraftGuiClosed(this);
    1410            }
    1411        }
    1412
    1413        /**
    1414         * Checks if this entity is inside of an opaque block
    1415         */
    1416        public boolean isEntityInsideOpaqueBlock()
    1417        {
    1418            return !this.sleeping && super.isEntityInsideOpaqueBlock();
    1419        }
    1420
    1421        public boolean func_71066_bF()
    1422        {
    1423            return false;
    1424        }
    1425
    1426        /**
    1427         * Attempts to have the player sleep in a bed at the specified location.
    1428         */
    1429        public EnumStatus sleepInBedAt(int par1, int par2, int par3)
    1430        {
    1431            PlayerSleepInBedEvent event = new PlayerSleepInBedEvent(this, par1, par2, par3);
    1432            MinecraftForge.EVENT_BUS.post(event);
    1433            if (event.result != null)
    1434            {
    1435                return event.result;
    1436            }
    1437            if (!this.worldObj.isRemote)
    1438            {
    1439                if (this.isPlayerSleeping() || !this.isEntityAlive())
    1440                {
    1441                    return EnumStatus.OTHER_PROBLEM;
    1442                }
    1443
    1444                if (!this.worldObj.provider.isSurfaceWorld())
    1445                {
    1446                    return EnumStatus.NOT_POSSIBLE_HERE;
    1447                }
    1448
    1449                if (this.worldObj.isDaytime())
    1450                {
    1451                    return EnumStatus.NOT_POSSIBLE_NOW;
    1452                }
    1453
    1454                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)
    1455                {
    1456                    return EnumStatus.TOO_FAR_AWAY;
    1457                }
    1458
    1459                double var4 = 8.0D;
    1460                double var6 = 5.0D;
    1461                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));
    1462
    1463                if (!var8.isEmpty())
    1464                {
    1465                    return EnumStatus.NOT_SAFE;
    1466                }
    1467            }
    1468
    1469            this.setSize(0.2F, 0.2F);
    1470            this.yOffset = 0.2F;
    1471
    1472            if (this.worldObj.blockExists(par1, par2, par3))
    1473            {
    1474                int var9 = this.worldObj.getBlockMetadata(par1, par2, par3);
    1475                int var5 = BlockBed.getDirection(var9);
    1476                Block block = Block.blocksList[worldObj.getBlockId(par1, par2, par3)];
    1477                if (block != null)
    1478                {
    1479                    var5 = block.getBedDirection(worldObj, par1, par2, par3);
    1480                }
    1481                float var10 = 0.5F;
    1482                float var7 = 0.5F;
    1483
    1484                switch (var5)
    1485                {
    1486                    case 0:
    1487                        var7 = 0.9F;
    1488                        break;
    1489                    case 1:
    1490                        var10 = 0.1F;
    1491                        break;
    1492                    case 2:
    1493                        var7 = 0.1F;
    1494                        break;
    1495                    case 3:
    1496                        var10 = 0.9F;
    1497                }
    1498
    1499                this.func_71013_b(var5);
    1500                this.setPosition((double)((float)par1 + var10), (double)((float)par2 + 0.9375F), (double)((float)par3 + var7));
    1501            }
    1502            else
    1503            {
    1504                this.setPosition((double)((float)par1 + 0.5F), (double)((float)par2 + 0.9375F), (double)((float)par3 + 0.5F));
    1505            }
    1506
    1507            this.sleeping = true;
    1508            this.sleepTimer = 0;
    1509            this.playerLocation = new ChunkCoordinates(par1, par2, par3);
    1510            this.motionX = this.motionZ = this.motionY = 0.0D;
    1511
    1512            if (!this.worldObj.isRemote)
    1513            {
    1514                this.worldObj.updateAllPlayersSleepingFlag();
    1515            }
    1516
    1517            return EnumStatus.OK;
    1518        }
    1519
    1520        private void func_71013_b(int par1)
    1521        {
    1522            this.field_71079_bU = 0.0F;
    1523            this.field_71089_bV = 0.0F;
    1524
    1525            switch (par1)
    1526            {
    1527                case 0:
    1528                    this.field_71089_bV = -1.8F;
    1529                    break;
    1530                case 1:
    1531                    this.field_71079_bU = 1.8F;
    1532                    break;
    1533                case 2:
    1534                    this.field_71089_bV = 1.8F;
    1535                    break;
    1536                case 3:
    1537                    this.field_71079_bU = -1.8F;
    1538            }
    1539        }
    1540
    1541        /**
    1542         * Wake up the player if they're sleeping.
    1543         */
    1544        public void wakeUpPlayer(boolean par1, boolean par2, boolean par3)
    1545        {
    1546            this.setSize(0.6F, 1.8F);
    1547            this.resetHeight();
    1548            ChunkCoordinates var4 = this.playerLocation;
    1549            ChunkCoordinates var5 = this.playerLocation;
    1550
    1551            Block block = (var4 == null ? null : Block.blocksList[worldObj.getBlockId(var4.posX, var4.posY, var4.posZ)]);
    1552
    1553            if (var4 != null && block != null && block.isBed(worldObj, var4.posX, var4.posY, var4.posZ, this))
    1554            {
    1555                block.setBedOccupied(this.worldObj, var4.posX, var4.posY, var4.posZ, this, false);
    1556                var5 = block.getBedSpawnPosition(worldObj, var4.posX, var4.posY, var4.posZ, this);
    1557
    1558                if (var5 == null)
    1559                {
    1560                    var5 = new ChunkCoordinates(var4.posX, var4.posY + 1, var4.posZ);
    1561                }
    1562
    1563                this.setPosition((double)((float)var5.posX + 0.5F), (double)((float)var5.posY + this.yOffset + 0.1F), (double)((float)var5.posZ + 0.5F));
    1564            }
    1565
    1566            this.sleeping = false;
    1567
    1568            if (!this.worldObj.isRemote && par2)
    1569            {
    1570                this.worldObj.updateAllPlayersSleepingFlag();
    1571            }
    1572
    1573            if (par1)
    1574            {
    1575                this.sleepTimer = 0;
    1576            }
    1577            else
    1578            {
    1579                this.sleepTimer = 100;
    1580            }
    1581
    1582            if (par3)
    1583            {
    1584                this.setSpawnChunk(this.playerLocation, false);
    1585            }
    1586        }
    1587
    1588        /**
    1589         * Checks if the player is currently in a bed
    1590         */
    1591        private boolean isInBed()
    1592        {
    1593            ChunkCoordinates c = playerLocation;
    1594            int blockID = worldObj.getBlockId(c.posX, c.posY, c.posZ);
    1595            return Block.blocksList[blockID] != null && Block.blocksList[blockID].isBed(worldObj, c.posX, c.posY, c.posZ, this);
    1596        }
    1597
    1598        /**
    1599         * Ensure that a block enabling respawning exists at the specified coordinates and find an empty space nearby to
    1600         * spawn.
    1601         */
    1602        public static ChunkCoordinates verifyRespawnCoordinates(World par0World, ChunkCoordinates par1ChunkCoordinates, boolean par2)
    1603        {
    1604            IChunkProvider var3 = par0World.getChunkProvider();
    1605            var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
    1606            var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4);
    1607            var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
    1608            var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4);
    1609
    1610            ChunkCoordinates c = par1ChunkCoordinates;
    1611            Block block = Block.blocksList[par0World.getBlockId(c.posX, c.posY, c.posZ)];
    1612
    1613            if (block != null && block.isBed(par0World, c.posX, c.posY, c.posZ, null))
    1614            {
    1615                ChunkCoordinates var8 = block.getBedSpawnPosition(par0World, c.posX, c.posY, c.posZ, null);
    1616                return var8;
    1617            }
    1618            else
    1619            {
    1620                Material var4 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY, par1ChunkCoordinates.posZ);
    1621                Material var5 = par0World.getBlockMaterial(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY + 1, par1ChunkCoordinates.posZ);
    1622                boolean var6 = !var4.isSolid() && !var4.isLiquid();
    1623                boolean var7 = !var5.isSolid() && !var5.isLiquid();
    1624                return par2 && var6 && var7 ? par1ChunkCoordinates : null;
    1625            }
    1626        }
    1627
    1628        @SideOnly(Side.CLIENT)
    1629
    1630        /**
    1631         * Returns the orientation of the bed in degrees.
    1632         */
    1633        public float getBedOrientationInDegrees()
    1634        {
    1635            if (this.playerLocation != null)
    1636            {
    1637                int x = playerLocation.posX;
    1638                int y = playerLocation.posY;
    1639                int z = playerLocation.posZ;
    1640                Block block = Block.blocksList[worldObj.getBlockId(x, y, z)];
    1641                int var2 = (block == null ? 0 : block.getBedDirection(worldObj, x, y, z));
    1642
    1643                switch (var2)
    1644                {
    1645                    case 0:
    1646                        return 90.0F;
    1647                    case 1:
    1648                        return 0.0F;
    1649                    case 2:
    1650                        return 270.0F;
    1651                    case 3:
    1652                        return 180.0F;
    1653                }
    1654            }
    1655
    1656            return 0.0F;
    1657        }
    1658
    1659        /**
    1660         * Returns whether player is sleeping or not
    1661         */
    1662        public boolean isPlayerSleeping()
    1663        {
    1664            return this.sleeping;
    1665        }
    1666
    1667        /**
    1668         * Returns whether or not the player is asleep and the screen has fully faded.
    1669         */
    1670        public boolean isPlayerFullyAsleep()
    1671        {
    1672            return this.sleeping && this.sleepTimer >= 100;
    1673        }
    1674
    1675        @SideOnly(Side.CLIENT)
    1676        public int getSleepTimer()
    1677        {
    1678            return this.sleepTimer;
    1679        }
    1680
    1681        @SideOnly(Side.CLIENT)
    1682        protected boolean getHideCape(int par1)
    1683        {
    1684            return (this.dataWatcher.getWatchableObjectByte(16) & 1 << par1) != 0;
    1685        }
    1686
    1687        protected void setHideCape(int par1, boolean par2)
    1688        {
    1689            byte var3 = this.dataWatcher.getWatchableObjectByte(16);
    1690
    1691            if (par2)
    1692            {
    1693                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 | 1 << par1)));
    1694            }
    1695            else
    1696            {
    1697                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 & ~(1 << par1))));
    1698            }
    1699        }
    1700
    1701        /**
    1702         * Add a chat message to the player
    1703         */
    1704        public void addChatMessage(String par1Str) {}
    1705
    1706        /**
    1707         * Returns the location of the bed the player will respawn at, or null if the player has not slept in a bed.
    1708         */
    1709        public ChunkCoordinates getBedLocation()
    1710        {
    1711            return this.spawnChunk;
    1712        }
    1713
    1714        public boolean isSpawnForced()
    1715        {
    1716            return this.spawnForced;
    1717        }
    1718
    1719        /**
    1720         * Defines a spawn coordinate to player spawn. Used by bed after the player sleep on it.
    1721         */
    1722        public void setSpawnChunk(ChunkCoordinates par1ChunkCoordinates, boolean par2)
    1723        {
    1724            if (par1ChunkCoordinates != null)
    1725            {
    1726                this.spawnChunk = new ChunkCoordinates(par1ChunkCoordinates);
    1727                this.spawnForced = par2;
    1728            }
    1729            else
    1730            {
    1731                this.spawnChunk = null;
    1732                this.spawnForced = false;
    1733            }
    1734        }
    1735
    1736        /**
    1737         * Will trigger the specified trigger.
    1738         */
    1739        public void triggerAchievement(StatBase par1StatBase)
    1740        {
    1741            this.addStat(par1StatBase, 1);
    1742        }
    1743
    1744        /**
    1745         * Adds a value to a statistic field.
    1746         */
    1747        public void addStat(StatBase par1StatBase, int par2) {}
    1748
    1749        /**
    1750         * Causes this entity to do an upwards motion (jumping).
    1751         */
    1752        protected void jump()
    1753        {
    1754            super.jump();
    1755            this.addStat(StatList.jumpStat, 1);
    1756
    1757            if (this.isSprinting())
    1758            {
    1759                this.addExhaustion(0.8F);
    1760            }
    1761            else
    1762            {
    1763                this.addExhaustion(0.2F);
    1764            }
    1765        }
    1766
    1767        /**
    1768         * Moves the entity based on the specified heading.  Args: strafe, forward
    1769         */
    1770        public void moveEntityWithHeading(float par1, float par2)
    1771        {
    1772            double var3 = this.posX;
    1773            double var5 = this.posY;
    1774            double var7 = this.posZ;
    1775
    1776            if (this.capabilities.isFlying && this.ridingEntity == null)
    1777            {
    1778                double var9 = this.motionY;
    1779                float var11 = this.jumpMovementFactor;
    1780                this.jumpMovementFactor = this.capabilities.getFlySpeed();
    1781                super.moveEntityWithHeading(par1, par2);
    1782                this.motionY = var9 * 0.6D;
    1783                this.jumpMovementFactor = var11;
    1784            }
    1785            else
    1786            {
    1787                super.moveEntityWithHeading(par1, par2);
    1788            }
    1789
    1790            this.addMovementStat(this.posX - var3, this.posY - var5, this.posZ - var7);
    1791        }
    1792
    1793        /**
    1794         * Adds a value to a movement statistic field - like run, walk, swin or climb.
    1795         */
    1796        public void addMovementStat(double par1, double par3, double par5)
    1797        {
    1798            if (this.ridingEntity == null)
    1799            {
    1800                int var7;
    1801
    1802                if (this.isInsideOfMaterial(Material.water))
    1803                {
    1804                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
    1805
    1806                    if (var7 > 0)
    1807                    {
    1808                        this.addStat(StatList.distanceDoveStat, var7);
    1809                        this.addExhaustion(0.015F * (float)var7 * 0.01F);
    1810                    }
    1811                }
    1812                else if (this.isInWater())
    1813                {
    1814                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
    1815
    1816                    if (var7 > 0)
    1817                    {
    1818                        this.addStat(StatList.distanceSwumStat, var7);
    1819                        this.addExhaustion(0.015F * (float)var7 * 0.01F);
    1820                    }
    1821                }
    1822                else if (this.isOnLadder())
    1823                {
    1824                    if (par3 > 0.0D)
    1825                    {
    1826                        this.addStat(StatList.distanceClimbedStat, (int)Math.round(par3 * 100.0D));
    1827                    }
    1828                }
    1829                else if (this.onGround)
    1830                {
    1831                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
    1832
    1833                    if (var7 > 0)
    1834                    {
    1835                        this.addStat(StatList.distanceWalkedStat, var7);
    1836
    1837                        if (this.isSprinting())
    1838                        {
    1839                            this.addExhaustion(0.099999994F * (float)var7 * 0.01F);
    1840                        }
    1841                        else
    1842                        {
    1843                            this.addExhaustion(0.01F * (float)var7 * 0.01F);
    1844                        }
    1845                    }
    1846                }
    1847                else
    1848                {
    1849                    var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F);
    1850
    1851                    if (var7 > 25)
    1852                    {
    1853                        this.addStat(StatList.distanceFlownStat, var7);
    1854                    }
    1855                }
    1856            }
    1857        }
    1858
    1859        /**
    1860         * Adds a value to a mounted movement statistic field - by minecart, boat, or pig.
    1861         */
    1862        private void addMountedMovementStat(double par1, double par3, double par5)
    1863        {
    1864            if (this.ridingEntity != null)
    1865            {
    1866                int var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F);
    1867
    1868                if (var7 > 0)
    1869                {
    1870                    if (this.ridingEntity instanceof EntityMinecart)
    1871                    {
    1872                        this.addStat(StatList.distanceByMinecartStat, var7);
    1873
    1874                        if (this.startMinecartRidingCoordinate == null)
    1875                        {
    1876                            this.startMinecartRidingCoordinate = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ));
    1877                        }
    1878                        else if ((double)this.startMinecartRidingCoordinate.getDistanceSquared(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) >= 1000000.0D)
    1879                        {
    1880                            this.addStat(AchievementList.onARail, 1);
    1881                        }
    1882                    }
    1883                    else if (this.ridingEntity instanceof EntityBoat)
    1884                    {
    1885                        this.addStat(StatList.distanceByBoatStat, var7);
    1886                    }
    1887                    else if (this.ridingEntity instanceof EntityPig)
    1888                    {
    1889                        this.addStat(StatList.distanceByPigStat, var7);
    1890                    }
    1891                }
    1892            }
    1893        }
    1894
    1895        /**
    1896         * Called when the mob is falling. Calculates and applies fall damage.
    1897         */
    1898        protected void fall(float par1)
    1899        {
    1900            if (!this.capabilities.allowFlying)
    1901            {
    1902                if (par1 >= 2.0F)
    1903                {
    1904                    this.addStat(StatList.distanceFallenStat, (int)Math.round((double)par1 * 100.0D));
    1905                }
    1906
    1907                super.fall(par1);
    1908            }
    1909        }
    1910
    1911        /**
    1912         * This method gets called when the entity kills another one.
    1913         */
    1914        public void onKillEntity(EntityLiving par1EntityLiving)
    1915        {
    1916            if (par1EntityLiving instanceof IMob)
    1917            {
    1918                this.triggerAchievement(AchievementList.killEnemy);
    1919            }
    1920        }
    1921
    1922        /**
    1923         * Sets the Entity inside a web block.
    1924         */
    1925        public void setInWeb()
    1926        {
    1927            if (!this.capabilities.isFlying)
    1928            {
    1929                super.setInWeb();
    1930            }
    1931        }
    1932
    1933        @SideOnly(Side.CLIENT)
    1934
    1935        /**
    1936         * Gets the Icon Index of the item currently held
    1937         */
    1938        public int getItemIcon(ItemStack par1ItemStack, int par2)
    1939        {
    1940            int var3 = super.getItemIcon(par1ItemStack, par2);
    1941
    1942            if (par1ItemStack.itemID == Item.fishingRod.shiftedIndex && this.fishEntity != null)
    1943            {
    1944                var3 = par1ItemStack.getIconIndex() + 16;
    1945            }
    1946            else
    1947            {
    1948                if (par1ItemStack.getItem().requiresMultipleRenderPasses())
    1949                {
    1950                    return par1ItemStack.getItem().getIconIndex(par1ItemStack, par2);
    1951                }
    1952
    1953                if (this.itemInUse != null && par1ItemStack.itemID == Item.bow.shiftedIndex)
    1954                {
    1955                    int var4 = par1ItemStack.getMaxItemUseDuration() - this.itemInUseCount;
    1956
    1957                    if (var4 >= 18)
    1958                    {
    1959                        return 133;
    1960                    }
    1961
    1962                    if (var4 > 13)
    1963                    {
    1964                        return 117;
    1965                    }
    1966
    1967                    if (var4 > 0)
    1968                    {
    1969                        return 101;
    1970                    }
    1971                }
    1972                var3 = par1ItemStack.getItem().getIconIndex(par1ItemStack, par2, this, itemInUse, itemInUseCount);
    1973            }
    1974
    1975            return var3;
    1976        }
    1977
    1978        public ItemStack getCurrentArmor(int par1)
    1979        {
    1980            return this.inventory.armorItemInSlot(par1);
    1981        }
    1982
    1983        protected void func_82164_bB() {}
    1984
    1985        protected void func_82162_bC() {}
    1986
    1987        /**
    1988         * This method increases the player's current amount of experience.
    1989         */
    1990        public void addExperience(int par1)
    1991        {
    1992            this.func_85039_t(par1);
    1993            int var2 = Integer.MAX_VALUE - this.experienceTotal;
    1994
    1995            if (par1 > var2)
    1996            {
    1997                par1 = var2;
    1998            }
    1999
    2000            this.experience += (float)par1 / (float)this.xpBarCap();
    2001
    2002            for (this.experienceTotal += par1; this.experience >= 1.0F; this.experience /= (float)this.xpBarCap())
    2003            {
    2004                this.experience = (this.experience - 1.0F) * (float)this.xpBarCap();
    2005                this.addExperienceLevel(1);
    2006            }
    2007        }
    2008
    2009        /**
    2010         * Add experience levels to this player.
    2011         */
    2012        public void addExperienceLevel(int par1)
    2013        {
    2014            this.experienceLevel += par1;
    2015
    2016            if (this.experienceLevel < 0)
    2017            {
    2018                this.experienceLevel = 0;
    2019                this.experience = 0.0F;
    2020                this.experienceTotal = 0;
    2021            }
    2022
    2023            if (par1 > 0 && this.experienceLevel % 5 == 0 && (float)this.field_82249_h < (float)this.ticksExisted - 100.0F)
    2024            {
    2025                float var2 = this.experienceLevel > 30 ? 1.0F : (float)this.experienceLevel / 30.0F;
    2026                this.worldObj.playSoundAtEntity(this, "random.levelup", var2 * 0.75F, 1.0F);
    2027                this.field_82249_h = this.ticksExisted;
    2028            }
    2029        }
    2030
    2031        /**
    2032         * This method returns the cap amount of experience that the experience bar can hold. With each level, the
    2033         * experience cap on the player's experience bar is raised by 10.
    2034         */
    2035        public int xpBarCap()
    2036        {
    2037            return this.experienceLevel >= 30 ? 62 + (this.experienceLevel - 30) * 7 : (this.experienceLevel >= 15 ? 17 + (this.experienceLevel - 15) * 3 : 17);
    2038        }
    2039
    2040        /**
    2041         * increases exhaustion level by supplied amount
    2042         */
    2043        public void addExhaustion(float par1)
    2044        {
    2045            if (!this.capabilities.disableDamage)
    2046            {
    2047                if (!this.worldObj.isRemote)
    2048                {
    2049                    this.foodStats.addExhaustion(par1);
    2050                }
    2051            }
    2052        }
    2053
    2054        /**
    2055         * Returns the player's FoodStats object.
    2056         */
    2057        public FoodStats getFoodStats()
    2058        {
    2059            return this.foodStats;
    2060        }
    2061
    2062        public boolean canEat(boolean par1)
    2063        {
    2064            return (par1 || this.foodStats.needFood()) && !this.capabilities.disableDamage;
    2065        }
    2066
    2067        /**
    2068         * Checks if the player's health is not full and not zero.
    2069         */
    2070        public boolean shouldHeal()
    2071        {
    2072            return this.getHealth() > 0 && this.getHealth() < this.getMaxHealth();
    2073        }
    2074
    2075        /**
    2076         * sets the itemInUse when the use item button is clicked. Args: itemstack, int maxItemUseDuration
    2077         */
    2078        public void setItemInUse(ItemStack par1ItemStack, int par2)
    2079        {
    2080            if (par1ItemStack != this.itemInUse)
    2081            {
    2082                this.itemInUse = par1ItemStack;
    2083                this.itemInUseCount = par2;
    2084
    2085                if (!this.worldObj.isRemote)
    2086                {
    2087                    this.setEating(true);
    2088                }
    2089            }
    2090        }
    2091
    2092        /**
    2093         * Returns true if the item the player is holding can harvest the block at the given coords. Args: x, y, z.
    2094         */
    2095        public boolean canCurrentToolHarvestBlock(int par1, int par2, int par3)
    2096        {
    2097            if (this.capabilities.allowEdit)
    2098            {
    2099                return true;
    2100            }
    2101            else
    2102            {
    2103                int var4 = this.worldObj.getBlockId(par1, par2, par3);
    2104
    2105                if (var4 > 0)
    2106                {
    2107                    Block var5 = Block.blocksList[var4];
    2108
    2109                    if (var5.blockMaterial.func_85157_q())
    2110                    {
    2111                        return true;
    2112                    }
    2113
    2114                    if (this.getCurrentEquippedItem() != null)
    2115                    {
    2116                        ItemStack var6 = this.getCurrentEquippedItem();
    2117
    2118                        if (var6.canHarvestBlock(var5) || var6.getStrVsBlock(var5) > 1.0F)
    2119                        {
    2120                            return true;
    2121                        }
    2122                    }
    2123                }
    2124
    2125                return false;
    2126            }
    2127        }
    2128
    2129        public boolean canPlayerEdit(int par1, int par2, int par3, int par4, ItemStack par5ItemStack)
    2130        {
    2131            return this.capabilities.allowEdit ? true : (par5ItemStack != null ? par5ItemStack.func_82835_x() : false);
    2132        }
    2133
    2134        /**
    2135         * Get the experience points the entity currently has.
    2136         */
    2137        protected int getExperiencePoints(EntityPlayer par1EntityPlayer)
    2138        {
    2139            if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
    2140            {
    2141                return 0;
    2142            }
    2143            else
    2144            {
    2145                int var2 = this.experienceLevel * 7;
    2146                return var2 > 100 ? 100 : var2;
    2147            }
    2148        }
    2149
    2150        /**
    2151         * Only use is to identify if class is an instance of player for experience dropping
    2152         */
    2153        protected boolean isPlayer()
    2154        {
    2155            return true;
    2156        }
    2157
    2158        /**
    2159         * Gets the username of the entity.
    2160         */
    2161        public String getEntityName()
    2162        {
    2163            return this.username;
    2164        }
    2165
    2166        /**
    2167         * Copies the values from the given player into this player if boolean par2 is true. Always clones Ender Chest
    2168         * Inventory.
    2169         */
    2170        public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2)
    2171        {
    2172            if (par2)
    2173            {
    2174                this.inventory.copyInventory(par1EntityPlayer.inventory);
    2175                this.health = par1EntityPlayer.health;
    2176                this.foodStats = par1EntityPlayer.foodStats;
    2177                this.experienceLevel = par1EntityPlayer.experienceLevel;
    2178                this.experienceTotal = par1EntityPlayer.experienceTotal;
    2179                this.experience = par1EntityPlayer.experience;
    2180                this.func_85040_s(par1EntityPlayer.getScore());
    2181                this.field_82152_aq = par1EntityPlayer.field_82152_aq;
    2182            }
    2183            else if (this.worldObj.getGameRules().getGameRuleBooleanValue("keepInventory"))
    2184            {
    2185                this.inventory.copyInventory(par1EntityPlayer.inventory);
    2186                this.experienceLevel = par1EntityPlayer.experienceLevel;
    2187                this.experienceTotal = par1EntityPlayer.experienceTotal;
    2188                this.experience = par1EntityPlayer.experience;
    2189                this.func_85040_s(par1EntityPlayer.getScore());
    2190            }
    2191
    2192            this.theInventoryEnderChest = par1EntityPlayer.theInventoryEnderChest;
    2193
    2194            //Copy over a section of the Entity Data from the old player.
    2195            //Allows mods to specify data that persists after players respawn.
    2196            NBTTagCompound old = par1EntityPlayer.getEntityData();
    2197            if (old.hasKey(PERSISTED_NBT_TAG))
    2198            {
    2199                getEntityData().setCompoundTag(PERSISTED_NBT_TAG, old.getCompoundTag(PERSISTED_NBT_TAG));
    2200            }
    2201        }
    2202
    2203        /**
    2204         * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
    2205         * prevent them from trampling crops
    2206         */
    2207        protected boolean canTriggerWalking()
    2208        {
    2209            return !this.capabilities.isFlying;
    2210        }
    2211
    2212        /**
    2213         * Sends the player's abilities to the server (if there is one).
    2214         */
    2215        public void sendPlayerAbilities() {}
    2216
    2217        public void sendGameTypeToPlayer(EnumGameType par1EnumGameType) {}
    2218
    2219        /**
    2220         * Gets the name of this command sender (usually username, but possibly "Rcon")
    2221         */
    2222        public String getCommandSenderName()
    2223        {
    2224            return this.username;
    2225        }
    2226
    2227        public StringTranslate getTranslator()
    2228        {
    2229            return StringTranslate.getInstance();
    2230        }
    2231
    2232        /**
    2233         * Translates and formats the given string key with the given arguments.
    2234         */
    2235        public String translateString(String par1Str, Object ... par2ArrayOfObj)
    2236        {
    2237            return this.getTranslator().translateKeyFormat(par1Str, par2ArrayOfObj);
    2238        }
    2239
    2240        /**
    2241         * Returns the InventoryEnderChest of this player.
    2242         */
    2243        public InventoryEnderChest getInventoryEnderChest()
    2244        {
    2245            return this.theInventoryEnderChest;
    2246        }
    2247
    2248        /**
    2249         * 0 = item, 1-n is armor
    2250         */
    2251        public ItemStack getCurrentItemOrArmor(int par1)
    2252        {
    2253            return par1 == 0 ? this.inventory.getCurrentItem() : this.inventory.armorInventory[par1 - 1];
    2254        }
    2255
    2256        /**
    2257         * Returns the item that this EntityLiving is holding, if any.
    2258         */
    2259        public ItemStack getHeldItem()
    2260        {
    2261            return this.inventory.getCurrentItem();
    2262        }
    2263
    2264        /**
    2265         * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
    2266         */
    2267        public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
    2268        {
    2269            this.inventory.armorInventory[par1] = par2ItemStack;
    2270        }
    2271
    2272        public ItemStack[] getLastActiveItems()
    2273        {
    2274            return this.inventory.armorInventory;
    2275        }
    2276
    2277        @SideOnly(Side.CLIENT)
    2278        public boolean getHideCape()
    2279        {
    2280            return this.getHideCape(1);
    2281        }
    2282
    2283        public void openGui(Object mod, int modGuiId, World world, int x, int y, int z)
    2284        {
    2285            FMLNetworkHandler.openGui(this, mod, modGuiId, world, x, y, z);
    2286        }
    2287    }