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 }