New ISoundHandler interface, useful for adding custom sounds and dealign with sound based events.

Includes basuic AudioMod compatibility.
This commit is contained in:
LexManos 2012-04-22 19:52:09 -07:00
parent d6b387f39b
commit 796d4fea70
6 changed files with 511 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import net.minecraft.src.Entity;
import net.minecraft.src.ModLoader;
import net.minecraft.src.Packet100OpenWindow;
import net.minecraft.src.RenderBlocks;
import net.minecraft.src.SoundPoolEntry;
import net.minecraft.src.Tessellator;
import net.minecraft.src.RenderGlobal;
import net.minecraft.src.EntityPlayer;
@ -392,4 +393,73 @@ public class ForgeHooksClient
e.printStackTrace();
}
}
public static LinkedList<ISoundHandler> soundHandlers = new LinkedList<ISoundHandler>();
public static void onSetupAudio(SoundManager soundManager)
{
for (ISoundHandler handler : soundHandlers)
{
handler.onSetupAudio(soundManager);
}
}
public static void onLoadSoundSettings(SoundManager soundManager)
{
for (ISoundHandler handler : soundHandlers)
{
handler.onLoadSoundSettings(soundManager);
}
}
public static SoundPoolEntry onPlayBackgroundMusic(SoundManager soundManager, SoundPoolEntry entry)
{
for (ISoundHandler handler : soundHandlers)
{
entry = handler.onPlayBackgroundMusic(soundManager, entry);
if (entry == null)
{
return null;
}
}
return entry;
}
public static SoundPoolEntry onPlayStreaming(SoundManager soundManager, SoundPoolEntry entry, String soundName, float x, float y, float z)
{
for (ISoundHandler handler : soundHandlers)
{
entry = handler.onPlayStreaming(soundManager, entry, soundName, x, y, z);
if (entry == null)
{
return null;
}
}
return entry;
}
public static SoundPoolEntry onPlaySound(SoundManager soundManager, SoundPoolEntry entry, String soundName, float x, float y, float z, float volume, float pitch)
{
for (ISoundHandler handler : soundHandlers)
{
entry = handler.onPlaySound(soundManager, entry, soundName, x, y, z, volume, pitch);
if (entry == null)
{
return null;
}
}
return entry;
}
public static SoundPoolEntry onPlaySoundEffect(SoundManager soundManager, SoundPoolEntry entry, String soundName, float volume, float pitch)
{
for (ISoundHandler handler : soundHandlers)
{
entry = handler.onPlaySoundEffect(soundManager, entry, soundName,volume, pitch);
if (entry == null)
{
return null;
}
}
return entry;
}
}

View File

