BonsaiRuntime

Top-level runtime instance — load a project, advance the choice loop, listen for events. Thin facade over the internal core: only members that are part of the public contract appear here. Editor / authoring / test plumbing (perf counters, diagnostics, raw expression evaluator, raw play history, raw scene stack) lives on the core and is internal to the runtime assembly.

public sealed class BonsaiRuntime

Inheritance System.Object → BonsaiRuntime

Remarks

Lifecycle: construct via FromJson(string), call StartProject(string, SceneScope) (optionally with a sceneId to begin in a named scene), then alternate between reading GetChoices() / GetEventQueue() and committing via SelectChoice(string) / MoveTo(string) / EnterScene(string, bool) / StartEncounter(string).

Each external mutation (MoveTo(string), EnterScene(string, bool), LeaveScene(), StartEncounter(string)) clears the pending event queue first — pull events between every step.

Not thread-safe. All calls must originate on the same thread; a typical Unity integration drives the runtime from the main thread.

Lifecycle

HasStarted

True once StartProject(string, SceneScope) or RestoreFromJson(string, RecoveryMode, ResolutionPolicy) has run.

public bool HasStarted { get; }
Property Value

System.Boolean

IsProjectComplete

True after a completeProject event has fired this run. GetChoices() returns IsComplete = true from this point on.

public bool IsProjectComplete { get; }
Property Value

System.Boolean

Metadata

Project-level static facts — name, uuid, schema version, entry scene id, etc.

public ProjectMetadata Metadata { get; }
Property Value

ProjectMetadata

FromJson(string)

Load a single-file project JSON export. Returns a ready runtime — call StartProject(string, SceneScope) to begin the session.

public static BonsaiRuntime FromJson(string projectJson);
Parameters

projectJson System.String

Project export contents as produced by the editor’s “Export single JSON” affordance. Must be non-null and parseable; throws on either failure.

Returns

BonsaiRuntime
A runtime instance bound to the loaded project, in the pre-start state. Call StartProject(string, SceneScope) next.

Exceptions

System.ArgumentNullException
projectJson is null.

BonsaiException
The JSON is malformed or fails project-load validation.

Example

var runtime = BonsaiRuntime.FromJson(projectJson);
runtime.StartProject();

Reset()

Clear per-run state (history, undo, variables, scene stack, event log) without running the project. Call StartProject(string, SceneScope) again to begin a fresh session.

public void Reset();

Example

runtime.Reset();
runtime.StartProject();

Remarks

Does NOT fire Refreshed — the runtime is returned to an empty pre-start state. Follow with StartProject(string, SceneScope) / RestoreFromJson(string, RecoveryMode, ResolutionPolicy) (which both fire), or re-pull manually if calling Reset() standalone.

StartProject(string, SceneScope)

Canonical session start. With no sceneId, reads Metadata’s entry scene when one is declared; otherwise initialises at the world layer (empty scene stack — player browses GetEncounters() from the starting location). With a sceneId, overrides the declared entry; pass Isolated to pin the session to that scene and end with OnSceneBoundaryReached when it exits.

public void StartProject(string? sceneId=null, SceneScope scope=SceneScope.Full);
Parameters

sceneId System.String

Optional scene id or uuid to start in. Omit (or pass null) to use the declared entry scene. Throws when the id resolves to no scene.

scope SceneScope

SceneScopeFull (default) runs the rest of the project normally; Isolated pins the session to sceneId and ends with OnSceneBoundaryReached when the scene exits.

Exceptions

BonsaiException
sceneId does not resolve to a known scene.

Example

runtime.Reset();
runtime.StartProject();
var firstEvents = runtime.GetEventQueue();

Remarks

Fires intro events (AdvanceTime, EnterScene) before returning; drain GetEventQueue() immediately after.

Entity enumerations

AllAudioCues

All authored audio cues.

public IReadOnlyList<AudioCueView> AllAudioCues { get; }
Property Value

System.Collections.Generic.IReadOnlyList<AudioCueView>

AllCharacters

All authored characters.

public IReadOnlyList<CharacterView> AllCharacters { get; }
Property Value

System.Collections.Generic.IReadOnlyList<CharacterView>

AllCodexEntries

All authored codex entries.

public IReadOnlyList<CodexEntryView> AllCodexEntries { get; }
Property Value

System.Collections.Generic.IReadOnlyList<CodexEntryView>

AllItems

All authored items.

public IReadOnlyList<ItemView> AllItems { get; }
Property Value

System.Collections.Generic.IReadOnlyList<ItemView>

AllLocations

All authored locations. Connections are unfiltered — for the visibility-filtered live view, use GetLocation(string) or CurrentLocation.

public IReadOnlyList<LocationView> AllLocations { get; }
Property Value

