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