    001package net.minecraft.entity.player;
    002
    003import java.io.ByteArrayOutputStream;
    004import java.io.DataOutputStream;
    005import java.io.IOException;
    006import java.util.ArrayList;
    007import java.util.Iterator;
    008import java.util.LinkedList;
    009import java.util.List;
    010import net.minecraft.entity.Entity;
    011import net.minecraft.entity.IMerchant;
    012import net.minecraft.entity.item.EntityItem;
    013import net.minecraft.entity.projectile.EntityArrow;
    014import net.minecraft.inventory.Container;
    015import net.minecraft.inventory.ContainerBeacon;
    016import net.minecraft.inventory.ContainerBrewingStand;
    017import net.minecraft.inventory.ContainerChest;
    018import net.minecraft.inventory.ContainerDispenser;
    019import net.minecraft.inventory.ContainerEnchantment;
    020import net.minecraft.inventory.ContainerFurnace;
    021import net.minecraft.inventory.ContainerMerchant;
    022import net.minecraft.inventory.ContainerRepair;
    023import net.minecraft.inventory.ContainerWorkbench;
    024import net.minecraft.inventory.ICrafting;
    025import net.minecraft.inventory.IInventory;
    026import net.minecraft.inventory.InventoryMerchant;
    027import net.minecraft.inventory.SlotCrafting;
    028import net.minecraft.item.EnumAction;
    029import net.minecraft.item.Item;
    030import net.minecraft.item.ItemInWorldManager;
    031import net.minecraft.item.ItemMapBase;
    032import net.minecraft.item.ItemStack;
    033import net.minecraft.nbt.NBTTagCompound;
    034import net.minecraft.network.NetServerHandler;
    035import net.minecraft.network.packet.Packet;
    036import net.minecraft.network.packet.Packet100OpenWindow;
    037import net.minecraft.network.packet.Packet101CloseWindow;
    038import net.minecraft.network.packet.Packet103SetSlot;
    039import net.minecraft.network.packet.Packet104WindowItems;
    040import net.minecraft.network.packet.Packet105UpdateProgressbar;
    041import net.minecraft.network.packet.Packet17Sleep;
    042import net.minecraft.network.packet.Packet18Animation;
    043import net.minecraft.network.packet.Packet200Statistic;
    044import net.minecraft.network.packet.Packet202PlayerAbilities;
    045import net.minecraft.network.packet.Packet204ClientInfo;
    046import net.minecraft.network.packet.Packet250CustomPayload;
    047import net.minecraft.network.packet.Packet29DestroyEntity;
    048import net.minecraft.network.packet.Packet38EntityStatus;
    049import net.minecraft.network.packet.Packet39AttachEntity;
    050import net.minecraft.network.packet.Packet3Chat;
    051import net.minecraft.network.packet.Packet41EntityEffect;
    052import net.minecraft.network.packet.Packet42RemoveEntityEffect;
    053import net.minecraft.network.packet.Packet43Experience;
    054import net.minecraft.network.packet.Packet56MapChunks;
    055import net.minecraft.network.packet.Packet70GameEvent;
    056import net.minecraft.network.packet.Packet8UpdateHealth;
    057import net.minecraft.potion.PotionEffect;
    058import net.minecraft.server.MinecraftServer;
    059import net.minecraft.stats.AchievementList;
    060import net.minecraft.stats.StatBase;
    061import net.minecraft.tileentity.TileEntity;
    062import net.minecraft.tileentity.TileEntityBeacon;
    063import net.minecraft.tileentity.TileEntityBrewingStand;
    064import net.minecraft.tileentity.TileEntityDispenser;
    065import net.minecraft.tileentity.TileEntityFurnace;
    066import net.minecraft.util.ChunkCoordinates;
    067import net.minecraft.util.DamageSource;
    068import net.minecraft.util.EntityDamageSource;
    069import net.minecraft.util.MathHelper;
    070import net.minecraft.util.StringTranslate;
    071import net.minecraft.village.MerchantRecipeList;
    072import net.minecraft.world.ChunkCoordIntPair;
    073import net.minecraft.world.EnumGameType;
    074import net.minecraft.world.World;
    075import net.minecraft.world.WorldServer;
    076import net.minecraft.world.chunk.Chunk;
    077
    078import net.minecraftforge.common.ForgeHooks;
    079import net.minecraftforge.common.MinecraftForge;
    080import net.minecraftforge.event.entity.player.PlayerDropsEvent;
    081import net.minecraftforge.event.world.ChunkWatchEvent;
    082
    083public 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.detectAndSendChanges();
    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().sendChatMsg(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.isEntityInvulnerable())
    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 && par1DamageSource != DamageSource.outOfWorld)
    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.removeEntity(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.detectAndSendChanges();
    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    /**
    864     * Sets the player's game mode and sends it to them.
    865     */
    866    public void setGameType(EnumGameType par1EnumGameType)
    867    {
    868        this.theItemInWorldManager.setGameType(par1EnumGameType);
    869        this.playerNetServerHandler.sendPacketToPlayer(new Packet70GameEvent(3, par1EnumGameType.getID()));
    870    }
    871
    872    public void sendChatToPlayer(String par1Str)
    873    {
    874        this.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat(par1Str));
    875    }
    876
    877    /**
    878     * Returns true if the command sender is allowed to use the given command.
    879     */
    880    public boolean canCommandSenderUseCommand(int par1, String par2Str)
    881    {
    882        return "seed".equals(par2Str) && !this.mcServer.isDedicatedServer() ? true : (!"tell".equals(par2Str) && !"help".equals(par2Str) && !"me".equals(par2Str) ? this.mcServer.getConfigurationManager().areCommandsAllowed(this.username) : true);
    883    }
    884
    885    public String func_71114_r()
    886    {
    887        String var1 = this.playerNetServerHandler.netManager.getSocketAddress().toString();
    888        var1 = var1.substring(var1.indexOf("/") + 1);
    889        var1 = var1.substring(0, var1.indexOf(":"));
    890        return var1;
    891    }
    892
    893    public void updateClientInfo(Packet204ClientInfo par1Packet204ClientInfo)
    894    {
    895        if (this.translator.getLanguageList().containsKey(par1Packet204ClientInfo.getLanguage()))
    896        {
    897            this.translator.setLanguage(par1Packet204ClientInfo.getLanguage());
    898        }
    899
    900        int var2 = 256 >> par1Packet204ClientInfo.getRenderDistance();
    901
    902        if (var2 > 3 && var2 < 15)
    903        {
    904            this.renderDistance = var2;
    905        }
    906
    907        this.chatVisibility = par1Packet204ClientInfo.getChatVisibility();
    908        this.chatColours = par1Packet204ClientInfo.getChatColours();
    909
    910        if (this.mcServer.isSinglePlayer() && this.mcServer.getServerOwner().equals(this.username))
    911        {
    912            this.mcServer.setDifficultyForAllWorlds(par1Packet204ClientInfo.getDifficulty());
    913        }
    914
    915        this.setHideCape(1, !par1Packet204ClientInfo.getShowCape());
    916    }
    917
    918    public StringTranslate getTranslator()
    919    {
    920        return this.translator;
    921    }
    922
    923    public int getChatVisibility()
    924    {
    925        return this.chatVisibility;
    926    }
    927
    928    /**
    929     * on recieving this message the client (if permission is given) will download the requested textures
    930     */
    931    public void requestTexturePackLoad(String par1Str, int par2)
    932    {
    933        String var3 = par1Str + "\u0000" + par2;
    934        this.playerNetServerHandler.sendPacketToPlayer(new Packet250CustomPayload("MC|TPack", var3.getBytes()));
    935    }
    936
    937    /**
    938     * Return the position for this command sender.
    939     */
    940    public ChunkCoordinates getPlayerCoordinates()
    941    {
    942        return new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY + 0.5D), MathHelper.floor_double(this.posZ));
    943    }
    944}