サウンドシステムの扱いについて

Minecraft 1.4.7, Minecraft Forge #534でサウンドシステムを触った時のメモ。


MinecraftのサウンドシステムはPaul's Code SoundSystem (http://www.paulscode.com/forum/index.php?topic=4.0)を利用していることがクレジット等からわかるので、まずはそのソースコードを読む。また、Forge側にもいくつかサウンド関連のイベントが存在するのでそちらも読む。列挙すると、

  • SoundEvent(抽象クラス)
  • SoundSetupEvent
  • SoundLoadEvent
  • PlaySoundSourceEvent
  • PlayStreamingSourceEvent
  • PlaySoundEffectSourceEvent

  • SoundResultEvent(抽象クラス)

  • PlaySoundEvent
  • PlayBackgroundMusicEvent
  • PlaySoundEffectEvent

となる。今回やりたいのはいわゆる効果音の再生なので、用があるのはSoundSetupEventだけになる。

そのSoundSetupEventは、SoundManagerクラスのtryToSetLibraryAndCodecsメソッドでイベントバスに投げられている。実際にやってみると分かるが、このイベントが投げられるのは@Mod.PreInit@Mod.Initの間なので、イベントハンドラの設定は@Mod.PreInitでするべき。

SoundSetupEventは、SoundManagerの初期化終了後に呼び出されるイベントという意味になる。今回のような時はいちいち取得するのも面倒なので、このイベントでSoundManagerを取得し、適当なフィールドに保存しておくのが良いかと思う。

@SideOnly(Side.CLIENT)
public class SoundEventHandler {
  public static SoundManager manager;
  
  @ForgeSubscribe
  public void onSoundSetup(SoundSetupEvent event) {
    manager = event.manager;
  }
}

サウンドを利用するにはまず登録が必要となる。この登録処理はどこで行っても良いが、私はイベントハンドラ内で行っている。 注意点として、.minecraft/resources/***/***のような実際のファイルシステム上のパスではなくSomeMod.class.getResource("***/***")のような取得方法をしている場合、開発環境ではうまく行っても実際にはうまくいかない。理由としては、恐らく内部実装がjar(zip)内データの扱いが出来ないことが原因だと推測する。

登録は以下の形にする。

manager.addSound(登録名, 実体へのFileインスタンス);

登録名とは、"aaa/bbb/ccc.ogg"というような任意の文字列 + 拡張子の形の文字列、実体へのFileインスタンスは、実際のファイルへのFile(java.io.File)インスタンスである。


アイテムのonItemUse内で音を再生する時、次のように書く。

public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10) {
    if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) {
        System.out.printf("[+] Play Sound!\n");
        SoundEventHandler.manager.playSound("aaa.bbb.ccc", (float) par2EntityPlayer.posX + 0.5F, (float) par2EntityPlayer.posY + 0.5F, (float) par2EntityPlayer.posZ + 0.5F, 1.0F, 1.0F);
    }
    return true;
}

playSoundのパラメータは、登録名から拡張子を除いたもの, 再生するX座標, 再生するY座標, 再生するZ座標, ボリューム, ピッチとなっている。


Streaming等の他の要素についても同様に進めることが出来るが、それについてはソースコードを参照。