001 package net.minecraft.entity; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 006 import java.util.ArrayList; 007 import java.util.List; 008 import java.util.Random; 009 import java.util.UUID; 010 011 import net.minecraft.block.Block; 012 import net.minecraft.block.BlockFluid; 013 import net.minecraft.block.StepSound; 014 import net.minecraft.block.material.Material; 015 import net.minecraft.crash.CrashReport; 016 import net.minecraft.crash.CrashReportCategory; 017 import net.minecraft.enchantment.EnchantmentProtection; 018 import net.minecraft.entity.effect.EntityLightningBolt; 019 import net.minecraft.entity.item.EntityBoat; 020 import net.minecraft.entity.item.EntityItem; 021 import net.minecraft.entity.item.EntityItemFrame; 022 import net.minecraft.entity.item.EntityMinecart; 023 import net.minecraft.entity.item.EntityPainting; 024 import net.minecraft.entity.player.EntityPlayer; 025 import net.minecraft.item.Item; 026 import net.minecraft.item.ItemStack; 027 import net.minecraft.nbt.NBTTagCompound; 028 import net.minecraft.nbt.NBTTagDouble; 029 import net.minecraft.nbt.NBTTagFloat; 030 import net.minecraft.nbt.NBTTagList; 031 import net.minecraft.server.MinecraftServer; 032 import net.minecraft.util.AxisAlignedBB; 033 import net.minecraft.util.DamageSource; 034 import net.minecraft.util.Direction; 035 import net.minecraft.util.MathHelper; 036 import net.minecraft.util.MovingObjectPosition; 037 import net.minecraft.util.ReportedException; 038 import net.minecraft.util.StatCollector; 039 import net.minecraft.util.Vec3; 040 import net.minecraft.world.Explosion; 041 import net.minecraft.world.World; 042 import net.minecraft.world.WorldServer; 043 044 public abstract class Entity 045 { 046 private static int nextEntityID = 0; 047 public int entityId; 048 public double renderDistanceWeight; 049 050 /** 051 * Blocks entities from spawning when they do their AABB check to make sure the spot is clear of entities that can 052 * prevent spawning. 053 */ 054 public boolean preventEntitySpawning; 055 056 /** The entity that is riding this entity */ 057 public Entity riddenByEntity; 058 059 /** The entity we are currently riding */ 060 public Entity ridingEntity; 061 062 /** Reference to the World object. */ 063 public World worldObj; 064 public double prevPosX; 065 public double prevPosY; 066 public double prevPosZ; 067 068 /** Entity position X */ 069 public double posX; 070 071 /** Entity position Y */ 072 public double posY; 073 074 /** Entity position Z */ 075 public double posZ; 076 077 /** Entity motion X */ 078 public double motionX; 079 080 /** Entity motion Y */ 081 public double motionY; 082 083 /** Entity motion Z */ 084 public double motionZ; 085 086 /** Entity rotation Yaw */ 087 public float rotationYaw; 088 089 /** Entity rotation Pitch */ 090 public float rotationPitch; 091 public float prevRotationYaw; 092 public float prevRotationPitch; 093 094 /** Axis aligned bounding box. */ 095 public final AxisAlignedBB boundingBox; 096 public boolean onGround; 097 098 /** 099 * True if after a move this entity has collided with something on X- or Z-axis 100 */ 101 public boolean isCollidedHorizontally; 102 103 /** 104 * True if after a move this entity has collided with something on Y-axis 105 */ 106 public boolean isCollidedVertically; 107 108 /** 109 * True if after a move this entity has collided with something either vertically or horizontally 110 */ 111 public boolean isCollided; 112 public boolean velocityChanged; 113 protected boolean isInWeb; 114 public boolean field_70135_K; 115 116 /** 117 * Gets set by setDead, so this must be the flag whether an Entity is dead (inactive may be better term) 118 */ 119 public boolean isDead; 120 public float yOffset; 121 122 /** How wide this entity is considered to be */ 123 public float width; 124 125 /** How high this entity is considered to be */ 126 public float height; 127 128 /** The previous ticks distance walked multiplied by 0.6 */ 129 public float prevDistanceWalkedModified; 130 131 /** The distance walked multiplied by 0.6 */ 132 public float distanceWalkedModified; 133 public float field_82151_R; 134 public float fallDistance; 135 136 /** 137 * The distance that has to be exceeded in order to triger a new step sound and an onEntityWalking event on a block 138 */ 139 private int nextStepDistance; 140 141 /** 142 * The entity's X coordinate at the previous tick, used to calculate position during rendering routines 143 */ 144 public double lastTickPosX; 145 146 /** 147 * The entity's Y coordinate at the previous tick, used to calculate position during rendering routines 148 */ 149 public double lastTickPosY; 150 151 /** 152 * The entity's Z coordinate at the previous tick, used to calculate position during rendering routines 153 */ 154 public double lastTickPosZ; 155 public float ySize; 156 157 /** 158 * How high this entity can step up when running into a block to try to get over it (currently make note the entity 159 * will always step up this amount and not just the amount needed) 160 */ 161 public float stepHeight; 162 163 /** 164 * Whether this entity won't clip with collision or not (make note it won't disable gravity) 165 */ 166 public boolean noClip; 167 168 /** 169 * Reduces the velocity applied by entity collisions by the specified percent. 170 */ 171 public float entityCollisionReduction; 172 protected Random rand; 173 174 /** How many ticks has this entity had ran since being alive */ 175 public int ticksExisted; 176 177 /** 178 * The amount of ticks you have to stand inside of fire before be set on fire 179 */ 180 public int fireResistance; 181 private int fire; 182 183 /** 184 * Whether this entity is currently inside of water (if it handles water movement that is) 185 */ 186 protected boolean inWater; 187 188 /** 189 * Remaining time an entity will be "immune" to further damage after being hurt. 190 */ 191 public int hurtResistantTime; 192 private boolean firstUpdate; 193 @SideOnly(Side.CLIENT) 194 195 /** downloadable location of player's skin */ 196 public String skinUrl; 197 @SideOnly(Side.CLIENT) 198 199 /** downloadable location of player's cloak */ 200 public String cloakUrl; 201 protected boolean isImmuneToFire; 202 protected DataWatcher dataWatcher; 203 private double entityRiderPitchDelta; 204 private double entityRiderYawDelta; 205 206 /** Has this entity been added to the chunk its within */ 207 public boolean addedToChunk; 208 public int chunkCoordX; 209 public int chunkCoordY; 210 public int chunkCoordZ; 211 @SideOnly(Side.CLIENT) 212 public int serverPosX; 213 @SideOnly(Side.CLIENT) 214 public int serverPosY; 215 @SideOnly(Side.CLIENT) 216 public int serverPosZ; 217 218 /** 219 * Render entity even if it is outside the camera frustum. Only true in EntityFish for now. Used in RenderGlobal: 220 * render if ignoreFrustumCheck or in frustum. 221 */ 222 public boolean ignoreFrustumCheck; 223 public boolean isAirBorne; 224 public int timeUntilPortal; 225 226 /** Whether the entity is inside a Portal */ 227 protected boolean inPortal; 228 protected int field_82153_h; 229 230 /** Which dimension the player is in (-1 = the Nether, 0 = normal world) */ 231 public int dimension; 232 protected int field_82152_aq; 233 private boolean invulnerable; 234 public EnumEntitySize myEntitySize; 235 /** Forge: Used to store custom data for each entity. */ 236 private NBTTagCompound customEntityData; 237 public boolean captureDrops = false; 238 public ArrayList<EntityItem> capturedDrops = new ArrayList<EntityItem>(); 239 private UUID persistentID; 240 241 public Entity(World par1World) 242 { 243 this.entityId = nextEntityID++; 244 this.renderDistanceWeight = 1.0D; 245 this.preventEntitySpawning = false; 246 this.boundingBox = AxisAlignedBB.getBoundingBox(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D); 247 this.onGround = false; 248 this.isCollided = false; 249 this.velocityChanged = false; 250 this.field_70135_K = true; 251 this.isDead = false; 252 this.yOffset = 0.0F; 253 this.width = 0.6F; 254 this.height = 1.8F; 255 this.prevDistanceWalkedModified = 0.0F; 256 this.distanceWalkedModified = 0.0F; 257 this.field_82151_R = 0.0F; 258 this.fallDistance = 0.0F; 259 this.nextStepDistance = 1; 260 this.ySize = 0.0F; 261 this.stepHeight = 0.0F; 262 this.noClip = false; 263 this.entityCollisionReduction = 0.0F; 264 this.rand = new Random(); 265 this.ticksExisted = 0; 266 this.fireResistance = 1; 267 this.fire = 0; 268 this.inWater = false; 269 this.hurtResistantTime = 0; 270 this.firstUpdate = true; 271 this.isImmuneToFire = false; 272 this.dataWatcher = new DataWatcher(); 273 this.addedToChunk = false; 274 this.field_82152_aq = 0; 275 this.invulnerable = false; 276 this.myEntitySize = EnumEntitySize.SIZE_2; 277 this.worldObj = par1World; 278 this.setPosition(0.0D, 0.0D, 0.0D); 279 280 if (par1World != null) 281 { 282 this.dimension = par1World.provider.dimensionId; 283 } 284 285 this.dataWatcher.addObject(0, Byte.valueOf((byte)0)); 286 this.dataWatcher.addObject(1, Short.valueOf((short)300)); 287 this.entityInit(); 288 } 289 290 protected abstract void entityInit(); 291 292 public DataWatcher getDataWatcher() 293 { 294 return this.dataWatcher; 295 } 296 297 public boolean equals(Object par1Obj) 298 { 299 return par1Obj instanceof Entity ? ((Entity)par1Obj).entityId == this.entityId : false; 300 } 301 302 public int hashCode() 303 { 304 return this.entityId; 305 } 306 307 @SideOnly(Side.CLIENT) 308 309 /** 310 * Keeps moving the entity up so it isn't colliding with blocks and other requirements for this entity to be spawned 311 * (only actually used on players though its also on Entity) 312 */ 313 protected void preparePlayerToSpawn() 314 { 315 if (this.worldObj != null) 316 { 317 while (this.posY > 0.0D) 318 { 319 this.setPosition(this.posX, this.posY, this.posZ); 320 321 if (this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty()) 322 { 323 break; 324 } 325 326 ++this.posY; 327 } 328 329 this.motionX = this.motionY = this.motionZ = 0.0D; 330 this.rotationPitch = 0.0F; 331 } 332 } 333 334 /** 335 * Will get destroyed next tick. 336 */ 337 public void setDead() 338 { 339 this.isDead = true; 340 } 341 342 /** 343 * Sets the width and height of the entity. Args: width, height 344 */ 345 protected void setSize(float par1, float par2) 346 { 347 this.width = par1; 348 this.height = par2; 349 float var3 = par1 % 2.0F; 350 351 if ((double)var3 < 0.375D) 352 { 353 this.myEntitySize = EnumEntitySize.SIZE_1; 354 } 355 else if ((double)var3 < 0.75D) 356 { 357 this.myEntitySize = EnumEntitySize.SIZE_2; 358 } 359 else if ((double)var3 < 1.0D) 360 { 361 this.myEntitySize = EnumEntitySize.SIZE_3; 362 } 363 else if ((double)var3 < 1.375D) 364 { 365 this.myEntitySize = EnumEntitySize.SIZE_4; 366 } 367 else if ((double)var3 < 1.75D) 368 { 369 this.myEntitySize = EnumEntitySize.SIZE_5; 370 } 371 else 372 { 373 this.myEntitySize = EnumEntitySize.SIZE_6; 374 } 375 } 376 377 /** 378 * Sets the rotation of the entity 379 */ 380 protected void setRotation(float par1, float par2) 381 { 382 this.rotationYaw = par1 % 360.0F; 383 this.rotationPitch = par2 % 360.0F; 384 } 385 386 /** 387 * Sets the x,y,z of the entity from the given parameters. Also seems to set up a bounding box. 388 */ 389 public void setPosition(double par1, double par3, double par5) 390 { 391 this.posX = par1; 392 this.posY = par3; 393 this.posZ = par5; 394 float var7 = this.width / 2.0F; 395 float var8 = this.height; 396 this.boundingBox.setBounds(par1 - (double)var7, par3 - (double)this.yOffset + (double)this.ySize, par5 - (double)var7, par1 + (double)var7, par3 - (double)this.yOffset + (double)this.ySize + (double)var8, par5 + (double)var7); 397 } 398 399 @SideOnly(Side.CLIENT) 400 401 /** 402 * Adds par1*0.15 to the entity's yaw, and *subtracts* par2*0.15 from the pitch. Clamps pitch from -90 to 90. Both 403 * arguments in degrees. 404 */ 405 public void setAngles(float par1, float par2) 406 { 407 float var3 = this.rotationPitch; 408 float var4 = this.rotationYaw; 409 this.rotationYaw = (float)((double)this.rotationYaw + (double)par1 * 0.15D); 410 this.rotationPitch = (float)((double)this.rotationPitch - (double)par2 * 0.15D); 411 412 if (this.rotationPitch < -90.0F) 413 { 414 this.rotationPitch = -90.0F; 415 } 416 417 if (this.rotationPitch > 90.0F) 418 { 419 this.rotationPitch = 90.0F; 420 } 421 422 this.prevRotationPitch += this.rotationPitch - var3; 423 this.prevRotationYaw += this.rotationYaw - var4; 424 } 425 426 /** 427 * Called to update the entity's position/logic. 428 */ 429 public void onUpdate() 430 { 431 this.onEntityUpdate(); 432 } 433 434 /** 435 * Gets called every tick from main Entity class 436 */ 437 public void onEntityUpdate() 438 { 439 this.worldObj.theProfiler.startSection("entityBaseTick"); 440 441 if (this.ridingEntity != null && this.ridingEntity.isDead) 442 { 443 this.ridingEntity = null; 444 } 445 446 this.prevDistanceWalkedModified = this.distanceWalkedModified; 447 this.prevPosX = this.posX; 448 this.prevPosY = this.posY; 449 this.prevPosZ = this.posZ; 450 this.prevRotationPitch = this.rotationPitch; 451 this.prevRotationYaw = this.rotationYaw; 452 int var2; 453 454 if (!this.worldObj.isRemote && this.worldObj instanceof WorldServer) 455 { 456 this.worldObj.theProfiler.startSection("portal"); 457 MinecraftServer var1 = ((WorldServer)this.worldObj).getMinecraftServer(); 458 var2 = this.getMaxInPortalTime(); 459 460 if (this.inPortal) 461 { 462 if (var1.getAllowNether()) 463 { 464 if (this.ridingEntity == null && this.field_82153_h++ >= var2) 465 { 466 this.field_82153_h = var2; 467 this.timeUntilPortal = this.getPortalCooldown(); 468 byte var3; 469 470 if (this.worldObj.provider.dimensionId == -1) 471 { 472 var3 = 0; 473 } 474 else 475 { 476 var3 = -1; 477 } 478 479 this.travelToDimension(var3); 480 } 481 482 this.inPortal = false; 483 } 484 } 485 else 486 { 487 if (this.field_82153_h > 0) 488 { 489 this.field_82153_h -= 4; 490 } 491 492 if (this.field_82153_h < 0) 493 { 494 this.field_82153_h = 0; 495 } 496 } 497 498 if (this.timeUntilPortal > 0) 499 { 500 --this.timeUntilPortal; 501 } 502 503 this.worldObj.theProfiler.endSection(); 504 } 505 506 if (this.isSprinting() && !this.isInWater()) 507 { 508 int var5 = MathHelper.floor_double(this.posX); 509 var2 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset); 510 int var6 = MathHelper.floor_double(this.posZ); 511 int var4 = this.worldObj.getBlockId(var5, var2, var6); 512 513 if (var4 > 0) 514 { 515 this.worldObj.spawnParticle("tilecrack_" + var4 + "_" + this.worldObj.getBlockMetadata(var5, var2, var6), this.posX + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, this.boundingBox.minY + 0.1D, this.posZ + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, -this.motionX * 4.0D, 1.5D, -this.motionZ * 4.0D); 516 } 517 } 518 519 this.handleWaterMovement(); 520 521 if (this.worldObj.isRemote) 522 { 523 this.fire = 0; 524 } 525 else if (this.fire > 0) 526 { 527 if (this.isImmuneToFire) 528 { 529 this.fire -= 4; 530 531 if (this.fire < 0) 532 { 533 this.fire = 0; 534 } 535 } 536 else 537 { 538 if (this.fire % 20 == 0) 539 { 540 this.attackEntityFrom(DamageSource.onFire, 1); 541 } 542 543 --this.fire; 544 } 545 } 546 547 if (this.handleLavaMovement()) 548 { 549 this.setOnFireFromLava(); 550 this.fallDistance *= 0.5F; 551 } 552 553 if (this.posY < -64.0D) 554 { 555 this.kill(); 556 } 557 558 if (!this.worldObj.isRemote) 559 { 560 this.setFlag(0, this.fire > 0); 561 this.setFlag(2, this.ridingEntity != null && ridingEntity.shouldRiderSit()); 562 } 563 564 this.firstUpdate = false; 565 this.worldObj.theProfiler.endSection(); 566 } 567 568 /** 569 * Return the amount of time this entity should stay in a portal before being transported. 570 */ 571 public int getMaxInPortalTime() 572 { 573 return 0; 574 } 575 576 /** 577 * Called whenever the entity is walking inside of lava. 578 */ 579 protected void setOnFireFromLava() 580 { 581 if (!this.isImmuneToFire) 582 { 583 this.attackEntityFrom(DamageSource.lava, 4); 584 this.setFire(15); 585 } 586 } 587 588 /** 589 * Sets entity to burn for x amount of seconds, cannot lower amount of existing fire. 590 */ 591 public void setFire(int par1) 592 { 593 int var2 = par1 * 20; 594 var2 = EnchantmentProtection.func_92041_a(this, var2); 595 596 if (this.fire < var2) 597 { 598 this.fire = var2; 599 } 600 } 601 602 /** 603 * Removes fire from entity. 604 */ 605 public void extinguish() 606 { 607 this.fire = 0; 608 } 609 610 /** 611 * sets the dead flag. Used when you fall off the bottom of the world. 612 */ 613 protected void kill() 614 { 615 this.setDead(); 616 } 617 618 /** 619 * Checks if the offset position from the entity's current position is inside of liquid. Args: x, y, z 620 */ 621 public boolean isOffsetPositionInLiquid(double par1, double par3, double par5) 622 { 623 AxisAlignedBB var7 = this.boundingBox.getOffsetBoundingBox(par1, par3, par5); 624 List var8 = this.worldObj.getCollidingBoundingBoxes(this, var7); 625 return !var8.isEmpty() ? false : !this.worldObj.isAnyLiquid(var7); 626 } 627 628 /** 629 * Tries to moves the entity by the passed in displacement. Args: x, y, z 630 */ 631 public void moveEntity(double par1, double par3, double par5) 632 { 633 if (this.noClip) 634 { 635 this.boundingBox.offset(par1, par3, par5); 636 this.posX = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0D; 637 this.posY = this.boundingBox.minY + (double)this.yOffset - (double)this.ySize; 638 this.posZ = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0D; 639 } 640 else 641 { 642 this.worldObj.theProfiler.startSection("move"); 643 this.ySize *= 0.4F; 644 double var7 = this.posX; 645 double var9 = this.posY; 646 double var11 = this.posZ; 647 648 if (this.isInWeb) 649 { 650 this.isInWeb = false; 651 par1 *= 0.25D; 652 par3 *= 0.05000000074505806D; 653 par5 *= 0.25D; 654 this.motionX = 0.0D; 655 this.motionY = 0.0D; 656 this.motionZ = 0.0D; 657 } 658 659 double var13 = par1; 660 double var15 = par3; 661 double var17 = par5; 662 AxisAlignedBB var19 = this.boundingBox.copy(); 663 boolean var20 = this.onGround && this.isSneaking() && this instanceof EntityPlayer; 664 665 if (var20) 666 { 667 double var21; 668 669 for (var21 = 0.05D; par1 != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(par1, -1.0D, 0.0D)).isEmpty(); var13 = par1) 670 { 671 if (par1 < var21 && par1 >= -var21) 672 { 673 par1 = 0.0D; 674 } 675 else if (par1 > 0.0D) 676 { 677 par1 -= var21; 678 } 679 else 680 { 681 par1 += var21; 682 } 683 } 684 685 for (; par5 != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(0.0D, -1.0D, par5)).isEmpty(); var17 = par5) 686 { 687 if (par5 < var21 && par5 >= -var21) 688 { 689 par5 = 0.0D; 690 } 691 else if (par5 > 0.0D) 692 { 693 par5 -= var21; 694 } 695 else 696 { 697 par5 += var21; 698 } 699 } 700 701 while (par1 != 0.0D && par5 != 0.0D && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.getOffsetBoundingBox(par1, -1.0D, par5)).isEmpty()) 702 { 703 if (par1 < var21 && par1 >= -var21) 704 { 705 par1 = 0.0D; 706 } 707 else if (par1 > 0.0D) 708 { 709 par1 -= var21; 710 } 711 else 712 { 713 par1 += var21; 714 } 715 716 if (par5 < var21 && par5 >= -var21) 717 { 718 par5 = 0.0D; 719 } 720 else if (par5 > 0.0D) 721 { 722 par5 -= var21; 723 } 724 else 725 { 726 par5 += var21; 727 } 728 729 var13 = par1; 730 var17 = par5; 731 } 732 } 733 734 List var35 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.addCoord(par1, par3, par5)); 735 736 for (int var22 = 0; var22 < var35.size(); ++var22) 737 { 738 par3 = ((AxisAlignedBB)var35.get(var22)).calculateYOffset(this.boundingBox, par3); 739 } 740 741 this.boundingBox.offset(0.0D, par3, 0.0D); 742 743 if (!this.field_70135_K && var15 != par3) 744 { 745 par5 = 0.0D; 746 par3 = 0.0D; 747 par1 = 0.0D; 748 } 749 750 boolean var34 = this.onGround || var15 != par3 && var15 < 0.0D; 751 int var23; 752 753 for (var23 = 0; var23 < var35.size(); ++var23) 754 { 755 par1 = ((AxisAlignedBB)var35.get(var23)).calculateXOffset(this.boundingBox, par1); 756 } 757 758 this.boundingBox.offset(par1, 0.0D, 0.0D); 759 760 if (!this.field_70135_K && var13 != par1) 761 { 762 par5 = 0.0D; 763 par3 = 0.0D; 764 par1 = 0.0D; 765 } 766 767 for (var23 = 0; var23 < var35.size(); ++var23) 768 { 769 par5 = ((AxisAlignedBB)var35.get(var23)).calculateZOffset(this.boundingBox, par5); 770 } 771 772 this.boundingBox.offset(0.0D, 0.0D, par5); 773 774 if (!this.field_70135_K && var17 != par5) 775 { 776 par5 = 0.0D; 777 par3 = 0.0D; 778 par1 = 0.0D; 779 } 780 781 double var25; 782 double var27; 783 int var30; 784 double var36; 785 786 if (this.stepHeight > 0.0F && var34 && (var20 || this.ySize < 0.05F) && (var13 != par1 || var17 != par5)) 787 { 788 var36 = par1; 789 var25 = par3; 790 var27 = par5; 791 par1 = var13; 792 par3 = (double)this.stepHeight; 793 par5 = var17; 794 AxisAlignedBB var29 = this.boundingBox.copy(); 795 this.boundingBox.setBB(var19); 796 var35 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.addCoord(var13, par3, var17)); 797 798 for (var30 = 0; var30 < var35.size(); ++var30) 799 { 800 par3 = ((AxisAlignedBB)var35.get(var30)).calculateYOffset(this.boundingBox, par3); 801 } 802 803 this.boundingBox.offset(0.0D, par3, 0.0D); 804 805 if (!this.field_70135_K && var15 != par3) 806 { 807 par5 = 0.0D; 808 par3 = 0.0D; 809 par1 = 0.0D; 810 } 811 812 for (var30 = 0; var30 < var35.size(); ++var30) 813 { 814 par1 = ((AxisAlignedBB)var35.get(var30)).calculateXOffset(this.boundingBox, par1); 815 } 816 817 this.boundingBox.offset(par1, 0.0D, 0.0D); 818 819 if (!this.field_70135_K && var13 != par1) 820 { 821 par5 = 0.0D; 822 par3 = 0.0D; 823 par1 = 0.0D; 824 } 825 826 for (var30 = 0; var30 < var35.size(); ++var30) 827 { 828 par5 = ((AxisAlignedBB)var35.get(var30)).calculateZOffset(this.boundingBox, par5); 829 } 830 831 this.boundingBox.offset(0.0D, 0.0D, par5); 832 833 if (!this.field_70135_K && var17 != par5) 834 { 835 par5 = 0.0D; 836 par3 = 0.0D; 837 par1 = 0.0D; 838 } 839 840 if (!this.field_70135_K && var15 != par3) 841 { 842 par5 = 0.0D; 843 par3 = 0.0D; 844 par1 = 0.0D; 845 } 846 else 847 { 848 par3 = (double)(-this.stepHeight); 849 850 for (var30 = 0; var30 < var35.size(); ++var30) 851 { 852 par3 = ((AxisAlignedBB)var35.get(var30)).calculateYOffset(this.boundingBox, par3); 853 } 854 855 this.boundingBox.offset(0.0D, par3, 0.0D); 856 } 857 858 if (var36 * var36 + var27 * var27 >= par1 * par1 + par5 * par5) 859 { 860 par1 = var36; 861 par3 = var25; 862 par5 = var27; 863 this.boundingBox.setBB(var29); 864 } 865 /* Fixes a vanilla bug where the player view would dip when stepping between certain blocks 866 * https://mojang.atlassian.net/browse/MC-1594 867 else 868 { 869 double var40 = this.boundingBox.minY - (double)((int)this.boundingBox.minY); 870 871 if (var40 > 0.0D) 872 { 873 this.ySize = (float)((double)this.ySize + var40 + 0.01D); 874 } 875 } 876 */ 877 } 878 879 this.worldObj.theProfiler.endSection(); 880 this.worldObj.theProfiler.startSection("rest"); 881 this.posX = (this.boundingBox.minX + this.boundingBox.maxX) / 2.0D; 882 this.posY = this.boundingBox.minY + (double)this.yOffset - (double)this.ySize; 883 this.posZ = (this.boundingBox.minZ + this.boundingBox.maxZ) / 2.0D; 884 this.isCollidedHorizontally = var13 != par1 || var17 != par5; 885 this.isCollidedVertically = var15 != par3; 886 this.onGround = var15 != par3 && var15 < 0.0D; 887 this.isCollided = this.isCollidedHorizontally || this.isCollidedVertically; 888 this.updateFallState(par3, this.onGround); 889 890 if (var13 != par1) 891 { 892 this.motionX = 0.0D; 893 } 894 895 if (var15 != par3) 896 { 897 this.motionY = 0.0D; 898 } 899 900 if (var17 != par5) 901 { 902 this.motionZ = 0.0D; 903 } 904 905 var36 = this.posX - var7; 906 var25 = this.posY - var9; 907 var27 = this.posZ - var11; 908 909 if (this.canTriggerWalking() && !var20 && this.ridingEntity == null) 910 { 911 int var37 = MathHelper.floor_double(this.posX); 912 var30 = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset); 913 int var31 = MathHelper.floor_double(this.posZ); 914 int var32 = this.worldObj.getBlockId(var37, var30, var31); 915 916 if (var32 == 0) 917 { 918 int var33 = this.worldObj.func_85175_e(var37, var30 - 1, var31); 919 920 if (var33 == 11 || var33 == 32 || var33 == 21) 921 { 922 var32 = this.worldObj.getBlockId(var37, var30 - 1, var31); 923 } 924 } 925 926 if (var32 != Block.ladder.blockID) 927 { 928 var25 = 0.0D; 929 } 930 931 this.distanceWalkedModified = (float)((double)this.distanceWalkedModified + (double)MathHelper.sqrt_double(var36 * var36 + var27 * var27) * 0.6D); 932 this.field_82151_R = (float)((double)this.field_82151_R + (double)MathHelper.sqrt_double(var36 * var36 + var25 * var25 + var27 * var27) * 0.6D); 933 934 if (this.field_82151_R > (float)this.nextStepDistance && var32 > 0) 935 { 936 this.nextStepDistance = (int)this.field_82151_R + 1; 937 938 if (this.isInWater()) 939 { 940 float var39 = MathHelper.sqrt_double(this.motionX * this.motionX * 0.20000000298023224D + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D) * 0.35F; 941 942 if (var39 > 1.0F) 943 { 944 var39 = 1.0F; 945 } 946 947 this.playSound("liquid.swim", var39, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F); 948 } 949 950 this.playStepSound(var37, var30, var31, var32); 951 Block.blocksList[var32].onEntityWalking(this.worldObj, var37, var30, var31, this); 952 } 953 } 954 955 this.doBlockCollisions(); 956 boolean var38 = this.isWet(); 957 958 if (this.worldObj.isBoundingBoxBurning(this.boundingBox.contract(0.001D, 0.001D, 0.001D))) 959 { 960 this.dealFireDamage(1); 961 962 if (!var38) 963 { 964 ++this.fire; 965 966 if (this.fire == 0) 967 { 968 this.setFire(8); 969 } 970 } 971 } 972 else if (this.fire <= 0) 973 { 974 this.fire = -this.fireResistance; 975 } 976 977 if (var38 && this.fire > 0) 978 { 979 this.playSound("random.fizz", 0.7F, 1.6F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F); 980 this.fire = -this.fireResistance; 981 } 982 983 this.worldObj.theProfiler.endSection(); 984 } 985 } 986 987 /** 988 * Checks for block collisions, and calls the associated onBlockCollided method for the collided block. 989 */ 990 protected void doBlockCollisions() 991 { 992 int var1 = MathHelper.floor_double(this.boundingBox.minX + 0.001D); 993 int var2 = MathHelper.floor_double(this.boundingBox.minY + 0.001D); 994 int var3 = MathHelper.floor_double(this.boundingBox.minZ + 0.001D); 995 int var4 = MathHelper.floor_double(this.boundingBox.maxX - 0.001D); 996 int var5 = MathHelper.floor_double(this.boundingBox.maxY - 0.001D); 997 int var6 = MathHelper.floor_double(this.boundingBox.maxZ - 0.001D); 998 999 if (this.worldObj.checkChunksExist(var1, var2, var3, var4, var5, var6)) 1000 { 1001 for (int var7 = var1; var7 <= var4; ++var7) 1002 { 1003 for (int var8 = var2; var8 <= var5; ++var8) 1004 { 1005 for (int var9 = var3; var9 <= var6; ++var9) 1006 { 1007 int var10 = this.worldObj.getBlockId(var7, var8, var9); 1008 1009 if (var10 > 0) 1010 { 1011 Block.blocksList[var10].onEntityCollidedWithBlock(this.worldObj, var7, var8, var9, this); 1012 } 1013 } 1014 } 1015 } 1016 } 1017 } 1018 1019 /** 1020 * Plays step sound at given x, y, z for the entity 1021 */ 1022 protected void playStepSound(int par1, int par2, int par3, int par4) 1023 { 1024 StepSound var5 = Block.blocksList[par4].stepSound; 1025 1026 if (this.worldObj.getBlockId(par1, par2 + 1, par3) == Block.snow.blockID) 1027 { 1028 var5 = Block.snow.stepSound; 1029 this.playSound(var5.getStepSound(), var5.getVolume() * 0.15F, var5.getPitch()); 1030 } 1031 else if (!Block.blocksList[par4].blockMaterial.isLiquid()) 1032 { 1033 this.playSound(var5.getStepSound(), var5.getVolume() * 0.15F, var5.getPitch()); 1034 } 1035 } 1036 1037 public void playSound(String par1Str, float par2, float par3) 1038 { 1039 this.worldObj.playSoundAtEntity(this, par1Str, par2, par3); 1040 } 1041 1042 /** 1043 * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to 1044 * prevent them from trampling crops 1045 */ 1046 protected boolean canTriggerWalking() 1047 { 1048 return true; 1049 } 1050 1051 /** 1052 * Takes in the distance the entity has fallen this tick and whether its on the ground to update the fall distance 1053 * and deal fall damage if landing on the ground. Args: distanceFallenThisTick, onGround 1054 */ 1055 protected void updateFallState(double par1, boolean par3) 1056 { 1057 if (par3) 1058 { 1059 if (this.fallDistance > 0.0F) 1060 { 1061 this.fall(this.fallDistance); 1062 this.fallDistance = 0.0F; 1063 } 1064 } 1065 else if (par1 < 0.0D) 1066 { 1067 this.fallDistance = (float)((double)this.fallDistance - par1); 1068 } 1069 } 1070 1071 /** 1072 * returns the bounding box for this entity 1073 */ 1074 public AxisAlignedBB getBoundingBox() 1075 { 1076 return null; 1077 } 1078 1079 /** 1080 * Will deal the specified amount of damage to the entity if the entity isn't immune to fire damage. Args: 1081 * amountDamage 1082 */ 1083 protected void dealFireDamage(int par1) 1084 { 1085 if (!this.isImmuneToFire) 1086 { 1087 this.attackEntityFrom(DamageSource.inFire, par1); 1088 } 1089 } 1090 1091 public final boolean isImmuneToFire() 1092 { 1093 return this.isImmuneToFire; 1094 } 1095 1096 /** 1097 * Called when the mob is falling. Calculates and applies fall damage. 1098 */ 1099 protected void fall(float par1) 1100 { 1101 if (this.riddenByEntity != null) 1102 { 1103 this.riddenByEntity.fall(par1); 1104 } 1105 } 1106 1107 /** 1108 * Checks if this entity is either in water or on an open air block in rain (used in wolves). 1109 */ 1110 public boolean isWet() 1111 { 1112 return this.inWater || this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) || this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY + (double)this.height), MathHelper.floor_double(this.posZ)); 1113 } 1114 1115 /** 1116 * Checks if this entity is inside water (if inWater field is true as a result of handleWaterMovement() returning 1117 * true) 1118 */ 1119 public boolean isInWater() 1120 { 1121 return this.inWater; 1122 } 1123 1124 /** 1125 * Returns if this entity is in water and will end up adding the waters velocity to the entity 1126 */ 1127 public boolean handleWaterMovement() 1128 { 1129 if (this.worldObj.handleMaterialAcceleration(this.boundingBox.expand(0.0D, -0.4000000059604645D, 0.0D).contract(0.001D, 0.001D, 0.001D), Material.water, this)) 1130 { 1131 if (!this.inWater && !this.firstUpdate) 1132 { 1133 float var1 = MathHelper.sqrt_double(this.motionX * this.motionX * 0.20000000298023224D + this.motionY * this.motionY + this.motionZ * this.motionZ * 0.20000000298023224D) * 0.2F; 1134 1135 if (var1 > 1.0F) 1136 { 1137 var1 = 1.0F; 1138 } 1139 1140 this.playSound("liquid.splash", var1, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F); 1141 float var2 = (float)MathHelper.floor_double(this.boundingBox.minY); 1142 int var3; 1143 float var4; 1144 float var5; 1145 1146 for (var3 = 0; (float)var3 < 1.0F + this.width * 20.0F; ++var3) 1147 { 1148 var4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width; 1149 var5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width; 1150 this.worldObj.spawnParticle("bubble", this.posX + (double)var4, (double)(var2 + 1.0F), this.posZ + (double)var5, this.motionX, this.motionY - (double)(this.rand.nextFloat() * 0.2F), this.motionZ); 1151 } 1152 1153 for (var3 = 0; (float)var3 < 1.0F + this.width * 20.0F; ++var3) 1154 { 1155 var4 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width; 1156 var5 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width; 1157 this.worldObj.spawnParticle("splash", this.posX + (double)var4, (double)(var2 + 1.0F), this.posZ + (double)var5, this.motionX, this.motionY, this.motionZ); 1158 } 1159 } 1160 1161 this.fallDistance = 0.0F; 1162 this.inWater = true; 1163 this.fire = 0; 1164 } 1165 else 1166 { 1167 this.inWater = false; 1168 } 1169 1170 return this.inWater; 1171 } 1172 1173 /** 1174 * Checks if the current block the entity is within of the specified material type 1175 */ 1176 public boolean isInsideOfMaterial(Material par1Material) 1177 { 1178 double var2 = this.posY + (double)this.getEyeHeight(); 1179 int var4 = MathHelper.floor_double(this.posX); 1180 int var5 = MathHelper.floor_float((float)MathHelper.floor_double(var2)); 1181 int var6 = MathHelper.floor_double(this.posZ); 1182 int var7 = this.worldObj.getBlockId(var4, var5, var6); 1183 1184 if (var7 != 0 && Block.blocksList[var7].blockMaterial == par1Material) 1185 { 1186 float var8 = BlockFluid.getFluidHeightPercent(this.worldObj.getBlockMetadata(var4, var5, var6)) - 0.11111111F; 1187 float var9 = (float)(var5 + 1) - var8; 1188 return var2 < (double)var9; 1189 } 1190 else 1191 { 1192 return false; 1193 } 1194 } 1195 1196 public float getEyeHeight() 1197 { 1198 return 0.0F; 1199 } 1200 1201 /** 1202 * Whether or not the current entity is in lava 1203 */ 1204 public boolean handleLavaMovement() 1205 { 1206 return this.worldObj.isMaterialInBB(this.boundingBox.expand(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), Material.lava); 1207 } 1208 1209 /** 1210 * Used in both water and by flying objects 1211 */ 1212 public void moveFlying(float par1, float par2, float par3) 1213 { 1214 float var4 = par1 * par1 + par2 * par2; 1215 1216 if (var4 >= 1.0E-4F) 1217 { 1218 var4 = MathHelper.sqrt_float(var4); 1219 1220 if (var4 < 1.0F) 1221 { 1222 var4 = 1.0F; 1223 } 1224 1225 var4 = par3 / var4; 1226 par1 *= var4; 1227 par2 *= var4; 1228 float var5 = MathHelper.sin(this.rotationYaw * (float)Math.PI / 180.0F); 1229 float var6 = MathHelper.cos(this.rotationYaw * (float)Math.PI / 180.0F); 1230 this.motionX += (double)(par1 * var6 - par2 * var5); 1231 this.motionZ += (double)(par2 * var6 + par1 * var5); 1232 } 1233 } 1234 1235 @SideOnly(Side.CLIENT) 1236 public int getBrightnessForRender(float par1) 1237 { 1238 int var2 = MathHelper.floor_double(this.posX); 1239 int var3 = MathHelper.floor_double(this.posZ); 1240 1241 if (this.worldObj.blockExists(var2, 0, var3)) 1242 { 1243 double var4 = (this.boundingBox.maxY - this.boundingBox.minY) * 0.66D; 1244 int var6 = MathHelper.floor_double(this.posY - (double)this.yOffset + var4); 1245 return this.worldObj.getLightBrightnessForSkyBlocks(var2, var6, var3, 0); 1246 } 1247 else 1248 { 1249 return 0; 1250 } 1251 } 1252 1253 /** 1254 * Gets how bright this entity is. 1255 */ 1256 public float getBrightness(float par1) 1257 { 1258 int var2 = MathHelper.floor_double(this.posX); 1259 int var3 = MathHelper.floor_double(this.posZ); 1260 1261 if (this.worldObj.blockExists(var2, 0, var3)) 1262 { 1263 double var4 = (this.boundingBox.maxY - this.boundingBox.minY) * 0.66D; 1264 int var6 = MathHelper.floor_double(this.posY - (double)this.yOffset + var4); 1265 return this.worldObj.getLightBrightness(var2, var6, var3); 1266 } 1267 else 1268 { 1269 return 0.0F; 1270 } 1271 } 1272 1273 /** 1274 * Sets the reference to the World object. 1275 */ 1276 public void setWorld(World par1World) 1277 { 1278 this.worldObj = par1World; 1279 } 1280 1281 /** 1282 * Sets the entity's position and rotation. Args: posX, posY, posZ, yaw, pitch 1283 */ 1284 public void setPositionAndRotation(double par1, double par3, double par5, float par7, float par8) 1285 { 1286 this.prevPosX = this.posX = par1; 1287 this.prevPosY = this.posY = par3; 1288 this.prevPosZ = this.posZ = par5; 1289 this.prevRotationYaw = this.rotationYaw = par7; 1290 this.prevRotationPitch = this.rotationPitch = par8; 1291 this.ySize = 0.0F; 1292 double var9 = (double)(this.prevRotationYaw - par7); 1293 1294 if (var9 < -180.0D) 1295 { 1296 this.prevRotationYaw += 360.0F; 1297 } 1298 1299 if (var9 >= 180.0D) 1300 { 1301 this.prevRotationYaw -= 360.0F; 1302 } 1303 1304 this.setPosition(this.posX, this.posY, this.posZ); 1305 this.setRotation(par7, par8); 1306 } 1307 1308 /** 1309 * Sets the location and Yaw/Pitch of an entity in the world 1310 */ 1311 public void setLocationAndAngles(double par1, double par3, double par5, float par7, float par8) 1312 { 1313 this.lastTickPosX = this.prevPosX = this.posX = par1; 1314 this.lastTickPosY = this.prevPosY = this.posY = par3 + (double)this.yOffset; 1315 this.lastTickPosZ = this.prevPosZ = this.posZ = par5; 1316 this.rotationYaw = par7; 1317 this.rotationPitch = par8; 1318 this.setPosition(this.posX, this.posY, this.posZ); 1319 } 1320 1321 /** 1322 * Returns the distance to the entity. Args: entity 1323 */ 1324 public float getDistanceToEntity(Entity par1Entity) 1325 { 1326 float var2 = (float)(this.posX - par1Entity.posX); 1327 float var3 = (float)(this.posY - par1Entity.posY); 1328 float var4 = (float)(this.posZ - par1Entity.posZ); 1329 return MathHelper.sqrt_float(var2 * var2 + var3 * var3 + var4 * var4); 1330 } 1331 1332 /** 1333 * Gets the squared distance to the position. Args: x, y, z 1334 */ 1335 public double getDistanceSq(double par1, double par3, double par5) 1336 { 1337 double var7 = this.posX - par1; 1338 double var9 = this.posY - par3; 1339 double var11 = this.posZ - par5; 1340 return var7 * var7 + var9 * var9 + var11 * var11; 1341 } 1342 1343 /** 1344 * Gets the distance to the position. Args: x, y, z 1345 */ 1346 public double getDistance(double par1, double par3, double par5) 1347 { 1348 double var7 = this.posX - par1; 1349 double var9 = this.posY - par3; 1350 double var11 = this.posZ - par5; 1351 return (double)MathHelper.sqrt_double(var7 * var7 + var9 * var9 + var11 * var11); 1352 } 1353 1354 /** 1355 * Returns the squared distance to the entity. Args: entity 1356 */ 1357 public double getDistanceSqToEntity(Entity par1Entity) 1358 { 1359 double var2 = this.posX - par1Entity.posX; 1360 double var4 = this.posY - par1Entity.posY; 1361 double var6 = this.posZ - par1Entity.posZ; 1362 return var2 * var2 + var4 * var4 + var6 * var6; 1363 } 1364 1365 /** 1366 * Called by a player entity when they collide with an entity 1367 */ 1368 public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {} 1369 1370 /** 1371 * Applies a velocity to each of the entities pushing them away from each other. Args: entity 1372 */ 1373 public void applyEntityCollision(Entity par1Entity) 1374 { 1375 if (par1Entity.riddenByEntity != this && par1Entity.ridingEntity != this) 1376 { 1377 double var2 = par1Entity.posX - this.posX; 1378 double var4 = par1Entity.posZ - this.posZ; 1379 double var6 = MathHelper.abs_max(var2, var4); 1380 1381 if (var6 >= 0.009999999776482582D) 1382 { 1383 var6 = (double)MathHelper.sqrt_double(var6); 1384 var2 /= var6; 1385 var4 /= var6; 1386 double var8 = 1.0D / var6; 1387 1388 if (var8 > 1.0D) 1389 { 1390 var8 = 1.0D; 1391 } 1392 1393 var2 *= var8; 1394 var4 *= var8; 1395 var2 *= 0.05000000074505806D; 1396 var4 *= 0.05000000074505806D; 1397 var2 *= (double)(1.0F - this.entityCollisionReduction); 1398 var4 *= (double)(1.0F - this.entityCollisionReduction); 1399 this.addVelocity(-var2, 0.0D, -var4); 1400 par1Entity.addVelocity(var2, 0.0D, var4); 1401 } 1402 } 1403 } 1404 1405 /** 1406 * Adds to the current velocity of the entity. Args: x, y, z 1407 */ 1408 public void addVelocity(double par1, double par3, double par5) 1409 { 1410 this.motionX += par1; 1411 this.motionY += par3; 1412 this.motionZ += par5; 1413 this.isAirBorne = true; 1414 } 1415 1416 /** 1417 * Sets that this entity has been attacked. 1418 */ 1419 protected void setBeenAttacked() 1420 { 1421 this.velocityChanged = true; 1422 } 1423 1424 /** 1425 * Called when the entity is attacked. 1426 */ 1427 public boolean attackEntityFrom(DamageSource par1DamageSource, int par2) 1428 { 1429 if (this.isEntityInvulnerable()) 1430 { 1431 return false; 1432 } 1433 else 1434 { 1435 this.setBeenAttacked(); 1436 return false; 1437 } 1438 } 1439 1440 /** 1441 * Returns true if other Entities should be prevented from moving through this Entity. 1442 */ 1443 public boolean canBeCollidedWith() 1444 { 1445 return false; 1446 } 1447 1448 /** 1449 * Returns true if this entity should push and be pushed by other entities when colliding. 1450 */ 1451 public boolean canBePushed() 1452 { 1453 return false; 1454 } 1455 1456 /** 1457 * Adds a value to the player score. Currently not actually used and the entity passed in does nothing. Args: 1458 * entity, scoreToAdd 1459 */ 1460 public void addToPlayerScore(Entity par1Entity, int par2) {} 1461 1462 /** 1463 * adds the ID of this entity to the NBT given 1464 */ 1465 public boolean addEntityID(NBTTagCompound par1NBTTagCompound) 1466 { 1467 String var2 = this.getEntityString(); 1468 1469 if (!this.isDead && var2 != null) 1470 { 1471 par1NBTTagCompound.setString("id", var2); 1472 this.writeToNBT(par1NBTTagCompound); 1473 return true; 1474 } 1475 else 1476 { 1477 return false; 1478 } 1479 } 1480 1481 @SideOnly(Side.CLIENT) 1482 1483 /** 1484 * Checks using a Vec3d to determine if this entity is within range of that vector to be rendered. Args: vec3D 1485 */ 1486 public boolean isInRangeToRenderVec3D(Vec3 par1Vec3) 1487 { 1488 double var2 = this.posX - par1Vec3.xCoord; 1489 double var4 = this.posY - par1Vec3.yCoord; 1490 double var6 = this.posZ - par1Vec3.zCoord; 1491 double var8 = var2 * var2 + var4 * var4 + var6 * var6; 1492 return this.isInRangeToRenderDist(var8); 1493 } 1494 1495 @SideOnly(Side.CLIENT) 1496 1497 /** 1498 * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge 1499 * length * 64 * renderDistanceWeight Args: distance 1500 */ 1501 public boolean isInRangeToRenderDist(double par1) 1502 { 1503 double var3 = this.boundingBox.getAverageEdgeLength(); 1504 var3 *= 64.0D * this.renderDistanceWeight; 1505 return par1 < var3 * var3; 1506 } 1507 1508 @SideOnly(Side.CLIENT) 1509 1510 /** 1511 * Returns the texture's file path as a String. 1512 */ 1513 public String getTexture() 1514 { 1515 return null; 1516 } 1517 1518 /** 1519 * Save the entity to NBT (calls an abstract helper method to write extra data) 1520 */ 1521 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 1522 { 1523 try 1524 { 1525 par1NBTTagCompound.setTag("Pos", this.newDoubleNBTList(new double[] {this.posX, this.posY + (double)this.ySize, this.posZ})); 1526 par1NBTTagCompound.setTag("Motion", this.newDoubleNBTList(new double[] {this.motionX, this.motionY, this.motionZ})); 1527 par1NBTTagCompound.setTag("Rotation", this.newFloatNBTList(new float[] {this.rotationYaw, this.rotationPitch})); 1528 par1NBTTagCompound.setFloat("FallDistance", this.fallDistance); 1529 par1NBTTagCompound.setShort("Fire", (short)this.fire); 1530 par1NBTTagCompound.setShort("Air", (short)this.getAir()); 1531 par1NBTTagCompound.setBoolean("OnGround", this.onGround); 1532 par1NBTTagCompound.setInteger("Dimension", this.dimension); 1533 par1NBTTagCompound.setBoolean("Invulnerable", this.invulnerable); 1534 par1NBTTagCompound.setInteger("PortalCooldown", this.timeUntilPortal); 1535 if (persistentID != null) 1536 { 1537 par1NBTTagCompound.setLong("PersistentIDMSB", persistentID.getMostSignificantBits()); 1538 par1NBTTagCompound.setLong("PersistentIDLSB", persistentID.getLeastSignificantBits()); 1539 } 1540 if (customEntityData != null) 1541 { 1542 par1NBTTagCompound.setCompoundTag("ForgeData", customEntityData); 1543 } 1544 this.writeEntityToNBT(par1NBTTagCompound); 1545 } 1546 catch (Throwable var5) 1547 { 1548 CrashReport var3 = CrashReport.makeCrashReport(var5, "Saving entity NBT"); 1549 CrashReportCategory var4 = var3.makeCategory("Entity being saved"); 1550 this.func_85029_a(var4); 1551 throw new ReportedException(var3); 1552 } 1553 } 1554 1555 /** 1556 * Reads the entity from NBT (calls an abstract helper method to read specialized data) 1557 */ 1558 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 1559 { 1560 try 1561 { 1562 NBTTagList var2 = par1NBTTagCompound.getTagList("Pos"); 1563 NBTTagList var6 = par1NBTTagCompound.getTagList("Motion"); 1564 NBTTagList var7 = par1NBTTagCompound.getTagList("Rotation"); 1565 this.motionX = ((NBTTagDouble)var6.tagAt(0)).data; 1566 this.motionY = ((NBTTagDouble)var6.tagAt(1)).data; 1567 this.motionZ = ((NBTTagDouble)var6.tagAt(2)).data; 1568 1569 if (Math.abs(this.motionX) > 10.0D) 1570 { 1571 this.motionX = 0.0D; 1572 } 1573 1574 if (Math.abs(this.motionY) > 10.0D) 1575 { 1576 this.motionY = 0.0D; 1577 } 1578 1579 if (Math.abs(this.motionZ) > 10.0D) 1580 { 1581 this.motionZ = 0.0D; 1582 } 1583 1584 this.prevPosX = this.lastTickPosX = this.posX = ((NBTTagDouble)var2.tagAt(0)).data; 1585 this.prevPosY = this.lastTickPosY = this.posY = ((NBTTagDouble)var2.tagAt(1)).data; 1586 this.prevPosZ = this.lastTickPosZ = this.posZ = ((NBTTagDouble)var2.tagAt(2)).data; 1587 this.prevRotationYaw = this.rotationYaw = ((NBTTagFloat)var7.tagAt(0)).data; 1588 this.prevRotationPitch = this.rotationPitch = ((NBTTagFloat)var7.tagAt(1)).data; 1589 this.fallDistance = par1NBTTagCompound.getFloat("FallDistance"); 1590 this.fire = par1NBTTagCompound.getShort("Fire"); 1591 this.setAir(par1NBTTagCompound.getShort("Air")); 1592 this.onGround = par1NBTTagCompound.getBoolean("OnGround"); 1593 this.dimension = par1NBTTagCompound.getInteger("Dimension"); 1594 this.invulnerable = par1NBTTagCompound.getBoolean("Invulnerable"); 1595 this.timeUntilPortal = par1NBTTagCompound.getInteger("PortalCooldown"); 1596 this.setPosition(this.posX, this.posY, this.posZ); 1597 this.setRotation(this.rotationYaw, this.rotationPitch); 1598 if (par1NBTTagCompound.hasKey("ForgeData")) 1599 { 1600 customEntityData = par1NBTTagCompound.getCompoundTag("ForgeData"); 1601 } 1602 if (par1NBTTagCompound.hasKey("PersistentIDMSB") && par1NBTTagCompound.hasKey("PersistentIDLSB")) 1603 { 1604 persistentID = new UUID(par1NBTTagCompound.getLong("PersistentIDMSB"), par1NBTTagCompound.getLong("PersistentIDLSB")); 1605 } 1606 this.readEntityFromNBT(par1NBTTagCompound); 1607 } 1608 catch (Throwable var5) 1609 { 1610 CrashReport var3 = CrashReport.makeCrashReport(var5, "Loading entity NBT"); 1611 CrashReportCategory var4 = var3.makeCategory("Entity being loaded"); 1612 this.func_85029_a(var4); 1613 throw new ReportedException(var3); 1614 } 1615 } 1616 1617 /** 1618 * Returns the string that identifies this Entity's class 1619 */ 1620 protected final String getEntityString() 1621 { 1622 return EntityList.getEntityString(this); 1623 } 1624 1625 /** 1626 * (abstract) Protected helper method to read subclass entity data from NBT. 1627 */ 1628 protected abstract void readEntityFromNBT(NBTTagCompound var1); 1629 1630 /** 1631 * (abstract) Protected helper method to write subclass entity data to NBT. 1632 */ 1633 protected abstract void writeEntityToNBT(NBTTagCompound var1); 1634 1635 /** 1636 * creates a NBT list from the array of doubles passed to this function 1637 */ 1638 protected NBTTagList newDoubleNBTList(double ... par1ArrayOfDouble) 1639 { 1640 NBTTagList var2 = new NBTTagList(); 1641 double[] var3 = par1ArrayOfDouble; 1642 int var4 = par1ArrayOfDouble.length; 1643 1644 for (int var5 = 0; var5 < var4; ++var5) 1645 { 1646 double var6 = var3[var5]; 1647 var2.appendTag(new NBTTagDouble((String)null, var6)); 1648 } 1649 1650 return var2; 1651 } 1652 1653 /** 1654 * Returns a new NBTTagList filled with the specified floats 1655 */ 1656 protected NBTTagList newFloatNBTList(float ... par1ArrayOfFloat) 1657 { 1658 NBTTagList var2 = new NBTTagList(); 1659 float[] var3 = par1ArrayOfFloat; 1660 int var4 = par1ArrayOfFloat.length; 1661 1662 for (int var5 = 0; var5 < var4; ++var5) 1663 { 1664 float var6 = var3[var5]; 1665 var2.appendTag(new NBTTagFloat((String)null, var6)); 1666 } 1667 1668 return var2; 1669 } 1670 1671 @SideOnly(Side.CLIENT) 1672 public float getShadowSize() 1673 { 1674 return this.height / 2.0F; 1675 } 1676 1677 /** 1678 * Drops an item stack at the entity's position. Args: itemID, count 1679 */ 1680 public EntityItem dropItem(int par1, int par2) 1681 { 1682 return this.dropItemWithOffset(par1, par2, 0.0F); 1683 } 1684 1685 /** 1686 * Drops an item stack with a specified y offset. Args: itemID, count, yOffset 1687 */ 1688 public EntityItem dropItemWithOffset(int par1, int par2, float par3) 1689 { 1690 return this.entityDropItem(new ItemStack(par1, par2, 0), par3); 1691 } 1692 1693 /** 1694 * Drops an item at the position of the entity. 1695 */ 1696 public EntityItem entityDropItem(ItemStack par1ItemStack, float par2) 1697 { 1698 EntityItem var3 = new EntityItem(this.worldObj, this.posX, this.posY + (double)par2, this.posZ, par1ItemStack); 1699 var3.delayBeforeCanPickup = 10; 1700 if (captureDrops) 1701 { 1702 capturedDrops.add(var3); 1703 } 1704 else 1705 { 1706 this.worldObj.spawnEntityInWorld(var3); 1707 } 1708 return var3; 1709 } 1710 1711 /** 1712 * Checks whether target entity is alive. 1713 */ 1714 public boolean isEntityAlive() 1715 { 1716 return !this.isDead; 1717 } 1718 1719 /** 1720 * Checks if this entity is inside of an opaque block 1721 */ 1722 public boolean isEntityInsideOpaqueBlock() 1723 { 1724 for (int var1 = 0; var1 < 8; ++var1) 1725 { 1726 float var2 = ((float)((var1 >> 0) % 2) - 0.5F) * this.width * 0.8F; 1727 float var3 = ((float)((var1 >> 1) % 2) - 0.5F) * 0.1F; 1728 float var4 = ((float)((var1 >> 2) % 2) - 0.5F) * this.width * 0.8F; 1729 int var5 = MathHelper.floor_double(this.posX + (double)var2); 1730 int var6 = MathHelper.floor_double(this.posY + (double)this.getEyeHeight() + (double)var3); 1731 int var7 = MathHelper.floor_double(this.posZ + (double)var4); 1732 1733 if (this.worldObj.isBlockNormalCube(var5, var6, var7)) 1734 { 1735 return true; 1736 } 1737 } 1738 1739 return false; 1740 } 1741 1742 /** 1743 * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. 1744 */ 1745 public boolean interact(EntityPlayer par1EntityPlayer) 1746 { 1747 return false; 1748 } 1749 1750 /** 1751 * Returns a boundingBox used to collide the entity with other entities and blocks. This enables the entity to be 1752 * pushable on contact, like boats or minecarts. 1753 */ 1754 public AxisAlignedBB getCollisionBox(Entity par1Entity) 1755 { 1756 return null; 1757 } 1758 1759 /** 1760 * Handles updating while being ridden by an entity 1761 */ 1762 public void updateRidden() 1763 { 1764 if (this.ridingEntity.isDead) 1765 { 1766 this.ridingEntity = null; 1767 } 1768 else 1769 { 1770 this.motionX = 0.0D; 1771 this.motionY = 0.0D; 1772 this.motionZ = 0.0D; 1773 this.onUpdate(); 1774 1775 if (this.ridingEntity != null) 1776 { 1777 this.ridingEntity.updateRiderPosition(); 1778 this.entityRiderYawDelta += (double)(this.ridingEntity.rotationYaw - this.ridingEntity.prevRotationYaw); 1779 1780 for (this.entityRiderPitchDelta += (double)(this.ridingEntity.rotationPitch - this.ridingEntity.prevRotationPitch); this.entityRiderYawDelta >= 180.0D; this.entityRiderYawDelta -= 360.0D) 1781 { 1782 ; 1783 } 1784 1785 while (this.entityRiderYawDelta < -180.0D) 1786 { 1787 this.entityRiderYawDelta += 360.0D; 1788 } 1789 1790 while (this.entityRiderPitchDelta >= 180.0D) 1791 { 1792 this.entityRiderPitchDelta -= 360.0D; 1793 } 1794 1795 while (this.entityRiderPitchDelta < -180.0D) 1796 { 1797 this.entityRiderPitchDelta += 360.0D; 1798 } 1799 1800 double var1 = this.entityRiderYawDelta * 0.5D; 1801 double var3 = this.entityRiderPitchDelta * 0.5D; 1802 float var5 = 10.0F; 1803 1804 if (var1 > (double)var5) 1805 { 1806 var1 = (double)var5; 1807 } 1808 1809 if (var1 < (double)(-var5)) 1810 { 1811 var1 = (double)(-var5); 1812 } 1813 1814 if (var3 > (double)var5) 1815 { 1816 var3 = (double)var5; 1817 } 1818 1819 if (var3 < (double)(-var5)) 1820 { 1821 var3 = (double)(-var5); 1822 } 1823 1824 this.entityRiderYawDelta -= var1; 1825 this.entityRiderPitchDelta -= var3; 1826 this.rotationYaw = (float)((double)this.rotationYaw + var1); 1827 this.rotationPitch = (float)((double)this.rotationPitch + var3); 1828 } 1829 } 1830 } 1831 1832 public void updateRiderPosition() 1833 { 1834 if (!(this.riddenByEntity instanceof EntityPlayer) || !((EntityPlayer)this.riddenByEntity).func_71066_bF()) 1835 { 1836 this.riddenByEntity.lastTickPosX = this.lastTickPosX; 1837 this.riddenByEntity.lastTickPosY = this.lastTickPosY + this.getMountedYOffset() + this.riddenByEntity.getYOffset(); 1838 this.riddenByEntity.lastTickPosZ = this.lastTickPosZ; 1839 } 1840 1841 this.riddenByEntity.setPosition(this.posX, this.posY + this.getMountedYOffset() + this.riddenByEntity.getYOffset(), this.posZ); 1842 } 1843 1844 /** 1845 * Returns the Y Offset of this entity. 1846 */ 1847 public double getYOffset() 1848 { 1849 return (double)this.yOffset; 1850 } 1851 1852 /** 1853 * Returns the Y offset from the entity's position for any entity riding this one. 1854 */ 1855 public double getMountedYOffset() 1856 { 1857 return (double)this.height * 0.75D; 1858 } 1859 1860 /** 1861 * Called when a player mounts an entity. e.g. mounts a pig, mounts a boat. 1862 */ 1863 public void mountEntity(Entity par1Entity) 1864 { 1865 this.entityRiderPitchDelta = 0.0D; 1866 this.entityRiderYawDelta = 0.0D; 1867 1868 if (par1Entity == null) 1869 { 1870 if (this.ridingEntity != null) 1871 { 1872 this.setLocationAndAngles(this.ridingEntity.posX, this.ridingEntity.boundingBox.minY + (double)this.ridingEntity.height, this.ridingEntity.posZ, this.rotationYaw, this.rotationPitch); 1873 this.ridingEntity.riddenByEntity = null; 1874 } 1875 1876 this.ridingEntity = null; 1877 } 1878 else if (this.ridingEntity == par1Entity) 1879 { 1880 this.unmountEntity(par1Entity); 1881 this.ridingEntity.riddenByEntity = null; 1882 this.ridingEntity = null; 1883 } 1884 else 1885 { 1886 if (this.ridingEntity != null) 1887 { 1888 this.ridingEntity.riddenByEntity = null; 1889 } 1890 1891 if (par1Entity.riddenByEntity != null) 1892 { 1893 par1Entity.riddenByEntity.ridingEntity = null; 1894 } 1895 1896 this.ridingEntity = par1Entity; 1897 par1Entity.riddenByEntity = this; 1898 } 1899 } 1900 1901 /** 1902 * Called when a player unounts an entity. 1903 */ 1904 public void unmountEntity(Entity par1Entity) 1905 { 1906 double var3 = par1Entity.posX; 1907 double var5 = par1Entity.boundingBox.minY + (double)par1Entity.height; 1908 double var7 = par1Entity.posZ; 1909 1910 for (double var9 = -1.5D; var9 < 2.0D; ++var9) 1911 { 1912 for (double var11 = -1.5D; var11 < 2.0D; ++var11) 1913 { 1914 if (var9 != 0.0D || var11 != 0.0D) 1915 { 1916 int var13 = (int)(this.posX + var9); 1917 int var14 = (int)(this.posZ + var11); 1918 AxisAlignedBB var2 = this.boundingBox.getOffsetBoundingBox(var9, 1.0D, var11); 1919 1920 if (this.worldObj.getAllCollidingBoundingBoxes(var2).isEmpty()) 1921 { 1922 if (this.worldObj.doesBlockHaveSolidTopSurface(var13, (int)this.posY, var14)) 1923 { 1924 this.setLocationAndAngles(this.posX + var9, this.posY + 1.0D, this.posZ + var11, this.rotationYaw, this.rotationPitch); 1925 return; 1926 } 1927 1928 if (this.worldObj.doesBlockHaveSolidTopSurface(var13, (int)this.posY - 1, var14) || this.worldObj.getBlockMaterial(var13, (int)this.posY - 1, var14) == Material.water) 1929 { 1930 var3 = this.posX + var9; 1931 var5 = this.posY + 1.0D; 1932 var7 = this.posZ + var11; 1933 } 1934 } 1935 } 1936 } 1937 } 1938 1939 this.setLocationAndAngles(var3, var5, var7, this.rotationYaw, this.rotationPitch); 1940 } 1941 1942 @SideOnly(Side.CLIENT) 1943 1944 /** 1945 * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX, 1946 * posY, posZ, yaw, pitch 1947 */ 1948 public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9) 1949 { 1950 this.setPosition(par1, par3, par5); 1951 this.setRotation(par7, par8); 1952 List var10 = this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox.contract(0.03125D, 0.0D, 0.03125D)); 1953 1954 if (!var10.isEmpty()) 1955 { 1956 double var11 = 0.0D; 1957 1958 for (int var13 = 0; var13 < var10.size(); ++var13) 1959 { 1960 AxisAlignedBB var14 = (AxisAlignedBB)var10.get(var13); 1961 1962 if (var14.maxY > var11) 1963 { 1964 var11 = var14.maxY; 1965 } 1966 } 1967 1968 par3 += var11 - this.boundingBox.minY; 1969 this.setPosition(par1, par3, par5); 1970 } 1971 } 1972 1973 public float getCollisionBorderSize() 1974 { 1975 return 0.1F; 1976 } 1977 1978 /** 1979 * returns a (normalized) vector of where this entity is looking 1980 */ 1981 public Vec3 getLookVec() 1982 { 1983 return null; 1984 } 1985 1986 /** 1987 * Called by portal blocks when an entity is within it. 1988 */ 1989 public void setInPortal() 1990 { 1991 if (this.timeUntilPortal > 0) 1992 { 1993 this.timeUntilPortal = this.getPortalCooldown(); 1994 } 1995 else 1996 { 1997 double var1 = this.prevPosX - this.posX; 1998 double var3 = this.prevPosZ - this.posZ; 1999 2000 if (!this.worldObj.isRemote && !this.inPortal) 2001 { 2002 this.field_82152_aq = Direction.func_82372_a(var1, var3); 2003 } 2004 2005 this.inPortal = true; 2006 } 2007 } 2008 2009 /** 2010 * Return the amount of cooldown before this entity can use a portal again. 2011 */ 2012 public int getPortalCooldown() 2013 { 2014 return 900; 2015 } 2016 2017 @SideOnly(Side.CLIENT) 2018 2019 /** 2020 * Sets the velocity to the args. Args: x, y, z 2021 */ 2022 public void setVelocity(double par1, double par3, double par5) 2023 { 2024 this.motionX = par1; 2025 this.motionY = par3; 2026 this.motionZ = par5; 2027 } 2028 2029 @SideOnly(Side.CLIENT) 2030 public void handleHealthUpdate(byte par1) {} 2031 2032 @SideOnly(Side.CLIENT) 2033 2034 /** 2035 * Setups the entity to do the hurt animation. Only used by packets in multiplayer. 2036 */ 2037 public void performHurtAnimation() {} 2038 2039 @SideOnly(Side.CLIENT) 2040 public void updateCloak() {} 2041 2042 public ItemStack[] getLastActiveItems() 2043 { 2044 return null; 2045 } 2046 2047 /** 2048 * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot 2049 */ 2050 public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack) {} 2051 2052 /** 2053 * Returns true if the entity is on fire. Used by render to add the fire effect on rendering. 2054 */ 2055 public boolean isBurning() 2056 { 2057 return this.fire > 0 || this.getFlag(0); 2058 } 2059 2060 /** 2061 * Returns true if the entity is riding another entity, used by render to rotate the legs to be in 'sit' position 2062 * for players. 2063 */ 2064 public boolean isRiding() 2065 { 2066 return (this.ridingEntity != null && ridingEntity.shouldRiderSit()) || this.getFlag(2); 2067 } 2068 2069 /** 2070 * Returns if this entity is sneaking. 2071 */ 2072 public boolean isSneaking() 2073 { 2074 return this.getFlag(1); 2075 } 2076 2077 /** 2078 * Sets the sneaking flag. 2079 */ 2080 public void setSneaking(boolean par1) 2081 { 2082 this.setFlag(1, par1); 2083 } 2084 2085 /** 2086 * Get if the Entity is sprinting. 2087 */ 2088 public boolean isSprinting() 2089 { 2090 return this.getFlag(3); 2091 } 2092 2093 /** 2094 * Set sprinting switch for Entity. 2095 */ 2096 public void setSprinting(boolean par1) 2097 { 2098 this.setFlag(3, par1); 2099 } 2100 2101 public boolean getHasActivePotion() 2102 { 2103 return this.getFlag(5); 2104 } 2105 2106 public void setHasActivePotion(boolean par1) 2107 { 2108 this.setFlag(5, par1); 2109 } 2110 2111 @SideOnly(Side.CLIENT) 2112 public boolean isEating() 2113 { 2114 return this.getFlag(4); 2115 } 2116 2117 public void setEating(boolean par1) 2118 { 2119 this.setFlag(4, par1); 2120 } 2121 2122 /** 2123 * Returns true if the flag is active for the entity. Known flags: 0) is burning; 1) is sneaking; 2) is riding 2124 * something; 3) is sprinting; 4) is eating 2125 */ 2126 protected boolean getFlag(int par1) 2127 { 2128 return (this.dataWatcher.getWatchableObjectByte(0) & 1 << par1) != 0; 2129 } 2130 2131 /** 2132 * Enable or disable a entity flag, see getEntityFlag to read the know flags. 2133 */ 2134 protected void setFlag(int par1, boolean par2) 2135 { 2136 byte var3 = this.dataWatcher.getWatchableObjectByte(0); 2137 2138 if (par2) 2139 { 2140 this.dataWatcher.updateObject(0, Byte.valueOf((byte)(var3 | 1 << par1))); 2141 } 2142 else 2143 { 2144 this.dataWatcher.updateObject(0, Byte.valueOf((byte)(var3 & ~(1 << par1)))); 2145 } 2146 } 2147 2148 public int getAir() 2149 { 2150 return this.dataWatcher.getWatchableObjectShort(1); 2151 } 2152 2153 public void setAir(int par1) 2154 { 2155 this.dataWatcher.updateObject(1, Short.valueOf((short)par1)); 2156 } 2157 2158 /** 2159 * Called when a lightning bolt hits the entity. 2160 */ 2161 public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt) 2162 { 2163 this.dealFireDamage(5); 2164 ++this.fire; 2165 2166 if (this.fire == 0) 2167 { 2168 this.setFire(8); 2169 } 2170 } 2171 2172 /** 2173 * This method gets called when the entity kills another one. 2174 */ 2175 public void onKillEntity(EntityLiving par1EntityLiving) {} 2176 2177 /** 2178 * Adds velocity to push the entity out of blocks at the specified x, y, z position Args: x, y, z 2179 */ 2180 protected boolean pushOutOfBlocks(double par1, double par3, double par5) 2181 { 2182 int var7 = MathHelper.floor_double(par1); 2183 int var8 = MathHelper.floor_double(par3); 2184 int var9 = MathHelper.floor_double(par5); 2185 double var10 = par1 - (double)var7; 2186 double var12 = par3 - (double)var8; 2187 double var14 = par5 - (double)var9; 2188 List var16 = this.worldObj.getAllCollidingBoundingBoxes(this.boundingBox); 2189 2190 if (var16.isEmpty() && !this.worldObj.func_85174_u(var7, var8, var9)) 2191 { 2192 return false; 2193 } 2194 else 2195 { 2196 boolean var17 = !this.worldObj.func_85174_u(var7 - 1, var8, var9); 2197 boolean var18 = !this.worldObj.func_85174_u(var7 + 1, var8, var9); 2198 boolean var19 = !this.worldObj.func_85174_u(var7, var8 - 1, var9); 2199 boolean var20 = !this.worldObj.func_85174_u(var7, var8 + 1, var9); 2200 boolean var21 = !this.worldObj.func_85174_u(var7, var8, var9 - 1); 2201 boolean var22 = !this.worldObj.func_85174_u(var7, var8, var9 + 1); 2202 byte var23 = 3; 2203 double var24 = 9999.0D; 2204 2205 if (var17 && var10 < var24) 2206 { 2207 var24 = var10; 2208 var23 = 0; 2209 } 2210 2211 if (var18 && 1.0D - var10 < var24) 2212 { 2213 var24 = 1.0D - var10; 2214 var23 = 1; 2215 } 2216 2217 if (var20 && 1.0D - var12 < var24) 2218 { 2219 var24 = 1.0D - var12; 2220 var23 = 3; 2221 } 2222 2223 if (var21 && var14 < var24) 2224 { 2225 var24 = var14; 2226 var23 = 4; 2227 } 2228 2229 if (var22 && 1.0D - var14 < var24) 2230 { 2231 var24 = 1.0D - var14; 2232 var23 = 5; 2233 } 2234 2235 float var26 = this.rand.nextFloat() * 0.2F + 0.1F; 2236 2237 if (var23 == 0) 2238 { 2239 this.motionX = (double)(-var26); 2240 } 2241 2242 if (var23 == 1) 2243 { 2244 this.motionX = (double)var26; 2245 } 2246 2247 if (var23 == 2) 2248 { 2249 this.motionY = (double)(-var26); 2250 } 2251 2252 if (var23 == 3) 2253 { 2254 this.motionY = (double)var26; 2255 } 2256 2257 if (var23 == 4) 2258 { 2259 this.motionZ = (double)(-var26); 2260 } 2261 2262 if (var23 == 5) 2263 { 2264 this.motionZ = (double)var26; 2265 } 2266 2267 return true; 2268 } 2269 } 2270 2271 /** 2272 * Sets the Entity inside a web block. 2273 */ 2274 public void setInWeb() 2275 { 2276 this.isInWeb = true; 2277 this.fallDistance = 0.0F; 2278 } 2279 2280 /** 2281 * Gets the username of the entity. 2282 */ 2283 public String getEntityName() 2284 { 2285 String var1 = EntityList.getEntityString(this); 2286 2287 if (var1 == null) 2288 { 2289 var1 = "generic"; 2290 } 2291 2292 return StatCollector.translateToLocal("entity." + var1 + ".name"); 2293 } 2294 2295 /** 2296 * Return the Entity parts making up this Entity (currently only for dragons) 2297 */ 2298 public Entity[] getParts() 2299 { 2300 return null; 2301 } 2302 2303 /** 2304 * Returns true if Entity argument is equal to this Entity 2305 */ 2306 public boolean isEntityEqual(Entity par1Entity) 2307 { 2308 return this == par1Entity; 2309 } 2310 2311 public float setRotationYawHead() 2312 { 2313 return 0.0F; 2314 } 2315 2316 @SideOnly(Side.CLIENT) 2317 2318 /** 2319 * Sets the head's yaw rotation of the entity. 2320 */ 2321 public void setHeadRotationYaw(float par1) {} 2322 2323 /** 2324 * If returns false, the item will not inflict any damage against entities. 2325 */ 2326 public boolean canAttackWithItem() 2327 { 2328 return true; 2329 } 2330 2331 public boolean func_85031_j(Entity par1Entity) 2332 { 2333 return false; 2334 } 2335 2336 public String toString() 2337 { 2338 return String.format("%s[\'%s\'/%d, l=\'%s\', x=%.2f, y=%.2f, z=%.2f]", new Object[] {this.getClass().getSimpleName(), this.getEntityName(), Integer.valueOf(this.entityId), this.worldObj == null ? "~NULL~" : this.worldObj.getWorldInfo().getWorldName(), Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ)}); 2339 } 2340 2341 /** 2342 * Return whether this entity is invulnerable to damage. 2343 */ 2344 public boolean isEntityInvulnerable() 2345 { 2346 return this.invulnerable; 2347 } 2348 2349 public void func_82149_j(Entity par1Entity) 2350 { 2351 this.setLocationAndAngles(par1Entity.posX, par1Entity.posY, par1Entity.posZ, par1Entity.rotationYaw, par1Entity.rotationPitch); 2352 } 2353 2354 /** 2355 * Copies important data from another entity to this entity. Used when teleporting entities between worlds, as this 2356 * actually deletes the teleporting entity and re-creates it on the other side. Params: Entity to copy from, unused 2357 * (always true) 2358 */ 2359 public void copyDataFrom(Entity par1Entity, boolean par2) 2360 { 2361 NBTTagCompound var3 = new NBTTagCompound(); 2362 par1Entity.writeToNBT(var3); 2363 this.readFromNBT(var3); 2364 this.timeUntilPortal = par1Entity.timeUntilPortal; 2365 this.field_82152_aq = par1Entity.field_82152_aq; 2366 } 2367 2368 /** 2369 * Teleports the entity to another dimension. Params: Dimension number to teleport to 2370 */ 2371 public void travelToDimension(int par1) 2372 { 2373 if (!this.worldObj.isRemote && !this.isDead) 2374 { 2375 this.worldObj.theProfiler.startSection("changeDimension"); 2376 MinecraftServer var2 = MinecraftServer.getServer(); 2377 int var3 = this.dimension; 2378 WorldServer var4 = var2.worldServerForDimension(var3); 2379 WorldServer var5 = var2.worldServerForDimension(par1); 2380 this.dimension = par1; 2381 this.worldObj.setEntityDead(this); 2382 this.isDead = false; 2383 this.worldObj.theProfiler.startSection("reposition"); 2384 var2.getConfigurationManager().transferEntityToWorld(this, var3, var4, var5); 2385 this.worldObj.theProfiler.endStartSection("reloading"); 2386 Entity var6 = EntityList.createEntityByName(EntityList.getEntityString(this), var5); 2387 2388 if (var6 != null) 2389 { 2390 var6.copyDataFrom(this, true); 2391 var5.spawnEntityInWorld(var6); 2392 } 2393 2394 this.isDead = true; 2395 this.worldObj.theProfiler.endSection(); 2396 var4.resetUpdateEntityTick(); 2397 var5.resetUpdateEntityTick(); 2398 this.worldObj.theProfiler.endSection(); 2399 } 2400 } 2401 2402 public float func_82146_a(Explosion par1Explosion, Block par2Block, int par3, int par4, int par5) 2403 { 2404 return par2Block.getExplosionResistance(this, worldObj, par3, par4, par5, posX, posY + (double)getEyeHeight(), posZ); 2405 } 2406 2407 public int func_82143_as() 2408 { 2409 return 3; 2410 } 2411 2412 public int func_82148_at() 2413 { 2414 return this.field_82152_aq; 2415 } 2416 2417 /** 2418 * Return whether this entity should NOT trigger a pressure plate or a tripwire. 2419 */ 2420 public boolean doesEntityNotTriggerPressurePlate() 2421 { 2422 return false; 2423 } 2424 2425 public void func_85029_a(CrashReportCategory par1CrashReportCategory) 2426 { 2427 par1CrashReportCategory.addCrashSectionCallable("Entity Type", new CallableEntityType(this)); 2428 par1CrashReportCategory.addCrashSection("Entity ID", Integer.valueOf(this.entityId)); 2429 par1CrashReportCategory.addCrashSection("Name", this.getEntityName()); 2430 par1CrashReportCategory.addCrashSection("Exact location", String.format("%.2f, %.2f, %.2f", new Object[] {Double.valueOf(this.posX), Double.valueOf(this.posY), Double.valueOf(this.posZ)})); 2431 par1CrashReportCategory.addCrashSection("Block location", CrashReportCategory.func_85071_a(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ))); 2432 par1CrashReportCategory.addCrashSection("Momentum", String.format("%.2f, %.2f, %.2f", new Object[] {Double.valueOf(this.motionX), Double.valueOf(this.motionY), Double.valueOf(this.motionZ)})); 2433 } 2434 2435 @SideOnly(Side.CLIENT) 2436 2437 /** 2438 * Return whether this entity should be rendered as on fire. 2439 */ 2440 public boolean canRenderOnFire() 2441 { 2442 return this.isBurning(); 2443 } 2444 2445 /* ================================== Forge Start =====================================*/ 2446 /** 2447 * Returns a NBTTagCompound that can be used to store custom data for this entity. 2448 * It will be written, and read from disc, so it persists over world saves. 2449 * @return A NBTTagCompound 2450 */ 2451 public NBTTagCompound getEntityData() 2452 { 2453 if (customEntityData == null) 2454 { 2455 customEntityData = new NBTTagCompound(); 2456 } 2457 return customEntityData; 2458 } 2459 2460 /** 2461 * Used in model rendering to determine if the entity riding this entity should be in the 'sitting' position. 2462 * @return false to prevent an entity that is mounted to this entity from displaying the 'sitting' animation. 2463 */ 2464 public boolean shouldRiderSit() 2465 { 2466 return true; 2467 } 2468 2469 /** 2470 * Called when a user uses the creative pick block button on this entity. 2471 * 2472 * @param target The full target the player is looking at 2473 * @return A ItemStack to add to the player's inventory, Null if nothing should be added. 2474 */ 2475 public ItemStack getPickedResult(MovingObjectPosition target) 2476 { 2477 if (this instanceof EntityPainting) 2478 { 2479 return new ItemStack(Item.painting); 2480 } 2481 else if (this instanceof EntityMinecart) 2482 { 2483 return ((EntityMinecart)this).getCartItem(); 2484 } 2485 else if (this instanceof EntityBoat) 2486 { 2487 return new ItemStack(Item.boat); 2488 } 2489 else if (this instanceof EntityItemFrame) 2490 { 2491 ItemStack held = ((EntityItemFrame)this).getDisplayedItem(); 2492 if (held == null) 2493 { 2494 return new ItemStack(Item.itemFrame); 2495 } 2496 else 2497 { 2498 return held.copy(); 2499 } 2500 } 2501 else 2502 { 2503 int id = EntityList.getEntityID(this); 2504 if (id > 0 && EntityList.entityEggs.containsKey(id)) 2505 { 2506 return new ItemStack(Item.monsterPlacer, 1, id); 2507 } 2508 } 2509 return null; 2510 } 2511 2512 public UUID getPersistentID() 2513 { 2514 return persistentID; 2515 } 2516 2517 public synchronized void generatePersistentID() 2518 { 2519 if (persistentID == null) 2520 { 2521 persistentID = UUID.randomUUID(); 2522 } 2523 } 2524 }