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