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