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.openContainer.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.openContainer.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.openContainer.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.openContainer = new ContainerWorkbench(this.inventory, this.worldObj, par1, par2, par3); 468 this.openContainer.windowId = this.currentWindowId; 469 this.openContainer.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.openContainer = new ContainerEnchantment(this.inventory, this.worldObj, par1, par2, par3); 477 this.openContainer.windowId = this.currentWindowId; 478 this.openContainer.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.openContainer = new ContainerRepair(this.inventory, this.worldObj, par1, par2, par3, this); 489 this.openContainer.windowId = this.currentWindowId; 490 this.openContainer.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.openContainer != this.inventoryContainer) 499 { 500 this.closeScreen(); 501 } 502 503 this.incrementWindowID(); 504 this.playerNetServerHandler.sendPacketToPlayer(new Packet100OpenWindow(this.currentWindowId, 0, par1IInventory.getInvName(), par1IInventory.getSizeInventory())); 505 this.openContainer = new ContainerChest(this.inventory, par1IInventory); 506 this.openContainer.windowId = this.currentWindowId; 507 this.openContainer.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.openContainer = new ContainerFurnace(this.inventory, par1TileEntityFurnace); 518 this.openContainer.windowId = this.currentWindowId; 519 this.openContainer.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.openContainer = new ContainerDispenser(this.inventory, par1TileEntityDispenser); 530 this.openContainer.windowId = this.currentWindowId; 531 this.openContainer.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.openContainer = new ContainerBrewingStand(this.inventory, par1TileEntityBrewingStand); 542 this.openContainer.windowId = this.currentWindowId; 543 this.openContainer.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.openContainer = new ContainerBeacon(this.inventory, par1TileEntityBeacon); 554 this.openContainer.windowId = this.currentWindowId; 555 this.openContainer.addCraftingToCrafters(this); 556 } 557 558 public void displayGUIMerchant(IMerchant par1IMerchant) 559 { 560 this.incrementWindowID(); 561 this.openContainer = new ContainerMerchant(this.inventory, par1IMerchant, this.worldObj); 562 this.openContainer.windowId = this.currentWindowId; 563 this.openContainer.addCraftingToCrafters(this); 564 InventoryMerchant var2 = ((ContainerMerchant)this.openContainer).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 * Sends the contents of an inventory slot to the client-side Container. This doesn't have to match the actual 587 * contents of that slot. Args: Container, slot number, slot contents 588 */ 589 public void sendSlotContents(Container par1Container, int par2, ItemStack par3ItemStack) 590 { 591 if (!(par1Container.getSlot(par2) instanceof SlotCrafting)) 592 { 593 if (!this.playerInventoryBeingManipulated) 594 { 595 this.playerNetServerHandler.sendPacketToPlayer(new Packet103SetSlot(par1Container.windowId, par2, par3ItemStack)); 596 } 597 } 598 } 599 600 public void sendContainerToPlayer(Container par1Container) 601 { 602 this.sendContainerAndContentsToPlayer(par1Container, par1Container.getInventory()); 603 } 604 605 public void sendContainerAndContentsToPlayer(Container par1Container, List par2List) 606 { 607 this.playerNetServerHandler.sendPacketToPlayer(new Packet104WindowItems(par1Container.windowId, par2List)); 608 this.playerNetServerHandler.sendPacketToPlayer(new Packet103SetSlot(-1, -1, this.inventory.getItemStack())); 609 } 610 611 /** 612 * Sends two ints to the client-side Container. Used for furnace burning time, smelting progress, brewing progress, 613 * and enchanting level. Normally the first int identifies which variable to update, and the second contains the new 614 * value. Both are truncated to shorts in non-local SMP. 615 */ 616 public void sendProgressBarUpdate(Container par1Container, int par2, int par3) 617 { 618 this.playerNetServerHandler.sendPacketToPlayer(new Packet105UpdateProgressbar(par1Container.windowId, par2, par3)); 619 } 620 621 /** 622 * sets current screen to null (used on escape buttons of GUIs) 623 */ 624 public void closeScreen() 625 { 626 this.playerNetServerHandler.sendPacketToPlayer(new Packet101CloseWindow(this.openContainer.windowId)); 627 this.closeInventory(); 628 } 629 630 /** 631 * updates item held by mouse 632 */ 633 public void updateHeldItem() 634 { 635 if (!this.playerInventoryBeingManipulated) 636 { 637 this.playerNetServerHandler.sendPacketToPlayer(new Packet103SetSlot(-1, -1, this.inventory.getItemStack())); 638 } 639 } 640 641 public void closeInventory() 642 { 643 this.openContainer.onCraftGuiClosed(this); 644 this.openContainer = this.inventoryContainer; 645 } 646 647 /** 648 * Adds a value to a statistic field. 649 */ 650 public void addStat(StatBase par1StatBase, int par2) 651 { 652 if (par1StatBase != null) 653 { 654 if (!par1StatBase.isIndependent) 655 { 656 while (par2 > 100) 657 { 658 this.playerNetServerHandler.sendPacketToPlayer(new Packet200Statistic(par1StatBase.statId, 100)); 659 par2 -= 100; 660 } 661 662 this.playerNetServerHandler.sendPacketToPlayer(new Packet200Statistic(par1StatBase.statId, par2)); 663 } 664 } 665 } 666 667 public void mountEntityAndWakeUp() 668 { 669 if (this.ridingEntity != null) 670 { 671 this.mountEntity(this.ridingEntity); 672 } 673 674 if (this.riddenByEntity != null) 675 { 676 this.riddenByEntity.mountEntity(this); 677 } 678 679 if (this.sleeping) 680 { 681 this.wakeUpPlayer(true, false, false); 682 } 683 } 684 685 /** 686 * this function is called when a players inventory is sent to him, lastHealth is updated on any dimension 687 * transitions, then reset. 688 */ 689 public void setPlayerHealthUpdated() 690 { 691 this.lastHealth = -99999999; 692 } 693 694 /** 695 * Add a chat message to the player 696 */ 697 public void addChatMessage(String par1Str) 698 { 699 StringTranslate var2 = StringTranslate.getInstance(); 700 String var3 = var2.translateKey(par1Str); 701 this.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat(var3)); 702 } 703 704 /** 705 * Used for when item use count runs out, ie: eating completed 706 */ 707 protected void onItemUseFinish() 708 { 709 this.playerNetServerHandler.sendPacketToPlayer(new Packet38EntityStatus(this.entityId, (byte)9)); 710 super.onItemUseFinish(); 711 } 712 713 /** 714 * sets the itemInUse when the use item button is clicked. Args: itemstack, int maxItemUseDuration 715 */ 716 public void setItemInUse(ItemStack par1ItemStack, int par2) 717 { 718 super.setItemInUse(par1ItemStack, par2); 719 720 if (par1ItemStack != null && par1ItemStack.getItem() != null && par1ItemStack.getItem().getItemUseAction(par1ItemStack) == EnumAction.eat) 721 { 722 this.getServerForPlayer().getEntityTracker().sendPacketToAllAssociatedPlayers(this, new Packet18Animation(this, 5)); 723 } 724 } 725 726 /** 727 * Copies the values from the given player into this player if boolean par2 is true. Always clones Ender Chest 728 * Inventory. 729 */ 730 public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2) 731 { 732 super.clonePlayer(par1EntityPlayer, par2); 733 this.lastExperience = -1; 734 this.lastHealth = -1; 735 this.lastFoodLevel = -1; 736 this.destroyedItemsNetCache.addAll(((EntityPlayerMP)par1EntityPlayer).destroyedItemsNetCache); 737 } 738 739 protected void onNewPotionEffect(PotionEffect par1PotionEffect) 740 { 741 super.onNewPotionEffect(par1PotionEffect); 742 this.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(this.entityId, par1PotionEffect)); 743 } 744 745 protected void onChangedPotionEffect(PotionEffect par1PotionEffect) 746 { 747 super.onChangedPotionEffect(par1PotionEffect); 748 this.playerNetServerHandler.sendPacketToPlayer(new Packet41EntityEffect(this.entityId, par1PotionEffect)); 749 } 750 751 protected void onFinishedPotionEffect(PotionEffect par1PotionEffect) 752 { 753 super.onFinishedPotionEffect(par1PotionEffect); 754 this.playerNetServerHandler.sendPacketToPlayer(new Packet42RemoveEntityEffect(this.entityId, par1PotionEffect)); 755 } 756 757 /** 758 * Move the entity to the coordinates informed, but keep yaw/pitch values. 759 */ 760 public void setPositionAndUpdate(double par1, double par3, double par5) 761 { 762 this.playerNetServerHandler.setPlayerLocation(par1, par3, par5, this.rotationYaw, this.rotationPitch); 763 } 764 765 /** 766 * Called when the player performs a critical hit on the Entity. Args: entity that was hit critically 767 */ 768 public void onCriticalHit(Entity par1Entity) 769 { 770 this.getServerForPlayer().getEntityTracker().sendPacketToAllAssociatedPlayers(this, new Packet18Animation(par1Entity, 6)); 771 } 772 773 public void onEnchantmentCritical(Entity par1Entity) 774 { 775 this.getServerForPlayer().getEntityTracker().sendPacketToAllAssociatedPlayers(this, new Packet18Animation(par1Entity, 7)); 776 } 777 778 /** 779 * Sends the player's abilities to the server (if there is one). 780 */ 781 public void sendPlayerAbilities() 782 { 783 if (this.playerNetServerHandler != null) 784 { 785 this.playerNetServerHandler.sendPacketToPlayer(new Packet202PlayerAbilities(this.capabilities)); 786 } 787 } 788 789 public WorldServer getServerForPlayer() 790 { 791 return (WorldServer)this.worldObj; 792 } 793 794 public void sendGameTypeToPlayer(EnumGameType par1EnumGameType) 795 { 796 this.theItemInWorldManager.setGameType(par1EnumGameType); 797 this.playerNetServerHandler.sendPacketToPlayer(new Packet70GameEvent(3, par1EnumGameType.getID())); 798 } 799 800 public void sendChatToPlayer(String par1Str) 801 { 802 this.playerNetServerHandler.sendPacketToPlayer(new Packet3Chat(par1Str)); 803 } 804 805 /** 806 * Returns true if the command sender is allowed to use the given command. 807 */ 808 public boolean canCommandSenderUseCommand(int par1, String par2Str) 809 { 810 return "seed".equals(par2Str) && !this.mcServer.isDedicatedServer() ? true : (!"tell".equals(par2Str) && !"help".equals(par2Str) && !"me".equals(par2Str) ? this.mcServer.getConfigurationManager().areCommandsAllowed(this.username) : true); 811 } 812 813 public String func_71114_r() 814 { 815 String var1 = this.playerNetServerHandler.netManager.getSocketAddress().toString(); 816 var1 = var1.substring(var1.indexOf("/") + 1); 817 var1 = var1.substring(0, var1.indexOf(":")); 818 return var1; 819 } 820 821 public void updateClientInfo(Packet204ClientInfo par1Packet204ClientInfo) 822 { 823 if (this.translator.getLanguageList().containsKey(par1Packet204ClientInfo.getLanguage())) 824 { 825 this.translator.setLanguage(par1Packet204ClientInfo.getLanguage()); 826 } 827 828 int var2 = 256 >> par1Packet204ClientInfo.getRenderDistance(); 829 830 if (var2 > 3 && var2 < 15) 831 { 832 this.renderDistance = var2; 833 } 834 835 this.chatVisibility = par1Packet204ClientInfo.getChatVisibility(); 836 this.chatColours = par1Packet204ClientInfo.getChatColours(); 837 838 if (this.mcServer.isSinglePlayer() && this.mcServer.getServerOwner().equals(this.username)) 839 { 840 this.mcServer.setDifficultyForAllWorlds(par1Packet204ClientInfo.getDifficulty()); 841 } 842 843 this.setHideCape(1, !par1Packet204ClientInfo.getShowCape()); 844 } 845 846 public StringTranslate getTranslator() 847 { 848 return this.translator; 849 } 850 851 public int getChatVisibility() 852 { 853 return this.chatVisibility; 854 } 855 856 /** 857 * on recieving this message the client (if permission is given) will download the requested textures 858 */ 859 public void requestTexturePackLoad(String par1Str, int par2) 860 { 861 String var3 = par1Str + "\u0000" + par2; 862 this.playerNetServerHandler.sendPacketToPlayer(new Packet250CustomPayload("MC|TPack", var3.getBytes())); 863 } 864 865 /** 866 * Return the coordinates for this player as ChunkCoordinates. 867 */ 868 public ChunkCoordinates getPlayerCoordinates() 869 { 870 return new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY + 0.5D), MathHelper.floor_double(this.posZ)); 871 } 872 }