System.Collections.Generic.IReadOnlyList<LocationView>

AllMedia

All authored media definitions.

public IReadOnlyList<MediaView> AllMedia { get; }
Property Value

System.Collections.Generic.IReadOnlyList<MediaView>

AllScenes

All authored scenes.

public IReadOnlyList<SceneView> AllScenes { get; }
Property Value

System.Collections.Generic.IReadOnlyList<SceneView>

AllSkills

All authored skills.

public IReadOnlyList<SkillView> AllSkills { get; }
Property Value

System.Collections.Generic.IReadOnlyList<SkillView>

AllVariables

All authored variables.

public IReadOnlyList<VariableView> AllVariables { get; }
Property Value

System.Collections.Generic.IReadOnlyList<VariableView>

Step / choice

GetAllBackgroundAudio()

Returns every audio media item flagged IsBackground, in declaration order. Use for menu / loop track selection.

public IReadOnlyList<BackgroundAudioResult> GetAllBackgroundAudio();
Returns

System.Collections.Generic.IReadOnlyList<BackgroundAudioResult>
All audio-type BackgroundAudioResult items where IsBackground is true, in declaration order.

Example

foreach (var bg in runtime.GetAllBackgroundAudio()) { /* preload bg.File */ }

GetAllBackgroundClips()

Read-only catalog of every background clip authored across the entire project (independent of play state).

public IReadOnlyList<BackgroundClipResult> GetAllBackgroundClips();
Returns

System.Collections.Generic.IReadOnlyList<BackgroundClipResult>
One BackgroundClipResult per authored background clip, in declaration order.

Example

foreach (var clip in runtime.GetAllBackgroundClips()) { /* preload clip.MediaId */ }

GetChoices()

Current visible choices, or IsComplete = true when the project is done.

public ChoiceSet GetChoices();
Returns

ChoiceSet
A ChoiceSet with Choices, Groups, the set-level Timeout, and the LeaveAvailable hint. Freshly allocated per call.

Example

var set = runtime.GetChoices();
if (!set.IsComplete)
{
    foreach (var choice in set.Choices) { /* present choice.Title to the player */ }
}

GetEventQueue()

Drain events produced since the last step (StartProject / StartProject / SelectChoice / MoveTo / EnterScene / StartEncounter). See HookEvent, SequenceEvent, VariableChangedEvent, and other EventBase subclasses for field shapes.

public IReadOnlyList<EventBase> GetEventQueue();
Returns

System.Collections.Generic.IReadOnlyList<EventBase>
Events produced by the most recent step, in fire order. Empty before the first step.

Example

foreach (var ev in runtime.GetEventQueue())
{
    switch (ev)
    {
        case HookEvent hook: Console.WriteLine($"hook {hook.Name}"); break;
        case DialogueEvent line: Console.WriteLine($"{line.Character?.Name}: {line.Text}"); break;
        case SkillCheckResolvedEvent roll: Console.WriteLine($"{roll.SkillId}{roll.Outcome}"); break;
        default: /* ignore unknown event types */ break;
    }
}

Remarks

Reading the queue does NOT clear it — multiple consumers (UI, audio, debug log) can safely iterate the same step. The queue resets on the next state-changing call.

GetSceneBackgroundClips()

Background clips for the media referenced by PlaySequence events in the currently-active scene’s nodes — a UI-side preload hint.

public IReadOnlyList<BackgroundClipResult> GetSceneBackgroundClips();
Returns

System.Collections.Generic.IReadOnlyList<BackgroundClipResult>
Background clips reachable from the active scene’s nodes; empty at the world layer.

Example

foreach (var clip in runtime.GetSceneBackgroundClips()) { /* preload clip.MediaId */ }

GetStoryBeats()

Story beats for media that has been played this run, in play order, with effective importance computed via decay (baseImportance - importanceDecay × choicesSincePlayed, clamped to Trivial). Drives host-side “recap” panels.

public IReadOnlyList<StoryBeatResult> GetStoryBeats();
Returns

System.Collections.Generic.IReadOnlyList<StoryBeatResult>
One StoryBeatResult per played-this-run media item, in play order. Empty before any beat plays.

Example

foreach (var beat in runtime.GetStoryBeats()) { /* render beat.MediaId at beat.Importance */ }

PeekMedia()

Deduplicated lists of video + audio assets the current visible choices would play, for prewarming UI / streaming. Call after GetChoices(). Audio entries are cue refs whose effective start falls within the first 3 seconds of the choice; video entries are each choice’s first sequence.

public PeekResult PeekMedia();
Returns

PeekResult
A PeekResult with Video + Audio lists (both PeekMedia()). Empty when no visible choice references media.

Example

var peek = runtime.PeekMedia();
foreach (var v in peek.Video) { /* preload v.MediaId */ }

