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