package net.minecraft.client.audio; import net.minecraftforge.client.*; import net.minecraftforge.client.event.sound.*; import net.minecraftforge.common.MinecraftForge; import static net.minecraftforge.client.event.sound.SoundEvent.*; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.util.MathHelper; import paulscode.sound.SoundSystem; import paulscode.sound.SoundSystemConfig; import paulscode.sound.codecs.CodecJOrbis; import paulscode.sound.codecs.CodecWav; import paulscode.sound.libraries.LibraryLWJGLOpenAL; @SideOnly(Side.CLIENT) public class SoundManager { /** A reference to the sound system. */ public static SoundSystem sndSystem; /** Sound pool containing sounds. */ public SoundPool soundPoolSounds = new SoundPool(); /** Sound pool containing streaming audio. */ public SoundPool soundPoolStreaming = new SoundPool(); /** Sound pool containing music. */ public SoundPool soundPoolMusic = new SoundPool(); /** * The last ID used when a sound is played, passed into SoundSystem to give active sounds a unique ID */ private int latestSoundID = 0; /** A reference to the game settings. */ private GameSettings options; /** Identifiers of all currently playing sounds. Type: HashSet<String> */ private Set playingSounds = new HashSet(); private List field_92072_h = new ArrayList(); /** Set to true when the SoundManager has been initialised. */ private static boolean loaded = false; /** RNG. */ private Random rand = new Random(); private int ticksBeforeMusic; public static int MUSIC_INTERVAL = 12000; public SoundManager() { this.ticksBeforeMusic = this.rand.nextInt(MUSIC_INTERVAL); } /** * Used for loading sound settings from GameSettings */ public void loadSoundSettings(GameSettings par1GameSettings) { this.soundPoolStreaming.isGetRandomSound = false; this.options = par1GameSettings; if (!loaded && (par1GameSettings == null || par1GameSettings.soundVolume != 0.0F || par1GameSettings.musicVolume != 0.0F)) { this.tryToSetLibraryAndCodecs(); } ModCompatibilityClient.audioModLoad(this); MinecraftForge.EVENT_BUS.post(new SoundLoadEvent(this)); } /** * Tries to add the paulscode library and the relevant codecs. If it fails, the volumes (sound and music) will be * set to zero in the options file. */ private void tryToSetLibraryAndCodecs() { try { float var1 = this.options.soundVolume; float var2 = this.options.musicVolume; this.options.soundVolume = 0.0F; this.options.musicVolume = 0.0F; this.options.saveOptions(); SoundSystemConfig.addLibrary(LibraryLWJGLOpenAL.class); SoundSystemConfig.setCodec("ogg", CodecJOrbis.class); SoundSystemConfig.setCodec("mus", CodecMus.class); SoundSystemConfig.setCodec("wav", CodecWav.class); ModCompatibilityClient.audioModAddCodecs(); MinecraftForge.EVENT_BUS.post(new SoundSetupEvent(this)); sndSystem = new SoundSystem(); this.options.soundVolume = var1; this.options.musicVolume = var2; this.options.saveOptions(); } catch (Throwable var3) { var3.printStackTrace(); System.err.println("error linking with the LibraryJavaSound plug-in"); } loaded = true; } /** * Called when one of the sound level options has changed. */ public void onSoundOptionsChanged() { if (!loaded && (this.options.soundVolume != 0.0F || this.options.musicVolume != 0.0F)) { this.tryToSetLibraryAndCodecs(); } if (loaded) { if (this.options.musicVolume == 0.0F) { sndSystem.stop("BgMusic"); } else { sndSystem.setVolume("BgMusic", this.options.musicVolume); } } } /** * Called when Minecraft is closing down. */ public void closeMinecraft() { if (loaded) { sndSystem.cleanup(); } } /** * Adds a sounds with the name from the file. Args: name, file */ public void addSound(String par1Str, File par2File) { this.soundPoolSounds.addSound(par1Str, par2File); } /** * Adds an audio file to the streaming SoundPool. */ public void addStreaming(String par1Str, File par2File) { this.soundPoolStreaming.addSound(par1Str, par2File); } /** * Adds an audio file to the music SoundPool. */ public void addMusic(String par1Str, File par2File) { this.soundPoolMusic.addSound(par1Str, par2File); } /** * If its time to play new music it starts it up. */ public void playRandomMusicIfReady() { if (loaded && this.options.musicVolume != 0.0F) { if (!sndSystem.playing("BgMusic") && !sndSystem.playing("streaming")) { if (this.ticksBeforeMusic > 0) { --this.ticksBeforeMusic; return; } SoundPoolEntry var1 = this.soundPoolMusic.getRandomSound(); var1 = ModCompatibilityClient.audioModPickBackgroundMusic(this, var1); var1 = SoundEvent.getResult(new PlayBackgroundMusicEvent(this, var1)); if (var1 != null) { this.ticksBeforeMusic = this.rand.nextInt(MUSIC_INTERVAL) + MUSIC_INTERVAL; sndSystem.backgroundMusic("BgMusic", var1.soundUrl, var1.soundName, false); sndSystem.setVolume("BgMusic", this.options.musicVolume); sndSystem.play("BgMusic"); } } } } /** * Sets the listener of sounds */ public void setListener(EntityLiving par1EntityLiving, float par2) { if (loaded && this.options.soundVolume != 0.0F) { if (par1EntityLiving != null) { float var3 = par1EntityLiving.prevRotationPitch + (par1EntityLiving.rotationPitch - par1EntityLiving.prevRotationPitch) * par2; float var4 = par1EntityLiving.prevRotationYaw + (par1EntityLiving.rotationYaw - par1EntityLiving.prevRotationYaw) * par2; double var5 = par1EntityLiving.prevPosX + (par1EntityLiving.posX - par1EntityLiving.prevPosX) * (double)par2; double var7 = par1EntityLiving.prevPosY + (par1EntityLiving.posY - par1EntityLiving.prevPosY) * (double)par2; double var9 = par1EntityLiving.prevPosZ + (par1EntityLiving.posZ - par1EntityLiving.prevPosZ) * (double)par2; float var11 = MathHelper.cos(-var4 * 0.017453292F - (float)Math.PI); float var12 = MathHelper.sin(-var4 * 0.017453292F - (float)Math.PI); float var13 = -var12; float var14 = -MathHelper.sin(-var3 * 0.017453292F - (float)Math.PI); float var15 = -var11; float var16 = 0.0F; float var17 = 1.0F; float var18 = 0.0F; sndSystem.setListenerPosition((float)var5, (float)var7, (float)var9); sndSystem.setListenerOrientation(var13, var14, var15, var16, var17, var18); } } } /** * Stops all currently playing sounds */ public void stopAllSounds() { Iterator var1 = this.playingSounds.iterator(); while (var1.hasNext()) { String var2 = (String)var1.next(); sndSystem.stop(var2); } this.playingSounds.clear(); } public void playStreaming(String par1Str, float par2, float par3, float par4) { if (loaded && (this.options.soundVolume != 0.0F || par1Str == null)) { String var5 = "streaming"; if (sndSystem.playing(var5)) { sndSystem.stop(var5); } if (par1Str != null) { SoundPoolEntry var6 = this.soundPoolStreaming.getRandomSoundFromSoundPool(par1Str); var6 = SoundEvent.getResult(new PlayStreamingEvent(this, var6, par1Str, par2, par3, par4)); if (var6 != null) { if (sndSystem.playing("BgMusic")) { sndSystem.stop("BgMusic"); } float var7 = 16.0F; sndSystem.newStreamingSource(true, var5, var6.soundUrl, var6.soundName, false, par2, par3, par4, 2, var7 * 4.0F); sndSystem.setVolume(var5, 0.5F * this.options.soundVolume); MinecraftForge.EVENT_BUS.post(new PlayStreamingSourceEvent(this, var5, par2, par3, par4)); sndSystem.play(var5); } } } } /** * Updates the sound associated with the entity with that entity's position and velocity. Args: the entity */ public void updateSoundLocation(Entity par1Entity) { this.updateSoundLocation(par1Entity, par1Entity); } /** * Updates the sound associated with soundEntity with the position and velocity of trackEntity. Args: soundEntity, * trackEntity */ public void updateSoundLocation(Entity par1Entity, Entity par2Entity) { String var3 = "entity_" + par1Entity.entityId; if (this.playingSounds.contains(var3)) { if (sndSystem.playing(var3)) { sndSystem.setPosition(var3, (float)par2Entity.posX, (float)par2Entity.posY, (float)par2Entity.posZ); sndSystem.setVelocity(var3, (float)par2Entity.motionX, (float)par2Entity.motionY, (float)par2Entity.motionZ); } else { this.playingSounds.remove(var3); } } } /** * Returns true if a sound is currently associated with the given entity, or false otherwise. */ public boolean isEntitySoundPlaying(Entity par1Entity) { if (par1Entity != null && loaded) { String var2 = "entity_" + par1Entity.entityId; return sndSystem.playing(var2); } else { return false; } } /** * Stops playing the sound associated with the given entity */ public void stopEntitySound(Entity par1Entity) { if (par1Entity != null && loaded) { String var2 = "entity_" + par1Entity.entityId; if (this.playingSounds.contains(var2)) { if (sndSystem.playing(var2)) { sndSystem.stop(var2); } this.playingSounds.remove(var2); } } } /** * Sets the volume of the sound associated with the given entity, if one is playing. The volume is scaled by the * global sound volume. Args: the entity, the volume (from 0 to 1) */ public void setEntitySoundVolume(Entity par1Entity, float par2) { if (par1Entity != null && loaded) { if (loaded && this.options.soundVolume != 0.0F) { String var3 = "entity_" + par1Entity.entityId; if (sndSystem.playing(var3)) { sndSystem.setVolume(var3, par2 * this.options.soundVolume); } } } } /** * Sets the pitch of the sound associated with the given entity, if one is playing. Args: the entity, the pitch */ public void setEntitySoundPitch(Entity par1Entity, float par2) { if (par1Entity != null && loaded) { if (loaded && this.options.soundVolume != 0.0F) { String var3 = "entity_" + par1Entity.entityId; if (sndSystem.playing(var3)) { sndSystem.setPitch(var3, par2); } } } } /** * If a sound is already playing from the given entity, update the position and velocity of that sound to match the * entity. Otherwise, start playing a sound from that entity. Args: The sound name, the entity, the volume, the * pitch, unknown flag */ public void playEntitySound(String par1Str, Entity par2Entity, float par3, float par4, boolean par5) { if (par2Entity != null) { if (loaded && (this.options.soundVolume != 0.0F || par1Str == null)) { String var6 = "entity_" + par2Entity.entityId; if (this.playingSounds.contains(var6)) { this.updateSoundLocation(par2Entity); } else { if (sndSystem.playing(var6)) { sndSystem.stop(var6); } if (par1Str == null) { return; } SoundPoolEntry var7 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str); if (var7 != null && par3 > 0.0F) { float var8 = 16.0F; if (par3 > 1.0F) { var8 *= par3; } sndSystem.newSource(par5, var6, var7.soundUrl, var7.soundName, false, (float)par2Entity.posX, (float)par2Entity.posY, (float)par2Entity.posZ, 2, var8); sndSystem.setLooping(var6, true); sndSystem.setPitch(var6, par4); if (par3 > 1.0F) { par3 = 1.0F; } sndSystem.setVolume(var6, par3 * this.options.soundVolume); sndSystem.setVelocity(var6, (float)par2Entity.motionX, (float)par2Entity.motionY, (float)par2Entity.motionZ); sndSystem.play(var6); this.playingSounds.add(var6); } } } } } /** * Plays a sound. Args: soundName, x, y, z, volume, pitch */ public void playSound(String par1Str, float par2, float par3, float par4, float par5, float par6) { if (loaded && this.options.soundVolume != 0.0F) { SoundPoolEntry var7 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str); var7 = SoundEvent.getResult(new PlaySoundEvent(this, var7, par1Str, par2, par3, par4, par5, par6)); if (var7 != null && par5 > 0.0F) { this.latestSoundID = (this.latestSoundID + 1) % 256; String var8 = "sound_" + this.latestSoundID; float var9 = 16.0F; if (par5 > 1.0F) { var9 *= par5; } sndSystem.newSource(par5 > 1.0F, var8, var7.soundUrl, var7.soundName, false, par2, par3, par4, 2, var9); sndSystem.setPitch(var8, par6); if (par5 > 1.0F) { par5 = 1.0F; } sndSystem.setVolume(var8, par5 * this.options.soundVolume); MinecraftForge.EVENT_BUS.post(new PlaySoundSourceEvent(this, var8, par2, par3, par4)); sndSystem.play(var8); } } } /** * Plays a sound effect with the volume and pitch of the parameters passed. The sound isn't affected by position of * the player (full volume and center balanced) */ public void playSoundFX(String par1Str, float par2, float par3) { if (loaded && this.options.soundVolume != 0.0F) { SoundPoolEntry var4 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str); var4 = SoundEvent.getResult(new PlaySoundEffectEvent(this, var4, par1Str, par2, par3)); if (var4 != null) { this.latestSoundID = (this.latestSoundID + 1) % 256; String var5 = "sound_" + this.latestSoundID; sndSystem.newSource(false, var5, var4.soundUrl, var4.soundName, false, 0.0F, 0.0F, 0.0F, 0, 0.0F); if (par2 > 1.0F) { par2 = 1.0F; } par2 *= 0.25F; sndSystem.setPitch(var5, par3); sndSystem.setVolume(var5, par2 * this.options.soundVolume); MinecraftForge.EVENT_BUS.post(new PlaySoundEffectSourceEvent(this, var5)); sndSystem.play(var5); } } } /** * Pauses all currently playing sounds */ public void pauseAllSounds() { Iterator var1 = this.playingSounds.iterator(); while (var1.hasNext()) { String var2 = (String)var1.next(); sndSystem.pause(var2); } } /** * Resumes playing all currently playing sounds (after pauseAllSounds) */ public void resumeAllSounds() { Iterator var1 = this.playingSounds.iterator(); while (var1.hasNext()) { String var2 = (String)var1.next(); sndSystem.play(var2); } } public void func_92071_g() { if (!this.field_92072_h.isEmpty()) { Iterator var1 = this.field_92072_h.iterator(); while (var1.hasNext()) { ScheduledSound var2 = (ScheduledSound)var1.next(); --var2.field_92064_g; if (var2.field_92064_g <= 0) { this.playSound(var2.field_92069_a, var2.field_92067_b, var2.field_92068_c, var2.field_92065_d, var2.field_92066_e, var2.field_92063_f); var1.remove(); } } } } public void func_92070_a(String par1Str, float par2, float par3, float par4, float par5, float par6, int par7) { this.field_92072_h.add(new ScheduledSound(par1Str, par2, par3, par4, par5, par6, par7)); } }