    001    package net.minecraft.src;
    002
    003    public class EntityBat extends EntityAmbientCreature
    004    {
    005        private ChunkCoordinates field_82237_a;
    006
    007        public EntityBat(World par1World)
    008        {
    009            super(par1World);
    010            this.texture = "/mob/bat.png";
    011            this.setSize(0.5F, 0.9F);
    012            this.func_82236_f(true);
    013        }
    014
    015        protected void entityInit()
    016        {
    017            super.entityInit();
    018            this.dataWatcher.addObject(16, new Byte((byte)0));
    019        }
    020
    021        /**
    022         * Returns the volume for the sounds this mob makes.
    023         */
    024        protected float getSoundVolume()
    025        {
    026            return 0.1F;
    027        }
    028
    029        /**
    030         * Returns the sound this mob makes while it's alive.
    031         */
    032        protected String getLivingSound()
    033        {
    034            return "mob.bat.idle";
    035        }
    036
    037        /**
    038         * Returns the sound this mob makes when it is hurt.
    039         */
    040        protected String getHurtSound()
    041        {
    042            return "mob.bat.hurt";
    043        }
    044
    045        /**
    046         * Returns the sound this mob makes on death.
    047         */
    048        protected String getDeathSound()
    049        {
    050            return "mob.bat.death";
    051        }
    052
    053        public int getMaxHealth()
    054        {
    055            return 6;
    056        }
    057
    058        public boolean func_82235_h()
    059        {
    060            return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
    061        }
    062
    063        public void func_82236_f(boolean par1)
    064        {
    065            byte var2 = this.dataWatcher.getWatchableObjectByte(16);
    066
    067            if (par1)
    068            {
    069                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 | 1)));
    070            }
    071            else
    072            {
    073                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & -2)));
    074            }
    075        }
    076
    077        /**
    078         * Returns true if the newer Entity AI code should be run
    079         */
    080        protected boolean isAIEnabled()
    081        {
    082            return true;
    083        }
    084
    085        /**
    086         * Called to update the entity's position/logic.
    087         */
    088        public void onUpdate()
    089        {
    090            super.onUpdate();
    091
    092            if (this.func_82235_h())
    093            {
    094                this.motionX = this.motionY = this.motionZ = 0.0D;
    095                this.posY = (double)MathHelper.floor_double(this.posY) + 1.0D - (double)this.height;
    096            }
    097            else
    098            {
    099                this.motionY *= 0.6000000238418579D;
    100            }
    101        }
    102
    103        protected void updateAITasks()
    104        {
    105            super.updateAITasks();
    106
    107            if (this.func_82235_h())
    108            {
    109                if (!this.worldObj.isBlockNormalCube(MathHelper.floor_double(this.posX), (int)this.posY + 1, MathHelper.floor_double(this.posZ)))
    110                {
    111                    this.func_82236_f(false);
    112                    this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1015, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
    113                }
    114                else
    115                {
    116                    if (this.rand.nextInt(200) == 0)
    117                    {
    118                        this.rotationYawHead = (float)this.rand.nextInt(360);
    119                    }
    120
    121                    if (this.worldObj.getClosestPlayerToEntity(this, 4.0D) != null)
    122                    {
    123                        this.func_82236_f(false);
    124                        this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1015, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
    125                    }
    126                }
    127            }
    128            else
    129            {
    130                if (this.field_82237_a != null && (!this.worldObj.isAirBlock(this.field_82237_a.posX, this.field_82237_a.posY, this.field_82237_a.posZ) || this.field_82237_a.posY < 1))
    131                {
    132                    this.field_82237_a = null;
    133                }
    134
    135                if (this.field_82237_a == null || this.rand.nextInt(30) == 0 || this.field_82237_a.getDistanceSquared((int)this.posX, (int)this.posY, (int)this.posZ) < 4.0F)
    136                {
    137                    this.field_82237_a = new ChunkCoordinates((int)this.posX + this.rand.nextInt(7) - this.rand.nextInt(7), (int)this.posY + this.rand.nextInt(6) - 2, (int)this.posZ + this.rand.nextInt(7) - this.rand.nextInt(7));
    138                }
    139
    140                double var1 = (double)this.field_82237_a.posX + 0.5D - this.posX;
    141                double var3 = (double)this.field_82237_a.posY + 0.1D - this.posY;
    142                double var5 = (double)this.field_82237_a.posZ + 0.5D - this.posZ;
    143                this.motionX += (Math.signum(var1) * 0.5D - this.motionX) * 0.10000000149011612D;
    144                this.motionY += (Math.signum(var3) * 0.699999988079071D - this.motionY) * 0.10000000149011612D;
    145                this.motionZ += (Math.signum(var5) * 0.5D - this.motionZ) * 0.10000000149011612D;
    146                float var7 = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
    147                float var8 = MathHelper.wrapAngleTo180_float(var7 - this.rotationYaw);
    148                this.moveForward = 0.5F;
    149                this.rotationYaw += var8;
    150
    151                if (this.rand.nextInt(100) == 0 && this.worldObj.isBlockNormalCube(MathHelper.floor_double(this.posX), (int)this.posY + 1, MathHelper.floor_double(this.posZ)))
    152                {
    153                    this.func_82236_f(true);
    154                }
    155            }
    156        }
    157
    158        /**
    159         * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
    160         * prevent them from trampling crops
    161         */
    162        protected boolean canTriggerWalking()
    163        {
    164            return false;
    165        }
    166
    167        /**
    168         * Called when the mob is falling. Calculates and applies fall damage.
    169         */
    170        protected void fall(float par1) {}
    171
    172        /**
    173         * Takes in the distance the entity has fallen this tick and whether its on the ground to update the fall distance
    174         * and deal fall damage if landing on the ground.  Args: distanceFallenThisTick, onGround
    175         */
    176        protected void updateFallState(double par1, boolean par3) {}
    177
    178        public boolean func_82144_au()
    179        {
    180            return true;
    181        }
    182
    183        /**
    184         * Called when the entity is attacked.
    185         */
    186        public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    187        {
    188            if (!this.worldObj.isRemote && this.func_82235_h())
    189            {
    190                this.func_82236_f(false);
    191            }
    192
    193            return super.attackEntityFrom(par1DamageSource, par2);
    194        }
    195
    196        /**
    197         * (abstract) Protected helper method to read subclass entity data from NBT.
    198         */
    199        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    200        {
    201            super.readEntityFromNBT(par1NBTTagCompound);
    202            this.dataWatcher.updateObject(16, Byte.valueOf(par1NBTTagCompound.getByte("BatFlags")));
    203        }
    204
    205        /**
    206         * (abstract) Protected helper method to write subclass entity data to NBT.
    207         */
    208        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    209        {
    210            super.writeEntityToNBT(par1NBTTagCompound);
    211            par1NBTTagCompound.setByte("BatFlags", this.dataWatcher.getWatchableObjectByte(16));
    212        }
    213
    214        /**
    215         * Checks if the entity's current position is a valid location to spawn this entity.
    216         */
    217        public boolean getCanSpawnHere()
    218        {
    219            int var1 = MathHelper.floor_double(this.boundingBox.minY);
    220
    221            if (var1 >= 63)
    222            {
    223                return false;
    224            }
    225            else
    226            {
    227                int var2 = MathHelper.floor_double(this.posX);
    228                int var3 = MathHelper.floor_double(this.posZ);
    229                int var4 = this.worldObj.getBlockLightValue(var2, var1, var3);
    230                return var4 > this.rand.nextInt(7) ? false : super.getCanSpawnHere();
    231            }
    232        }
    233
    234        public void func_82163_bD() {}
    235    }