001    package net.minecraft.src;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    import java.io.File;
006    import java.util.Random;
007    
008    import net.minecraftforge.client.ForgeHooksClient;
009    import net.minecraftforge.client.ModCompatibilityClient;
010    import net.minecraftforge.client.event.sound.PlaySoundEffectEvent;
011    import net.minecraftforge.client.event.sound.PlaySoundEffectSourceEvent;
012    import net.minecraftforge.client.event.sound.PlaySoundEvent;
013    import net.minecraftforge.client.event.sound.PlaySoundSourceEvent;
014    import net.minecraftforge.client.event.sound.PlayStreamingEvent;
015    import net.minecraftforge.client.event.sound.PlayStreamingSourceEvent;
016    import net.minecraftforge.client.event.sound.SoundEvent;
017    import net.minecraftforge.client.event.sound.PlayBackgroundMusicEvent;
018    import net.minecraftforge.client.event.sound.SoundLoadEvent;
019    import net.minecraftforge.client.event.sound.SoundSetupEvent;
020    import net.minecraftforge.common.MinecraftForge;
021    import static net.minecraftforge.client.event.sound.SoundEvent.*;
022    import paulscode.sound.SoundSystem;
023    import paulscode.sound.SoundSystemConfig;
024    import paulscode.sound.codecs.CodecJOrbis;
025    import paulscode.sound.codecs.CodecWav;
026    import paulscode.sound.libraries.LibraryLWJGLOpenAL;
027    
028    @SideOnly(Side.CLIENT)
029    public class SoundManager
030    {
031        /** A reference to the sound system. */
032        public static SoundSystem sndSystem;
033    
034        /** Sound pool containing sounds. */
035        public SoundPool soundPoolSounds = new SoundPool();
036    
037        /** Sound pool containing streaming audio. */
038        public SoundPool soundPoolStreaming = new SoundPool();
039    
040        /** Sound pool containing music. */
041        public SoundPool soundPoolMusic = new SoundPool();
042    
043        /**
044         * The last ID used when a sound is played, passed into SoundSystem to give active sounds a unique ID
045         */
046        private int latestSoundID = 0;
047    
048        /** A reference to the game settings. */
049        private GameSettings options;
050    
051        /** Set to true when the SoundManager has been initialised. */
052        private static boolean loaded = false;
053    
054        /** RNG. */
055        private Random rand = new Random();
056        private int ticksBeforeMusic;
057    
058        public static int MUSIC_INTERVAL = 12000;
059    
060        public SoundManager()
061        {
062            this.ticksBeforeMusic = this.rand.nextInt(MUSIC_INTERVAL);
063        }
064    
065        /**
066         * Used for loading sound settings from GameSettings
067         */
068        public void loadSoundSettings(GameSettings par1GameSettings)
069        {
070            this.soundPoolStreaming.isGetRandomSound = false;
071            this.options = par1GameSettings;
072    
073            if (!loaded && (par1GameSettings == null || par1GameSettings.soundVolume != 0.0F || par1GameSettings.musicVolume != 0.0F))
074            {
075                this.tryToSetLibraryAndCodecs();
076            }
077            ModCompatibilityClient.audioModLoad(this);
078            MinecraftForge.EVENT_BUS.post(new SoundLoadEvent(this));
079        }
080    
081        /**
082         * Tries to add the paulscode library and the relevant codecs. If it fails, the volumes (sound and music) will be
083         * set to zero in the options file.
084         */
085        private void tryToSetLibraryAndCodecs()
086        {
087            try
088            {
089                float var1 = this.options.soundVolume;
090                float var2 = this.options.musicVolume;
091                this.options.soundVolume = 0.0F;
092                this.options.musicVolume = 0.0F;
093                this.options.saveOptions();
094                SoundSystemConfig.addLibrary(LibraryLWJGLOpenAL.class);
095                SoundSystemConfig.setCodec("ogg", CodecJOrbis.class);
096                SoundSystemConfig.setCodec("mus", CodecMus.class);
097                SoundSystemConfig.setCodec("wav", CodecWav.class);
098                ModCompatibilityClient.audioModAddCodecs();
099                MinecraftForge.EVENT_BUS.post(new SoundSetupEvent(this));
100                sndSystem = new SoundSystem();
101                this.options.soundVolume = var1;
102                this.options.musicVolume = var2;
103                this.options.saveOptions();
104            }
105            catch (Throwable var3)
106            {
107                var3.printStackTrace();
108                System.err.println("error linking with the LibraryJavaSound plug-in");
109            }
110    
111            loaded = true;
112        }
113    
114        /**
115         * Called when one of the sound level options has changed.
116         */
117        public void onSoundOptionsChanged()
118        {
119            if (!loaded && (this.options.soundVolume != 0.0F || this.options.musicVolume != 0.0F))
120            {
121                this.tryToSetLibraryAndCodecs();
122            }
123    
124            if (loaded)
125            {
126                if (this.options.musicVolume == 0.0F)
127                {
128                    sndSystem.stop("BgMusic");
129                }
130                else
131                {
132                    sndSystem.setVolume("BgMusic", this.options.musicVolume);
133                }
134            }
135        }
136    
137        /**
138         * Called when Minecraft is closing down.
139         */
140        public void closeMinecraft()
141        {
142            if (loaded)
143            {
144                sndSystem.cleanup();
145            }
146        }
147    
148        /**
149         * Adds a sounds with the name from the file. Args: name, file
150         */
151        public void addSound(String par1Str, File par2File)
152        {
153            this.soundPoolSounds.addSound(par1Str, par2File);
154        }
155    
156        /**
157         * Adds an audio file to the streaming SoundPool.
158         */
159        public void addStreaming(String par1Str, File par2File)
160        {
161            this.soundPoolStreaming.addSound(par1Str, par2File);
162        }
163    
164        /**
165         * Adds an audio file to the music SoundPool.
166         */
167        public void addMusic(String par1Str, File par2File)
168        {
169            this.soundPoolMusic.addSound(par1Str, par2File);
170        }
171    
172        /**
173         * If its time to play new music it starts it up.
174         */
175        public void playRandomMusicIfReady()
176        {
177            if (loaded && this.options.musicVolume != 0.0F)
178            {
179                if (!sndSystem.playing("BgMusic") && !sndSystem.playing("streaming"))
180                {
181                    if (this.ticksBeforeMusic > 0)
182                    {
183                        --this.ticksBeforeMusic;
184                        return;
185                    }
186    
187                    SoundPoolEntry var1 = this.soundPoolMusic.getRandomSound();
188                    var1 = ModCompatibilityClient.audioModPickBackgroundMusic(this, var1);
189                    var1 = SoundEvent.getResult(new PlayBackgroundMusicEvent(this, var1));
190    
191                    if (var1 != null)
192                    {
193                        this.ticksBeforeMusic = this.rand.nextInt(MUSIC_INTERVAL) + MUSIC_INTERVAL;
194                        sndSystem.backgroundMusic("BgMusic", var1.soundUrl, var1.soundName, false);
195                        sndSystem.setVolume("BgMusic", this.options.musicVolume);
196                        sndSystem.play("BgMusic");
197                    }
198                }
199            }
200        }
201    
202        /**
203         * Sets the listener of sounds
204         */
205        public void setListener(EntityLiving par1EntityLiving, float par2)
206        {
207            if (loaded && this.options.soundVolume != 0.0F)
208            {
209                if (par1EntityLiving != null)
210                {
211                    float var3 = par1EntityLiving.prevRotationYaw + (par1EntityLiving.rotationYaw - par1EntityLiving.prevRotationYaw) * par2;
212                    double var4 = par1EntityLiving.prevPosX + (par1EntityLiving.posX - par1EntityLiving.prevPosX) * (double)par2;
213                    double var6 = par1EntityLiving.prevPosY + (par1EntityLiving.posY - par1EntityLiving.prevPosY) * (double)par2;
214                    double var8 = par1EntityLiving.prevPosZ + (par1EntityLiving.posZ - par1EntityLiving.prevPosZ) * (double)par2;
215                    float var10 = MathHelper.cos(-var3 * 0.017453292F - (float)Math.PI);
216                    float var11 = MathHelper.sin(-var3 * 0.017453292F - (float)Math.PI);
217                    float var12 = -var11;
218                    float var13 = 0.0F;
219                    float var14 = -var10;
220                    float var15 = 0.0F;
221                    float var16 = 1.0F;
222                    float var17 = 0.0F;
223                    sndSystem.setListenerPosition((float)var4, (float)var6, (float)var8);
224                    sndSystem.setListenerOrientation(var12, var13, var14, var15, var16, var17);
225                }
226            }
227        }
228    
229        public void playStreaming(String par1Str, float par2, float par3, float par4, float par5, float par6)
230        {
231            if (loaded && (this.options.soundVolume != 0.0F || par1Str == null))
232            {
233                String var7 = "streaming";
234    
235                if (sndSystem.playing("streaming"))
236                {
237                    sndSystem.stop("streaming");
238                }
239    
240                if (par1Str != null)
241                {
242                    SoundPoolEntry var8 = this.soundPoolStreaming.getRandomSoundFromSoundPool(par1Str);
243                    var8 = SoundEvent.getResult(new PlayStreamingEvent(this, var8, par1Str, par2, par3, par4));
244    
245                    if (var8 != null && par5 > 0.0F)
246                    {
247                        if (sndSystem.playing("BgMusic"))
248                        {
249                            sndSystem.stop("BgMusic");
250                        }
251    
252                        float var9 = 16.0F;
253                        sndSystem.newStreamingSource(true, var7, var8.soundUrl, var8.soundName, false, par2, par3, par4, 2, var9 * 4.0F);
254                        sndSystem.setVolume(var7, 0.5F * this.options.soundVolume);
255                        MinecraftForge.EVENT_BUS.post(new PlayStreamingSourceEvent(this, var7, par2, par3, par4));
256                        sndSystem.play(var7);
257                    }
258                }
259            }
260        }
261    
262        /**
263         * Plays a sound. Args: soundName, x, y, z, volume, pitch
264         */
265        public void playSound(String par1Str, float par2, float par3, float par4, float par5, float par6)
266        {
267            if (loaded && this.options.soundVolume != 0.0F)
268            {
269                SoundPoolEntry var7 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str);
270                var7 = SoundEvent.getResult(new PlaySoundEvent(this, var7, par1Str, par2, par3, par4, par5, par6));
271    
272                if (var7 != null && par5 > 0.0F)
273                {
274                    this.latestSoundID = (this.latestSoundID + 1) % 256;
275                    String var8 = "sound_" + this.latestSoundID;
276                    float var9 = 16.0F;
277    
278                    if (par5 > 1.0F)
279                    {
280                        var9 *= par5;
281                    }
282    
283                    sndSystem.newSource(par5 > 1.0F, var8, var7.soundUrl, var7.soundName, false, par2, par3, par4, 2, var9);
284                    sndSystem.setPitch(var8, par6);
285    
286                    if (par5 > 1.0F)
287                    {
288                        par5 = 1.0F;
289                    }
290    
291                    sndSystem.setVolume(var8, par5 * this.options.soundVolume);
292                    MinecraftForge.EVENT_BUS.post(new PlaySoundSourceEvent(this, var8, par2, par3, par4));
293                    sndSystem.play(var8);
294                }
295            }
296        }
297    
298        /**
299         * Plays a sound effect with the volume and pitch of the parameters passed. The sound isn't affected by position of
300         * the player (full volume and center balanced)
301         */
302        public void playSoundFX(String par1Str, float par2, float par3)
303        {
304            if (loaded && this.options.soundVolume != 0.0F)
305            {
306                SoundPoolEntry var4 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str);
307                var4 = SoundEvent.getResult(new PlaySoundEffectEvent(this, var4, par1Str, par2, par3));
308    
309                if (var4 != null)
310                {
311                    this.latestSoundID = (this.latestSoundID + 1) % 256;
312                    String var5 = "sound_" + this.latestSoundID;
313                    sndSystem.newSource(false, var5, var4.soundUrl, var4.soundName, false, 0.0F, 0.0F, 0.0F, 0, 0.0F);
314    
315                    if (par2 > 1.0F)
316                    {
317                        par2 = 1.0F;
318                    }
319    
320                    par2 *= 0.25F;
321                    sndSystem.setPitch(var5, par3);
322                    sndSystem.setVolume(var5, par2 * this.options.soundVolume);
323                    MinecraftForge.EVENT_BUS.post(new PlaySoundEffectSourceEvent(this, var5));
324                    sndSystem.play(var5);
325                }
326            }
327        }
328    }