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