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