@ -0,0 +1,95 @@
package net.minecraft.src.forge;
import net.minecraft.src.SoundManager;
import net.minecraft.src.SoundPoolEntry;
public interface ISoundHandler
{
/**
* This event is raised by the SoundManager when it does its first setup of the
* SoundSystemConfig's codecs, use this function to add your own codecs.
* @param soundManager The SoundManager instance
*/
void onSetupAudio(SoundManager soundManager);
/**
* Raised by the SoundManager.loadSoundSettings, this would be a good place for
* adding your custom sounds to the SoundPool.
*
* @param soundManager The SoundManager instance
*/
void onLoadSoundSettings(SoundManager soundManager);
/**
* Raised when the SoundManager tries to play a Background Music file,
* If you return null from this function it will prevent the sound from being played,
* you can return a different entry if you want to change the sound being played.
*
* If you do not want to change anything, just return the passed in entry.
*
* @param soundManager The SoundManager instance
* @param entry The current entry that will be played
* @return The new sound entry to play, or the current one passed in.
*/
SoundPoolEntry onPlayBackgroundMusic(SoundManager soundManager, SoundPoolEntry entry);
/**
* Raised when the SoundManager tries to play a 'Streaming' file,
* in vanilla it is only the Jukebox that uses this function.
*
* If you return null from this function it will prevent the sound from being played,
* you can return a different entry if you want to change the sound being played.
*
* If you do not want to change anything, just return the passed in entry.
*
* @param soundManager The SoundManager instance
* @param entry The current entry that will be played
* @param soundName The name of the request sound
* @param x The X position where the sound will be played
* @param y The Y position where the sound will be played
* @param z The Z position where the sound will be played
* @return The new sound entry to play, or the current one passed in.
*/
SoundPoolEntry onPlayStreaming(SoundManager soundManager, SoundPoolEntry entry, String soundName, float x, float y, float z);
/***
* Raised when the SoundManager tries to play a normal sound,
* dogs barking, footsteps, etc. THe majority of all sounds during normal game play.
*
* If you return null from this function it will prevent the sound from being played,
* you can return a different entry if you want to change the sound being played.
*
* If you do not want to change anything, just return the passed in entry.
*
* @param soundManager The SoundManager instance
* @param entry The current entry that will be played
* @param soundName The name of the request sound
* @param x The X position where the sound will be played
* @param y The Y position where the sound will be played
* @param z The Z position where the sound will be played
* @param volume The sound's volume, between 0.0 and 1.0
* @param pitch The sound's pitch
* @return The new sound entry to play, or the current one passed in.
*/
SoundPoolEntry onPlaySound(SoundManager soundManager, SoundPoolEntry entry, String soundName, float x, float y, float z, float volume, float pitch);
/**
* Raised when the SoundManager tries to play a effect sound,
* currently the only known sounds are 'random.click' when a GUI button is clicked,
* or 'portal.trigger' and 'portal.travel' when the player is near/inside a portal.
*
* If you return null from this function it will prevent the sound from being played,
* you can return a different entry if you want to change the sound being played.
*
* If you do not want to change anything, just return the passed in entry.
*
* @param soundManager The SoundManager instance
* @param entry The current entry that will be played
* @param soundName The name of the request sound
* @param volume The sound's volume, between 0.0 and 1.0
* @param pitch The sound's pitch
* @return The new sound entry to play, or the current one passed in.
*/
SoundPoolEntry onPlaySoundEffect(SoundManager soundManager, SoundPoolEntry entry, String soundName, float volume, float pitch);
}

View File

