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