Mod Settings
Anomaly auto-discovers typed MelonPreferences entries and renders them as a grouped list under Settings > Mods. Each row shows its description, current/default value, and a Reset action for that entry. Reset is disabled when the entry already matches its default.
Use a raw MelonPreferences category ID without dots, such as example_mod, and keep it separate from your dotted Anomaly namespace, such as example.mod. The supported loader treats dots as TOML paths, which can lose saved entries. Pass the same raw category ID to ModSettings.RegisterCategory. ClientConfig.For and ClientPersistence.For still take dotted Anomaly IDs and encode their storage identifiers internally.
Automatic controls
Section titled “Automatic controls”- Boolean entries become toggles.
- Enums become dropdowns.
- Numeric entries with a ValueRange or finite metadata bounds become sliders.
- Long and decimal entries use text fields even when ranged, preserving their precision.
- Other numeric and string entries become input fields.
using Anomaly.Client.Api.UI.ModSettings;using MelonLoader;
const string PreferenceCategoryId = "example_mod";var category = MelonPreferences.CreateCategory(PreferenceCategoryId, "My Mod");var enabled = category.CreateEntry("enabled", true, "Enabled");var volume = category.CreateEntry("volume", 0.75f, "Volume");
ModSettings.RegisterCategory(PreferenceCategoryId, new ModSettingCategoryMetadata{ DisplayName = "My Mod", SortOrder = 10,});
ModSettings.RegisterEntry(volume, new ModSettingMetadata{ DisplayName = "Output volume", Group = "Audio", MinValue = 0, MaxValue = 1, Order = 20,});RegisterCategory and RegisterEntry copy and replace metadata for the same target. Re-register after changing a metadata object; later object mutation does not change the UI. Passing null clears the override. ModSettings.Refresh requests a coalesced rebuild on the next frame.
Metadata can change display name, description, group, numeric bounds, explicit choices, visibility, and sort order. Descriptions wrap beside the control; metadata description takes precedence over the MelonPreferences entry description.
Numeric choices store a zero-based index, string choices store the selected label, and enum choices use exact declared names. Labels must be nonempty and unique. Choices require a numeric, string, or enum entry and cannot be combined with bounds. Bounds must be a finite increasing pair for a numeric entry. Invalid stored dropdown values remain unchanged and show a placeholder/warning until the user selects or resets a value.
Persistence and ownership
Section titled “Persistence and ownership”Edits and per-entry resets apply immediately through MelonPreferences validation and change events. Successful edits save after a 250 ms debounce. Invalid typed input stays visible with an inline explanation and is not applied. Save failures remain visible with Retry save; dirty categories are retried every two seconds. If MelonLoader has latched a file error, repair the file or permissions and restart; Anomaly does not clear that loader-owned failure flag.
MelonPreferences owns the underlying values and file. Call its save operation yourself when your code needs immediate durability. Do not store Launcher-owned state or protected identity fields in a mod preference category.
Continue to Compatibility.