-
-
Notifications
You must be signed in to change notification settings - Fork 0
Mod Integration
To integrate optional Mod Manager support with your mod.
To add a banner for your mod, make sure your mod folder contains a file named "banner.png" containing your mod's banner image.
Likewise, to add an icon for your mod, make sure your mod folder contains a file named "icon.png" containing your mod's icon.
To integrate version checking with the Mod Manager mod, create a new Manifest.xml
file in the same directory as your mod's ModInfo.xml
. The basic template for a Manifest.xml
file looks as so. You can also see the Mod Manager Manifest as another example of how to implement the Mod Manifest file.
<ModManifest>
<ManifestUrl>https://link-to-remote-mod-folder/Manifest.xml</ManifestUrl> <!-- This is the link to the remote Manifest.xml hosted on another website, for example GitHub.com -->
<Version>1.0.0</Version> <!-- This is the current mod version to compare the remote mod version against. -->
<GameVersion ReleaseType="Alpha" Major="20" Minor="5" Build="2" /> <!-- This represents the following: Alpha 20.5 (b2) -->
</ModManifest>
When the game is loaded with Mod Manager, all Remote Manifests will be fetched at startup and saved in memory from the specified ManifestUrl
from all local Manifest files.
This is also fetched from both the local and remote Manifests and compared during runtime to notify the user if there are any updates for the mod. The versioning system that Mod Manager supports is Semantic Versioning, meaning any changes to the version will notify the user of an update (provided the new number is higher than the previous one).
The GameVersion
tag allows the user to infer about compatibility of the mod with the current game version they are running. If the current GameVersion is Alpha 20.5 (b2) but the user is still running a mod supporting the GameVersion Alpha 20.3 (b3), then they are notified that the mod may not be compatible with the current GameVersion. Whereas if they are running a mod with a supported GameVersion of Alpha 19.6 (b8), then they are notified that the mod will in most cases not be compatible with the current GameVersion. This setting does not depend on the ManifestUrl
setting, however notifies the user of a new mod updates GameVersion if a Remote Manifest is present and the GameVersion
tag is specified in the Remote Manifest.
Create a new class in your mod's C# project called ModManagerAPI.cs
and paste the code from the original Mod Manager API class definition. This class may periodically update over time so keep your eyes out for patch notes which will mention if your API class needs to be updated.
The Mod Manager API has been built so that it can be seamlessly integrated into your projects without causing any errors during development for both you and your end-users (the players running your mod can still use it without the Mod Manager installed without any errors).
Before you begin using the Mod Manager API wrappers provided in the ModManagerAPI.cs
file you have now created, you must always wrap any Mod Manager API function calls in the following if-statements.
if(ModManagerAPI.IsModManagerLoaded())
{
}
Failure to do so will result in warnings being reported to both you and the end-user when running the mod, which will not prevent use of the mod but serve as a warning that Mod Manager API calls will be ignored due to no Mod Manager being detected.
Mod Settings allow you to store persistent settings for your mod by hooking directly into field values and setting up the settings page that the end-user will see and interact with automatically. Mod Settings only work when the Mod Manager API has detected an instance of the Mod Manager DLL loaded into the current process.
To begin integrating Mod Settings into your mod, create a new instance of the ModManagerAPI.ModSettings
wrapper in your mod's IModApi
extended class.
using CustomModManager.API;
// Class definition here
public void InitMod(Mod _modInstance)
{
if(ModManagerAPI.IsModManagerLoaded())
{
ModManagerAPI.ModSettings settings = ModManagerAPI.GetModSettings(_modInstance);
}
}
After compiling your project and opening the game, your Mod Settings Tab will look as such:
To create a mod setting with your new ModManagerAPI.ModSettings
instance, ensure you have a variable you want to store/load your setting from, then call ModSettings.Hook<T>(string key, string nameUnlocalized, Action<T> setCallback, Func<T> getCallback, Func<T, (string unformatted, string formatted)> toString, Func<string, (T result, bool success)> fromString);
with your new ModSettings
instance.
// Define your variable at the beginning of the class.
private int test123 = 0; // Note: This value will be the default setting when reset.
modSettings.Hook(
"test123", // This is the Mod Setting key. This must always be unique for all settings for the mod.
"xuiModSettingTest123", // This is the localization key for the setting's label. The value is fetched from the Localization.txt file in your mod's Config folder.
value => this.test123 = value, // This is the value setter, it updates the value of the variable we have hooked onto.
() => this.test123, // This is the value getter, it gets the value of the variable we have hooked onto.
toStr => (toStr.ToString(), toStr.ToString()), // This is the string representation of the currently applied setting.
str => // This is the converter from the String representation of the setting, back to the variable type of the setting.
{
bool success = int.TryParse(str, out int val); // Attempt to convert the input to an integer.
// If success is true, the input will be accepted.
// If success is false, the input will be rejected, and the text will change to red to indicate
// to the user that an invalid input has been entered and will not be saved.
return (val, success);
});
After compiling your project and opening the game, your setting will appear in the mod's Settings Tab like so:
You will notice that the label shows the localization key. This will automatically get translated when specified in your mod's Localization.txt file.
Once you've hooked a variable to a mod setting, you can then access the wrapper methods returned from the Hook
method.
ModManagerAPI.ModSettings.ModSetting<T> modSetting = settings.Hook(...);
SetAllowedValues
turns the text input into a combo selector input with predefined values. Using our previous example, we can limit the inputs to the following numbers 1, 2, 5, 10, 100
like so:
modSetting.SetAllowedValues(new int[] { 1, 2, 5, 10, 100 });
After compiling your project and opening the game, the setting will now look like this:
SetMinimumMaximumAndIncrementValues
calls SetAllowedValues
and automatically populates the array with a range of values specified in this method's parameters. For example, consider an array containing a minimum value of 0 and a maximum value of 30, where each element is incremented by 5 from the minimum to the maximum. We can specify this for the setting like so:
modSetting.SetMinimumMaximumAndIncrementValues(0, 30, 5);
This will call the following behind the scenes:
modSetting.SetAllowedValues(new int[] { 0, 5, 10, 15, 20, 25, 30 });
After compiling your project and opening the game, the setting will look like this:
SetWrap
allows the combo selector input to wrap around to the initial allowed values.
modSetting.SetWrap(true);
After compiling your project and opening the game, the setting will now work like this:
The API was designed as a wrapper instead of a DLL because one of the features of the API is that the Mod Manager mod should be optional for the end-user, hence it provides an optional way to interface with the Mod Manager mod should the user choose to use it.
The downside to this approach however, is that each implementation of the API will therefore need to be updated every time the main API is updated, hence the Mod Manager runs on Semantic Versioning to try ensure minimal breakage and clear communication between users and Mod Developers. Hence, the API of 1.0.0
may not be compatible with 2.0.0
in some cases, and so on. However the API of 1.0.0
should be compatible with 1.1.0
, 1.1.1
, etc.