Baldur’s Gate 3 Mod Configuration Menu (BG3MCM
or MCM) is a mod that provides an in-game UI to enable players to intuitively manage mod settings as defined by mod authors. It supports various setting types, including integers, floats, checkboxes, text inputs, lists, combos/dropdowns, radio buttons, sliders, drags, and color pickers.
This documentation is aimed at mod authors who want to integrate their mods with MCM. If you are a player looking to use MCM to configure mods, please refer to the Nexus Mods page for instructions. This documentation provides a thorough guide on the concepts behind MCM, the features it provides to mod authors, and how to integrate MCM into your mod. You can also use the table of contents below to navigate to a desired section.
¶ Table of Contents
- Overview
- Table of Contents
- Features for mod authors
- Concepts
- Integrating MCM into your mod
- Defining a blueprint
- The MCM Schema
- Using values from MCM
- Inserting custom UI elements
- How validation works
- Localization support
- MCM demo
- Closing words
¶ Features for mod authors
Below are listed some nice features that MCM provides to mod authors:
• Easy to use: MCM provides a simple and intuitive way to define your mod’s settings. Integrating MCM into your mod only requires creating a simple blueprint JSON file and replacing a few lines of code;
• UI without writing client-side code: MCM handles the UI for you, so you don’t have to write any client-side code or learn the IMGUI API to display your mod’s settings, since IMGUI is only available on the client side.
• Simplifies settings management: MCM takes care of saving and loading your mod’s settings automatically, so you don’t have to build an entire configuration system to manage JSON files. MCM has 8k+ lines of code so that you don’t have to deal with that.
• Instant saving and loading: Unlike the traditional way of handling settings, MCM-integrated mods update settings in real-time as they are changed, without requiring save reloads;
• Minimizes user error: MCM handles the UI and validation of settings, reducing the risk of user error when configuring your mod and encouraging them to do so safely. By skipping the need for manual editing of configuration files, a very common source of errors, users are less likely to encounter issues or need to ask how to configure your mod.
• Validation checks: MCM runs dozens of validation checks to ensure that your blueprint for integration was correctly written, while providing detailed error messages if something is wrong. It also validates the settings’ values at runtime to ensure that they respect the defined constraints, which is especially useful if JSON settings files were manually edited, something that is supported by MCM;
• Supports bespoke UI injection: MCM allows you to inject your own UI elements into the MCM UI, so you could even have a mix of MCM-generated UI and your own custom UI in the same mod. This is useful when your mod has specific features to expose in the UI that are largely unrelated to configuration;
• Cross-mod settings access: The unified config approach promoted by MCM allows for straightforward access to settings from other mods, as arbitrary implementations are mostly eliminated, facilitating compatibility and interoperability.
• Doesn’t clutter UI: MCM centralizes settings for all mods that use it, so you don’t have to worry about cluttering players’ screens with yet another IMGUI window, thinking when should it initialize, activate, or even about keybindings - and possible conflicts thereof - for showing such windows. Users will have a familiar (Noesis) button in the ESC menu (main menu is planned) for opening MCM.
• Furthermore, you can conditionally hide elements of your configuration based on settings’ values (by usingVisibleIf
, more details below).• Robustness: MCM has more than 40 automated server-side tests aiming to ensure that it works as expected, edge cases are handled, and errors are gracefully reported without halting the framework or game; errors from one mod won’t affect the others.
• UI agnostic: MCM was designed to be, first and foremost, a standalone configuration manager. This means that even if support for IMGUI were to be entirely removed or replaced, the underlying structure of MCM would still function correctly;
• This also means that users who can’t see the IMGUI window will still have MCM working as a config manager.See AlsoDark!BG3 | Escape AttemptMinthara x plus!f!readerBaldur's Gate: An Emotional Tribute to Our Furry FriendsHistwar: Les Grognards - PC• Multiple profiles: MCM has support for creating, saving, loading, and deleting multiple configuration profiles, which is useful for mod authors to separate their testing configurations while developing mods;
• Localization support: MCM supports localizing mod settings, allowing you to optionally provide translations for different languages.
On top of it all, if you currently offer multiple mod versions with different code to avoid dealing with the complexities of providing settings, you can simplify this by using a single version with MCM to introduce settings. This approach allows you to avoid creating and maintaining several different .pak releases for your mods.
You can even technically integrate MCM as an optional requirement (with hardcoded defaults or MCM values if present), although that takes a bit more effort than just adding it as a standard requirement.
¶ Concepts
First, let’s establish some important concepts so that we’re on the same page when discussing MCM. These will be used throughout the documentation:
Setting: A single configuration option that can be set by the user.
Config/Configuration/Settings: All the possible settings; the entire set of settings for a mod.
Blueprint: Defines the structure of a mod’s configuration for MCM to use (with aMCM_blueprint.json
file); written by you.
MCM Schema: Dictates the structure of the blueprint; is the ‘metaschema’; defined by MCM.
¶ Integrating MCM into your mod
Mod authors need to integrate their mods with MCM for their settings to appear in the UI. The subsections below go in detail about this process, but it is essentially done in two steps:
- Define the blueprint JSON file for your mod’s settings and place it alongside your mod’s
meta.lsx
file. - Replace your mod’s logic for reading/writing settings with calls to the MCM API, using settings’ IDs as defined in the blueprint.
It’s extremely recommended to define BG3MCM as a dependency in your
meta.lsx
file. This allows mod managers to ensure that MCM is loaded before your own mod - eliminating the need to instruct users to do so manually and avoiding incorrect reports/troubleshooting when they don’t!
• Example for listing two dependencies in a meta.lsx file, one being BG3MCM; (Volition Cabinet is not required for MCM)
• You can set dependencies and their minimum required versions. It is also recommended to always set the required version (Version64
) of MCM to the version you’re using during the development of your mod. As modding evolves, mod managers might start to use these to enforce correct versions for dependencies.
The MCM_blueprint.json
file is how you specify your mod’s configuration definition; this JSON file will define how your settings are to be structured, what are their name, input type, default, etc., allowing for automatic generation of a user-friendly interface and validation of user-set values.
¶ Defining a blueprint
Recap: a blueprint is a JSON file that defines the structure of your mod’s configuration settings. It is used by MCM to generate the UI and validate the settings for you. It should be named
MCM_blueprint.json
and placed alongside your mod’smeta.lsx
file.
¶ The MCM Schema
The MCM Schema dictates how you should structure your blueprint file, and you can get it from GitHub.
This schema file can be used to write and validate your MCM_blueprint.json
file, as it will help enforcing the intended structure of the MCM Schema in your blueprint file, ensuring that it is correctly formatted and adheres to it.
While not mandatory, it is highly recommended to set the schema up in a code editor. By adding this JSON schema entry to your settings in VSCode, for example, you can easily write and validate your blueprint files:
- Press F1, type and select ‘Open User Settings (JSON)’
- Copy the following and paste inside the main object of the JSON you just opened:
"json.schemas": [ { "fileMatch": [ "MCM_blueprint*.json" ], "url": "https://raw.githubusercontent.com/AtilioA/BG3-MCM/main/.vscode/schema.json" }],
- This might require a Reload Window or just reopening your editor, but you’re done! You won’t need to do this again, and the schema file will be always up-to-date with MCM releases.
* Alternatively, you can replace the url
value with the path to the schema JSON file (e.g., where you place IDEHelpers or Osi.lua files). However, only do so if you have problems with the URL above.
You can also use a service like https://www.jsonschemavalidator.net/s/cV447mjH by pasting your blueprint in the right pane; however, that can be cumbersome, and you’d have to paste the latest schema in the left to make sure you’re not using an older version. Prefer the aforementioned method.
Having the schema file set up in your IDE will help you write the blueprint file correctly, without having to guess the structure or wonder if you’re missing something. A few minor features, such as
ModName
(to replace the string used for your mod’s name) are only documented by the JSON schema.
Following are the main components of the MCM schema. Don’t stress over this too much, the schema file will guide you while writing blueprints if you have set it up.
- Organizational structure: the MCM Schema defines a hierarchical organization using
Tabs
andSections
:Tabs
: Serve as top-level organizational units in the MCM menu. Each tab can exclusively contain eitherSections
or standaloneSettings
.Sections
: Sub-divisions within tabs to group related settings.
Settings
:Id
: A unique string identifier for each setting, similar to a variable name in your code; used to reference the setting programmatically.Name
: The readable name of the setting as to be displayed in the MCM menu.Type
: Defines the data type and ultimately the UI representation of the setting, with supported types includingint
,float
,checkbox
,text
,enum
,radio
,slider_int
,slider_float
,drag_int
,drag_float
,color_picker
,color_edit
;Default
: Specifies the initial value of the setting used during initialization or when a reset is needed. Supports various data types (integer
,number
,boolean
,string
,object
,null
) depending on the setting type.Description
andTooltip
: Textual explanations of the setting’s purpose and usage, whereDescription
is visible below the setting’s widget andTooltip
appears on hover. It is required to have at least one of these.Options
: Additional parameters that tailor the setting’s behavior, applicable to certain types likeenum
,radio
, sliders and drags. This includes:Choices
: The options to be made available forenum
andradio
types.Min
andMax
: Boundary values for types such asslider
/drag
.Multiline
: Whether the text input should be multiline, used fortext
type.
VisibleIf
: Allows defining a simple boolean expression that determines the visibility of a setting (also tab or section) based on the values of other settings.
Thus, the main content of the blueprint is defined in the Tabs
and Settings
properties. You’ll need to include at least one of these - either a list of tabs, or a list of standalone settings. However, for now, only defining a Settings array is not properly supported. Versions 1.10+ might be able to handle it correctly.
Within each tab, you can define either Sections
or a list of Settings
. Sections provide a way to group related settings together under a header.
Each setting has an Id
, Name
, Type
, Default
value, and at least a Tooltip
or a Description
. Each setting Id
must be unique across the entire blueprint, and that is validated by one of the many validation checks MCM performs.
Future versions of MCM might make this structure less strict, allowing nesting tabs inside sections and vice-versa.
If your mod is symlinked, you can try out changes to your mod’s blueprint in-game by using
reset
in the console without having to restart the game every time you make a change to the blueprint file.
For examples of mods that use MCM, you can check:
MCM demo (1.5.1) - slightly outdated, showcases all input types, tab insertion and a bit of client/server communication
Auto Send Food To Camp
Smart Autosaving
Preemptively Label Containers
¶ Using values from MCM
After setting up the blueprint, mod authors can access the values set by the player through the MCM API from anywhere in their mod’s code.
Remember, SE makes this ModuleUUID
constant hold the value of the mod you’re writing.
-- Get the value of a setting with the ID "MySetting". ModuleUUID has the UUID of your modlocal mySettingValue = Mods.BG3MCM.MCMAPI:GetSettingValue("MySetting", ModuleUUID)-- Set the value of a settingMods.BG3MCM.MCMAPI:SetSettingValue("MySetting", newValue, ModuleUUID)
You can also listen to changes to settings values by listening to net messages like this:
Ext.RegisterNetListener("MCM_Saved_Setting", function(call, payload) local data = Ext.Json.Parse(payload) if not data or data.modGUID ~= ModuleUUID or not data.settingId then return end if data.settingId == "debug_level" then _D("Setting debug level to " .. data.value) ASFTCPrinter.DebugLevel = data.value endend)
¶ Reducing verbiage
To avoid typing Mods.BG3MCM.MCMAPI:GetSettingValue
and passing your mod’s UUID every time you get/set a setting value, you can define a simple global function such as this early in your scripts:
function MCMGet(settingID) return Mods.BG3MCM.MCMAPI:GetSettingValue(settingID, ModuleUUID)end-- Now, get values by calling MCMGet("setting_id")
Global functions are only accessible within your mod table, so this function won’t be causing conflicts with other MCM mods that also define it.
Likewise, you can allow global usage of MCMAPI
by incorporating MCM’s table early in your scripts with setmetatable(Mods[Ext.Mod.GetMod(ModuleUUID).Info.Directory], { __index = Mods.BG3MCM })
.
Otherwise, prepend Mods.BG3MCM
to all API calls.
¶ Inserting custom UI elements
MCM allows mod authors to insert custom UI elements into the MCM UI. This can be done using the InsertModMenuTab
function from MCM’s IMGUIAPI
:
Mods.BG3MCM.IMGUIAPI:InsertModMenuTab(ModuleUUID, "Tab name", function(tabHeader) local myCustomWidget = tabHeader:AddButton("My custom widget") myCustomWidget.OnClick = function() _D("My custom widget was clicked!") endend)
This will create a new tab or insert the content at the end of an existing one.
You can define an entire tab’s content — not just a widget — and call the
InsertModMenuTab
function to insert it into the MCM window, inside the space dedicated for your mod.
• For reference, EasyCheat is a mod that leverages theInsertModMenuTab
method to add custom logic inside MCM.
¶ Listening to MCM events
With the introduction of
ModEvents
in SE v18, the existing method for listening to MCM events will be deprecated. While the information in this section remains valid, please note that it is subject to change. MCM will maintain backward compatibility with the current method for the time being.
Currently, mod events are implemented using a workaround involving net messages, which were originally intended for use within a single mod only.
MCM uses a set of channels to communicate between the client and server. Some of these can be useful for mod authors to listen to, as they can use this to update their mod’s behavior based on changes from MCM, such as when a setting is saved:
MCM_Saved_Setting
: fired whenever a setting value has been saved and written to the settings JSON file by MCM. The payload contains the setting ID and the new value. Example usage:
-- In your MCM-integrated mod's codeExt.RegisterNetListener("MCM_Saved_Setting", function(call, payload) local data = Ext.Json.Parse(payload) if not data or data.modGUID ~= ModuleUUID or not data.settingId then return end if data.settingId == "debug_level" then _D("Setting debug level to " .. data.value) MyMod.DebugLevel = data.value endend)
Here are some other events that can be listened to:
MCM_Setting_Reset
: Fired when a setting is reset to its default value.- Profile-related events:
MCM_Server_Created_Profile
: Fired when a new profile is created.MCM_Server_Set_Profile
: Fired when a profile is set as the active one.MCM_Server_Deleted_Profile
: Fired when a profile is deleted.
- Other events:
MCM_Mod_Tab_Added
: Fired when a mod inserts a custom tab into the MCM UI.MCM_Mod_Tab_Activated
: Fired when the user clicks a mod in the mod list in MCM’s left panel.
Always verify the
modGUID
in the payload to confirm that the event pertains to the mod of interest (typically your own, which you have global access to viaModuleUUID
).
¶ How validation works
Validation is divided into two main categories: blueprint validation and settings validation. Blueprint validation ensures that the blueprint JSON file is correctly formatted and adheres to the MCM schema. Settings validation, on the other hand, ensures that the settings values are valid and respect the constraints defined in the blueprint.
MCM performs validation checks when:
- Blueprint validation:
- Loading blueprints from the
MCM_blueprint.json
;
- Loading blueprints from the
- Settings validation:
- Loading settings from a JSON file (+ e.g., switching between profiles);
- Setting values programmatically through the API;
- Processing user input from the UI.
• Settings not present in the blueprint will be removed from the settings JSON file;
• Invalid settings values will be replaced with their respective default value as specified in the blueprint;
• New settings are automatically introduced to the settings JSON file when new settings are added to the schema;
Therefore, mod authors can safely add or remove settings from the blueprint without worrying about inconsistencies in the settings JSON file.
¶ Localization support
In your blueprint, you can define localization handles for various elements of the configuration, including:
- Tabs names and descriptions
- Sections names
- Settings names, descriptions, and tooltips
- Enum/radio choice labels
This is achieved through the use of “handles” - unique identifiers that can be used to look up the localized strings, just as used by the vanilla game. For basically any element that you can put a user-facing string in the blueprint, you can use a handle by adding a Handles
object in the same level as the element, like this:
{ "TabId": "myTab", "TabName": "My tab default display name", "Handles": { "NameHandle": "h3b019e17g75fcg48ccg8063g4de5bfcc7792" }},
These handles should have been listed in a loca file in your mod in order to be used;
• If handles are provided and their content can be retrieved, the localized string will be used instead of the usual name/description/tooltip;
• If the handle is not found, the usual string will be used.
The BG3 Mod Helper extension can help you create localization files and replace strings with handles to be translated.
¶ TODO: ported IMGUI icons
–
¶ MCM demo
The demo below showcases the different types of config options that can be used (all of them as of v1.5.0). The demo also shows how to insert custom UI elements into the menu and how to listen and react to MCM events:
NOTE: with the introduction of ModEvents
in SE v18, the current way of listening to MCM events will get deprecated.
MCM Demo.zip
¶ Closing words
I hope this documentation has provided you with a clear understanding of how to integrate MCM into your mod. If you have any suggestions or encountered any points of confusion or errors, no matter how small or mundane, please let me know on the Nexus page or on Discord (BG3MC). I’m keen on ensuring MCM has excellent design and documentation. I also hope MCM enhances your development experience and provides a better experience for your users!
I’d like to thank the community again for their support and feedback, as well as the mod authors who have already integrated MCM into their mods. It’s been awesome to see what you’ve been building with it so far.