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