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