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