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