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