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 }