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