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