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