    001    package net.minecraft.src;
    002
    003    import java.io.ByteArrayOutputStream;
    004    import java.io.DataOutputStream;
    005    import java.io.IOException;
    006    import java.util.ArrayList;
    007    import java.util.Iterator;
    008    import java.util.LinkedList;
    009    import java.util.List;
    010    import net.minecraft.server.MinecraftServer;
    011    import net.minecraftforge.common.ForgeHooks;
    012    import net.minecraftforge.common.MinecraftForge;
    013    import net.minecraftforge.event.entity.player.PlayerDropsEvent;
    014
    015    public class EntityPlayerMP extends EntityPlayer implements ICrafting
    016    {
    017        private StringTranslate translator = new StringTranslate("en_US");
    018
    019        /**
    020         * The NetServerHandler assigned to this player by the ServerConfigurationManager.
    021         */
    022        public NetServerHandler playerNetServerHandler;
    023
    024        /** Reference to the MinecraftServer object. */
    025        public MinecraftServer mcServer;
    026
    027        /** The ItemInWorldManager belonging to this player */
    028        public ItemInWorldManager theItemInWorldManager;
    029
    030        /** player X position as seen by PlayerManager */
    031        public double managedPosX;
    032
    033        /** player Z position as seen by PlayerManager */
    034        public double managedPosZ;
    035
    036        /** LinkedList that holds the loaded chunks. */
    037        public final List loadedChunks = new LinkedList();
    038
    039        /** entities added to this list will  be packet29'd to the player */
    040        public final List destroyedItemsNetCache = new LinkedList();
    041
    042        /** set to getHealth */
    043        private int lastHealth = -99999999;
    044
    045        /** set to foodStats.GetFoodLevel */
    046        private int lastFoodLevel = -99999999;
    047
    048        /** set to foodStats.getSaturationLevel() == 0.0F each tick */
    049        private boolean wasHungry = true;
    050
    051        /** Amount of experience the client was last set to */
    052        private int lastExperience = -99999999;
    053
    054        /** de-increments onUpdate, attackEntityFrom is ignored if this >0 */
    055        private int initialInvulnerability = 60;
    056
    057        /** must be between 3>x>15 (strictly between) */
    058        private int renderDistance = 0;
    059        private int chatVisibility = 0;
    060        private boolean chatColours = true;
    061
    062        /**
    063         * The currently in use window ID. Incremented every time a window is opened.
    064         */
    065        public int currentWindowId = 0;
    066
    067        /**
    068         * poor mans concurency flag, lets hope the jvm doesn't re-order the setting of this flag wrt the inventory change
    069         * on the next line
    070         */
    071        public boolean playerInventoryBeingManipulated;
    072        public int ping;
    073
    074        /**
    075         * Set when a player beats the ender dragon, used to respawn the player at the spawn point while retaining inventory
    076         * and XP
    077         */
    078        public boolean playerConqueredTheEnd = false;
    079
    080        public EntityPlayerMP(MinecraftServer par1MinecraftServer, World par2World, String par3Str, ItemInWorldManager par4ItemInWorldManager)
    081        {
    082            super(par2World);
    083            par4ItemInWorldManager.thisPlayerMP = this;
    084            this.theItemInWorldManager = par4ItemInWorldManager;
    085            this.renderDistance = par1MinecraftServer.getConfigurationManager().getViewDistance();
    086            ChunkCoordinates var5 = par2World.provider.getRandomizedSpawnPoint();
    087            int var6 = var5.posX;
    088            int var7 = var5.posZ;
    089            int var8 = var5.posY;
    090
    091            this.setLocationAndAngles((double)var6 + 0.5D, (double)var8, (double)var7 + 0.5D, 0.0F, 0.0F);
    092            this.mcServer = par1MinecraftServer;
    093            this.stepHeight = 0.0F;
    094            this.username = par3Str;
    095            this.yOffset = 0.0F;
    096        }
    097
    098        /**
    099         * (abstract) Protected helper method to read subclass entity data from NBT.
    100         */
    101        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    102        {
    103            super.readEntityFromNBT(par1NBTTagCompound);
    104
    105            if (par1NBTTagCompound.hasKey("playerGameType"))
    106            {
    107                this.theItemInWorldManager.setGameType(EnumGameType.getByID(par1NBTTagCompound.getInteger("playerGameType")));
    108            }
    109        }
    110
    111        /**
    112         * (abstract) Protected helper method to write subclass entity data to NBT.
    113         */
    114        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    115        {
    116            super.writeEntityToNBT(par1NBTTagCompound);
    117            par1NBTTagCompound.setInteger("playerGameType", this.theItemInWorldManager.getGameType().getID());
    118        }
    119
    120        public void func_82242_a(int par1)
    121        {
    122            super.func_82242_a(par1);
    123            this.lastExperience = -1;
    124        }
    125
    126        public void addSelfToInternalCraftingInventory()
    127        {
    128            this.craftingInventory.addCraftingToCrafters(this);
    129        }
    130
    131        /**
    132         * sets the players height back to normal after doing things like sleeping and dieing
    133         */
    134        protected void resetHeight()
    135        {
    136            this.yOffset = 0.0F;
    137        }
    138
    139        public float getEyeHeight()
    140        {
    141            return 1.62F;
    142        }
    143
    144        /**
    145         * Called to update the entity's position/logic.
    146         */
    147        public void onUpdate()
    148        {
    149            this.theItemInWorldManager.updateBlockRemoving();
    150            --this.initialInvulnerability;
    151            this.craftingInventory.updateCraftingResults();
    152
    153            if (!this.loadedChunks.isEmpty())
    154            {
    155                ArrayList var1 = new ArrayList();
    156                Iterator var2 = this.loadedChunks.iterator();
    157                ArrayList var3 = new ArrayList();
    158
    159                while (var2.hasNext() && var1.size() < 5)
    160                {
    161                    ChunkCoordIntPair var4 = (ChunkCoordIntPair)var2.next();
    162                    var2.remove();
    163
    164                    if (var4 != null && this.worldObj.blockExists(var4.chunkXPos << 4, 0, var4.chunkZPos << 4))
    165                    {
    166                        var1.add(this.worldObj.getChunkFromChunkCoords(var4.chunkXPos, var4.chunkZPos));
    167                        //BugFix: 16 makes it load an extra chunk, which isn't associated with a player, which makes it not unload unless a player walks near it.
    168                        //ToDo: Find a way to efficiently clean abandoned chunks.
    169                        //var3.addAll(((WorldServer)this.worldObj).getAllTileEntityInBox(var4.chunkXPos * 16, 0, var4.chunkZPos * 16, var4.chunkXPos * 16 + 16, 256, var4.chunkZPos * 16 + 16));
    170                        var3.addAll(((WorldServer)this.worldObj).getAllTileEntityInBox(var4.chunkXPos * 16, 0, var4.chunkZPos * 16, var4.chunkXPos * 16 + 15, 256, var4.chunkZPos * 16 + 15));
    171
    172                    }
    173                }
    174
    175                if (!var1.isEmpty())
    176                {
    177                    this.playerNetServerHandler.sendPacketToPlayer(new Packet56MapChunks(var1));
    178                    Iterator var9 = var3.iterator();
    179
    180                    while (var9.hasNext())
    181                    {
    182                        TileEntity var5 = (TileEntity)var9.next();
    183                        this.sendTileEntityToPlayer(var5);
    184                    }
    185                }
    186            }
    187
    188            if (!this.destroyedItemsNetCache.isEmpty())
    189            {
    190                int var6 = Math.min(this.destroyedItemsNetCache.size(), 127);
    191                int[] var7 = new int[var6];
    192                Iterator var8 = this.destroyedItemsNetCache.iterator();
    193                int var10 = 0;
    194
    195                while (var8.hasNext() && var10 < var6)
    196                {
    197                    var7[var10++] = ((Integer)var8.next()).intValue();
    198                    var8.remove();
    199                }
    200
    201                this.playerNetServerHandler.sendPacketToPlayer(new Packet29DestroyEntity(var7));
    202            }
    203        }
    204
    205        public void onUpdateEntity()
    206        {
    207            super.onUpdate();
    208
    209            for (int var1 = 0; var1 < this.inventory.getSizeInventory(); ++var1)
    210            {
    211                ItemStack var2 = this.inventory.getStackInSlot(var1);
    212
    213                if (var2 != null && Item.itemsList[var2.itemID].isMap() && this.playerNetServerHandler.packetSize() <= 5)
    214                {
    215                    Packet var3 = ((ItemMapBase)Item.itemsList[var2.itemID]).createMapDataPacket(var2, this.worldObj, this);
    216
    217                    if (var3 != null)
    218                    {
    219                        this.playerNetServerHandler.sendPacketToPlayer(var3);
    220                    }
    221                }
    222            }
    223
    224            if (this.getHealth() != this.lastHealth || this.lastFoodLevel != this.foodStats.getFoodLevel() || this.foodStats.getSaturationLevel() == 0.0F != this.wasHungry)
    225            {
    226                this.playerNetServerHandler.sendPacketToPlayer(new Packet8UpdateHealth(this.getHealth(), this.foodStats.getFoodLevel(), this.foodStats.getSaturationLevel()));
    227                this.lastHealth = this.getHealth();
    228                this.lastFoodLevel = this.foodStats.getFoodLevel();
    229                this.wasHungry = this.foodStats.getSaturationLevel() == 0.0F;
    230            }
    231
    232            if (this.experienceTotal != this.lastExperience)
    233            {
    234                this.lastExperience = this.experienceTotal;
    235                this.playerNetServerHandler.sendPacketToPlayer(new Packet43Experience(this.experience, this.experienceTotal, this.experienceLevel));
    236            }
    237        }
    238
    239        /**
    240         * Called when the mob's health reaches 0.
    241         */
    242        public void onDeath(DamageSource par1DamageSource)
    243        {
    244            if (ForgeHooks.onLivingDeath(this, par1DamageSource))
    245            {
    246                return;
    247            }
    248
    249            this.mcServer.getConfigurationManager().sendPacketToAllPlayers(new Packet3Chat(par1DamageSource.getDeathMessage(this)));
    250
    251            if (!this.worldObj.func_82736_K().func_82766_b("keepInventory"))
    252            {
    253                captureDrops = true;
    254                capturedDrops.clear();
    255
    256                this.inventory.dropAllItems();
    257
    258                captureDrops = false;
    259                PlayerDropsEvent event = new PlayerDropsEvent(this, par1DamageSource, capturedDrops, recentlyHit > 0);
    260                if (!MinecraftForge.EVENT_BUS.post(event))
    261                {
    262                    for (EntityItem item : capturedDrops)
    263                    {
    264                        joinEntityItemWithWorld(item);
    265                    }
    266                }
    267            }
    268        }
    269
    270        /**
    271         * Called when the entity is attacked.
    272         */
    273        public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    274        {
    275            if (this.initialInvulnerability > 0)
    276            {
    277                return false;
    278            }
    279            else
    280            {
    281                if (!this.mcServer.isPVPEnabled() && par1DamageSource instanceof EntityDamageSource)
    282                {
    283                    Entity var3 = par1DamageSource.getEntity();
    284
    285                    if (var3 instanceof EntityPlayer)
    286                    {
    287                        return false;
    288                    }
    289
    290                    if (var3 instanceof EntityArrow)
    291                    {
    292                        EntityArrow var4 = (EntityArrow)var3;
    293
    294                        if (var4.shootingEntity instanceof EntityPlayer)
    295                        {
    296                            return false;
    297                        }
    298                    }
    299                }
    300
    301                return super.attackEntityFrom(par1DamageSource, par2);
    302            }
    303        }
    304
    305        /**
    306         * returns if pvp is enabled or not
    307         */
    308        protected boolean isPVPEnabled()
    309        {
    310            return this.mcServer.isPVPEnabled();
    311        }
    312
    313        public void travelToTheEnd(int par1)
    314        {
    315            if (this.dimension == 1 && par1 == 1)
    316            {
    317                this.triggerAchievement(AchievementList.theEnd2);
    318                this.worldObj.setEntityDead(this);
    319                this.playerConqueredTheEnd = true;
    320                this.playerNetServerHandler.sendPacketToPlayer(new Packet70GameEvent(4, 0));
    321            }
    322            else
    323            {
    324                if (this.dimension == 1 && par1 == 0)
    325                {
    326                    this.triggerAchievement(AchievementList.theEnd);
    327                    ChunkCoordinates var2 = this.mcServer.worldServerForDimension(par1).getEntrancePortalLocation();
    328
    329                    if (var2 != null)
    330                    {
    331                        this.playerNetServerHandler.setPlayerLocation((double)var2.posX, (double)var2.posY, (double)var2.posZ, 0.0F, 0.0F);
    332                    }
    333
    334                    par1 = 1;
    335                }
    336                else
    337                {
    338                    this.triggerAchievement(AchievementList.portal);
    339                }
    340
    341                this.mcServer.getConfigurationManager().transferPlayerToDimension(this, par1);
    342                this.lastExperience = -1;
    343                this.lastHealth = -1;
    344                this.lastFoodLevel = -1;
    345            }
    346        }
    347
    348        /**
    349         * called from onUpdate for all tileEntity in specific chunks
    350         */
    351        private void sendTileEntityToPlayer(TileEntity par1TileEntity)
    352        {
    353            if (par1TileEntity != null)
    354            {
    355                Packet var2 = par1TileEntity.getDescriptionPacket();
    356
    357                if (var2 != null)
    358                {
    359                    this.playerNetServerHandler.sendPacketToPlayer(var2);
    360                }
    361            }
    362        }
    363
    364        /**
    365         * Called whenever an item is picked up from walking over it. Args: pickedUpEntity, stackSize
    366         */
    367        public void onItemPickup(Entity par1Entity, int par2)
    368        {
    369            super.onItemPickup(par1Entity, par2);
    370            this.craftingInventory.updateCraftingResults();
    371        }
    372
    373        /**
    374         * Attempts to have the player sleep in a bed at the specified location.
    375         */
    376        public EnumStatus sleepInBedAt(int par1, int par2, int par3)
    377        {
    378            EnumStatus var4 = super.sleepInBedAt(par1, par2, par3);
    379
    380            if (var4 == EnumStatus.OK)
    381            {
    382                Packet17Sleep var5 = new Packet17Sleep(this, 0, par1, par2, par3);
    383                this.getServerForPlayer().getEntityTracker().sendPacketToAllPlayersTrackingEntity(this, var5);
    384                this.playerNetServerHandler.setPlayerLocation(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
    385                this.playerNetServerHandler.sendPacketToPlayer(var5);
    386            }
    387
    388            return var4;
    389        }
    390
    391        /**
    392         * Wake up the player if they're sleeping.
    393         */
    394        public void wakeUpPlayer(boolean par1, boolean par2, boolean par3)
    395        {
    396            if (this.isPlayerSleeping())
    397            {
    398                this.getServerForPlayer().getEntityTracker().sendPacketToAllAssociatedPlayers(this, new Packet18Animation(this, 3));
    399            }
    400
    401            super.wakeUpPlayer(par1, par2, par3);
    402
    403            if (this.playerNetServerHandler != null)
    404            {
    405                this.playerNetServerHandler.setPlayerLocation(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
    406            }
    407        }
    408
    409        /**
    410         * Called when a player mounts an entity. e.g. mounts a pig, mounts a boat.
    411         */
    412        public void mountEntity(Entity par1Entity)
    413        {
    414            super.mountEntity(par1Entity);
    415            this.playerNetServerHandler.sendPacketToPlayer(new Packet39AttachEntity(this, this.ridingEntity));
    416            this.playerNetServerHandler.setPlayerLocation(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
    417        }
    418
    419        /**
    420         * Takes in the distance the entity has fallen this tick and whether its on the ground to update the fall distance
    421         * and deal fall damage if landing on the ground.  Args: distanceFallenThisTick, onGround
    422         */
    423        protected void updateFallState(double par1, boolean par3) {}
    424
    425        /**
    426         * likeUpdateFallState, but called from updateFlyingState, rather than moveEntity
    427         */
    428        public void updateFlyingState(double par1, boolean par3)
    429        {
    430            super.updateFallState(par1, par3);
    431        }
    432
    433        public void incrementWindowID()
    434        {
    435            this.currentWindowId = this.currentWindowId % 100 + 1;
    436        }
    437
    438        /**
    439         * Displays the crafting GUI for a workbench.
    440         */
    441        public void displayGUIWorkbench(int par1, int par2, int par3)
    442        {
    443            this.incrementWindowID();
    444            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 1, "Crafting", 9));
    445            this.craftingInventory = new ContainerWorkbench(this.inventory, this.worldObj, par1, par2, par3);
    446            this.craftingInventory.windowId = this.currentWindowId;
    447            this.craftingInventory.addCraftingToCrafters(this);
    448        }
    449
    450        public void displayGUIEnchantment(int par1, int par2, int par3)
    451        {
    452            this.incrementWindowID();
    453            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 4, "Enchanting", 9));
    454            this.craftingInventory = new ContainerEnchantment(this.inventory, this.worldObj, par1, par2, par3);
    455            this.craftingInventory.windowId = this.currentWindowId;
    456            this.craftingInventory.addCraftingToCrafters(this);
    457        }
    458
    459        public void func_82244_d(int par1, int par2, int par3)
    460        {
    461            this.incrementWindowID();
    462            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 8, "Repairing", 9));
    463            this.craftingInventory = new ContainerRepair(this.inventory, this.worldObj, par1, par2, par3, this);
    464            this.craftingInventory.windowId = this.currentWindowId;
    465            this.craftingInventory.addCraftingToCrafters(this);
    466        }
    467
    468        /**
    469         * Displays the GUI for interacting with a chest inventory. Args: chestInventory
    470         */
    471        public void displayGUIChest(IInventory par1IInventory)
    472        {
    473            if (this.craftingInventory != this.inventorySlots)
    474            {
    475                this.closeScreen();
    476            }
    477
    478            this.incrementWindowID();
    479            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 0, par1IInventory.getInvName(), par1IInventory.getSizeInventory()));
    480            this.craftingInventory = new ContainerChest(this.inventory, par1IInventory);
    481            this.craftingInventory.windowId = this.currentWindowId;
    482            this.craftingInventory.addCraftingToCrafters(this);
    483        }
    484
    485        /**
    486         * Displays the furnace GUI for the passed in furnace entity. Args: tileEntityFurnace
    487         */
    488        public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace)
    489        {
    490            this.incrementWindowID();
    491            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 2, par1TileEntityFurnace.getInvName(), par1TileEntityFurnace.getSizeInventory()));
    492            this.craftingInventory = new ContainerFurnace(this.inventory, par1TileEntityFurnace);
    493            this.craftingInventory.windowId = this.currentWindowId;
    494            this.craftingInventory.addCraftingToCrafters(this);
    495        }
    496
    497        /**
    498         * Displays the dipsenser GUI for the passed in dispenser entity. Args: TileEntityDispenser
    499         */
    500        public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser)
    501        {
    502            this.incrementWindowID();
    503            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 3, par1TileEntityDispenser.getInvName(), par1TileEntityDispenser.getSizeInventory()));
    504            this.craftingInventory = new ContainerDispenser(this.inventory, par1TileEntityDispenser);
    505            this.craftingInventory.windowId = this.currentWindowId;
    506            this.craftingInventory.addCraftingToCrafters(this);
    507        }
    508
    509        /**
    510         * Displays the GUI for interacting with a brewing stand.
    511         */
    512        public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand)
    513        {
    514            this.incrementWindowID();
    515            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 5, par1TileEntityBrewingStand.getInvName(), par1TileEntityBrewingStand.getSizeInventory()));
    516            this.craftingInventory = new ContainerBrewingStand(this.inventory, par1TileEntityBrewingStand);
    517            this.craftingInventory.windowId = this.currentWindowId;
    518            this.craftingInventory.addCraftingToCrafters(this);
    519        }
    520
    521        public void func_82240_a(TileEntityBeacon par1TileEntityBeacon)
    522        {
    523            this.incrementWindowID();
    524            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 7, par1TileEntityBeacon.getInvName(), par1TileEntityBeacon.getSizeInventory()));
    525            this.craftingInventory = new ContainerBeacon(this.inventory, par1TileEntityBeacon);
    526            this.craftingInventory.windowId = this.currentWindowId;
    527            this.craftingInventory.addCraftingToCrafters(this);
    528        }
    529
    530        public void displayGUIMerchant(IMerchant par1IMerchant)
    531        {
    532            this.incrementWindowID();
    533            this.craftingInventory = new ContainerMerchant(this.inventory, par1IMerchant, this.worldObj);
    534            this.craftingInventory.windowId = this.currentWindowId;
    535            this.craftingInventory.addCraftingToCrafters(this);
    536            InventoryMerchant var2 = ((ContainerMerchant)this.craftingInventory).getMerchantInventory();
    537            this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 6, var2.getInvName(), var2.getSizeInventory()));
    538            MerchantRecipeList var3 = par1IMerchant.getRecipes(this);
    539
    540            if (var3 != null)
    541            {
    542                try
    543                {
    544                    ByteArrayOutputStream var4 = new ByteArrayOutputStream();
    545                    DataOutputStream var5 = new DataOutputStream(var4);
    546                    var5.writeInt(this.currentWindowId);
    547                    var3.writeRecipiesToStream(var5);
    548                    this.playerNetServerHandler.sendPacketToPlayer(new Packet250CustomPayload("MC|TrList", var4.toByteArray()));
    549                }
    550                catch (IOException var6)
    551                {
    552                    var6.printStackTrace();
    553                }
    554            }
    555        }
    556
    557        /**
    558         * inform the player of a change in a single slot
    559         */
    560        public void updateCraftingInventorySlot(Container par1Container, int par2, ItemStack par3ItemStack)
    561        {
    562            if (!(par1Container.getSlot(par2) instanceof SlotCrafting))
    563            {
    564                if (!this.playerInventoryBeingManipulated)
    565                {
    566                    this.playerNetServerHandler.sendPacketToPlayer(new Packet103SetSlot(par1Container.windowId, par2, par3ItemStack));
    567                }
    568            }
    569        }
    570
    571        public void sendContainerToPlayer(Container par1Container)
    572        {
    573            this.sendContainerAndContentsToPlayer(par1Container, par1Container.getInventory());
    574        }
    575
    576        public void sendContainerAndContentsToPlayer(Container par1Container, List par2List)
    577        {
    578            this.playerNetServerHandler.sendPacketToPlayer(new Packet104WindowItems(par1Container.windowId, par2List));
    579            this.playerNetServerHandler.sendPacketToPlayer(new Packet103SetSlot(-1, -1, this.inventory.getItemStack()));
    580        }
    581
    582        /**
    583         * send information about the crafting inventory to the client(currently only for furnace times)
    584         */
    585        public void updateCraftingInventoryInfo(Container par1Container, int par2, int par3)
    586        {
    587            this.playerNetServerHandler.sendPacketToPlayer(new Packet105UpdateProgressbar(par1Container.windowId, par2, par3));
    588        }
    589
    590        /**
    591         * sets current screen to null (used on escape buttons of GUIs)
    592         */
    593        public void closeScreen()
    594        {
    595            this.playerNetServerHandler.sendPacketToPlayer(new Packet101CloseWindow(this.craftingInventory.windowId));
    596            this.closeInventory();
    597        }
    598
    599        public void sendInventoryToPlayer()
    600        {
    601            if (!this.playerInventoryBeingManipulated)
    602            {
    603                this.playerNetServerHandler.sendPacketToPlayer(new Packet103SetSlot(-1, -1, this.inventory.getItemStack()));
    604            }
    605        }
    606
    607        public void closeInventory()
    608        {
    609            this.craftingInventory.onCraftGuiClosed(this);
    610            this.craftingInventory = this.inventorySlots;
    611        }
    612
    613        /**
    614         * Adds a value to a statistic field.
    615         */
    616        public void addStat(StatBase par1StatBase, int par2)
    617        {
    618            if (par1StatBase != null)
    619            {
    620                if (!par1StatBase.isIndependent)
    621                {
    622                    while (par2 > 100)
    623                    {
    624                        this.playerNetServerHandler.sendPacketToPlayer(new Packet200Statistic(par1StatBase.statId, 100));
    625                        par2 -= 100;
    626                    }
    627
    628                    this.playerNetServerHandler.sendPacketToPlayer(new Packet200Statistic(par1StatBase.statId, par2));
    629                }
    630            }
    631        }
    632
    633        public void mountEntityAndWakeUp()
    634        {
    635            if (this.ridingEntity != null)
    636            {
    637                this.mountEntity(this.ridingEntity);
    638            }
    639
    640            if (this.riddenByEntity != null)
    641            {
    642                this.riddenByEntity.mountEntity(this);
    643            }
    644
    645            if (this.sleeping)
    646            {
    647                this.wakeUpPlayer(true, false, false);
    648            }
    649        }
    650
    651        /**
    652         * this function is called when a players inventory is sent to him, lastHealth is updated on any dimension
    653         * transitions, then reset.
    654         */
    655        public void setPlayerHealthUpdated()
    656        {
    657            this.lastHealth = -99999999;
    658        }
    659
    660        /**
    661         * Add a chat message to the player
    662         */
    663        public void addChatMessage(String par1Str)
    664        {
    665            StringTranslate var2 = StringTranslate.getInstance();
    666            String var3 = var2.translateKey(par1Str);
    667            this.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat(var3));
    668        }
    669
    670        /**
    671         * Used for when item use count runs out, ie: eating completed
    672         */
    673        protected void onItemUseFinish()
    674        {
    675            this.playerNetServerHandler.sendPacketToPlayer(new Packet38EntityStatus(this.entityId, (byte)9));
    676            super.onItemUseFinish();
    677        }
    678
    679        /**
    680         * sets the itemInUse when the use item button is clicked. Args: itemstack, int maxItemUseDuration
    681         */
    682        public void setItemInUse(ItemStack par1ItemStack, int par2)
    683        {
    684            super.setItemInUse(par1ItemStack, par2);
    685
    686            if (par1ItemStack != null && par1ItemStack.getItem() != null && par1ItemStack.getItem().getItemUseAction(par1ItemStack) == EnumAction.eat)
    687            {
    688                this.getServerForPlayer().getEntityTracker().sendPacketToAllAssociatedPlayers(this, new Packet18Animation(this, 5));
    689            }
    690        }
    691
    692        /**
    693         * Copies the values from the given player into this player if boolean par2 is true. Always clones Ender Chest
    694         * Inventory.
    695         */
    696        public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2)
    697        {
    698            super.clonePlayer(par1EntityPlayer, par2);
    699            this.lastExperience = -1;
    700            this.lastHealth = -1;
    701            this.lastFoodLevel = -1;
    702            this.destroyedItemsNetCache.addAll(((EntityPlayerMP)par1EntityPlayer).destroyedItemsNetCache);
    703        }
    704
    705        protected void onNewPotionEffect(PotionEffect par1PotionEffect)
    706        {
    707            super.onNewPotionEffect(par1PotionEffect);
    708            this.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(this.entityId, par1PotionEffect));
    709        }
    710
    711        protected void onChangedPotionEffect(PotionEffect par1PotionEffect)
    712        {
    713            super.onChangedPotionEffect(par1PotionEffect);
    714            this.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(this.entityId, par1PotionEffect));
    715        }
    716
    717        protected void onFinishedPotionEffect(PotionEffect par1PotionEffect)
    718        {
    719            super.onFinishedPotionEffect(par1PotionEffect);
    720            this.playerNetServerHandler.sendPacketToPlayer(new Packet42RemoveEntityEffect(this.entityId, par1PotionEffect));
    721        }
    722
    723        /**
    724         * Move the entity to the coordinates informed, but keep yaw/pitch values.
    725         */
    726        public void setPositionAndUpdate(double par1, double par3, double par5)
    727        {
    728            this.playerNetServerHandler.setPlayerLocation(par1, par3, par5, this.rotationYaw, this.rotationPitch);
    729        }
    730
    731        /**
    732         * Called when the player performs a critical hit on the Entity. Args: entity that was hit critically
    733         */
    734        public void onCriticalHit(Entity par1Entity)
    735        {
    736            this.getServerForPlayer().getEntityTracker().sendPacketToAllAssociatedPlayers(this, new Packet18Animation(par1Entity, 6));
    737        }
    738
    739        public void onEnchantmentCritical(Entity par1Entity)
    740        {
    741            this.getServerForPlayer().getEntityTracker().sendPacketToAllAssociatedPlayers(this, new Packet18Animation(par1Entity, 7));
    742        }
    743
    744        /**
    745         * Sends the player's abilities to the server (if there is one).
    746         */
    747        public void sendPlayerAbilities()
    748        {
    749            if (this.playerNetServerHandler != null)
    750            {
    751                this.playerNetServerHandler.sendPacketToPlayer(new Packet202PlayerAbilities(this.capabilities));
    752            }
    753        }
    754
    755        public WorldServer getServerForPlayer()
    756        {
    757            return (WorldServer)this.worldObj;
    758        }
    759
    760        public void sendGameTypeToPlayer(EnumGameType par1EnumGameType)
    761        {
    762            this.theItemInWorldManager.setGameType(par1EnumGameType);
    763            this.playerNetServerHandler.sendPacketToPlayer(new Packet70GameEvent(3, par1EnumGameType.getID()));
    764        }
    765
    766        public void sendChatToPlayer(String par1Str)
    767        {
    768            this.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat(par1Str));
    769        }
    770
    771        /**
    772         * Returns true if the command sender is allowed to use the given command.
    773         */
    774        public boolean canCommandSenderUseCommand(int par1, String par2Str)
    775        {
    776            return "seed".equals(par2Str) && !this.mcServer.isDedicatedServer() ? true : (!"tell".equals(par2Str) && !"help".equals(par2Str) && !"me".equals(par2Str) ? this.mcServer.getConfigurationManager().areCommandsAllowed(this.username) : true);
    777        }
    778
    779        public String func_71114_r()
    780        {
    781            String var1 = this.playerNetServerHandler.netManager.getSocketAddress().toString();
    782            var1 = var1.substring(var1.indexOf("/") + 1);
    783            var1 = var1.substring(0, var1.indexOf(":"));
    784            return var1;
    785        }
    786
    787        public void updateClientInfo(Packet204ClientInfo par1Packet204ClientInfo)
    788        {
    789            if (this.translator.getLanguageList().containsKey(par1Packet204ClientInfo.getLanguage()))
    790            {
    791                this.translator.setLanguage(par1Packet204ClientInfo.getLanguage());
    792            }
    793
    794            int var2 = 256 >> par1Packet204ClientInfo.getRenderDistance();
    795
    796            if (var2 > 3 && var2 < 15)
    797            {
    798                this.renderDistance = var2;
    799            }
    800
    801            this.chatVisibility = par1Packet204ClientInfo.getChatVisibility();
    802            this.chatColours = par1Packet204ClientInfo.getChatColours();
    803
    804            if (this.mcServer.isSinglePlayer() && this.mcServer.getServerOwner().equals(this.username))
    805            {
    806                this.mcServer.setDifficultyForAllWorlds(par1Packet204ClientInfo.getDifficulty());
    807            }
    808
    809            this.func_82239_b(1, !par1Packet204ClientInfo.func_82563_j());
    810        }
    811
    812        public StringTranslate getTranslator()
    813        {
    814            return this.translator;
    815        }
    816
    817        public int getChatVisibility()
    818        {
    819            return this.chatVisibility;
    820        }
    821
    822        /**
    823         * on recieving this message the client (if permission is given) will download the requested textures
    824         */
    825        public void requestTexturePackLoad(String par1Str, int par2)
    826        {
    827            String var3 = par1Str + "\u0000" + par2;
    828            this.playerNetServerHandler.sendPacketToPlayer(new Packet250CustomPayload("MC|TPack", var3.getBytes()));
    829        }
    830
    831        public ChunkCoordinates func_82114_b()
    832        {
    833            return new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY + 0.5D), MathHelper.floor_double(this.posZ));
    834        }
    835    }