001 package net.minecraft.src; 002 003 import net.minecraftforge.client.*; 004 import net.minecraftforge.client.event.sound.*; 005 import net.minecraftforge.common.MinecraftForge; 006 import static net.minecraftforge.client.event.sound.SoundEvent.*; 007 import cpw.mods.fml.common.Side; 008 import cpw.mods.fml.common.asm.SideOnly; 009 import java.io.File; 010 import java.util.HashSet; 011 import java.util.Iterator; 012 import java.util.Random; 013 import java.util.Set; 014 import paulscode.sound.SoundSystem; 015 import paulscode.sound.SoundSystemConfig; 016 import paulscode.sound.codecs.CodecJOrbis; 017 import paulscode.sound.codecs.CodecWav; 018 import paulscode.sound.libraries.LibraryLWJGLOpenAL; 019 020 @SideOnly(Side.CLIENT) 021 public class SoundManager 022 { 023 /** A reference to the sound system. */ 024 public static SoundSystem sndSystem; 025 026 /** Sound pool containing sounds. */ 027 public SoundPool soundPoolSounds = new SoundPool(); 028 029 /** Sound pool containing streaming audio. */ 030 public SoundPool soundPoolStreaming = new SoundPool(); 031 032 /** Sound pool containing music. */ 033 public SoundPool soundPoolMusic = new SoundPool(); 034 035 /** 036 * The last ID used when a sound is played, passed into SoundSystem to give active sounds a unique ID 037 */ 038 private int latestSoundID = 0; 039 040 /** A reference to the game settings. */ 041 private GameSettings options; 042 private Set field_82470_g = new HashSet(); 043 044 /** Set to true when the SoundManager has been initialised. */ 045 private static boolean loaded = false; 046 047 /** RNG. */ 048 private Random rand = new Random(); 049 private int ticksBeforeMusic; 050 051 public static int MUSIC_INTERVAL = 12000; 052 053 public SoundManager() 054 { 055 this.ticksBeforeMusic = this.rand.nextInt(MUSIC_INTERVAL); 056 } 057 058 /** 059 * Used for loading sound settings from GameSettings 060 */ 061 public void loadSoundSettings(GameSettings par1GameSettings) 062 { 063 this.soundPoolStreaming.isGetRandomSound = false; 064 this.options = par1GameSettings; 065 066 if (!loaded && (par1GameSettings == null || par1GameSettings.soundVolume != 0.0F || par1GameSettings.musicVolume != 0.0F)) 067 { 068 this.tryToSetLibraryAndCodecs(); 069 } 070 ModCompatibilityClient.audioModLoad(this); 071 MinecraftForge.EVENT_BUS.post(new SoundLoadEvent(this)); 072 } 073 074 /** 075 * Tries to add the paulscode library and the relevant codecs. If it fails, the volumes (sound and music) will be 076 * set to zero in the options file. 077 */ 078 private void tryToSetLibraryAndCodecs() 079 { 080 try 081 { 082 float var1 = this.options.soundVolume; 083 float var2 = this.options.musicVolume; 084 this.options.soundVolume = 0.0F; 085 this.options.musicVolume = 0.0F; 086 this.options.saveOptions(); 087 SoundSystemConfig.addLibrary(LibraryLWJGLOpenAL.class); 088 SoundSystemConfig.setCodec("ogg", CodecJOrbis.class); 089 SoundSystemConfig.setCodec("mus", CodecMus.class); 090 SoundSystemConfig.setCodec("wav", CodecWav.class); 091 ModCompatibilityClient.audioModAddCodecs(); 092 MinecraftForge.EVENT_BUS.post(new SoundSetupEvent(this)); 093 sndSystem = new SoundSystem(); 094 this.options.soundVolume = var1; 095 this.options.musicVolume = var2; 096 this.options.saveOptions(); 097 } 098 catch (Throwable var3) 099 { 100 var3.printStackTrace(); 101 System.err.println("error linking with the LibraryJavaSound plug-in"); 102 } 103 104 loaded = true; 105 } 106 107 /** 108 * Called when one of the sound level options has changed. 109 */ 110 public void onSoundOptionsChanged() 111 { 112 if (!loaded && (this.options.soundVolume != 0.0F || this.options.musicVolume != 0.0F)) 113 { 114 this.tryToSetLibraryAndCodecs(); 115 } 116 117 if (loaded) 118 { 119 if (this.options.musicVolume == 0.0F) 120 { 121 sndSystem.stop("BgMusic"); 122 } 123 else 124 { 125 sndSystem.setVolume("BgMusic", this.options.musicVolume); 126 } 127 } 128 } 129 130 /** 131 * Called when Minecraft is closing down. 132 */ 133 public void closeMinecraft() 134 { 135 if (loaded) 136 { 137 sndSystem.cleanup(); 138 } 139 } 140 141 /** 142 * Adds a sounds with the name from the file. Args: name, file 143 */ 144 public void addSound(String par1Str, File par2File) 145 { 146 this.soundPoolSounds.addSound(par1Str, par2File); 147 } 148 149 /** 150 * Adds an audio file to the streaming SoundPool. 151 */ 152 public void addStreaming(String par1Str, File par2File) 153 { 154 this.soundPoolStreaming.addSound(par1Str, par2File); 155 } 156 157 /** 158 * Adds an audio file to the music SoundPool. 159 */ 160 public void addMusic(String par1Str, File par2File) 161 { 162 this.soundPoolMusic.addSound(par1Str, par2File); 163 } 164 165 /** 166 * If its time to play new music it starts it up. 167 */ 168 public void playRandomMusicIfReady() 169 { 170 if (loaded && this.options.musicVolume != 0.0F) 171 { 172 if (!sndSystem.playing("BgMusic") && !sndSystem.playing("streaming")) 173 { 174 if (this.ticksBeforeMusic > 0) 175 { 176 --this.ticksBeforeMusic; 177 return; 178 } 179 180 SoundPoolEntry var1 = this.soundPoolMusic.getRandomSound(); 181 var1 = ModCompatibilityClient.audioModPickBackgroundMusic(this, var1); 182 var1 = SoundEvent.getResult(new PlayBackgroundMusicEvent(this, var1)); 183 184 if (var1 != null) 185 { 186 this.ticksBeforeMusic = this.rand.nextInt(MUSIC_INTERVAL) + MUSIC_INTERVAL; 187 sndSystem.backgroundMusic("BgMusic", var1.soundUrl, var1.soundName, false); 188 sndSystem.setVolume("BgMusic", this.options.musicVolume); 189 sndSystem.play("BgMusic"); 190 } 191 } 192 } 193 } 194 195 /** 196 * Sets the listener of sounds 197 */ 198 public void setListener(EntityLiving par1EntityLiving, float par2) 199 { 200 if (loaded && this.options.soundVolume != 0.0F) 201 { 202 if (par1EntityLiving != null) 203 { 204 float var3 = par1EntityLiving.prevRotationYaw + (par1EntityLiving.rotationYaw - par1EntityLiving.prevRotationYaw) * par2; 205 double var4 = par1EntityLiving.prevPosX + (par1EntityLiving.posX - par1EntityLiving.prevPosX) * (double)par2; 206 double var6 = par1EntityLiving.prevPosY + (par1EntityLiving.posY - par1EntityLiving.prevPosY) * (double)par2; 207 double var8 = par1EntityLiving.prevPosZ + (par1EntityLiving.posZ - par1EntityLiving.prevPosZ) * (double)par2; 208 float var10 = MathHelper.cos(-var3 * 0.017453292F - (float)Math.PI); 209 float var11 = MathHelper.sin(-var3 * 0.017453292F - (float)Math.PI); 210 float var12 = -var11; 211 float var13 = 0.0F; 212 float var14 = -var10; 213 float var15 = 0.0F; 214 float var16 = 1.0F; 215 float var17 = 0.0F; 216 sndSystem.setListenerPosition((float)var4, (float)var6, (float)var8); 217 sndSystem.setListenerOrientation(var12, var13, var14, var15, var16, var17); 218 } 219 } 220 } 221 222 public void func_82464_d() 223 { 224 Iterator var1 = this.field_82470_g.iterator(); 225 226 while (var1.hasNext()) 227 { 228 String var2 = (String)var1.next(); 229 sndSystem.stop(var2); 230 } 231 232 this.field_82470_g.clear(); 233 } 234 235 public void playStreaming(String par1Str, float par2, float par3, float par4) 236 { 237 if (loaded && (this.options.soundVolume != 0.0F || par1Str == null)) 238 { 239 String var5 = "streaming"; 240 241 if (sndSystem.playing(var5)) 242 { 243 sndSystem.stop(var5); 244 } 245 246 if (par1Str != null) 247 { 248 SoundPoolEntry var6 = this.soundPoolStreaming.getRandomSoundFromSoundPool(par1Str); 249 var6 = SoundEvent.getResult(new PlayStreamingEvent(this, var6, par1Str, par2, par3, par4)); 250 251 if (var6 != null) 252 { 253 if (sndSystem.playing("BgMusic")) 254 { 255 sndSystem.stop("BgMusic"); 256 } 257 258 float var7 = 16.0F; 259 sndSystem.newStreamingSource(true, var5, var6.soundUrl, var6.soundName, false, par2, par3, par4, 2, var7 * 4.0F); 260 sndSystem.setVolume(var5, 0.5F * this.options.soundVolume); 261 MinecraftForge.EVENT_BUS.post(new PlayStreamingSourceEvent(this, var5, par2, par3, par4)); 262 sndSystem.play(var5); 263 } 264 } 265 } 266 } 267 268 public void func_82460_a(Entity par1Entity) 269 { 270 this.func_82462_a(par1Entity, par1Entity); 271 } 272 273 public void func_82462_a(Entity par1Entity, Entity par2Entity) 274 { 275 String var3 = "entity_" + par1Entity.entityId; 276 277 if (this.field_82470_g.contains(var3)) 278 { 279 if (sndSystem.playing(var3)) 280 { 281 sndSystem.setPosition(var3, (float)par2Entity.posX, (float)par2Entity.posY, (float)par2Entity.posZ); 282 sndSystem.setVelocity(var3, (float)par2Entity.motionX, (float)par2Entity.motionY, (float)par2Entity.motionZ); 283 } 284 else 285 { 286 this.field_82470_g.remove(var3); 287 } 288 } 289 } 290 291 public boolean func_82465_b(Entity par1Entity) 292 { 293 if (par1Entity != null && loaded && this.options.musicVolume != 0.0F) 294 { 295 String var2 = "entity_" + par1Entity.entityId; 296 return sndSystem.playing(var2); 297 } 298 else 299 { 300 return false; 301 } 302 } 303 304 public void func_82469_c(Entity par1Entity) 305 { 306 if (par1Entity != null && loaded && this.options.musicVolume != 0.0F) 307 { 308 String var2 = "entity_" + par1Entity.entityId; 309 310 if (this.field_82470_g.contains(var2)) 311 { 312 if (sndSystem.playing(var2)) 313 { 314 sndSystem.stop(var2); 315 } 316 317 this.field_82470_g.remove(var2); 318 } 319 } 320 } 321 322 public void func_82468_a(Entity par1Entity, float par2) 323 { 324 if (par1Entity != null && loaded && this.options.musicVolume != 0.0F) 325 { 326 if (loaded && this.options.soundVolume != 0.0F) 327 { 328 String var3 = "entity_" + par1Entity.entityId; 329 330 if (sndSystem.playing(var3)) 331 { 332 sndSystem.setVolume(var3, par2 * this.options.soundVolume); 333 } 334 } 335 } 336 } 337 338 public void func_82463_b(Entity par1Entity, float par2) 339 { 340 if (par1Entity != null && loaded && this.options.musicVolume != 0.0F) 341 { 342 if (loaded && this.options.soundVolume != 0.0F) 343 { 344 String var3 = "entity_" + par1Entity.entityId; 345 346 if (sndSystem.playing(var3)) 347 { 348 sndSystem.setPitch(var3, par2); 349 } 350 } 351 } 352 } 353 354 public void func_82467_a(String par1Str, Entity par2Entity, float par3, float par4, boolean par5) 355 { 356 if (par2Entity != null) 357 { 358 if (loaded && (this.options.soundVolume != 0.0F || par1Str == null)) 359 { 360 String var6 = "entity_" + par2Entity.entityId; 361 362 if (this.field_82470_g.contains(var6)) 363 { 364 this.func_82460_a(par2Entity); 365 } 366 else 367 { 368 if (sndSystem.playing(var6)) 369 { 370 sndSystem.stop(var6); 371 } 372 373 if (par1Str == null) 374 { 375 return; 376 } 377 378 SoundPoolEntry var7 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str); 379 380 if (var7 != null && par3 > 0.0F) 381 { 382 float var8 = 16.0F; 383 384 if (par3 > 1.0F) 385 { 386 var8 *= par3; 387 } 388 389 sndSystem.newSource(par5, var6, var7.soundUrl, var7.soundName, false, (float)par2Entity.posX, (float)par2Entity.posY, (float)par2Entity.posZ, 2, var8); 390 sndSystem.setLooping(var6, true); 391 sndSystem.setPitch(var6, par4); 392 393 if (par3 > 1.0F) 394 { 395 par3 = 1.0F; 396 } 397 398 sndSystem.setVolume(var6, par3 * this.options.soundVolume); 399 sndSystem.setVelocity(var6, (float)par2Entity.motionX, (float)par2Entity.motionY, (float)par2Entity.motionZ); 400 sndSystem.play(var6); 401 this.field_82470_g.add(var6); 402 } 403 } 404 } 405 } 406 } 407 408 /** 409 * Plays a sound. Args: soundName, x, y, z, volume, pitch 410 */ 411 public void playSound(String par1Str, float par2, float par3, float par4, float par5, float par6) 412 { 413 if (loaded && this.options.soundVolume != 0.0F) 414 { 415 SoundPoolEntry var7 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str); 416 var7 = SoundEvent.getResult(new PlaySoundEvent(this, var7, par1Str, par2, par3, par4, par5, par6)); 417 418 if (var7 != null && par5 > 0.0F) 419 { 420 this.latestSoundID = (this.latestSoundID + 1) % 256; 421 String var8 = "sound_" + this.latestSoundID; 422 float var9 = 16.0F; 423 424 if (par5 > 1.0F) 425 { 426 var9 *= par5; 427 } 428 429 sndSystem.newSource(par5 > 1.0F, var8, var7.soundUrl, var7.soundName, false, par2, par3, par4, 2, var9); 430 sndSystem.setPitch(var8, par6); 431 432 if (par5 > 1.0F) 433 { 434 par5 = 1.0F; 435 } 436 437 sndSystem.setVolume(var8, par5 * this.options.soundVolume); 438 MinecraftForge.EVENT_BUS.post(new PlaySoundSourceEvent(this, var8, par2, par3, par4)); 439 sndSystem.play(var8); 440 } 441 } 442 } 443 444 /** 445 * Plays a sound effect with the volume and pitch of the parameters passed. The sound isn't affected by position of 446 * the player (full volume and center balanced) 447 */ 448 public void playSoundFX(String par1Str, float par2, float par3) 449 { 450 if (loaded && this.options.soundVolume != 0.0F) 451 { 452 SoundPoolEntry var4 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str); 453 var4 = SoundEvent.getResult(new PlaySoundEffectEvent(this, var4, par1Str, par2, par3)); 454 455 if (var4 != null) 456 { 457 this.latestSoundID = (this.latestSoundID + 1) % 256; 458 String var5 = "sound_" + this.latestSoundID; 459 sndSystem.newSource(false, var5, var4.soundUrl, var4.soundName, false, 0.0F, 0.0F, 0.0F, 0, 0.0F); 460 461 if (par2 > 1.0F) 462 { 463 par2 = 1.0F; 464 } 465 466 par2 *= 0.25F; 467 sndSystem.setPitch(var5, par3); 468 sndSystem.setVolume(var5, par2 * this.options.soundVolume); 469 MinecraftForge.EVENT_BUS.post(new PlaySoundEffectSourceEvent(this, var5)); 470 sndSystem.play(var5); 471 } 472 } 473 } 474 475 public void func_82466_e() 476 { 477 Iterator var1 = this.field_82470_g.iterator(); 478 479 while (var1.hasNext()) 480 { 481 String var2 = (String)var1.next(); 482 sndSystem.pause(var2); 483 } 484 } 485 486 public void func_82461_f() 487 { 488 Iterator var1 = this.field_82470_g.iterator(); 489 490 while (var1.hasNext()) 491 { 492 String var2 = (String)var1.next(); 493 sndSystem.play(var2); 494 } 495 } 496 }