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