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
IsProjectComplete
True after a completeProject event has fired this run. GetChoices() returns IsComplete = true from this point on.
public bool IsProjectComplete { get; }
Property Value
Metadata
Project-level static facts — name, uuid, schema version, entry scene id, etc.
public ProjectMetadata Metadata { get; }
Property Value
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
SceneScope — Full (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
EntrySceneId
The project’s declared entry scene id, or null when the project starts at the world layer.
public string? EntrySceneId { get; }
Property Value
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
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
EnterScene(SceneView, bool)
Typed overload — equivalent to EnterScene(scene.Id, returnAfter).
public void EnterScene(SceneView scene, bool returnAfter);
Parameters
scene SceneView
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
CurrentLocationId
The uuid of CurrentLocation, or null when no location has been entered.
public string? CurrentLocationId { get; }
Property Value
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
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
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
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
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
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
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
SourceLocale
The project’s source locale (defaults to “en” if unspecified). Always populated.
public string SourceLocale { get; }
Property Value
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
CanUndo
True if at least one prior step is on the undo stack.
public bool CanUndo { get; }
Property Value
RedoDepth
Number of steps currently on the redo stack.
public int RedoDepth { get; }
Property Value
UndoDepth
Number of steps currently on the undo stack.
public int UndoDepth { get; }
Property Value
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
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
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.