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