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