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