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