Persistence

Store isolated player, server and world state with atomic writes and explicit schema migration.

Scopes and paths

APIData pathUse
Versioned serveraddon_data/<id>/server/<key>.jsonState shared by the server.
Versioned worldaddon_data/<id>/world/<map-or-world>/<key>.jsonState isolated by current map name or explicit world id.
Versioned playeraddon_data/<id>/players/<steamId>/<key>.jsonNamed per-player documents with migration.
Legacy player blobaddon_data/<id>/<steamId>.jsonOne unversioned object retained for compatibility.

Versioned result

LitherarpAddonDataResult<T> exposes Value, Success, Exists, Migrated, StoredVersion and Error. A missing file succeeds with a new value. A schema mismatch without a migration fails and does not guess.

1private sealed class StateV2
2{
3 public int CompletedRuns { get; set; }
4 public string LastWinner { get; set; } = string.Empty;
5}
6
7var loaded = context.LoadServerData<StateV2>(
8 currentVersion: 2,
9 key: "competition",
10 migrate: (storedVersion, data) => storedVersion switch
11 {
12 1 => new StateV2
13 {
14 CompletedRuns = data.GetProperty( "runs" ).GetInt32()
15 },
16 _ => throw new InvalidOperationException( "Unsupported stored schema." )
17 } );
18
19if ( !loaded.Success )
20{
21 context.Warning( loaded.Error );
22 return;
23}
24
25loaded.Value.CompletedRuns++;
26context.SaveServerData( loaded.Value, schemaVersion: 2, key: "competition" );

A successful migration is saved synchronously before load returns. The migration receives the old version and a cloned JsonElement containing the old data value.

Durability

Saves use atomic latest-write-wins queueing by default. The in-memory latest-write cache gives immediate read-after-save behavior. Pass synchronous: true only when the caller needs immediate disk durability. Context teardown calls FlushAddonData so the latest cached documents are written before shutdown completes.

Limits

  • Maximum serialized document size: 1,048,576 UTF-8 bytes.
  • Maximum versioned documents per scope: 128.
  • Keys and explicit world ids: at most 64 characters, using lowercase letters, digits, dot, underscore and hyphen.
  • Schema versions must be positive integers.

Public config sections and targeted player sections are transport state, not durable storage. Save the authoritative value here and sync only what UI needs.