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