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