SelectChoice(Choice)

Typed overload — equivalent to SelectChoice(choice.Uuid).

public void SelectChoice(Choice choice);
Parameters

choice Choice

A Choice returned by GetChoices(). Must belong to the current visible set.

Example

var choice = runtime.GetChoices().Choices[0];
runtime.SelectChoice(choice);

SelectChoice(string)

Commit the player’s selection. Fires the chosen node’s events, runs the mutation + evaluation phases, and produces the next event queue.

public void SelectChoice(string nodeId);
Parameters

nodeId System.String

Uuid of the chosen node (typically Choice.Uuid from GetChoices()). Throws when the node is not currently visible.

Exceptions

BonsaiException
The node id is not in the current visible set.

Example

var choice = runtime.GetChoices().Choices[0];
runtime.SelectChoice(choice.Uuid);
var events = runtime.GetEventQueue();

SelectChoices(string[])

Multiplayer-only. Commit one choice per seat in a single step, so per-player selections resolve as a single deterministic batch. Pass one node uuid per player (order matches NumPlayers). Single-player projects should use SelectChoice(string) instead.

public void SelectChoices(params string[] nodeIds);
Parameters

nodeIds System.String[]

One node uuid per seat, in NumPlayers order. Each uuid must resolve to a currently-visible choice for the matching seat.

Example

var p1 = runtime.GetChoices().Choices[0].Uuid;
runtime.SelectChoices(p1);

Scene / encounter

CurrentSceneId

Innermost active scene’s uuid — the top of the scene stack when one is pushed; the root active scene otherwise. Null at the world layer (no scene active).

public string? CurrentSceneId { get; }
Property Value

System.String

EntrySceneId

The project’s declared entry scene id, or null when the project starts at the world layer.

public string? EntrySceneId { get; }
Property Value

System.String

IsAtWorldLayer

True when no scene is active — the player is browsing the world layer, driven by GetEncounters() + MoveTo(string). Equivalent to CurrentSceneId == null.

public bool IsAtWorldLayer { get; }
Property Value

System.Boolean

IsCurrentSceneModal

True iff the player is inside a scene whose resolved modality is modal. Resolution chain is enterScene.modal → Scene.Modal → Project.DefaultModal, applied at push time and cached on the stack frame. Returns false at the world layer (no scene to be modal about). Drives “should the world UI allow MoveTo / Leave” gates host-side.

public bool IsCurrentSceneModal { get; }
Property Value

System.Boolean

EnterScene(SceneView, bool)

Typed overload — equivalent to EnterScene(scene.Id, returnAfter).

public void EnterScene(SceneView scene, bool returnAfter);
Parameters

scene SceneView

A SceneView from AllScenes.

returnAfter System.Boolean

When true, the current scene resumes after the entered scene exits.

Example

var scene = runtime.AllScenes[0];
runtime.EnterScene(scene, returnAfter: false);

EnterScene(string, bool)

Push or replace the top scene-stack frame with the named scene. Mirrors the EnterScene event semantics but driven externally. Clears the event queue first.

public void EnterScene(string sceneId, bool returnAfter);
Parameters

sceneId System.String

Scene id or uuid to enter. Throws when unresolved.

returnAfter System.Boolean

When true, the current scene resumes after the entered scene exits (push); when false, the entered scene replaces the current top frame.

Exceptions

BonsaiException
sceneId does not resolve to a known scene.

Example

runtime.EnterScene("scene_kim", returnAfter: false);

GetEncounters()

Encounters available at CurrentLocation — one entry per pinned scene whose pin VisibleWhen passes AND whose target scene has a non-null Trigger. Returns an empty set when the current scene is modal (affordance gate). Safe to poll every UI tick.

public EncounterSet GetEncounters();
Returns

EncounterSet
An EncounterSet wrapping the currently-available Encounters. Empty when no pins are visible or the current scene is modal.

Example

foreach (var enc in runtime.GetEncounters().Encounters)
{
    // present enc.DisplayName; on click call runtime.StartEncounter(enc.Uuid).
}

IsSceneCompleted(string)

True if an explicit completeScene event has fired in the named scene this run. Accepts the scene’s human id or its uuid.

public bool IsSceneCompleted(string sceneIdOrUuid);
Parameters

sceneIdOrUuid System.String

Scene id or uuid.

Returns

System.Boolean
True iff completeScene has fired for the named scene this run.

Example

var scene = runtime.AllScenes[0];
var done = runtime.IsSceneCompleted(scene.Uuid);

IsSceneResolved(string)

True if the named scene’s ResolvedWhen has ever evaluated true this run (latched once set). Accepts the scene’s human id or its uuid.

public bool IsSceneResolved(string sceneIdOrUuid);
Parameters

