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