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    }