sceneIdOrUuid System.String

Scene id or uuid.

Returns

System.Boolean
True iff ResolvedWhen has ever evaluated true for the named scene this run.

Example

var scene = runtime.AllScenes[0];
var resolved = runtime.IsSceneResolved(scene.Uuid);

LeaveScene()

Imperative “back out” entry point for non-modal scenes. Fires the leaving scene’s OnLeaveNodeId if set, then resets {scene}_active and pops the frame. Clears the event queue first.

public void LeaveScene();

Example

if (runtime.GetChoices().LeaveAvailable) runtime.LeaveScene();

StartEncounter(Encounter)

Typed overload — equivalent to StartEncounter(encounter.Uuid).

public void StartEncounter(Encounter encounter);
Parameters

encounter Encounter

An Encounter from GetEncounters().

Example

var enc = runtime.GetEncounters().Encounters[0];
runtime.StartEncounter(enc);

StartEncounter(string)

Start a pinned encounter at the current location. Clears the event queue first — any in-progress step’s events are dropped.

public void StartEncounter(string sceneId);
Parameters

sceneId System.String

Encounter scene’s uuid (typically Uuid from GetEncounters()). Throws when the scene is not currently available as an encounter.

Exceptions

BonsaiException
The encounter is not currently pinned at CurrentLocation.

Example

var enc = runtime.GetEncounters().Encounters[0];
runtime.StartEncounter(enc.Uuid);

Location

CurrentLocation

Current location as a live view — AvailableConnections is filtered by each connection’s VisibleWhen. Null when no location has been entered.

public LocationView? CurrentLocation { get; }
Property Value

LocationView

CurrentLocationId

The uuid of CurrentLocation, or null when no location has been entered.

public string? CurrentLocationId { get; }
Property Value

System.String

GetLocation(string)

Live LocationView for the given id or uuid. Connections are filtered by visibility (unlike AllLocations’s catalog form). Returns null when the id is unknown.

public LocationView? GetLocation(string locationId);
Parameters

locationId System.String

Location id or uuid.

Returns

LocationView
A LocationView with visibility-filtered connections, or null when unresolved.

Example

var first = runtime.AllLocations[0];
var loc = runtime.GetLocation(first.Uuid);

HasLocation(string)

True if the given id or uuid resolves to a known location in this project. Cheap lookup; no view allocation.

public bool HasLocation(string locationId);
Parameters

locationId System.String

Location id or uuid to check.

Returns

System.Boolean
True iff the id resolves to a location in the loaded project.

Example

var loc = runtime.AllLocations[0];
var known = runtime.HasLocation(loc.Uuid);

MoveTo(LocationConnectionView)

Typed overload — equivalent to MoveTo(connection.To).

public void MoveTo(LocationConnectionView connection);
Parameters

connection LocationConnectionView

A LocationConnectionView from CurrentLocation’s AvailableConnections.

Example

var conn = runtime.CurrentLocation?.AvailableConnections?.FirstOrDefault();
if (conn != null) runtime.MoveTo(conn);

MoveTo(LocationView)

Typed overload — equivalent to MoveTo(location.Id).

public void MoveTo(LocationView location);
Parameters

location LocationView

A LocationView from AllLocations or GetLocation(string).

Example

var loc = runtime.AllLocations[0];
runtime.MoveTo(loc);

MoveTo(string)

Move the player to a known location. Fires the leaving location’s onLeave events and the arriving location’s onEnter events. Clears the event queue first.

public void MoveTo(string locationId);
Parameters

locationId System.String

Location id or uuid. Throws when unresolved.

Exceptions

BonsaiException
locationId does not resolve to a known location.

Example

var loc = runtime.AllLocations[0];
runtime.MoveTo(loc.Uuid);

Time

CurrentTime

The current in-game time view, or null when time-of-day is not enabled.

public TimeView? CurrentTime { get; }
Property Value

TimeView

AdvanceTimeBy(int)

Advance in-game time by the given number of minutes. Queues an AdvanceTimeEvent and re-evaluates visibility. Throws when time-of-day is not enabled on the project.

public void AdvanceTimeBy(int minutes);
Parameters

minutes System.Int32

Minutes to advance. Negative values are rejected — time only moves forward.

Exceptions

BonsaiException
Time-of-day is not enabled on the project.

Example

if (runtime.CurrentTime != null) runtime.AdvanceTimeBy(30);

AdvanceTimeTo(int)

Advance to an absolute minutes-elapsed value. No-op when the target is in the past (time only moves forward). Equivalent to AdvanceTimeBy(int) with the delta.

public void AdvanceTimeTo(int minutesElapsed);
Parameters

minutesElapsed System.Int32

Target minutes-elapsed value (from project start).

Exceptions

BonsaiException
Time-of-day is not enabled on the project.

