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