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 }