Example

if (runtime.CurrentTime != null) runtime.AdvanceTimeTo(360);

SetTimeBucket(string)

Jump time to the start of the named time bucket (no-op when already past it; time only moves forward). Queues an AdvanceTimeEvent with Reason = "setBucket". Bucket ids are author-defined; the runtime does not yet expose a catalog accessor — pass an id you know exists.

public void SetTimeBucket(string bucketId);
Parameters

bucketId System.String

Author-defined time-bucket id (e.g. "morning").

Exceptions

BonsaiException
Time-of-day is not enabled on the project, or the bucket id is unknown.

Example

if (runtime.CurrentTime != null) runtime.SetTimeBucket("morning");

Variables

GetMeterVariables()

Filtered view over AllVariables — only variables declared as meters (for status-bar UI rendering). Each result carries a live value getter.

public IReadOnlyList<MeterVariable> GetMeterVariables();
Returns

System.Collections.Generic.IReadOnlyList<MeterVariable>
Meter-declared variables only. Empty when the project has no meters.

Example

foreach (var m in runtime.GetMeterVariables()) { /* render m.Id with m.GetValue() */ }

GetVariable(string)

Variable metadata (id, uuid, type, display name) plus a live value getter. Null when the id is unknown.

public VariableView? GetVariable(string id);
Parameters

id System.String

Variable id or uuid.

Returns

VariableView
A VariableView, or null when unresolved.

Example

var meta = runtime.GetVariable(runtime.AllVariables[0].Id);

GetVariableValue(string)

The variable’s current value as a boxed primitive (bool / int / decimal / string).

public object GetVariableValue(string key);
Parameters

key System.String

Variable uuid (primary) or expression-namespace id (secondary). Throws when unresolved.

Returns

System.Object
The variable’s current value, boxed. Cast or use Convert.ToInt32 etc.

Exceptions

BonsaiException
The key does not resolve to a known variable.

Example

var v = runtime.AllVariables[0];
var value = runtime.GetVariableValue(v.Uuid);

Remarks

Accepts the variable’s uuid (primary) or its expression-namespace id (secondary). Runtime-synthesized keys (current_location, time) have no uuid — use the id form.

OnBeforeVariable(string, Func<string,object,object>)

Variable bridge — register a validator/transformer fired before each set. The validator receives (key, proposedValue) and returns the value to store; throw to reject the change. Use for clamping (e.g. HP >= 0) or rejecting invalid transitions.

public void OnBeforeVariable(string key, Func<string,object,object> validator);
Parameters

key System.String

Variable uuid or expression-namespace id.

validator System.Func<System.String,System.Object,System.Object>

Receives (key, proposedValue), returns the stored value. Throw to reject.

Example

var v = runtime.AllVariables[0];
runtime.OnBeforeVariable(v.Uuid, (k, val) => val);

Remarks

See GetVariableValue(string) for accepted key forms. The validator’s key argument is always the expression-namespace id, regardless of which form was registered.

SetVariable(string, object)

Seed a variable’s value before StartProject(string, SceneScope). Throws once the session has started — use the variable bridge (SyncVariable(string, Func<object>) / OnBeforeVariable(string, Func<string,object,object>)) for mid-session mutations.

public void SetVariable(string key, object value);
Parameters

key System.String

Variable uuid or expression-namespace id.

value System.Object

New value (bool / int / decimal / string per the variable’s type).

Exceptions

System.InvalidOperationException
The session has already started.

Example

var v = runtime.AllVariables[0];
runtime.Reset();
runtime.SetVariable(v.Uuid, 5);

Remarks

See GetVariableValue(string) for accepted key forms.

SyncVariable(string, Func<object>)

Variable bridge — register a host-side getter for a variable. Every read of key goes through getter; the runtime never stores a value for synced keys. Use for engine-owned state (player position, HP).

public void SyncVariable(string key, Func<object> getter);
Parameters

key System.String

Variable uuid or expression-namespace id. The variable must be marked external-sync at authoring time.

getter System.Func<System.Object>

Returns the live value. Called every time an expression reads the key.

Exceptions

System.InvalidOperationException
Registered after the session started, or the variable is not marked external-sync.

Example

var v = runtime.AllVariables[0];
runtime.Reset();
runtime.SyncVariable(v.Uuid, () => 7);

Remarks

See GetVariableValue(string) for accepted key forms.

Unwatch(string)

Remove the watcher registered for key via Watch(string, Action<object,object>). No-op if none.

public void Unwatch(string key);
Parameters

key System.String

Variable uuid or expression-namespace id.

Example

var v = runtime.AllVariables[0];
runtime.Unwatch(v.Uuid);

Remarks

See GetVariableValue(string) for accepted key forms.