@ -55,6 +55,15 @@ public class MinecraftForgeClient
{
ForgeHooksClient.renderWorldLastHandlers.add(handler);
}
/**
* Registers a Sound Handler
* @param handler The handler
*/
public static void registerSoundHandler(ISoundHandler handler)
{
ForgeHooksClient.soundHandlers.add(handler);
}
/** Bind a texture. This is used to bind a texture file when
* performing your own rendering, rather than using ITextureProvider.

View File

@ -0,0 +1,177 @@
package net.minecraft.src.forge;
import java.io.File;
import java.io.IOException;
import paulscode.sound.SoundSystemConfig;
import net.minecraft.client.Minecraft;
import net.minecraft.src.*;
public class ModCompatibilityClient
{
/**
* Trys to get the class for the specified name, will also try the
* net.minecraft.src package in case we are in MCP
* Returns null if not found.
*
* @param name The class name
* @return The Class, or null if not found
*/
private static Class getClass(String name)
{
try
{
return Class.forName(name);
}
catch (Exception e)
{
try
{
return Class.forName("net.minecraft.src." + name);
}
catch (Exception e2)
{
return null;
}
}
}
/************************************************************************************************
* Risugami's AudioMod Compatibility
* http://www.minecraftforum.net/topic/75440-
*
* AudioMod adds a few extra codecs, loads audio from /resources/mods/*,
* introduces the concept of 'cave' sounds, which are determined by if
* the player is underneath a solid block.
*
* It also lowers the interval between background music songs to 6000
*/
public static SoundPool audioModSoundPoolCave;
private static int isAudioModInstalled = -1;
/**
* Determine if AudioMod is installed by checking for the existence of IBMX Codec,
* I wish there was a less ambiguous way, but there isn't.
* @return True if the IBMX codec was found (indicating AudioMod is installed)
*/
public static boolean isAudioModInstalled()
{
if (isAudioModInstalled == -1)
{
isAudioModInstalled = (getClass("paulscode.sound.codecs.CodecIBXM") != null ? 1 : 0);
}
return isAudioModInstalled == 1;
}
/**
* Populates the sound pools with with sounds from the /resources/mods folder
* And sets the interval between background music to 6000
*
* @param mngr The SoundManager instance
*/
public static void audioModLoad(SoundManager mngr)
{
if (!isAudioModInstalled())
{
return;
}
audioModSoundPoolCave = new SoundPool();
audioModLoadModAudio("minecraft/resources/mod/sound", mngr.getSoundsPool());
audioModLoadModAudio("minecraft/resources/mod/streaming", mngr.getStreamingPool());
audioModLoadModAudio("minecraft/resources/mod/music", mngr.getMusicPool());
audioModLoadModAudio("minecraft/resources/mod/cavemusic", audioModSoundPoolCave);
if (mngr.MUSIC_INTERVAL == 12000)
{
mngr.MUSIC_INTERVAL = 6000;
}
}
/**
* Walks the given path in the Minecraft app directory and adds audio to the SoundPool
* @param path The path to walk
* @param pool The pool to add sound to
*/
private static void audioModLoadModAudio(String path, SoundPool pool)
{
File folder = Minecraft.getAppDir(path);
try
{
audioModWalkFolder(folder, folder, pool);
}
catch (IOException ex)
{
ModLoader.getLogger().fine("Loading Mod audio failed for folder: " + path);
ModLoader.getLogger().fine(ex.toString());
ex.printStackTrace();
}
}
/**
* Walks the folder path recursively and calls pool.addSound on any file it finds.
*
* @param base The base path for the folder, determines the name when calling addSound
* @param folder The current folder
* @param pool The SoundPool to add the sound to
* @throws IOException
*/
private static void audioModWalkFolder(File base, File folder, SoundPool pool) throws IOException
{
if (folder.exists() || folder.mkdirs())
{
for (File file : folder.listFiles())
{
if (!file.getName().startsWith("."))
{
if (file.isDirectory())
{
audioModWalkFolder(base, file, pool);
}
else if (file.isFile())
{
String subpath = file.getPath().substring(base.getPath().length() + 1).replace('\\', '/');
pool.addSound(subpath, file);
}
}
}
}
}
/**
* Adds the IBXM codec and associates it with .xm, .s3m, and .mod
*/
public static void audioModAddCodecs()
{
Class codec = getClass("paulscode.sound.codecs.CodecIBXM");
if (isAudioModInstalled() && codec != null)
{
SoundSystemConfig.setCodec("xm", codec);
SoundSystemConfig.setCodec("s3m", codec);
SoundSystemConfig.setCodec("mod", codec);
}
}
/**
* If the current player is underground, it picks a random song from the cave sound pool,
* if they are not it returns the passed in entry.
*
* @param soundManager The SoundManager instance
* @param current The currently selected entry
* @return A soundPool entry to be played as the background music
*/
public static SoundPoolEntry audioModPickBackgroundMusic(SoundManager soundManager, SoundPoolEntry current)
{
Minecraft mc = ModLoader.getMinecraftInstance();
if (isAudioModInstalled() && mc != null && mc.theWorld != null && audioModSoundPoolCave != null)
{
Entity ent = mc.renderViewEntity;
int x = MathHelper.func_40346_b(ent.posX);
int y = MathHelper.func_40346_b(ent.posY);
int z = MathHelper.func_40346_b(ent.posZ);
return (mc.theWorld.canBlockSeeTheSky(x, y, z) ? current : audioModSoundPoolCave.getRandomSound());
}
return current;
}
}

View File

