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