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