@ -0,0 +1,108 @@
--- ../src_base/minecraft/net/minecraft/src/SoundManager.java 0000-00-00 00:00:00.000000000 -0000
+++ ../src_work/minecraft/net/minecraft/src/SoundManager.java 0000-00-00 00:00:00.000000000 -0000
@@ -2,6 +2,9 @@
import java.io.File;
import java.util.Random;
+
+import net.minecraft.src.forge.ForgeHooksClient;
+import net.minecraft.src.forge.ModCompatibilityClient;
import paulscode.sound.SoundSystem;
import paulscode.sound.SoundSystemConfig;
import paulscode.sound.codecs.CodecJOrbis;
@@ -36,10 +39,12 @@
/** RNG. */
private Random rand = new Random();
private int ticksBeforeMusic;
+
+ public static int MUSIC_INTERVAL = 12000;
public SoundManager()
{
- this.ticksBeforeMusic = this.rand.nextInt(12000);
+ this.ticksBeforeMusic = this.rand.nextInt(MUSIC_INTERVAL);
}
/**
@@ -54,6 +59,8 @@
{
this.tryToSetLibraryAndCodecs();
}
+ ModCompatibilityClient.audioModLoad(this);
+ ForgeHooksClient.onLoadSoundSettings(this);
}
/**
@@ -73,6 +80,8 @@
SoundSystemConfig.setCodec("ogg", CodecJOrbis.class);
SoundSystemConfig.setCodec("mus", CodecMus.class);
SoundSystemConfig.setCodec("wav", CodecWav.class);
+ ModCompatibilityClient.audioModAddCodecs();
+ ForgeHooksClient.onSetupAudio(this);
sndSystem = new SoundSystem();
this.options.soundVolume = var1;
this.options.musicVolume = var2;
@@ -161,10 +170,12 @@
}
SoundPoolEntry var1 = this.soundPoolMusic.getRandomSound();
+ var1 = ModCompatibilityClient.audioModPickBackgroundMusic(this, var1);
+ var1 = ForgeHooksClient.onPlayBackgroundMusic(this, var1);
if (var1 != null)
{
- this.ticksBeforeMusic = this.rand.nextInt(12000) + 12000;
+ 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");
@@ -214,6 +225,7 @@
if (par1Str != null)
{
SoundPoolEntry var8 = this.soundPoolStreaming.getRandomSoundFromSoundPool(par1Str);
+ var8 = ForgeHooksClient.onPlayStreaming(this, var8, par1Str, par2, par3, par4);
if (var8 != null && par5 > 0.0F)
{
@@ -239,6 +251,7 @@
if (loaded && this.options.soundVolume != 0.0F)
{
SoundPoolEntry var7 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str);
+ var7 = ForgeHooksClient.onPlaySound(this, var7, par1Str, par2, par3, par4, par5, par6);
if (var7 != null && par5 > 0.0F)
{
@@ -274,6 +287,7 @@
if (loaded && this.options.soundVolume != 0.0F)
{
SoundPoolEntry var4 = this.soundPoolSounds.getRandomSoundFromSoundPool(par1Str);
+ var4 = ForgeHooksClient.onPlaySoundEffect(this, var4, par1Str, par2, par3);
if (var4 != null)
{
@@ -293,4 +307,25 @@
}
}
}
+
+ /** Getters for private class members **/
+ public static SoundSystem getSoundSystem()
+ {
+ return sndSystem;
+ }
+
+ public SoundPool getSoundsPool()
+ {
+ return soundPoolSounds;
+ }
+
+ public SoundPool getStreamingPool()
+ {
+ return soundPoolStreaming;
+ }
+
+ public SoundPool getMusicPool()
+ {
+ return soundPoolMusic;
+ }
}

View File

@ -0,0 +1,52 @@
--- ../src_base/minecraft/net/minecraft/src/SoundPool.java 0000-00-00 00:00:00.000000000 -0000
+++ ../src_work/minecraft/net/minecraft/src/SoundPool.java 0000-00-00 00:00:00.000000000 -0000
@@ -2,6 +2,7 @@
import java.io.File;
import java.net.MalformedURLException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -33,6 +34,25 @@
*/
public SoundPoolEntry addSound(String par1Str, File par2File)
{
+ try
+ {
+ return addSound(par1Str, par2File.toURI().toURL());
+ }
+ catch (MalformedURLException ex)
+ {
+ ex.printStackTrace();
+ throw new RuntimeException(ex);
+ }
+ }
+ /**
+ * URL version of addSound, as the back-end sound engine has full support for various types of URLs
+ *
+ * @param par1Str The name of the sound to add
+ * @param url The url of the sound resource
+ * @return A SoundPoolEntry for the newly added sound
+ */
+ public SoundPoolEntry addSound(String par1Str, URL url)
+ {
try
{
String var3 = par1Str;
@@ -53,13 +73,13 @@
this.nameToSoundPoolEntriesMapping.put(par1Str, new ArrayList());
}
- SoundPoolEntry var4 = new SoundPoolEntry(var3, par2File.toURI().toURL());
+ SoundPoolEntry var4 = new SoundPoolEntry(var3, url);
((List)this.nameToSoundPoolEntriesMapping.get(par1Str)).add(var4);
this.allSoundPoolEntries.add(var4);
++this.numberOfSoundPoolEntries;
return var4;
}
- catch (MalformedURLException var5)
+ catch (Exception var5)
{
var5.printStackTrace();
throw new RuntimeException(var5);