Watch(string, Action<object,object>)

Subscribe to changes on a variable. Callback fires with (oldValue, newValue) on every commit. Only one watcher per key — re-calling replaces the previous callback.

public void Watch(string key, Action<object,object> callback);
Parameters

key System.String

Variable uuid or expression-namespace id.

callback System.Action<System.Object,System.Object>

Receives (oldValue, newValue) on every commit. Replaces any prior watcher on the same key.

Example

var v = runtime.AllVariables[0];
runtime.Watch(v.Uuid, (oldVal, newVal) => { /* react */ });

Remarks

See GetVariableValue(string) for accepted key forms.

Events

Entity queries

GetAudioCue(string)

Authored audio cue definition. Accepts id or uuid; returns null when missing.

public AudioCueView? GetAudioCue(string id);
Parameters

id System.String

Audio cue id or uuid.

Returns

AudioCueView
An AudioCueView, or null when unresolved.

Example

var cue = runtime.AllAudioCues.Count > 0 ? runtime.GetAudioCue(runtime.AllAudioCues[0].Uuid) : null;

GetCharacter(string)

Authored character view (display name, portrait, etc.). Accepts id or uuid; returns null when missing.

public CharacterView? GetCharacter(string id);
Parameters

id System.String

Character id or uuid.

Returns

CharacterView
A CharacterView, or null when unresolved.

Example

var c = runtime.AllCharacters.Count > 0 ? runtime.GetCharacter(runtime.AllCharacters[0].Uuid) : null;

GetMedia(string)

Authored media definition (video, image, audio). Accepts id or uuid; returns null when missing.

public MediaView? GetMedia(string id);
Parameters

id System.String

Media id or uuid.

Returns

MediaView
A MediaView, or null when unresolved.

Example

var m = runtime.AllMedia.Count > 0 ? runtime.GetMedia(runtime.AllMedia[0].Uuid) : null;

Localization

ActiveLocale

The currently-active display locale. Defaults to SourceLocale.

public string ActiveLocale { get; }
Property Value

System.String

AvailableLocales

Locales the project’s authoring metadata declares it supports. Empty before a project is loaded; static (does not reflect which overlays have been loaded).

public IReadOnlyList<LocaleInfo> AvailableLocales { get; }
Property Value

System.Collections.Generic.IReadOnlyList<LocaleInfo>

LoadedLocales

Locale codes for which an overlay is currently registered via LoadLocale(string, string).

public IReadOnlyCollection<string> LoadedLocales { get; }
Property Value

System.Collections.Generic.IReadOnlyCollection<System.String>

PseudoLocaleInfo

Display metadata for the dev/QA pseudo locale. Intentionally outside AvailableLocales (which mirrors the project’s authored supported-locales list) — consumers append this to their own picker UI when they want pseudo exposed.

public static LocaleInfo PseudoLocaleInfo { get; }
Property Value

LocaleInfo

SourceLocale

The project’s source locale (defaults to “en” if unspecified). Always populated.

public string SourceLocale { get; }
Property Value

System.String

LoadLocale(string, string)

Register a translation overlay (flat {"key": "text"} JSON) under the given locale code. Throws on malformed JSON or a non-object payload. The host loads the bytes from its own asset pipeline.

public void LoadLocale(string code, string jsonContent);
Parameters

code System.String

Locale code (e.g. "es").

jsonContent System.String

Flat { "key": "text" } overlay JSON. Throws on malformed JSON or non-object root.

Exceptions

BonsaiException
The JSON is malformed or not a flat object.

Example

runtime.LoadLocale("es", "{}");

SetActiveLocale(string)

Switch the active display locale. The overlay must already be loaded via LoadLocale(string, string). Re-resolves any cached view text.

public void SetActiveLocale(string code);
Parameters

code System.String

Locale code (e.g. "es"). Must be loaded; pass the source locale to return to the original.

Exceptions

BonsaiException
No overlay has been loaded under code.

Example

runtime.LoadLocale("es", "{}");
runtime.SetActiveLocale("es");

Remarks

Fires LocaleChanged on success — subscribers should re-resolve any held LocalizableTitle / LocalizableText instances.

SupportsLocale(string)

True iff SetActiveLocale(string) would accept code without throwing. Returns true for the source locale, the pseudo locale, and any code that currently has an overlay loaded via LoadLocale(string, string). Returns false for null/empty or any other code. Use this to gate locale-switch UI without try/catching.

public bool SupportsLocale(string code);
Parameters

code System.String

Locale code to probe (e.g. "ja").

Returns

System.Boolean
True if SetActiveLocale(string) would succeed for code.

Example

if (runtime.SupportsLocale("es"))
    runtime.SetActiveLocale("es");

UnloadLocale(string)

Drop a previously-loaded overlay. No-op if the code was never loaded.

