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