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