public void UnloadLocale(string code);
Parameters

code System.String

Locale code (e.g. "es").

Example

runtime.UnloadLocale("es");

Save / restore

Restore(ReplaySave, RecoveryMode, ResolutionPolicy)

Restore from a replay save. Long-running for big sessions — treat like a load screen. Diagnostics describe any project-drift fallouts. See Save() for the canonical save/restore example.

public ReplayDiagnostics Restore(ReplaySave save, RecoveryMode recoveryMode=RecoveryMode.BestEffort, ResolutionPolicy resolutionPolicy=ResolutionPolicy.Lenient);
Parameters

save ReplaySave

The ReplaySave previously produced by Save().

recoveryMode RecoveryMode

See RecoveryMode. BestEffort recovers as much as possible after project drift; Transactional rolls back on failure.

resolutionPolicy ResolutionPolicy

See ResolutionPolicy. Lenient resolves references by uuid OR id; Strict requires uuid.

Returns

ReplayDiagnostics
Diagnostics describing what was recovered, dropped, or remapped during replay.

Example

var snapshot = runtime.Save();
var diagnostics = runtime.Restore(snapshot);

Remarks

Replay-restore re-executes the recorded action stream against the current project. BestEffort recovers as much as possible after project drift; Transactional rolls back to the pre-restore snapshot on any failure. The ResolutionPolicy arg toggles between Lenient (uuid-or-id) and Strict (uuid-only) reference resolution. See also RecoveryMode.

RestoreFromJson(string, RecoveryMode, ResolutionPolicy)

Replay-restore from a save-JSON string (the inverse of SaveToJson()). Distinct from FromJson(string), which loads a writer-authored project definition. Long-running for big sessions — treat like a load screen.

public ReplayDiagnostics RestoreFromJson(string json, RecoveryMode recoveryMode=RecoveryMode.BestEffort, ResolutionPolicy resolutionPolicy=ResolutionPolicy.Lenient);
Parameters

json System.String

Save JSON produced by SaveToJson().

recoveryMode RecoveryMode

See RecoveryMode. BestEffort recovers as much as possible after project drift; Transactional rolls back on failure.

resolutionPolicy ResolutionPolicy

See ResolutionPolicy. Lenient resolves references by uuid OR id; Strict requires uuid.

Returns

ReplayDiagnostics
Diagnostics describing what was recovered, dropped, or remapped during replay.

Example

var json = runtime.SaveToJson();
var diagnostics = runtime.RestoreFromJson(json);

Remarks

See Restore(ReplaySave, RecoveryMode, ResolutionPolicy) for the semantics of RecoveryMode and ResolutionPolicy.

Save()

Capture the runtime state as a replay save (the public form; the runtime can rehydrate from this on a different project version). ReplaySave is a plain POCO — persist it with your preferred serializer (JSON, binary, in-memory save slot).

public ReplaySave Save();
Returns

ReplaySave
A ReplaySave POCO. Persist with your preferred serializer; pass back to Restore(ReplaySave, RecoveryMode, ResolutionPolicy) later.

Example

var snapshot = runtime.Save();
// ... persist snapshot via your save-system pipeline ...
var diagnostics = runtime.Restore(snapshot);

SaveToJson()

Convenience wrapper — equivalent to serializing Save()‘s result via Newtonsoft with the runtime’s default settings. Use Save() directly when you need a custom serializer (binary, MessagePack, your own save-system shape).

public string SaveToJson();
Returns

System.String
JSON string suitable for round-tripping through RestoreFromJson(string, RecoveryMode, ResolutionPolicy).

Example

var json = runtime.SaveToJson();

Undo / redo

CanRedo

True if at least one undone step is available to redo.

public bool CanRedo { get; }
Property Value

System.Boolean

CanUndo

True if at least one prior step is on the undo stack.

public bool CanUndo { get; }
Property Value

System.Boolean

RedoDepth

Number of steps currently on the redo stack.

public int RedoDepth { get; }
Property Value

System.Int32

UndoDepth

Number of steps currently on the undo stack.

public int UndoDepth { get; }
Property Value

System.Int32

Redo()

Re-apply the next redo entry. Throws when CanRedo is false. Pushes the current state onto the undo stack.

public void Redo();
Exceptions

System.InvalidOperationException
CanRedo is false (the redo stack is empty).

Example

if (runtime.CanRedo) runtime.Redo();

Undo()

Step back one commit. Throws when CanUndo is false. Pushes the current state onto the redo stack.

public void Undo();
Exceptions

System.InvalidOperationException
CanUndo is false (the undo stack is empty).

Example

if (runtime.CanUndo) runtime.Undo();

Determinism / debug

ForceSkillCheckOutcome(string, SkillCheckOutcome)

