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    }