← README
This doc helps SMAPI mod authors use Content Patcher's condition system in their own mods.
To add custom tokens for content packs to use, see the extensibility API. See the main README for other info.
Content Patcher has a conditions system which lets content packs check dozens of contextual values for conditional changes. For example:
"When": {
"PlayerGender": "male", // player is male
"Relationship: Abigail": "Married", // player is married to Abigail
"HavingChild": "{{spouse}}", // Abigail is having a child
"Season": "Winter" // current season is winter
}
Other SMAPI mods can use this conditions system too. They essentially create a dictionary representing the conditions they want to check (e.g. by parsing them from their own content packs), call the API below to get a 'managed conditions' object, then use that to manage the conditions.
To access the API:
- Add Content Patcher as a required dependency in your mod's
manifest.json
:"Dependencies": [ { "UniqueID": "Pathoschild.ContentPatcher", "MinimumVersion": "2.4.0" } ]
- Add a reference to the Content Patcher DLL in your mod's
.csproj
file. Make sure you setPrivate="False"
, so the DLL isn't added to your mod folder:<ItemGroup> <Reference Include="ContentPatcher" HintPath="$(GameModsPath)\ContentPatcher\ContentPatcher.dll" Private="False" /> </ItemGroup>
- Somewhere in your mod code (e.g. in the
GameLaunched
event), get a reference to Content Patcher's API:var api = this.Helper.ModRegistry.GetApi<ContentPatcher.IContentPatcherAPI>("Pathoschild.ContentPatcher");
Note: see caveats before calling this API.
Now that you have access to the API, you can parse conditions.
-
Create a
Dictionary<string, string>
model of the conditions you want to check. This can use Content Patcher features like tokens. For this example, let's assume you have these hardcoded conditions (see the conditions documentation for the format):var rawConditions = new Dictionary<string, string> { ["PlayerGender"] = "male", // player is male ["Relationship: Abigail"] = "Married", // player is married to Abigail ["HavingChild"] = "{{spouse}}", // Abigail is having a child ["Season"] = "Winter" // current season is winter };
-
Call the API to parse the conditions into an
IManagedConditions
wrapper. TheformatVersion
matches theFormat
field described in the author guide to enable forward compatibility with future versions of Content Patcher.var conditions = api.ParseConditions( manifest: this.ModManifest, raw: rawConditions, formatVersion: new SemanticVersion("1.20.0") );
-
Get the result from the
IsMatch
property. For example:conditions.UpdateContext(); if (conditions.IsMatch) ...
If you want to allow custom tokens added by other SMAPI mods, you can specify a list of mod IDs
to assume are installed. You don't need to do this for your own mod ID, for mods listed as
required dependencies in your mod's manifest.json
, or for mods listed via HasMod
in the
conditions dictionary.
var conditions = api.ParseConditions(
manifest: this.ModManifest,
raw: rawConditions,
formatVersion: new SemanticVersion("1.20.0"),
assumeModIds: new[] { "spacechase0.JsonAssets" }
);
The IManagedConditions
object you got above provides a number of properties and methods to manage
the parsed conditions. You can check IntelliSense in Visual Studio to see what's available, but
here are some of the most useful properties:
property | type | description |
---|---|---|
IsValid
| bool |
Whether the conditions were parsed successfully (regardless of whether they're in scope currently). |
ValidationError |
string |
When
If the conditions are valid, this is |
IsReady |
bool |
Whether the conditions' tokens are all valid in the current context. For example, this would be
false if the conditions use |
IsMatch |
bool |
Whether If there are no conditions (i.e. you parsed an empty dictionary), this is always true. |
IsMutable |
bool |
Whether |
And methods:
method | type | description |
---|---|---|
GetReasonNotMatched
| string |
If
If the conditions do match, this returns |
UpdateContext
| bool |
Updates the conditions based on Content Patcher's current context, and returns whether |
- The conditions API isn't available immediately.
-
The conditions API is available two ticks after the
GameLaunched
event (and anytime after that point). That's due to the Content Patcher lifecycle:GameLaunched
: other mods can register custom tokens.GameLaunched + 1 tick
: Content Patcher initializes the token context (including custom tokens).GameLaunched + 2 ticks
: other mods can use the conditions API.
- Conditions should be cached.
-
Parsing conditions through the API is a relatively expensive operation. If you'll recheck the same conditions often, it's best to save and reuse the
IManagedConditions
instance. - Conditions don't update automatically.
-
When using a cached
IManagedConditions
object, make sure to update it usingconditions.UpdateContext()
as needed.Note that condition updates are limited to Content Patcher's update rate. When you call
conditions.UpdateContext()
, it will reflect the tokens as of Content Patcher's last internal context update. - Conditions handle split-screen automatically.
-
For example,
IsMatch
returns whether it matches the current screen's context. The exception isUpdateContext
, which updates the context for all active screens.
- README for other info