001 package net.minecraft.src; 002 003 import cpw.mods.fml.common.FMLCommonHandler; 004 import cpw.mods.fml.common.Side; 005 import cpw.mods.fml.common.asm.SideOnly; 006 import cpw.mods.fml.common.network.FMLNetworkHandler; 007 008 import java.util.Iterator; 009 import java.util.List; 010 011 import net.minecraftforge.common.ForgeHooks; 012 import net.minecraftforge.common.ISpecialArmor.ArmorProperties; 013 import net.minecraftforge.common.MinecraftForge; 014 import net.minecraftforge.event.ForgeEventFactory; 015 import net.minecraftforge.event.entity.living.LivingHurtEvent; 016 import net.minecraftforge.event.entity.player.AttackEntityEvent; 017 import net.minecraftforge.event.entity.player.EntityInteractEvent; 018 import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; 019 import net.minecraftforge.event.entity.player.PlayerDropsEvent; 020 import net.minecraftforge.event.entity.player.PlayerSleepInBedEvent; 021 022 public abstract class EntityPlayer extends EntityLiving implements ICommandSender 023 { 024 /** Inventory of the player */ 025 public InventoryPlayer inventory = new InventoryPlayer(this); 026 private InventoryEnderChest theInventoryEnderChest = new InventoryEnderChest(); 027 028 /** the crafting inventory in you get when opening your inventory */ 029 public Container inventorySlots; 030 031 /** the crafting inventory you are currently using */ 032 public Container craftingInventory; 033 034 /** The player's food stats. (See class FoodStats) */ 035 protected FoodStats foodStats = new FoodStats(); 036 037 /** 038 * Used to tell if the player pressed jump twice. If this is at 0 and it's pressed (And they are allowed to fly, as 039 * defined in the player's movementInput) it sets this to 7. If it's pressed and it's greater than 0 enable fly. 040 */ 041 protected int flyToggleTimer = 0; 042 public byte field_71098_bD = 0; 043 public int score = 0; 044 public float prevCameraYaw; 045 public float cameraYaw; 046 public String username; 047 @SideOnly(Side.CLIENT) 048 public String playerCloakUrl; 049 050 /** 051 * Used by EntityPlayer to prevent too many xp orbs from getting absorbed at once. 052 */ 053 public int xpCooldown = 0; 054 public double field_71091_bM; 055 public double field_71096_bN; 056 public double field_71097_bO; 057 public double field_71094_bP; 058 public double field_71095_bQ; 059 public double field_71085_bR; 060 061 /** Boolean value indicating weather a player is sleeping or not */ 062 protected boolean sleeping; 063 064 /** 065 * The chunk coordinates of the bed the player is in (null if player isn't in a bed). 066 */ 067 public ChunkCoordinates playerLocation; 068 private int sleepTimer; 069 public float field_71079_bU; 070 @SideOnly(Side.CLIENT) 071 public float field_71082_cx; 072 public float field_71089_bV; 073 074 /** 075 * Holds the last coordinate to spawn based on last bed that the player sleep. 076 */ 077 private ChunkCoordinates spawnChunk; 078 private boolean field_82248_d; 079 080 /** Holds the coordinate of the player when enter a minecraft to ride. */ 081 private ChunkCoordinates startMinecartRidingCoordinate; 082 083 /** The player's capabilities. (See class PlayerCapabilities) */ 084 public PlayerCapabilities capabilities = new PlayerCapabilities(); 085 086 /** The current experience level the player is on. */ 087 public int experienceLevel; 088 089 /** 090 * The total amount of experience the player has. This also includes the amount of experience within their 091 * Experience Bar. 092 */ 093 public int experienceTotal; 094 095 /** 096 * The current amount of experience the player has within their Experience Bar. 097 */ 098 public float experience; 099 100 /** 101 * This is the item that is in use when the player is holding down the useItemButton (e.g., bow, food, sword) 102 */ 103 private ItemStack itemInUse; 104 105 /** 106 * This field starts off equal to getMaxItemUseDuration and is decremented on each tick 107 */ 108 private int itemInUseCount; 109 protected float speedOnGround = 0.1F; 110 protected float speedInAir = 0.02F; 111 private int field_82249_h = 0; 112 113 /** 114 * An instance of a fishing rod's hook. If this isn't null, the icon image of the fishing rod is slightly different 115 */ 116 public EntityFishHook fishEntity = null; 117 118 public EntityPlayer(World par1World) 119 { 120 super(par1World); 121 this.inventorySlots = new ContainerPlayer(this.inventory, !par1World.isRemote, this); 122 this.craftingInventory = this.inventorySlots; 123 this.yOffset = 1.62F; 124 ChunkCoordinates var2 = par1World.getSpawnPoint(); 125 this.setLocationAndAngles((double)var2.posX + 0.5D, (double)(var2.posY + 1), (double)var2.posZ + 0.5D, 0.0F, 0.0F); 126 this.entityType = "humanoid"; 127 this.field_70741_aB = 180.0F; 128 this.fireResistance = 20; 129 this.texture = "/mob/char.png"; 130 } 131 132 public int getMaxHealth() 133 { 134 return 20; 135 } 136 137 protected void entityInit() 138 { 139 super.entityInit(); 140 this.dataWatcher.addObject(16, Byte.valueOf((byte)0)); 141 this.dataWatcher.addObject(17, Byte.valueOf((byte)0)); 142 } 143 144 @SideOnly(Side.CLIENT) 145 146 /** 147 * returns the ItemStack containing the itemInUse 148 */ 149 public ItemStack getItemInUse() 150 { 151 return this.itemInUse; 152 } 153 154 @SideOnly(Side.CLIENT) 155 156 /** 157 * Returns the item in use count 158 */ 159 public int getItemInUseCount() 160 { 161 return this.itemInUseCount; 162 } 163 164 /** 165 * Checks if the entity is currently using an item (e.g., bow, food, sword) by holding down the useItemButton 166 */ 167 public boolean isUsingItem() 168 { 169 return this.itemInUse != null; 170 } 171 172 @SideOnly(Side.CLIENT) 173 174 /** 175 * gets the duration for how long the current itemInUse has been in use 176 */ 177 public int getItemInUseDuration() 178 { 179 return this.isUsingItem() ? this.itemInUse.getMaxItemUseDuration() - this.itemInUseCount : 0; 180 } 181 182 public void stopUsingItem() 183 { 184 if (this.itemInUse != null) 185 { 186 this.itemInUse.onPlayerStoppedUsing(this.worldObj, this, this.itemInUseCount); 187 } 188 189 this.clearItemInUse(); 190 } 191 192 public void clearItemInUse() 193 { 194 this.itemInUse = null; 195 this.itemInUseCount = 0; 196 197 if (!this.worldObj.isRemote) 198 { 199 this.setEating(false); 200 } 201 } 202 203 public boolean isBlocking() 204 { 205 return this.isUsingItem() && Item.itemsList[this.itemInUse.itemID].getItemUseAction(this.itemInUse) == EnumAction.block; 206 } 207 208 /** 209 * Called to update the entity's position/logic. 210 */ 211 public void onUpdate() 212 { 213 FMLCommonHandler.instance().onPlayerPreTick(this); 214 if (this.itemInUse != null) 215 { 216 ItemStack var1 = this.inventory.getCurrentItem(); 217 218 if (var1 == this.itemInUse) 219 { 220 itemInUse.getItem().onUsingItemTick(itemInUse, this, itemInUseCount); 221 if (this.itemInUseCount <= 25 && this.itemInUseCount % 4 == 0) 222 { 223 this.updateItemUse(var1, 5); 224 } 225 226 if (--this.itemInUseCount == 0 && !this.worldObj.isRemote) 227 { 228 this.onItemUseFinish(); 229 } 230 } 231 else 232 { 233 this.clearItemInUse(); 234 } 235 } 236 237 if (this.xpCooldown > 0) 238 { 239 --this.xpCooldown; 240 } 241 242 if (this.isPlayerSleeping()) 243 { 244 ++this.sleepTimer; 245 246 if (this.sleepTimer > 100) 247 { 248 this.sleepTimer = 100; 249 } 250 251 if (!this.worldObj.isRemote) 252 { 253 if (!this.isInBed()) 254 { 255 this.wakeUpPlayer(true, true, false); 256 } 257 else if (this.worldObj.isDaytime()) 258 { 259 this.wakeUpPlayer(false, true, true); 260 } 261 } 262 } 263 else if (this.sleepTimer > 0) 264 { 265 ++this.sleepTimer; 266 267 if (this.sleepTimer >= 110) 268 { 269 this.sleepTimer = 0; 270 } 271 } 272 273 super.onUpdate(); 274 275 if (!this.worldObj.isRemote && this.craftingInventory != null && !this.craftingInventory.canInteractWith(this)) 276 { 277 this.closeScreen(); 278 this.craftingInventory = this.inventorySlots; 279 } 280 281 if (this.isBurning() && this.capabilities.disableDamage) 282 { 283 this.extinguish(); 284 } 285 286 this.field_71091_bM = this.field_71094_bP; 287 this.field_71096_bN = this.field_71095_bQ; 288 this.field_71097_bO = this.field_71085_bR; 289 double var9 = this.posX - this.field_71094_bP; 290 double var3 = this.posY - this.field_71095_bQ; 291 double var5 = this.posZ - this.field_71085_bR; 292 double var7 = 10.0D; 293 294 if (var9 > var7) 295 { 296 this.field_71091_bM = this.field_71094_bP = this.posX; 297 } 298 299 if (var5 > var7) 300 { 301 this.field_71097_bO = this.field_71085_bR = this.posZ; 302 } 303 304 if (var3 > var7) 305 { 306 this.field_71096_bN = this.field_71095_bQ = this.posY; 307 } 308 309 if (var9 < -var7) 310 { 311 this.field_71091_bM = this.field_71094_bP = this.posX; 312 } 313 314 if (var5 < -var7) 315 { 316 this.field_71097_bO = this.field_71085_bR = this.posZ; 317 } 318 319 if (var3 < -var7) 320 { 321 this.field_71096_bN = this.field_71095_bQ = this.posY; 322 } 323 324 this.field_71094_bP += var9 * 0.25D; 325 this.field_71085_bR += var5 * 0.25D; 326 this.field_71095_bQ += var3 * 0.25D; 327 this.addStat(StatList.minutesPlayedStat, 1); 328 329 if (this.ridingEntity == null) 330 { 331 this.startMinecartRidingCoordinate = null; 332 } 333 334 if (!this.worldObj.isRemote) 335 { 336 this.foodStats.onUpdate(this); 337 } 338 FMLCommonHandler.instance().onPlayerPostTick(this); 339 } 340 341 public int func_82145_z() 342 { 343 return this.capabilities.disableDamage ? 0 : 80; 344 } 345 346 public int func_82147_ab() 347 { 348 return 10; 349 } 350 351 /** 352 * Plays sounds and makes particles for item in use state 353 */ 354 protected void updateItemUse(ItemStack par1ItemStack, int par2) 355 { 356 if (par1ItemStack.getItemUseAction() == EnumAction.drink) 357 { 358 this.worldObj.playSoundAtEntity(this, "random.drink", 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F); 359 } 360 361 if (par1ItemStack.getItemUseAction() == EnumAction.eat) 362 { 363 for (int var3 = 0; var3 < par2; ++var3) 364 { 365 Vec3 var4 = this.worldObj.func_82732_R().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.1D, Math.random() * 0.1D + 0.1D, 0.0D); 366 var4.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F); 367 var4.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F); 368 Vec3 var5 = this.worldObj.func_82732_R().getVecFromPool(((double)this.rand.nextFloat() - 0.5D) * 0.3D, (double)(-this.rand.nextFloat()) * 0.6D - 0.3D, 0.6D); 369 var5.rotateAroundX(-this.rotationPitch * (float)Math.PI / 180.0F); 370 var5.rotateAroundY(-this.rotationYaw * (float)Math.PI / 180.0F); 371 var5 = var5.addVector(this.posX, this.posY + (double)this.getEyeHeight(), this.posZ); 372 this.worldObj.spawnParticle("iconcrack_" + par1ItemStack.getItem().shiftedIndex, var5.xCoord, var5.yCoord, var5.zCoord, var4.xCoord, var4.yCoord + 0.05D, var4.zCoord); 373 } 374 375 this.worldObj.playSoundAtEntity(this, "random.eat", 0.5F + 0.5F * (float)this.rand.nextInt(2), (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F); 376 } 377 } 378 379 /** 380 * Used for when item use count runs out, ie: eating completed 381 */ 382 protected void onItemUseFinish() 383 { 384 if (this.itemInUse != null) 385 { 386 this.updateItemUse(this.itemInUse, 16); 387 int var1 = this.itemInUse.stackSize; 388 ItemStack var2 = this.itemInUse.onFoodEaten(this.worldObj, this); 389 390 if (var2 != this.itemInUse || var2 != null && var2.stackSize != var1) 391 { 392 this.inventory.mainInventory[this.inventory.currentItem] = var2; 393 394 if (var2.stackSize == 0) 395 { 396 this.inventory.mainInventory[this.inventory.currentItem] = null; 397 } 398 } 399 400 this.clearItemInUse(); 401 } 402 } 403 404 @SideOnly(Side.CLIENT) 405 public void handleHealthUpdate(byte par1) 406 { 407 if (par1 == 9) 408 { 409 this.onItemUseFinish(); 410 } 411 else 412 { 413 super.handleHealthUpdate(par1); 414 } 415 } 416 417 /** 418 * Dead and sleeping entities cannot move 419 */ 420 protected boolean isMovementBlocked() 421 { 422 return this.getHealth() <= 0 || this.isPlayerSleeping(); 423 } 424 425 /** 426 * sets current screen to null (used on escape buttons of GUIs) 427 */ 428 public void closeScreen() 429 { 430 this.craftingInventory = this.inventorySlots; 431 } 432 433 /** 434 * Handles updating while being ridden by an entity 435 */ 436 public void updateRidden() 437 { 438 double var1 = this.posX; 439 double var3 = this.posY; 440 double var5 = this.posZ; 441 float var7 = this.rotationYaw; 442 float var8 = this.rotationPitch; 443 super.updateRidden(); 444 this.prevCameraYaw = this.cameraYaw; 445 this.cameraYaw = 0.0F; 446 this.addMountedMovementStat(this.posX - var1, this.posY - var3, this.posZ - var5); 447 448 if (this.ridingEntity instanceof EntityPig) 449 { 450 this.rotationPitch = var8; 451 this.rotationYaw = var7; 452 this.renderYawOffset = ((EntityPig)this.ridingEntity).renderYawOffset; 453 } 454 } 455 456 @SideOnly(Side.CLIENT) 457 458 /** 459 * Keeps moving the entity up so it isn't colliding with blocks and other requirements for this entity to be spawned 460 * (only actually used on players though its also on Entity) 461 */ 462 public void preparePlayerToSpawn() 463 { 464 this.yOffset = 1.62F; 465 this.setSize(0.6F, 1.8F); 466 super.preparePlayerToSpawn(); 467 this.setEntityHealth(this.getMaxHealth()); 468 this.deathTime = 0; 469 } 470 471 protected void updateEntityActionState() 472 { 473 this.func_82168_bl(); 474 } 475 476 /** 477 * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons 478 * use this to react to sunlight and start to burn. 479 */ 480 public void onLivingUpdate() 481 { 482 if (this.flyToggleTimer > 0) 483 { 484 --this.flyToggleTimer; 485 } 486 487 if (this.worldObj.difficultySetting == 0 && this.getHealth() < this.getMaxHealth() && this.ticksExisted % 20 * 12 == 0) 488 { 489 this.heal(1); 490 } 491 492 this.inventory.decrementAnimations(); 493 this.prevCameraYaw = this.cameraYaw; 494 super.onLivingUpdate(); 495 this.landMovementFactor = this.capabilities.getWalkSpeed(); 496 this.jumpMovementFactor = this.speedInAir; 497 498 if (this.isSprinting()) 499 { 500 this.landMovementFactor = (float)((double)this.landMovementFactor + (double)this.capabilities.getWalkSpeed() * 0.3D); 501 this.jumpMovementFactor = (float)((double)this.jumpMovementFactor + (double)this.speedInAir * 0.3D); 502 } 503 504 float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ); 505 float var2 = (float)Math.atan(-this.motionY * 0.20000000298023224D) * 15.0F; 506 507 if (var1 > 0.1F) 508 { 509 var1 = 0.1F; 510 } 511 512 if (!this.onGround || this.getHealth() <= 0) 513 { 514 var1 = 0.0F; 515 } 516 517 if (this.onGround || this.getHealth() <= 0) 518 { 519 var2 = 0.0F; 520 } 521 522 this.cameraYaw += (var1 - this.cameraYaw) * 0.4F; 523 this.cameraPitch += (var2 - this.cameraPitch) * 0.8F; 524 525 if (this.getHealth() > 0) 526 { 527 List var3 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(1.0D, 0.0D, 1.0D)); 528 529 if (var3 != null) 530 { 531 Iterator var4 = var3.iterator(); 532 533 while (var4.hasNext()) 534 { 535 Entity var5 = (Entity)var4.next(); 536 537 if (!var5.isDead) 538 { 539 this.collideWithPlayer(var5); 540 } 541 } 542 } 543 } 544 } 545 546 private void collideWithPlayer(Entity par1Entity) 547 { 548 par1Entity.onCollideWithPlayer(this); 549 } 550 551 @SideOnly(Side.CLIENT) 552 public int getScore() 553 { 554 return this.score; 555 } 556 557 /** 558 * Called when the mob's health reaches 0. 559 */ 560 public void onDeath(DamageSource par1DamageSource) 561 { 562 super.onDeath(par1DamageSource); 563 this.setSize(0.2F, 0.2F); 564 this.setPosition(this.posX, this.posY, this.posZ); 565 this.motionY = 0.10000000149011612D; 566 567 captureDrops = true; 568 capturedDrops.clear(); 569 570 if (this.username.equals("Notch")) 571 { 572 this.dropPlayerItemWithRandomChoice(new ItemStack(Item.appleRed, 1), true); 573 } 574 575 if (!this.worldObj.func_82736_K().func_82766_b("keepInventory")) 576 { 577 this.inventory.dropAllItems(); 578 } 579 580 captureDrops = false; 581 582 if (!worldObj.isRemote) 583 { 584 PlayerDropsEvent event = new PlayerDropsEvent(this, par1DamageSource, capturedDrops, recentlyHit > 0); 585 if (!MinecraftForge.EVENT_BUS.post(event)) 586 { 587 for (EntityItem item : capturedDrops) 588 { 589 joinEntityItemWithWorld(item); 590 } 591 } 592 } 593 594 if (par1DamageSource != null) 595 { 596 this.motionX = (double)(-MathHelper.cos((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F); 597 this.motionZ = (double)(-MathHelper.sin((this.attackedAtYaw + this.rotationYaw) * (float)Math.PI / 180.0F) * 0.1F); 598 } 599 else 600 { 601 this.motionX = this.motionZ = 0.0D; 602 } 603 604 this.yOffset = 0.1F; 605 this.addStat(StatList.deathsStat, 1); 606 } 607 608 /** 609 * Adds a value to the player score. Currently not actually used and the entity passed in does nothing. Args: 610 * entity, scoreToAdd 611 */ 612 public void addToPlayerScore(Entity par1Entity, int par2) 613 { 614 this.score += par2; 615 616 if (par1Entity instanceof EntityPlayer) 617 { 618 this.addStat(StatList.playerKillsStat, 1); 619 } 620 else 621 { 622 this.addStat(StatList.mobKillsStat, 1); 623 } 624 } 625 626 /** 627 * Called when player presses the drop item key 628 */ 629 public EntityItem dropOneItem() 630 { 631 ItemStack stack = inventory.getCurrentItem(); 632 if (stack == null) 633 { 634 return null; 635 } 636 if (stack.getItem().onDroppedByPlayer(stack, this)) 637 { 638 return ForgeHooks.onPlayerTossEvent(this, inventory.decrStackSize(inventory.currentItem, 1)); 639 } 640 return null; 641 } 642 643 /** 644 * Args: itemstack - called when player drops an item stack that's not in his inventory (like items still placed in 645 * a workbench while the workbench'es GUI gets closed) 646 */ 647 public EntityItem dropPlayerItem(ItemStack par1ItemStack) 648 { 649 return ForgeHooks.onPlayerTossEvent(this, par1ItemStack); 650 } 651 652 /** 653 * Args: itemstack, flag 654 */ 655 public EntityItem dropPlayerItemWithRandomChoice(ItemStack par1ItemStack, boolean par2) 656 { 657 if (par1ItemStack == null) 658 { 659 return null; 660 } 661 else 662 { 663 EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY - 0.30000001192092896D + (double)this.getEyeHeight(), this.posZ, par1ItemStack); 664 var3.delayBeforeCanPickup = 40; 665 float var4 = 0.1F; 666 float var5; 667 668 if (par2) 669 { 670 var5 = this.rand.nextFloat() * 0.5F; 671 float var6 = this.rand.nextFloat() * (float)Math.PI * 2.0F; 672 var3.motionX = (double)(-MathHelper.sin(var6) * var5); 673 var3.motionZ = (double)(MathHelper.cos(var6) * var5); 674 var3.motionY = 0.20000000298023224D; 675 } 676 else 677 { 678 var4 = 0.3F; 679 var3.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4); 680 var3.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var4); 681 var3.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI) * var4 + 0.1F); 682 var4 = 0.02F; 683 var5 = this.rand.nextFloat() * (float)Math.PI * 2.0F; 684 var4 *= this.rand.nextFloat(); 685 var3.motionX += Math.cos((double)var5) * (double)var4; 686 var3.motionY += (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F); 687 var3.motionZ += Math.sin((double)var5) * (double)var4; 688 } 689 690 this.joinEntityItemWithWorld(var3); 691 this.addStat(StatList.dropStat, 1); 692 return var3; 693 } 694 } 695 696 /** 697 * Joins the passed in entity item with the world. Args: entityItem 698 */ 699 public void joinEntityItemWithWorld(EntityItem par1EntityItem) 700 { 701 if (captureDrops) 702 { 703 capturedDrops.add(par1EntityItem); 704 } 705 else 706 { 707 this.worldObj.spawnEntityInWorld(par1EntityItem); 708 } 709 } 710 711 /** 712 * Returns how strong the player is against the specified block at this moment 713 * Deprecated in favor of the more sensitive version 714 */ 715 @Deprecated 716 public float getCurrentPlayerStrVsBlock(Block par1Block) 717 { 718 return getCurrentPlayerStrVsBlock(par1Block, 0); 719 } 720 721 public float getCurrentPlayerStrVsBlock(Block par1Block, int meta) 722 { 723 ItemStack stack = inventory.getCurrentItem(); 724 float var2 = (stack == null ? 1.0F : stack.getItem().getStrVsBlock(stack, par1Block, meta)); 725 int var3 = EnchantmentHelper.getEfficiencyModifier(this); 726 727 if (var3 > 0 && ForgeHooks.canHarvestBlock(par1Block, this, meta)) 728 { 729 var2 += (float)(var3 * var3 + 1); 730 } 731 732 if (this.isPotionActive(Potion.digSpeed)) 733 { 734 var2 *= 1.0F + (float)(this.getActivePotionEffect(Potion.digSpeed).getAmplifier() + 1) * 0.2F; 735 } 736 737 if (this.isPotionActive(Potion.digSlowdown)) 738 { 739 var2 *= 1.0F - (float)(this.getActivePotionEffect(Potion.digSlowdown).getAmplifier() + 1) * 0.2F; 740 } 741 742 if (this.isInsideOfMaterial(Material.water) && !EnchantmentHelper.getAquaAffinityModifier(this)) 743 { 744 var2 /= 5.0F; 745 } 746 747 if (!this.onGround) 748 { 749 var2 /= 5.0F; 750 } 751 752 var2 = ForgeEventFactory.getBreakSpeed(this, par1Block, meta, var2); 753 return (var2 < 0 ? 0 : var2); 754 } 755 756 /** 757 * Checks if the player has the ability to harvest a block (checks current inventory item for a tool if necessary) 758 */ 759 public boolean canHarvestBlock(Block par1Block) 760 { 761 return ForgeEventFactory.doPlayerHarvestCheck(this, par1Block, inventory.canHarvestBlock(par1Block)); 762 } 763 764 /** 765 * (abstract) Protected helper method to read subclass entity data from NBT. 766 */ 767 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 768 { 769 super.readEntityFromNBT(par1NBTTagCompound); 770 NBTTagList var2 = par1NBTTagCompound.getTagList("Inventory"); 771 this.inventory.readFromNBT(var2); 772 this.sleeping = par1NBTTagCompound.getBoolean("Sleeping"); 773 this.sleepTimer = par1NBTTagCompound.getShort("SleepTimer"); 774 this.experience = par1NBTTagCompound.getFloat("XpP"); 775 this.experienceLevel = par1NBTTagCompound.getInteger("XpLevel"); 776 this.experienceTotal = par1NBTTagCompound.getInteger("XpTotal"); 777 778 if (this.sleeping) 779 { 780 this.playerLocation = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)); 781 this.wakeUpPlayer(true, true, false); 782 } 783 784 if (par1NBTTagCompound.hasKey("SpawnX") && par1NBTTagCompound.hasKey("SpawnY") && par1NBTTagCompound.hasKey("SpawnZ")) 785 { 786 this.spawnChunk = new ChunkCoordinates(par1NBTTagCompound.getInteger("SpawnX"), par1NBTTagCompound.getInteger("SpawnY"), par1NBTTagCompound.getInteger("SpawnZ")); 787 this.field_82248_d = par1NBTTagCompound.getBoolean("SpawnForced"); 788 } 789 790 this.foodStats.readNBT(par1NBTTagCompound); 791 this.capabilities.readCapabilitiesFromNBT(par1NBTTagCompound); 792 793 if (par1NBTTagCompound.hasKey("EnderItems")) 794 { 795 NBTTagList var3 = par1NBTTagCompound.getTagList("EnderItems"); 796 this.theInventoryEnderChest.loadInventoryFromNBT(var3); 797 } 798 } 799 800 /** 801 * (abstract) Protected helper method to write subclass entity data to NBT. 802 */ 803 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 804 { 805 super.writeEntityToNBT(par1NBTTagCompound); 806 par1NBTTagCompound.setTag("Inventory", this.inventory.writeToNBT(new NBTTagList())); 807 par1NBTTagCompound.setBoolean("Sleeping", this.sleeping); 808 par1NBTTagCompound.setShort("SleepTimer", (short)this.sleepTimer); 809 par1NBTTagCompound.setFloat("XpP", this.experience); 810 par1NBTTagCompound.setInteger("XpLevel", this.experienceLevel); 811 par1NBTTagCompound.setInteger("XpTotal", this.experienceTotal); 812 813 if (this.spawnChunk != null) 814 { 815 par1NBTTagCompound.setInteger("SpawnX", this.spawnChunk.posX); 816 par1NBTTagCompound.setInteger("SpawnY", this.spawnChunk.posY); 817 par1NBTTagCompound.setInteger("SpawnZ", this.spawnChunk.posZ); 818 par1NBTTagCompound.setBoolean("SpawnForced", this.field_82248_d); 819 } 820 821 this.foodStats.writeNBT(par1NBTTagCompound); 822 this.capabilities.writeCapabilitiesToNBT(par1NBTTagCompound); 823 par1NBTTagCompound.setTag("EnderItems", this.theInventoryEnderChest.saveInventoryToNBT()); 824 } 825 826 /** 827 * Displays the GUI for interacting with a chest inventory. Args: chestInventory 828 */ 829 public void displayGUIChest(IInventory par1IInventory) {} 830 831 public void displayGUIEnchantment(int par1, int par2, int par3) {} 832 833 public void func_82244_d(int par1, int par2, int par3) {} 834 835 /** 836 * Displays the crafting GUI for a workbench. 837 */ 838 public void displayGUIWorkbench(int par1, int par2, int par3) {} 839 840 public float getEyeHeight() 841 { 842 return 0.12F; 843 } 844 845 /** 846 * sets the players height back to normal after doing things like sleeping and dieing 847 */ 848 protected void resetHeight() 849 { 850 this.yOffset = 1.62F; 851 } 852 853 /** 854 * Called when the entity is attacked. 855 */ 856 public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) 857 { 858 if (this.capabilities.disableDamage && !par1DamageSource.canHarmInCreative()) 859 { 860 return false; 861 } 862 else 863 { 864 this.entityAge = 0; 865 866 if (this.getHealth() <= 0) 867 { 868 return false; 869 } 870 else 871 { 872 if (this.isPlayerSleeping() && !this.worldObj.isRemote) 873 { 874 this.wakeUpPlayer(true, true, false); 875 } 876 877 if (par1DamageSource.func_76350_n()) 878 { 879 if (this.worldObj.difficultySetting == 0) 880 { 881 par2 = 0; 882 } 883 884 if (this.worldObj.difficultySetting == 1) 885 { 886 par2 = par2 / 2 + 1; 887 } 888 889 if (this.worldObj.difficultySetting == 3) 890 { 891 par2 = par2 * 3 / 2; 892 } 893 } 894 895 if (par2 == 0) 896 { 897 return false; 898 } 899 else 900 { 901 Entity var3 = par1DamageSource.getEntity(); 902 903 if (var3 instanceof EntityArrow && ((EntityArrow)var3).shootingEntity != null) 904 { 905 var3 = ((EntityArrow)var3).shootingEntity; 906 } 907 908 if (var3 instanceof EntityLiving) 909 { 910 this.alertWolves((EntityLiving)var3, false); 911 } 912 913 this.addStat(StatList.damageTakenStat, par2); 914 return super.attackEntityFrom(par1DamageSource, par2); 915 } 916 } 917 } 918 } 919 920 /** 921 * Reduces damage, depending on potions 922 */ 923 protected int applyPotionDamageCalculations(DamageSource par1DamageSource, int par2) 924 { 925 int var3 = super.applyPotionDamageCalculations(par1DamageSource, par2); 926 927 if (var3 <= 0) 928 { 929 return 0; 930 } 931 else 932 { 933 int var4 = EnchantmentHelper.getEnchantmentModifierDamage(this.inventory.armorInventory, par1DamageSource); 934 935 if (var4 > 20) 936 { 937 var4 = 20; 938 } 939 940 if (var4 > 0 && var4 <= 20) 941 { 942 int var5 = 25 - var4; 943 int var6 = var3 * var5 + this.carryoverDamage; 944 var3 = var6 / 25; 945 this.carryoverDamage = var6 % 25; 946 } 947 948 return var3; 949 } 950 } 951 952 /** 953 * returns if pvp is enabled or not 954 */ 955 protected boolean isPVPEnabled() 956 { 957 return false; 958 } 959 960 /** 961 * Called when the player attack or gets attacked, it's alert all wolves in the area that are owned by the player to 962 * join the attack or defend the player. 963 */ 964 protected void alertWolves(EntityLiving par1EntityLiving, boolean par2) 965 { 966 if (!(par1EntityLiving instanceof EntityCreeper) && !(par1EntityLiving instanceof EntityGhast)) 967 { 968 if (par1EntityLiving instanceof EntityWolf) 969 { 970 EntityWolf var3 = (EntityWolf)par1EntityLiving; 971 972 if (var3.isTamed() && this.username.equals(var3.getOwnerName())) 973 { 974 return; 975 } 976 } 977 978 if (!(par1EntityLiving instanceof EntityPlayer) || this.isPVPEnabled()) 979 { 980 List var6 = this.worldObj.getEntitiesWithinAABB(EntityWolf.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(this.posX, this.posY, this.posZ, this.posX + 1.0D, this.posY + 1.0D, this.posZ + 1.0D).expand(16.0D, 4.0D, 16.0D)); 981 Iterator var4 = var6.iterator(); 982 983 while (var4.hasNext()) 984 { 985 EntityWolf var5 = (EntityWolf)var4.next(); 986 987 if (var5.isTamed() && var5.getEntityToAttack() == null && this.username.equals(var5.getOwnerName()) && (!par2 || !var5.isSitting())) 988 { 989 var5.setSitting(false); 990 var5.setTarget(par1EntityLiving); 991 } 992 } 993 } 994 } 995 } 996 997 protected void damageArmor(int par1) 998 { 999 this.inventory.damageArmor(par1); 1000 } 1001 1002 /** 1003 * Returns the current armor value as determined by a call to InventoryPlayer.getTotalArmorValue 1004 */ 1005 public int getTotalArmorValue() 1006 { 1007 return this.inventory.getTotalArmorValue(); 1008 } 1009 1010 public float func_82243_bO() 1011 { 1012 int var1 = 0; 1013 ItemStack[] var2 = this.inventory.armorInventory; 1014 int var3 = var2.length; 1015 1016 for (int var4 = 0; var4 < var3; ++var4) 1017 { 1018 ItemStack var5 = var2[var4]; 1019 1020 if (var5 != null) 1021 { 1022 ++var1; 1023 } 1024 } 1025 1026 return (float)var1 / (float)this.inventory.armorInventory.length; 1027 } 1028 1029 /** 1030 * Deals damage to the entity. If its a EntityPlayer then will take damage from the armor first and then health 1031 * second with the reduced value. Args: damageAmount 1032 */ 1033 protected void damageEntity(DamageSource par1DamageSource, int par2) 1034 { 1035 LivingHurtEvent event = new LivingHurtEvent(this, par1DamageSource, par2); 1036 if (MinecraftForge.EVENT_BUS.post(event) || event.ammount == 0) 1037 { 1038 return; 1039 } 1040 par2 = event.ammount; 1041 1042 if (!par1DamageSource.isUnblockable() && this.isBlocking()) 1043 { 1044 par2 = 1 + par2 >> 1; 1045 } 1046 1047 par2 = ArmorProperties.ApplyArmor(this, inventory.armorInventory, par1DamageSource, par2); 1048 if (par2 <= 0) 1049 { 1050 return; 1051 } 1052 par2 = this.applyPotionDamageCalculations(par1DamageSource, par2); 1053 this.addExhaustion(par1DamageSource.getHungerDamage()); 1054 this.health -= par2; 1055 } 1056 1057 /** 1058 * Displays the furnace GUI for the passed in furnace entity. Args: tileEntityFurnace 1059 */ 1060 public void displayGUIFurnace(TileEntityFurnace par1TileEntityFurnace) {} 1061 1062 /** 1063 * Displays the dipsenser GUI for the passed in dispenser entity. Args: TileEntityDispenser 1064 */ 1065 public void displayGUIDispenser(TileEntityDispenser par1TileEntityDispenser) {} 1066 1067 /** 1068 * Displays the GUI for editing a sign. Args: tileEntitySign 1069 */ 1070 public void displayGUIEditSign(TileEntity par1TileEntity) {} 1071 1072 /** 1073 * Displays the GUI for interacting with a brewing stand. 1074 */ 1075 public void displayGUIBrewingStand(TileEntityBrewingStand par1TileEntityBrewingStand) {} 1076 1077 public void func_82240_a(TileEntityBeacon par1TileEntityBeacon) {} 1078 1079 public void displayGUIMerchant(IMerchant par1IMerchant) {} 1080 1081 /** 1082 * Displays the GUI for interacting with a book. 1083 */ 1084 public void displayGUIBook(ItemStack par1ItemStack) {} 1085 1086 public boolean interactWith(Entity par1Entity) 1087 { 1088 if (MinecraftForge.EVENT_BUS.post(new EntityInteractEvent(this, par1Entity))) 1089 { 1090 return false; 1091 } 1092 if (par1Entity.interact(this)) 1093 { 1094 return true; 1095 } 1096 else 1097 { 1098 ItemStack var2 = this.getCurrentEquippedItem(); 1099 1100 if (var2 != null && par1Entity instanceof EntityLiving) 1101 { 1102 if (this.capabilities.isCreativeMode) 1103 { 1104 var2 = var2.copy(); 1105 } 1106 1107 if (var2.interactWith((EntityLiving)par1Entity)) 1108 { 1109 if (var2.stackSize <= 0 && !this.capabilities.isCreativeMode) 1110 { 1111 this.destroyCurrentEquippedItem(); 1112 } 1113 1114 return true; 1115 } 1116 } 1117 1118 return false; 1119 } 1120 } 1121 1122 /** 1123 * Returns the currently being used item by the player. 1124 */ 1125 public ItemStack getCurrentEquippedItem() 1126 { 1127 return this.inventory.getCurrentItem(); 1128 } 1129 1130 /** 1131 * Destroys the currently equipped item from the player's inventory. 1132 */ 1133 public void destroyCurrentEquippedItem() 1134 { 1135 ItemStack orig = getCurrentEquippedItem(); 1136 this.inventory.setInventorySlotContents(this.inventory.currentItem, (ItemStack)null); 1137 MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(this, orig)); 1138 } 1139 1140 /** 1141 * Returns the Y Offset of this entity. 1142 */ 1143 public double getYOffset() 1144 { 1145 return (double)(this.yOffset - 0.5F); 1146 } 1147 1148 /** 1149 * Attacks for the player the targeted entity with the currently equipped item. The equipped item has hitEntity 1150 * called on it. Args: targetEntity 1151 */ 1152 public void attackTargetEntityWithCurrentItem(Entity par1Entity) 1153 { 1154 if (MinecraftForge.EVENT_BUS.post(new AttackEntityEvent(this, par1Entity))) 1155 { 1156 return; 1157 } 1158 ItemStack stack = getCurrentEquippedItem(); 1159 if (stack != null && stack.getItem().onLeftClickEntity(stack, this, par1Entity)) 1160 { 1161 return; 1162 } 1163 if (par1Entity.canAttackWithItem()) 1164 { 1165 int var2 = this.inventory.getDamageVsEntity(par1Entity); 1166 1167 if (this.isPotionActive(Potion.damageBoost)) 1168 { 1169 var2 += 3 << this.getActivePotionEffect(Potion.damageBoost).getAmplifier(); 1170 } 1171 1172 if (this.isPotionActive(Potion.weakness)) 1173 { 1174 var2 -= 2 << this.getActivePotionEffect(Potion.weakness).getAmplifier(); 1175 } 1176 1177 int var3 = 0; 1178 int var4 = 0; 1179 1180 if (par1Entity instanceof EntityLiving) 1181 { 1182 var4 = EnchantmentHelper.getEnchantmentModifierLiving(this, (EntityLiving)par1Entity); 1183 var3 += EnchantmentHelper.getKnockbackModifier(this, (EntityLiving)par1Entity); 1184 } 1185 1186 if (this.isSprinting()) 1187 { 1188 ++var3; 1189 } 1190 1191 if (var2 > 0 || var4 > 0) 1192 { 1193 boolean var5 = this.fallDistance > 0.0F && !this.onGround && !this.isOnLadder() && !this.isInWater() && !this.isPotionActive(Potion.blindness) && this.ridingEntity == null && par1Entity instanceof EntityLiving; 1194 1195 if (var5) 1196 { 1197 var2 += this.rand.nextInt(var2 / 2 + 2); 1198 } 1199 1200 var2 += var4; 1201 boolean var6 = par1Entity.attackEntityFrom(DamageSource.causePlayerDamage(this), var2); 1202 1203 if (var6) 1204 { 1205 if (var3 > 0) 1206 { 1207 par1Entity.addVelocity((double)(-MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F) * (float)var3 * 0.5F), 0.1D, (double)(MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F) * (float)var3 * 0.5F)); 1208 this.motionX *= 0.6D; 1209 this.motionZ *= 0.6D; 1210 this.setSprinting(false); 1211 } 1212 1213 if (var5) 1214 { 1215 this.onCriticalHit(par1Entity); 1216 } 1217 1218 if (var4 > 0) 1219 { 1220 this.onEnchantmentCritical(par1Entity); 1221 } 1222 1223 if (var2 >= 18) 1224 { 1225 this.triggerAchievement(AchievementList.overkill); 1226 } 1227 1228 this.setLastAttackingEntity(par1Entity); 1229 } 1230 1231 ItemStack var7 = this.getCurrentEquippedItem(); 1232 1233 if (var7 != null && par1Entity instanceof EntityLiving) 1234 { 1235 var7.hitEntity((EntityLiving)par1Entity, this); 1236 1237 if (var7.stackSize <= 0) 1238 { 1239 this.destroyCurrentEquippedItem(); 1240 } 1241 } 1242 1243 if (par1Entity instanceof EntityLiving) 1244 { 1245 if (par1Entity.isEntityAlive()) 1246 { 1247 this.alertWolves((EntityLiving)par1Entity, true); 1248 } 1249 1250 this.addStat(StatList.damageDealtStat, var2); 1251 int var8 = EnchantmentHelper.getFireAspectModifier(this, (EntityLiving)par1Entity); 1252 1253 if (var8 > 0 && var6) 1254 { 1255 par1Entity.setFire(var8 * 4); 1256 } 1257 } 1258 1259 this.addExhaustion(0.3F); 1260 } 1261 } 1262 } 1263 1264 /** 1265 * Called when the player performs a critical hit on the Entity. Args: entity that was hit critically 1266 */ 1267 public void onCriticalHit(Entity par1Entity) {} 1268 1269 public void onEnchantmentCritical(Entity par1Entity) {} 1270 1271 @SideOnly(Side.CLIENT) 1272 public void respawnPlayer() {} 1273 1274 /** 1275 * Will get destroyed next tick. 1276 */ 1277 public void setDead() 1278 { 1279 super.setDead(); 1280 this.inventorySlots.onCraftGuiClosed(this); 1281 1282 if (this.craftingInventory != null) 1283 { 1284 this.craftingInventory.onCraftGuiClosed(this); 1285 } 1286 } 1287 1288 /** 1289 * Checks if this entity is inside of an opaque block 1290 */ 1291 public boolean isEntityInsideOpaqueBlock() 1292 { 1293 return !this.sleeping && super.isEntityInsideOpaqueBlock(); 1294 } 1295 1296 public boolean func_71066_bF() 1297 { 1298 return false; 1299 } 1300 1301 /** 1302 * Attempts to have the player sleep in a bed at the specified location. 1303 */ 1304 public EnumStatus sleepInBedAt(int par1, int par2, int par3) 1305 { 1306 PlayerSleepInBedEvent event = new PlayerSleepInBedEvent(this, par1, par2, par3); 1307 MinecraftForge.EVENT_BUS.post(event); 1308 if (event.result != null) 1309 { 1310 return event.result; 1311 } 1312 if (!this.worldObj.isRemote) 1313 { 1314 if (this.isPlayerSleeping() || !this.isEntityAlive()) 1315 { 1316 return EnumStatus.OTHER_PROBLEM; 1317 } 1318 1319 if (!this.worldObj.provider.isSurfaceWorld()) 1320 { 1321 return EnumStatus.NOT_POSSIBLE_HERE; 1322 } 1323 1324 if (this.worldObj.isDaytime()) 1325 { 1326 return EnumStatus.NOT_POSSIBLE_NOW; 1327 } 1328 1329 if (Math.abs(this.posX - (double)par1) > 3.0D || Math.abs(this.posY - (double)par2) > 2.0D || Math.abs(this.posZ - (double)par3) > 3.0D) 1330 { 1331 return EnumStatus.TOO_FAR_AWAY; 1332 } 1333 1334 double var4 = 8.0D; 1335 double var6 = 5.0D; 1336 List var8 = this.worldObj.getEntitiesWithinAABB(EntityMob.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)par1 - var4, (double)par2 - var6, (double)par3 - var4, (double)par1 + var4, (double)par2 + var6, (double)par3 + var4)); 1337 1338 if (!var8.isEmpty()) 1339 { 1340 return EnumStatus.NOT_SAFE; 1341 } 1342 } 1343 1344 this.setSize(0.2F, 0.2F); 1345 this.yOffset = 0.2F; 1346 1347 if (this.worldObj.blockExists(par1, par2, par3)) 1348 { 1349 int var9 = this.worldObj.getBlockMetadata(par1, par2, par3); 1350 int var5 = BlockBed.getDirection(var9); 1351 Block block = Block.blocksList[worldObj.getBlockId(par1, par2, par3)]; 1352 if (block != null) 1353 { 1354 var5 = block.getBedDirection(worldObj, par1, par2, par3); 1355 } 1356 float var10 = 0.5F; 1357 float var7 = 0.5F; 1358 1359 switch (var5) 1360 { 1361 case 0: 1362 var7 = 0.9F; 1363 break; 1364 case 1: 1365 var10 = 0.1F; 1366 break; 1367 case 2: 1368 var7 = 0.1F; 1369 break; 1370 case 3: 1371 var10 = 0.9F; 1372 } 1373 1374 this.func_71013_b(var5); 1375 this.setPosition((double)((float)par1 + var10), (double)((float)par2 + 0.9375F), (double)((float)par3 + var7)); 1376 } 1377 else 1378 { 1379 this.setPosition((double)((float)par1 + 0.5F), (double)((float)par2 + 0.9375F), (double)((float)par3 + 0.5F)); 1380 } 1381 1382 this.sleeping = true; 1383 this.sleepTimer = 0; 1384 this.playerLocation = new ChunkCoordinates(par1, par2, par3); 1385 this.motionX = this.motionZ = this.motionY = 0.0D; 1386 1387 if (!this.worldObj.isRemote) 1388 { 1389 this.worldObj.updateAllPlayersSleepingFlag(); 1390 } 1391 1392 return EnumStatus.OK; 1393 } 1394 1395 private void func_71013_b(int par1) 1396 { 1397 this.field_71079_bU = 0.0F; 1398 this.field_71089_bV = 0.0F; 1399 1400 switch (par1) 1401 { 1402 case 0: 1403 this.field_71089_bV = -1.8F; 1404 break; 1405 case 1: 1406 this.field_71079_bU = 1.8F; 1407 break; 1408 case 2: 1409 this.field_71089_bV = 1.8F; 1410 break; 1411 case 3: 1412 this.field_71079_bU = -1.8F; 1413 } 1414 } 1415 1416 /** 1417 * Wake up the player if they're sleeping. 1418 */ 1419 public void wakeUpPlayer(boolean par1, boolean par2, boolean par3) 1420 { 1421 this.setSize(0.6F, 1.8F); 1422 this.resetHeight(); 1423 ChunkCoordinates var4 = this.playerLocation; 1424 ChunkCoordinates var5 = this.playerLocation; 1425 1426 Block block = (var4 == null ? null : Block.blocksList[worldObj.getBlockId(var4.posX, var4.posY, var4.posZ)]); 1427 1428 if (var4 != null && block != null && block.isBed(worldObj, var4.posX, var4.posY, var4.posZ, this)) 1429 { 1430 block.setBedOccupied(this.worldObj, var4.posX, var4.posY, var4.posZ, this, false); 1431 var5 = block.getBedSpawnPosition(worldObj, var4.posX, var4.posY, var4.posZ, this); 1432 1433 if (var5 == null) 1434 { 1435 var5 = new ChunkCoordinates(var4.posX, var4.posY + 1, var4.posZ); 1436 } 1437 1438 this.setPosition((double)((float)var5.posX + 0.5F), (double)((float)var5.posY + this.yOffset + 0.1F), (double)((float)var5.posZ + 0.5F)); 1439 } 1440 1441 this.sleeping = false; 1442 1443 if (!this.worldObj.isRemote && par2) 1444 { 1445 this.worldObj.updateAllPlayersSleepingFlag(); 1446 } 1447 1448 if (par1) 1449 { 1450 this.sleepTimer = 0; 1451 } 1452 else 1453 { 1454 this.sleepTimer = 100; 1455 } 1456 1457 if (par3) 1458 { 1459 this.setSpawnChunk(this.playerLocation, false); 1460 } 1461 } 1462 1463 /** 1464 * Checks if the player is currently in a bed 1465 */ 1466 private boolean isInBed() 1467 { 1468 ChunkCoordinates c = playerLocation; 1469 int blockID = worldObj.getBlockId(c.posX, c.posY, c.posZ); 1470 return Block.blocksList[blockID] != null && Block.blocksList[blockID].isBed(worldObj, c.posX, c.posY, c.posZ, this); 1471 } 1472 1473 /** 1474 * Ensure that a block enabling respawning exists at the specified coordinates and find an empty space nearby to 1475 * spawn. 1476 */ 1477 public static ChunkCoordinates verifyRespawnCoordinates(World par0World, ChunkCoordinates par1ChunkCoordinates, boolean par2) 1478 { 1479 IChunkProvider var3 = par0World.getChunkProvider(); 1480 var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4); 1481 var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ - 3 >> 4); 1482 var3.loadChunk(par1ChunkCoordinates.posX - 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4); 1483 var3.loadChunk(par1ChunkCoordinates.posX + 3 >> 4, par1ChunkCoordinates.posZ + 3 >> 4); 1484 1485 ChunkCoordinates c = par1ChunkCoordinates; 1486 Block block = Block.blocksList[par0World.getBlockId(c.posX, c.posY, c.posZ)]; 1487 1488 if (block == null || !block.isBed(par0World, c.posX, c.posY, c.posZ, null)) 1489 { 1490 return par2 && par0World.isAirBlock(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY, par1ChunkCoordinates.posZ) && par0World.isAirBlock(par1ChunkCoordinates.posX, par1ChunkCoordinates.posY + 1, par1ChunkCoordinates.posZ) ? par1ChunkCoordinates : null; 1491 } 1492 else 1493 { 1494 ChunkCoordinates var4 = block.getBedSpawnPosition(par0World, c.posX, c.posY, c.posZ, null); 1495 return var4; 1496 } 1497 } 1498 1499 @SideOnly(Side.CLIENT) 1500 1501 /** 1502 * Returns the orientation of the bed in degrees. 1503 */ 1504 public float getBedOrientationInDegrees() 1505 { 1506 if (this.playerLocation != null) 1507 { 1508 int x = playerLocation.posX; 1509 int y = playerLocation.posY; 1510 int z = playerLocation.posZ; 1511 Block block = Block.blocksList[worldObj.getBlockId(x, y, z)]; 1512 int var2 = (block == null ? 0 : block.getBedDirection(worldObj, x, y, z)); 1513 1514 switch (var2) 1515 { 1516 case 0: 1517 return 90.0F; 1518 case 1: 1519 return 0.0F; 1520 case 2: 1521 return 270.0F; 1522 case 3: 1523 return 180.0F; 1524 } 1525 } 1526 1527 return 0.0F; 1528 } 1529 1530 /** 1531 * Returns whether player is sleeping or not 1532 */ 1533 public boolean isPlayerSleeping() 1534 { 1535 return this.sleeping; 1536 } 1537 1538 /** 1539 * Returns whether or not the player is asleep and the screen has fully faded. 1540 */ 1541 public boolean isPlayerFullyAsleep() 1542 { 1543 return this.sleeping && this.sleepTimer >= 100; 1544 } 1545 1546 @SideOnly(Side.CLIENT) 1547 public int getSleepTimer() 1548 { 1549 return this.sleepTimer; 1550 } 1551 1552 @SideOnly(Side.CLIENT) 1553 protected boolean func_82241_s(int par1) 1554 { 1555 return (this.dataWatcher.getWatchableObjectByte(16) & 1 << par1) != 0; 1556 } 1557 1558 protected void func_82239_b(int par1, boolean par2) 1559 { 1560 byte var3 = this.dataWatcher.getWatchableObjectByte(16); 1561 1562 if (par2) 1563 { 1564 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 | 1 << par1))); 1565 } 1566 else 1567 { 1568 this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var3 & ~(1 << par1)))); 1569 } 1570 } 1571 1572 /** 1573 * Add a chat message to the player 1574 */ 1575 public void addChatMessage(String par1Str) {} 1576 1577 /** 1578 * Returns the coordinates to respawn the player based on last bed that the player sleep. 1579 */ 1580 public ChunkCoordinates getSpawnChunk() 1581 { 1582 return this.spawnChunk; 1583 } 1584 1585 public boolean func_82245_bX() 1586 { 1587 return this.field_82248_d; 1588 } 1589 1590 /** 1591 * Defines a spawn coordinate to player spawn. Used by bed after the player sleep on it. 1592 */ 1593 public void setSpawnChunk(ChunkCoordinates par1ChunkCoordinates, boolean par2) 1594 { 1595 if (par1ChunkCoordinates != null) 1596 { 1597 this.spawnChunk = new ChunkCoordinates(par1ChunkCoordinates); 1598 this.field_82248_d = par2; 1599 } 1600 else 1601 { 1602 this.spawnChunk = null; 1603 this.field_82248_d = false; 1604 } 1605 } 1606 1607 /** 1608 * Will trigger the specified trigger. 1609 */ 1610 public void triggerAchievement(StatBase par1StatBase) 1611 { 1612 this.addStat(par1StatBase, 1); 1613 } 1614 1615 /** 1616 * Adds a value to a statistic field. 1617 */ 1618 public void addStat(StatBase par1StatBase, int par2) {} 1619 1620 /** 1621 * Causes this entity to do an upwards motion (jumping). 1622 */ 1623 protected void jump() 1624 { 1625 super.jump(); 1626 this.addStat(StatList.jumpStat, 1); 1627 1628 if (this.isSprinting()) 1629 { 1630 this.addExhaustion(0.8F); 1631 } 1632 else 1633 { 1634 this.addExhaustion(0.2F); 1635 } 1636 } 1637 1638 /** 1639 * Moves the entity based on the specified heading. Args: strafe, forward 1640 */ 1641 public void moveEntityWithHeading(float par1, float par2) 1642 { 1643 double var3 = this.posX; 1644 double var5 = this.posY; 1645 double var7 = this.posZ; 1646 1647 if (this.capabilities.isFlying && this.ridingEntity == null) 1648 { 1649 double var9 = this.motionY; 1650 float var11 = this.jumpMovementFactor; 1651 this.jumpMovementFactor = this.capabilities.getFlySpeed(); 1652 super.moveEntityWithHeading(par1, par2); 1653 this.motionY = var9 * 0.6D; 1654 this.jumpMovementFactor = var11; 1655 } 1656 else 1657 { 1658 super.moveEntityWithHeading(par1, par2); 1659 } 1660 1661 this.addMovementStat(this.posX - var3, this.posY - var5, this.posZ - var7); 1662 } 1663 1664 /** 1665 * Adds a value to a movement statistic field - like run, walk, swin or climb. 1666 */ 1667 public void addMovementStat(double par1, double par3, double par5) 1668 { 1669 if (this.ridingEntity == null) 1670 { 1671 int var7; 1672 1673 if (this.isInsideOfMaterial(Material.water)) 1674 { 1675 var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F); 1676 1677 if (var7 > 0) 1678 { 1679 this.addStat(StatList.distanceDoveStat, var7); 1680 this.addExhaustion(0.015F * (float)var7 * 0.01F); 1681 } 1682 } 1683 else if (this.isInWater()) 1684 { 1685 var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F); 1686 1687 if (var7 > 0) 1688 { 1689 this.addStat(StatList.distanceSwumStat, var7); 1690 this.addExhaustion(0.015F * (float)var7 * 0.01F); 1691 } 1692 } 1693 else if (this.isOnLadder()) 1694 { 1695 if (par3 > 0.0D) 1696 { 1697 this.addStat(StatList.distanceClimbedStat, (int)Math.round(par3 * 100.0D)); 1698 } 1699 } 1700 else if (this.onGround) 1701 { 1702 var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F); 1703 1704 if (var7 > 0) 1705 { 1706 this.addStat(StatList.distanceWalkedStat, var7); 1707 1708 if (this.isSprinting()) 1709 { 1710 this.addExhaustion(0.099999994F * (float)var7 * 0.01F); 1711 } 1712 else 1713 { 1714 this.addExhaustion(0.01F * (float)var7 * 0.01F); 1715 } 1716 } 1717 } 1718 else 1719 { 1720 var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par5 * par5) * 100.0F); 1721 1722 if (var7 > 25) 1723 { 1724 this.addStat(StatList.distanceFlownStat, var7); 1725 } 1726 } 1727 } 1728 } 1729 1730 /** 1731 * Adds a value to a mounted movement statistic field - by minecart, boat, or pig. 1732 */ 1733 private void addMountedMovementStat(double par1, double par3, double par5) 1734 { 1735 if (this.ridingEntity != null) 1736 { 1737 int var7 = Math.round(MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5) * 100.0F); 1738 1739 if (var7 > 0) 1740 { 1741 if (this.ridingEntity instanceof EntityMinecart) 1742 { 1743 this.addStat(StatList.distanceByMinecartStat, var7); 1744 1745 if (this.startMinecartRidingCoordinate == null) 1746 { 1747 this.startMinecartRidingCoordinate = new ChunkCoordinates(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)); 1748 } 1749 else if ((double)this.startMinecartRidingCoordinate.getDistanceSquared(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) >= 1000000.0D) 1750 { 1751 this.addStat(AchievementList.onARail, 1); 1752 } 1753 } 1754 else if (this.ridingEntity instanceof EntityBoat) 1755 { 1756 this.addStat(StatList.distanceByBoatStat, var7); 1757 } 1758 else if (this.ridingEntity instanceof EntityPig) 1759 { 1760 this.addStat(StatList.distanceByPigStat, var7); 1761 } 1762 } 1763 } 1764 } 1765 1766 /** 1767 * Called when the mob is falling. Calculates and applies fall damage. 1768 */ 1769 protected void fall(float par1) 1770 { 1771 if (!this.capabilities.allowFlying) 1772 { 1773 if (par1 >= 2.0F) 1774 { 1775 this.addStat(StatList.distanceFallenStat, (int)Math.round((double)par1 * 100.0D)); 1776 } 1777 1778 super.fall(par1); 1779 } 1780 } 1781 1782 /** 1783 * This method gets called when the entity kills another one. 1784 */ 1785 public void onKillEntity(EntityLiving par1EntityLiving) 1786 { 1787 if (par1EntityLiving instanceof IMob) 1788 { 1789 this.triggerAchievement(AchievementList.killEnemy); 1790 } 1791 } 1792 1793 @SideOnly(Side.CLIENT) 1794 1795 /** 1796 * Gets the Icon Index of the item currently held 1797 */ 1798 public int getItemIcon(ItemStack par1ItemStack, int par2) 1799 { 1800 int var3 = super.getItemIcon(par1ItemStack, par2); 1801 1802 if (par1ItemStack.itemID == Item.fishingRod.shiftedIndex && this.fishEntity != null) 1803 { 1804 var3 = par1ItemStack.getIconIndex() + 16; 1805 } 1806 else 1807 { 1808 if (par1ItemStack.getItem().requiresMultipleRenderPasses()) 1809 { 1810 return par1ItemStack.getItem().getIconFromDamageForRenderPass(par1ItemStack.getItemDamage(), par2); 1811 } 1812 1813 if (this.itemInUse != null && par1ItemStack.itemID == Item.bow.shiftedIndex) 1814 { 1815 int var4 = par1ItemStack.getMaxItemUseDuration() - this.itemInUseCount; 1816 1817 if (var4 >= 18) 1818 { 1819 return 133; 1820 } 1821 1822 if (var4 > 13) 1823 { 1824 return 117; 1825 } 1826 1827 if (var4 > 0) 1828 { 1829 return 101; 1830 } 1831 } 1832 var3 = par1ItemStack.getItem().getIconIndex(par1ItemStack, par2, this, itemInUse, itemInUseCount); 1833 } 1834 1835 return var3; 1836 } 1837 1838 public ItemStack func_82169_q(int par1) 1839 { 1840 return this.inventory.armorItemInSlot(par1); 1841 } 1842 1843 protected void func_82164_bB() {} 1844 1845 protected void func_82162_bC() {} 1846 1847 /** 1848 * This method increases the player's current amount of experience. 1849 */ 1850 public void addExperience(int par1) 1851 { 1852 this.score += par1; 1853 int var2 = Integer.MAX_VALUE - this.experienceTotal; 1854 1855 if (par1 > var2) 1856 { 1857 par1 = var2; 1858 } 1859 1860 this.experience += (float)par1 / (float)this.xpBarCap(); 1861 1862 for (this.experienceTotal += par1; this.experience >= 1.0F; this.experience /= (float)this.xpBarCap()) 1863 { 1864 this.experience = (this.experience - 1.0F) * (float)this.xpBarCap(); 1865 this.func_82242_a(1); 1866 } 1867 } 1868 1869 public void func_82242_a(int par1) 1870 { 1871 this.experienceLevel += par1; 1872 1873 if (this.experienceLevel < 0) 1874 { 1875 this.experienceLevel = 0; 1876 } 1877 1878 if (par1 > 0 && this.experienceLevel % 5 == 0 && (float)this.field_82249_h < (float)this.ticksExisted - 100.0F) 1879 { 1880 float var2 = this.experienceLevel > 30 ? 1.0F : (float)this.experienceLevel / 30.0F; 1881 this.worldObj.playSoundAtEntity(this, "random.levelup", var2 * 0.75F, 1.0F); 1882 this.field_82249_h = this.ticksExisted; 1883 } 1884 } 1885 1886 /** 1887 * This method returns the cap amount of experience that the experience bar can hold. With each level, the 1888 * experience cap on the player's experience bar is raised by 10. 1889 */ 1890 public int xpBarCap() 1891 { 1892 return this.experienceLevel >= 30 ? 62 + (this.experienceLevel - 30) * 7 : (this.experienceLevel >= 15 ? 17 + (this.experienceLevel - 15) * 3 : 17); 1893 } 1894 1895 /** 1896 * increases exhaustion level by supplied amount 1897 */ 1898 public void addExhaustion(float par1) 1899 { 1900 if (!this.capabilities.disableDamage) 1901 { 1902 if (!this.worldObj.isRemote) 1903 { 1904 this.foodStats.addExhaustion(par1); 1905 } 1906 } 1907 } 1908 1909 /** 1910 * Returns the player's FoodStats object. 1911 */ 1912 public FoodStats getFoodStats() 1913 { 1914 return this.foodStats; 1915 } 1916 1917 public boolean canEat(boolean par1) 1918 { 1919 return (par1 || this.foodStats.needFood()) && !this.capabilities.disableDamage; 1920 } 1921 1922 /** 1923 * Checks if the player's health is not full and not zero. 1924 */ 1925 public boolean shouldHeal() 1926 { 1927 return this.getHealth() > 0 && this.getHealth() < this.getMaxHealth(); 1928 } 1929 1930 /** 1931 * sets the itemInUse when the use item button is clicked. Args: itemstack, int maxItemUseDuration 1932 */ 1933 public void setItemInUse(ItemStack par1ItemStack, int par2) 1934 { 1935 if (par1ItemStack != this.itemInUse) 1936 { 1937 this.itemInUse = par1ItemStack; 1938 this.itemInUseCount = par2; 1939 1940 if (!this.worldObj.isRemote) 1941 { 1942 this.setEating(true); 1943 } 1944 } 1945 } 1946 1947 public boolean func_82246_f(int par1, int par2, int par3) 1948 { 1949 if (this.capabilities.allowEdit) 1950 { 1951 return true; 1952 } 1953 else 1954 { 1955 int var4 = this.worldObj.getBlockId(par1, par2, par3); 1956 1957 if (var4 > 0 && this.getCurrentEquippedItem() != null) 1958 { 1959 Block var5 = Block.blocksList[var4]; 1960 ItemStack var6 = this.getCurrentEquippedItem(); 1961 1962 if (var6.canHarvestBlock(var5) || var6.getStrVsBlock(var5) > 1.0F) 1963 { 1964 return true; 1965 } 1966 } 1967 1968 return false; 1969 } 1970 } 1971 1972 public boolean func_82247_a(int par1, int par2, int par3, int par4, ItemStack par5ItemStack) 1973 { 1974 return this.capabilities.allowEdit ? true : (par5ItemStack != null ? par5ItemStack.func_82835_x() : false); 1975 } 1976 1977 /** 1978 * Get the experience points the entity currently has. 1979 */ 1980 protected int getExperiencePoints(EntityPlayer par1EntityPlayer) 1981 { 1982 if (this.worldObj.func_82736_K().func_82766_b("keepInventory")) 1983 { 1984 return 0; 1985 } 1986 else 1987 { 1988 int var2 = this.experienceLevel * 7; 1989 return var2 > 100 ? 100 : var2; 1990 } 1991 } 1992 1993 /** 1994 * Only use is to identify if class is an instance of player for experience dropping 1995 */ 1996 protected boolean isPlayer() 1997 { 1998 return true; 1999 } 2000 2001 /** 2002 * Gets the username of the entity. 2003 */ 2004 public String getEntityName() 2005 { 2006 return this.username; 2007 } 2008 2009 /** 2010 * Copies the values from the given player into this player if boolean par2 is true. Always clones Ender Chest 2011 * Inventory. 2012 */ 2013 public void clonePlayer(EntityPlayer par1EntityPlayer, boolean par2) 2014 { 2015 if (par2) 2016 { 2017 this.inventory.copyInventory(par1EntityPlayer.inventory); 2018 this.health = par1EntityPlayer.health; 2019 this.foodStats = par1EntityPlayer.foodStats; 2020 this.experienceLevel = par1EntityPlayer.experienceLevel; 2021 this.experienceTotal = par1EntityPlayer.experienceTotal; 2022 this.experience = par1EntityPlayer.experience; 2023 this.score = par1EntityPlayer.score; 2024 this.field_82152_aq = par1EntityPlayer.field_82152_aq; 2025 } 2026 else if (this.worldObj.func_82736_K().func_82766_b("keepInventory")) 2027 { 2028 this.inventory.copyInventory(par1EntityPlayer.inventory); 2029 this.experienceLevel = par1EntityPlayer.experienceLevel; 2030 this.experienceTotal = par1EntityPlayer.experienceTotal; 2031 this.experience = par1EntityPlayer.experience; 2032 this.score = par1EntityPlayer.score; 2033 } 2034 2035 this.theInventoryEnderChest = par1EntityPlayer.theInventoryEnderChest; 2036 } 2037 2038 /** 2039 * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to 2040 * prevent them from trampling crops 2041 */ 2042 protected boolean canTriggerWalking() 2043 { 2044 return !this.capabilities.isFlying; 2045 } 2046 2047 /** 2048 * Sends the player's abilities to the server (if there is one). 2049 */ 2050 public void sendPlayerAbilities() {} 2051 2052 public void sendGameTypeToPlayer(EnumGameType par1EnumGameType) {} 2053 2054 /** 2055 * Gets the name of this command sender (usually username, but possibly "Rcon") 2056 */ 2057 public String getCommandSenderName() 2058 { 2059 return this.username; 2060 } 2061 2062 public StringTranslate getTranslator() 2063 { 2064 return StringTranslate.getInstance(); 2065 } 2066 2067 /** 2068 * Translates and formats the given string key with the given arguments. 2069 */ 2070 public String translateString(String par1Str, Object ... par2ArrayOfObj) 2071 { 2072 return this.getTranslator().translateKeyFormat(par1Str, par2ArrayOfObj); 2073 } 2074 2075 /** 2076 * Returns the InventoryEnderChest of this player. 2077 */ 2078 public InventoryEnderChest getInventoryEnderChest() 2079 { 2080 return this.theInventoryEnderChest; 2081 } 2082 2083 /** 2084 * 0 = item, 1-n is armor 2085 */ 2086 public ItemStack getCurrentItemOrArmor(int par1) 2087 { 2088 return par1 == 0 ? this.inventory.getCurrentItem() : this.inventory.armorInventory[par1 - 1]; 2089 } 2090 2091 /** 2092 * Returns the item that this EntityLiving is holding, if any. 2093 */ 2094 public ItemStack getHeldItem() 2095 { 2096 return this.inventory.getCurrentItem(); 2097 } 2098 2099 public void func_70062_b(int par1, ItemStack par2ItemStack) 2100 { 2101 this.inventory.armorInventory[par1] = par2ItemStack; 2102 } 2103 2104 public ItemStack[] getLastActiveItems() 2105 { 2106 return this.inventory.armorInventory; 2107 } 2108 2109 @SideOnly(Side.CLIENT) 2110 public boolean func_82238_cc() 2111 { 2112 return this.func_82241_s(1); 2113 } 2114 2115 public void openGui(Object mod, int modGuiId, World world, int x, int y, int z) 2116 { 2117 FMLNetworkHandler.openGui(this, mod, modGuiId, world, x, y, z); 2118 } 2119 }