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