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