Force a specific skill-check event to resolve to the given outcome next time it fires. Used by the simulator’s “force outcome” affordance and by determinism-test fixtures. Forced outcomes are per-run state — cleared by Reset() / StartProject(string, SceneScope), so call this AFTER starting the runtime, before the skill check resolves.

public void ForceSkillCheckOutcome(string skillCheckUuid, SkillCheckOutcome outcome);
Parameters

skillCheckUuid System.String

Uuid of the skill-check event (SkillCheckEvent.Uuid).

outcome SkillCheckOutcome

Forced SkillCheckOutcome — typically Success or Fail.

Example

runtime.ForceSkillCheckOutcome("evt_check", SkillCheckOutcome.Success);

SetMasterSeed(int)

Seed the runtime PRNGs (skill checks, slot machines). Call before StartProject(string, SceneScope) for a deterministic session — replays and unit tests pin this. Calling mid-session re-seeds in place.

public void SetMasterSeed(int seed);
Parameters

seed System.Int32

Master seed. Same value produces the same dice-roll sequence given the same actions.

Example

runtime.SetMasterSeed(42);

Play history

EvaluatedNodeIds()

Human ids of every evaluated node, in execution order. UUID-only records (no human id) are skipped — use EvaluatedNodes() if you need every entry.

public IReadOnlyList<string> EvaluatedNodeIds();
Returns

System.Collections.Generic.IReadOnlyList<System.String>
Human ids of evaluated nodes in execution order. Records without a human id are skipped.

Example

foreach (var id in runtime.EvaluatedNodeIds()) { /* id was evaluated */ }

EvaluatedNodes()

Records of every node that executed this run (player-chosen + auto-evaluated), in execution order.

public IReadOnlyList<NodeRecord> EvaluatedNodes();
Returns

System.Collections.Generic.IReadOnlyList<NodeRecord>
One NodeRecord per executed node, in execution order.

Example

foreach (var n in runtime.EvaluatedNodes()) { /* n.NodeUuid executed */ }

HasNodeBeenPlayed(string)

True if the node has executed at least once this run. Accepts uuid, human id, or tag-style id.

public bool HasNodeBeenPlayed(string nodeIdOrUuid);
Parameters

nodeIdOrUuid System.String

Node uuid, human id, or tag-style id.

Returns

System.Boolean
True iff the node has executed at least once this run.

Example

var played = runtime.HasNodeBeenPlayed("node_choice");

SelectedNodes()

Records of every node the player chose this run, in execution order.

public IReadOnlyList<NodeRecord> SelectedNodes();
Returns

System.Collections.Generic.IReadOnlyList<NodeRecord>
One NodeRecord per player-chosen node, in execution order. Empty before any choice is committed.

Example

foreach (var n in runtime.SelectedNodes()) { /* n.NodeUuid was selected at step n.CommitIndex */ }

Other

LocaleChanged Event

Raised once after SetActiveLocale(string) swaps the active locale. Subscribers should re-resolve any held LocalizableTitle / LocalizableText instances (e.g. a cached Choice they’re currently rendering). Game state is unchanged — the choice set, event queue, and variables all keep their structure; only displayed strings differ.

public event EventHandler? LocaleChanged;
Event Type

System.EventHandler

Remarks

Fires synchronously on the same thread that called SetActiveLocale(string). Same handler-isolation, no-fire-on-failure, and re-entrancy semantics as Refreshed. LoadLocale(string, string) and UnloadLocale(string) do NOT fire this event — they mutate the locale catalog but no resolution result changes until SetActiveLocale(string) is called.

Refreshed Event

Raised once after each public method that mutates displayed runtime state has completed. Subscribers should re-pull GetChoices(), GetEventQueue(), and any other state they display, then refresh their UI.

public event EventHandler? Refreshed;
Event Type

System.EventHandler

Remarks

Fires synchronously on the same thread that called the mutating method. Subscribe before calling StartProject(string, SceneScope) / RestoreFromJson(string, RecoveryMode, ResolutionPolicy) so the first fire delivers your initial sync; subscribers attaching later must call GetChoices() / GetEventQueue() once by hand to bootstrap. Mutating methods called from inside a handler throw BonsaiException; defer auto-advance and similar follow-ups to the next tick. Exceptions thrown by a handler are caught, logged via the runtime’s diagnostics log, and do not prevent other subscribers from running or the originating call from returning normally — studios that catch exceptions from a mutating call should re-pull manually to resync, since no fire occurs on failure. Reset() does NOT fire this event — it returns the runtime to an empty pre-start state. Follow it with StartProject(string, SceneScope) / RestoreFromJson(string, RecoveryMode, ResolutionPolicy), or re-pull manually.

Docs last synced: 2026-07-08
Screenshot viewer