> For the complete documentation index, see [llms.txt](https://stoneforgeteam.gitbook.io/stoneforgeteam-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stoneforgeteam.gitbook.io/stoneforgeteam-docs/core-concepts/mod-context.md).

# The mod context

Every mod gets a `ModContext` in `Load`. It's how the mod registers everything it adds to the game, and what StoneForge uses to take it all back when the mod is switched off.

```csharp
using StoneForge;

namespace MyMod;

public class MyMod : IStoneMod
{
    public void Load(ModContext context)
    {
        context.Log($"Hello from {context.Name} {context.Manifest.Version}");
    }

    public void Unload() { }
}
```

## Lifecycle

|                 |                                                                                                                                                                                                                                                                                        |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Load(context)` | Runs once, as the game starts (or when the player switches the mod on). Register items, buffs, skills, objects, hooks, UI and settings here. The game isn't running frames yet: do things that touch the game in events, `Tick` or UI callbacks.                                       |
| `Unload()`      | The player switched the mod off while the game runs. Undo anything you changed that you *didn't* register through the context: globals you set, instances you made, files. Everything registered through the context is taken back for you afterwards. Not called when the game quits. |

What's taken back for you: event and script hooks, `ITickable`s, `DrawGui` handlers, UI and windows, main menu buttons, settings (saved first), and your items, buffs and skills (removed from the game; a save from before still has them for when the mod is back).

## Every frame: ITickable

A mod class that implements `ITickable` is ticked every frame from when it's loaded:

```csharp
public class MyMod : IStoneMod, ITickable
{
    public void Tick(double deltaTime)   // seconds since the last frame
    {
        if (Keyboard.Pressed(Keyboard.F7))
            _context.Items.Give(_blade);
    }
    ...
}
```

Reading keys and the mouse: [Keyboard and mouse](/stoneforgeteam-docs/core-concepts/input.md).

Anything else can be ticked with `context.AddTickable(thing)` (and stopped with `RemoveTickable`). Items and buffs that implement `ITickable` are ticked once they're added.

## What the context has

| Member                                |                                                                                                                                                                                                                                                |
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Manifest`, `Id`, `Name`              | The mod's `mod.json`.                                                                                                                                                                                                                          |
| `Log(text)`                           | A line in the loader's log, tagged with the mod's name.                                                                                                                                                                                        |
| `Items`, `Buffs`, `Skills`, `Objects` | Registering [items](/stoneforgeteam-docs/content/items.md), [buffs](/stoneforgeteam-docs/content/buffs.md), [skills](/stoneforgeteam-docs/content/skills.md) and [game objects](/stoneforgeteam-docs/content/game-objects.md), and using them. |
| `ContentId(key)`                      | The full id of your content: `"mymod:key"`.                                                                                                                                                                                                    |
| `Settings`                            | [Settings](/stoneforgeteam-docs/core-concepts/settings.md) the player can change in the Mods window.                                                                                                                                           |
| `UI`                                  | [Screens](/stoneforgeteam-docs/ui/screens-and-elements.md) to put UI on.                                                                                                                                                                       |
| `DrawGui`, `DrawHud`                  | Events to [draw](/stoneforgeteam-docs/ui/drawing.md) every frame: over everything, or with the game's HUD under its windows.                                                                                                                   |
| `OnScript`, `OnCode`                  | [Hooks](/stoneforgeteam-docs/gml-and-c-code/hooks.md) by name.                                                                                                                                                                                 |
| `LoadSprite`, `LoadSound`             | Pictures and sounds from your `Assets` folder.                                                                                                                                                                                                 |
| `Files`                               | Reading and writing files.                                                                                                                                                                                                                     |
| `Mods`                                | The other mods running: see [Using other mods](/stoneforgeteam-docs/core-concepts/other-mods.md).                                                                                                                                              |
| `Localization`                        | The mod's translations: see [Localization](/stoneforgeteam-docs/core-concepts/localization.md).                                                                                                                                                |
| `Quests`, `Contracts`                 | [Custom quests and contracts](/stoneforgeteam-docs/world/quests-and-contracts.md).                                                                                                                                                             |
| `Dialogues`                           | [NPC dialogues](/stoneforgeteam-docs/ui/npc-dialogues.md).                                                                                                                                                                                     |
| `Failed`                              | An event: one of the mod's handlers threw. See [When a handler fails](#when-a-handler-fails).                                                                                                                                                  |
| `IsContributor`                       | Whether the current Steam account is in the mod's `contributors`.                                                                                                                                                                              |
| `AddTickable`, `RemoveTickable`       | Ticking things other than the mod class.                                                                                                                                                                                                       |

## When a handler fails

When one of a mod's handlers throws, StoneForge logs it, shows its error box and carries on without that handler's work. `context.Failed` tells the mod, the first time each handler throws: where it was (`"Tick"`, `"scr_effect_create (script after)"`...) and the exception. Use it to look after your players' data: warn them, or keep a copy of their save.

```csharp
context.Failed += (where, error) =>
{
    SaveBackups.Keep("mymod-error");
    context.Log($"{where} failed: {error.Message}");
};
```

It runs on the game thread. A `Failed` handler that throws is only logged. See also [Save backups](/stoneforgeteam-docs/getting-started/save-backups.md#after-a-mods-error).

## Values of your own: ModData

A mod's own values, kept in what the game keeps (an item's data, the save data, an instance's variables), go under keys only that mod uses: two mods' `"kills"` are two values, and neither touches the game's.

```csharp
var mine = item.ModData(context);              // an InventoryItem, an Item or a GroundItem
mine["kills"] = mine["kills"].AsInt + 1;

SaveData.ModData(context)["visits"] = 3;        // saved with the game
player.Instance.ModData(context)["marked"] = true;   // a variable on an instance
```

| Where                                                         | Kept                                                                                          |
| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `InventoryItem.ModData`, `Item.ModData`, `GroundItem.ModData` | In the item's data: with it and saved with it wherever it goes (a chest, the ground, a save). |
| `SaveData.ModData`                                            | In the save data: saved with the game, back when it's loaded. Nothing's kept with no game.    |
| `Instance.ModData`                                            | As variables on the instance, for as long as it's there. Not saved.                           |

| `ModData`                 |                                                                                         |
| ------------------------- | --------------------------------------------------------------------------------------- |
| `this[key]`               | A value; `undefined` if it hasn't been set. Setting it sets it.                         |
| `Has(key)`, `Remove(key)` | Whether it's set; take it away (a variable is left `undefined`).                        |
| `Keys`                    | The keys this mod has set here.                                                         |
| `GameKey(key)`            | The key as the game holds it: `"mymod:kills"` in a map, `"mymod__kills"` as a variable. |

## Pictures and sounds

```csharp
int icon = context.LoadSprite("icon.png");                       // Assets\icon.png
int strip = context.LoadSprite("fx/spark.png", frames: 6);       // 6 frames side by side
int music = context.LoadSound("theme.ogg");                      // an OGG stream
```

Paths are relative to the mod's `Assets` folder. The sprite is owned by the mod: loading the same path again reuses it, and it's retired when the mod unloads (don't delete it yourself). Both return `-1` if the file is missing or can't be loaded.

## Files

Mods can't use `System.IO`. `context.Files` is their file access:

```csharp
var files = context.Files;
string names = files.ReadAllText(files.AssetPath("names.txt"));
files.WriteAllText("notes.txt", "...");                                  // mods\MyMod\notes.txt
string[] logs = files.ListFiles(files.ModFolder, "*.txt");                // full paths
```

|                |                                                                                                                                                          |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Relative paths | In the mod's own folder (`mods\<mod>\`).                                                                                                                 |
| Reading        | Anywhere in the game's folder (`ModFiles.GameFolder`) or Stoneshard's data folder (`ModFiles.DataFolder`, `%LOCALAPPDATA%\StoneShard`: saves, settings). |
| Writing        | Only in the data folder or the mod's own folder: never the game's files, the loader or other mods.                                                       |

`Exists`, `DirectoryExists`, `ReadAllText`, `ReadAllLines`, `ReadAllBytes`, `ListFiles`, `WriteAllText`, `AppendAllText`, `WriteAllBytes`, `Delete`, `CreateDirectory`. A path outside what's allowed throws `UnauthorizedAccessException`.

## Trusted mods

A mod can ask for full access with `"trusted": true` in its `mod.json`: its own DLLs, the whole of .NET (networking, threads, files, reflection) and `Game.CallBuiltinUnrestricted`. It runs only once the player allows it in the Mods window, warned that it can do anything a program on their PC can. Ask for it only when a mod truly needs it, such as for multiplayer networking.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://stoneforgeteam.gitbook.io/stoneforgeteam-docs/core-concepts/mod-context.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
