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