<commit_before>﻿← [README](../README.md)

This doc helps SMAPI mod authors extend Content Patcher with custom functionality.

**To use Content Patcher conditions in your mod, see the [conditions API](conditions-api.md). See
the [main README](../README.md) for other info**.

## Contents
* [Overview](#overview)
  * [Introduction](#introduction)
  * [Access the API](#access-the-api)
* [Basic API](#basic-api)
* [Advanced API](#advanced-api)
  * [Caveats](#caveats)
  * [Token concepts](#token-concepts)
  * [Add a token](#add-a-token)
* [See also](#see-also)

## Overview
### Introduction
Content Patcher has a [mod-provided API](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Integrations#Mod-provided_APIs)
you can use from your own SMAPI mod to add custom tokens. Custom tokens are always prefixed with
the ID of the mod that created them, like `your-mod-id/SomeTokenName`.

There are two parts of the API you can use:

* The **basic API** is strongly recommended for most mods. This lets you create custom tokens
  with minimal knowledge of how Content Patcher works internally; Content Patcher will
  automatically handle the gritty details for you, and your tokens are highly compatible with
  future versions of SMAPI.

* The **advanced API** gives you much more control over how the token works. The disadvantages are
  that your token code will be more complex, you need a grasp of how Content Patcher works
  internally, and your token may break in future versions of Content Patcher when its internal
  implementation changes. Using the advanced API is strongly discouraged unless you can't use the
  basic API.

Note that you can use both at once from your mod code.

### Access the API
To access the API:

1. Add Content Patcher as [a dependency in your mod's `manifest.json`](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Manifest#Dependencies):

   ```js
   "Dependencies": [
      { "UniqueID": "Pathoschild.ContentPatcher", "IsRequired": false }
   ]
   ```

2. Copy [`IContentPatcherAPI`](../IContentPatcherAPI.cs)
   into your mod code, and **delete any methods you won't need for future compatibility**.
3. Hook into [SMAPI's `GameLoop.GameLaunched` event](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Events#GameLoop.GameLaunched)
   and get a copy of the API:
   ```c#
   var api = this.Helper.ModRegistry.GetApi<IContentPatcherAPI>("Pathoschild.ContentPatcher");
   ```
4. Use the API to extend Content Patcher (see below).

## Basic API
You can add a simple token by calling `RegisterToken` from SMAPI's `GameLaunched` event (see
_Access the API_ above). For example, this creates a `{{your-mod-id/PlayerName}}` token for the
current player's name:
```c#
api.RegisterToken(this.ModManifest, "PlayerName", () =>
{
    if (Context.IsWorldReady)
        return new[] { Game1.player.Name };
    if (SaveGame.loaded?.player != null)
        return new[] { SaveGame.loaded.player.Name }; // lets token be used before save is fully loaded
    return null;
});
```

`RegisterToken` in this case has three arguments:

argument   | type | purpose
---------- | ---- | -------
`mod`      | `IManifest` | The manifest of the mod defining the token. You can just pass in `this.ModManifest` from your entry class.
`name`     | `string` | The token name. This only needs to be unique for your mod; Content Patcher will prefix it with your mod ID automatically, so `PlayerName` in the above example will become `your-mod-id/PlayerName`.
`getValue` | `Func<IEnumerable<string>>` | A function which returns the current token value. If this returns a null or empty list, the token is considered unavailable in the current context and any patches or dynamic tokens using it are disabled.

That's it! Now any content pack which lists your mod as a dependency can use the token in its fields:
```js
{
   "Format": "1.22.0",
   "Changes": [
      {
         "Action": "EditData",
         "Target": "Characters/Dialogue/Abigail",
         "Entries": {
            "Mon": "Oh hey {{your-mod-id/PlayerName}}! Taking a break from work?"
         }
      }
   ]
}
```

## Advanced API
### Caveats
The _basic API_ section above is strongly recommended for most tokens, since Content
Patcher will handle details like context updates and change tracking for you, it's easier to
troubleshoot, and it's guaranteed not to break without a major-version update.

If you really need it, the advanced API gives you full control (almost equivalent to a token in the
Content Patcher core). However:

* <strong>This is experimental. There's no guarantee that future versions will be backwards
  compatible, or that you'll get any warning before it changes.</strong>
* <strong>This is low-level. You must account for the token design considerations documented below,
  unlike the basic API above which handles them for you.</strong>

### Token concepts
When registering a token through the advanced API, here are some design considerations to avoid
problems.

<dl><commit_msg>document scope in extensibility guide<commit_after>﻿← [README](../README.md)

This doc helps SMAPI mod authors extend Content Patcher with custom functionality.

**To use Content Patcher conditions in your mod, see the [conditions API](conditions-api.md). See
the [main README](../README.md) for other info**.

## Contents
* [Introduction](#introduction)
* [Access the API](#access-the-api)
* [Basic API](#basic-api)
  * [Concepts](#concepts)
  * [Add a token](#add-a-token)
* [Advanced API](#advanced-api)
  * [Caveats](#caveats)
  * [Concepts](#concepts-1)
  * [Add a token](#add-a-token)
* [See also](#see-also)

## Introduction
Content Patcher has a [mod-provided API](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Integrations#Mod-provided_APIs)
you can use from your own SMAPI mod to add custom tokens. Custom tokens are always prefixed with
the ID of the mod that created them, like `your-mod-id/SomeTokenName`.

There are two parts of the API you can use:

* The **basic API** is strongly recommended for most mods. This lets you create custom tokens
  with minimal knowledge of how Content Patcher works internally; Content Patcher will
  automatically handle the gritty details for you, and your tokens are highly compatible with
  future versions of SMAPI.

* The **advanced API** gives you much more control over how the token works. The disadvantages are
  that your token code will be more complex, you need a grasp of how Content Patcher works
  internally, and your token may break in future versions of Content Patcher when its internal
  implementation changes. Using the advanced API is strongly discouraged unless you can't use the
  basic API.

Note that you can use both at once from your mod code.

## Access the API
To access the API:

1. Add Content Patcher as [a dependency in your mod's `manifest.json`](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Manifest#Dependencies):

   ```js
   "Dependencies": [
      { "UniqueID": "Pathoschild.ContentPatcher", "IsRequired": false }
   ]
   ```

2. Copy [`IContentPatcherAPI`](../IContentPatcherAPI.cs)
   into your mod code, and **delete any methods you won't need for future compatibility**.
3. Hook into [SMAPI's `GameLoop.GameLaunched` event](https://stardewvalleywiki.com/Modding:Modder_Guide/APIs/Events#GameLoop.GameLaunched)
   and get a copy of the API:
   ```c#
   var api = this.Helper.ModRegistry.GetApi<IContentPatcherAPI>("Pathoschild.ContentPatcher");
   ```
4. Use the API to extend Content Patcher (see below).

## Basic API
### Concepts
The basic API handles most of the design considerations for you. There's just one thing to keep in
mind:

<dl>
<dt>Scope</dt>
<dd>

Content Patcher will call your code to get the values each time it updates tokens. That can happen
before a save is loaded, while it's still loading, and after it's loaded. You can return null or an
empty list if your token isn't ready yet. See the example under _[add a token](#add-a-token)_ which
handles all three cases.

</dd>
</dl>

### Add a token
You can add a simple token by calling `RegisterToken` from SMAPI's `GameLaunched` event (see
_[Access the API](#access-the-api)_ above). For example, this creates a `{{your-mod-id/PlayerName}}` token for the
current player's name:
```c#
api.RegisterToken(this.ModManifest, "PlayerName", () =>
{
    // save is loaded
    if (Context.IsWorldReady)
        return new[] { Game1.player.Name };

    // or save is currently loading
    if (SaveGame.loaded?.player != null)
        return new[] { SaveGame.loaded.player.Name };

    // no save loaded (e.g. on the title screen)
    return null;
});
```

`RegisterToken` in this case has three arguments:

argument   | type | purpose
---------- | ---- | -------
`mod`      | `IManifest` | The manifest of the mod defining the token. You can just pass in `this.ModManifest` from your entry class.
`name`     | `string` | The token name. This only needs to be unique for your mod; Content Patcher will prefix it with your mod ID automatically, so `PlayerName` in the above example will become `your-mod-id/PlayerName`.
`getValue` | `Func<IEnumerable<string>>` | A function which returns the current token value. If this returns a null or empty list, the token is considered unavailable in the current context and any patches or dynamic tokens using it are disabled.

That's it! Now any content pack which lists your mod as a dependency can use the token in its fields:
```js
{
   "Format": "1.22.0",
   "Changes": [
      {
         "Action": "EditData",
         "Target": "Characters/Dialogue/Abigail",
         "Entries": {
            "Mon": "Oh hey {{your-mod-id/PlayerName}}! Taking a break from work?"
         }
      }
   ]
}
```

## Advanced API
### Caveats
The _basic API_ section above is strongly recommended for most tokens, since Content
Patcher will handle details like context updates and change tracking for you, it's easier to
troubleshoot, and it's guaranteed not to break without a major-version update.

If you really need it, the advanced API gives you full control (almost equivalent to a token in the
Content Patcher core). However:

* <strong>This is experimental. There's no guarantee that future versions will be backwards
  compatible, or that you'll get any warning before it changes.</strong>
* <strong>This is low-level. You must account for the token design considerations documented below,
  unlike the basic API above which handles them for you.</strong>

### Concepts
When registering a token through the advanced API, here are some design considerations to avoid
problems.

<dl>
<dt>Scope</dt>
<dd>

See [_Basic API: concepts_](#concepts) above.

</dd>

{'fraction_non_alphanumeric': 0.10120165227187383, 'fraction_numerical': 0.0017837025910627112, 'mean_word_length': 3.9710685954269715, 'pattern_counts': {'":': 18, '<': 29, '<?xml version=': 0, '>': 31, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3611947', 'n_tokens_mistral': 3098, 'n_tokens_neox': 2962, 'n_words': 1323}