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