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