Posted October 13, 20168 yr I'm looking for some help to get this added as a proper PR to forge. I have a working class for adding the sound category that will work in a mod. I've tested this with with 1.9.4 and 1.10+. I have not yet tried to setup a Forge dev environment but the videos that cpw made make it look simple enough. I still pretty much a java rookies, but learning more as I go. Your comments are welcome. The class below allows the addition of a new sound category. It uses nothing more that the existing Forge utility classes for reflections and enums. You new sound category will have all the attributes of the vanilla sound categories. That is: A volume control for the category displays in the vanilla "Music & Sound Options..." dialog The volume level is saved and loaded from the client options.txt file. The Vanilla SoundHandler will correctly use the custom sound category Here's the class on GitHub. There are some notes about using it in the comments MODSoundCategory I've also included the code below. I have not started work to see what's required to make the vanilla "Music & Sound Options..." dialog behave correctly. Ideally it would work like the "Controls..." dialog. That is the volume controls could be scrolled. So far I've not seen anyone other mod add a custom SoundCategory / volume control. But it might be useful for other mods. And as a part of Forge mod authors could use it without fear of causing issues with vanilla or other mods. For the mxTune mod I'm working on I wanted a separate sound category for the instruments. I can get by without this PR, but I wanted to share this with the community. MODSoundCategory.class package net.aeronica.mods.mxtune.sound; import java.util.Map; import com.google.common.collect.Maps; import net.minecraft.client.Minecraft; import net.minecraft.client.settings.GameSettings; import net.minecraft.util.SoundCategory; import net.minecraftforge.common.util.EnumHelper; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.relauncher.FMLLaunchHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; /* * MODSoundCategory * * Add a new CONSTANT and reference name to net.minecraft.util.SoundCategory * * This allows the display of a volume control in the "Music & Sound Options" dialog. * Unfortunately the GuiScreenOptionsSounds dialog does not auto size * properly and move the Done button lower on the screen. * * To initialize the class create an instance during FMLPreInitializationEvent in * the file with the @Mod annotation or your common proxy class. * * Usage example: static final SoundCategory SC_MXTUNE = MODSoundCategory.add("MXTUNE"); * * The language file key is "soundCategory.mxtune" * The game settings "options.txt" key is "soundCategory_mxtune" * * To use the MXTUNE enum constant in code it must be referenced by name because * SoundCategory.MXTUNE does not exist at compile time. * e.g. SoundCategory.getByName("mxtune"); * * @author Paul Boese aka Aeronica * */ public class MODSoundCategory { private static final String SRG_soundLevels = "field_186714_aM"; private static final String SRG_SOUND_CATEGORIES = "field_187961_k"; private static Map<SoundCategory, Float> soundLevels; private static MODSoundCategory instance = new MODSoundCategory(); private MODSoundCategory() {} public static MODSoundCategory getInstance() {return instance;} /** * The "name" should be your MODID or MODID_name if your mod adds more * than one SoundCategory. * * @param name * @return a unique SoundCategory * @throws fatal error if name is not unique */ public static SoundCategory add(String name) { Map<String, SoundCategory> SOUND_CATEGORIES; String constantName; String referenceName; SoundCategory soundCategory; constantName = new String(name.toUpperCase().replace(" ", "")); referenceName = new String(constantName.toLowerCase()); soundCategory = EnumHelper.addEnum(SoundCategory.class , constantName, new Class[]{String.class}, new Object[]{referenceName}); SOUND_CATEGORIES = ObfuscationReflectionHelper.getPrivateValue(SoundCategory.class, SoundCategory.VOICE ,"SOUND_CATEGORIES", SRG_SOUND_CATEGORIES); if (SOUND_CATEGORIES.containsKey(referenceName)) throw new Error("Clash in Sound Category name pools! Cannot insert " + constantName); SOUND_CATEGORIES.put(referenceName, soundCategory); if (FMLLaunchHandler.side() == Side.CLIENT) setSoundLevels(); return soundCategory; } /** Game sound level options settings only exist on the client side */ @SideOnly(Side.CLIENT) private static void setSoundLevels() { /** SoundCategory now contains 'name' sound category so build a new map */ soundLevels = Maps.newEnumMap(SoundCategory.class); /** Replace the map in the GameSettings.class */ ObfuscationReflectionHelper.setPrivateValue(GameSettings.class, Minecraft.getMinecraft().gameSettings, soundLevels, "soundLevels", SRG_soundLevels); } } From this point on I'll just use bare bones minimal/incomplete code... Creating custom sound categories: package net.aeronica.mods.modtest; import net.aeronica.mods.mod189stuff.audio.MODSoundCategory; import net.aeronica.mods.mod189stuff.caps.ISimple; import net.minecraft.util.SoundCategory; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventHandler; import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; @Mod(modid = Main.MODID, name = Main.MODNAME, version = Main.VERSION) public class Main { public static final String MODID = "modtest"; public static final String MODNAME = "Mod Testing"; public static final String VERSION = "1.10.2-0.1.0-dev"; @Mod.Instance(MODID) public static Main instance; public static SoundCategory MODTEST_A; public static SoundCategory MODTEST_B; public static SoundCategory MODTEST_C; public static SoundCategory MODTEST_D; public static SoundCategory MODTEST_E; public static SoundCategory MODTEST_F; public static SoundCategory MODTEST_G; public static SoundCategory MODTEST_H; @EventHandler public void preInit(FMLPreInitializationEvent event) { // You need to register these on the the client and server side. A good place is your common proxy. MODTEST_A = MODSoundCategory.add("MODTEST_A"); MODTEST_B = MODSoundCategory.add("MODTEST_B"); MODTEST_C = MODSoundCategory.add("MODTEST_C"); MODTEST_D = MODSoundCategory.add("MODTEST_D"); MODTEST_E = MODSoundCategory.add("MODTEST_E"); MODTEST_F = MODSoundCategory.add("MODTEST_F"); MODTEST_G = MODSoundCategory.add("MODTEST_G"); MODTEST_H = MODSoundCategory.add("MODTEST_H"); } @EventHandler public void init(FMLInitializationEvent event) { } @EventHandler public void postInit(FMLPostInitializationEvent event) { } } Here's one way to use the custom sound category // some item . . . @Override public ActionResult<ItemStack> onItemRightClick(ItemStack itemStackIn, World worldIn, EntityPlayer playerIn, EnumHand hand) { if (!worldIn.isRemote) { // worldIn.playSound(EntityPlayer, BlockPos, SoundEvent, SoundCategory, volume, pitch) worldIn.playSound(null, new BlockPos(playerIn.posX,playerIn.posY,playerIn.posZ), SoundEvents.ENTITY_FIREWORK_BLAST, SoundCategory.getByName("modtest_a"), 1F, 1F); // instead of SoundCategory.getByName("modtest_a") you could use Main.MODTEST_A } } . . . If you add or change or remove your custom sound categories in your mod, vanilla will gracefully ignore and overwrite the settings. No worries about a crash for a missing custom sound category. If you goof up and add a conflicting sound category you will crash MC. Oops!, but of course as a developer you should know better right! Section of the client side options.txt where game settings are saved. key_key.hotbar.8:9 key_key.hotbar.9:10 soundCategory_master:1.0 soundCategory_music:0.03521127 soundCategory_record:0.20422535 soundCategory_weather:0.59859157 soundCategory_block:0.42957747 soundCategory_hostile:0.5633803 soundCategory_neutral:0.5140845 soundCategory_player:0.52112675 soundCategory_ambient:0.29577464 soundCategory_voice:0.57042253 soundCategory_mxtune:0.5422535 soundCategory_modtest_a:1.0 soundCategory_modtest_b:1.0 soundCategory_modtest_c:1.0 soundCategory_modtest_d:1.0 soundCategory_modtest_e:1.0 soundCategory_modtest_f:1.0 soundCategory_modtest_g:1.0 soundCategory_modtest_h:1.0 modelPart_cape:true modelPart_jacket:true Here's a demo of it in use: [embed=425,349]<iframe width="560" height="315" src="https://www.youtube.com/embed/A5lhR-pP4Mg" frameborder="0" allowfullscreen></iframe>[/embed] Here's how the current 1.10.2 vanilla "Music & Sounds Options.." looks after adding several more unique sound categories. Yup, the dialog needs some loving.
November 23, 20168 yr This is a very good feature. I would definitely use it if I update my Mod to 1.11 and it's there. (I would use it in 1.7.10 too, but I don't think the forge team is willing to add stuff to 1.7 :'(). One thing that I think needs to get added is a submenu. So you have a button "Mod Sound Sliders" which opens a submenu with a list of all modded sound sliders. (Similar to keybindings). Every mod is a major category, and maybe allow mods to add a minor category within the mod.
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.