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