State and History
The story’s state is the current value of your story variables: player stats, inventory, flags, anything you put in vars.
Sugarbox keeps state history without cloning the entire state object on every change. It does this by storing:
- an initial state, and
- a list of snapshots (partial updates) that represent what changed over time.
That history is what makes undo/redo style navigation possible, and it is also why saves can stay small even when your state grows.
Initial state
Section titled “Initial state”On initialization you pass vars. The initial state is treated as immutable. Every later state is derived from it plus snapshots.
import { SugarboxEngine } from "sugarbox";
export const engine = await SugarboxEngine.init({ name: "Dave's Adventure", startPassage: { name: "Start", data: "This is the starting passage", tags: ["prologue"], }, otherPassages: [], vars: { gold: 500, level: 1, },});Snapshots and state history
Section titled “Snapshots and state history”A snapshot is a partial object containing only the properties you changed since the previous snapshot. Sugarbox stores snapshots in an array (the state history) and uses an internal index to decide which point in that history represents “now”.
With the example above, a change like this:
engine.setVars((state) => { state.gold += 100;});records a snapshot that looks roughly like:
{ gold: 600}The initial state remains:
{ gold: 500, level: 1}Getting the current state
Section titled “Getting the current state”The “current state” is what you read via engine.vars.
When the engine needs the current state, it rebuilds it by starting from the initial state and applying snapshots up to the current index. This is why a cache adapter can help if you have a lot of snapshots and you read state frequently.
Updating state safely
Section titled “Updating state safely”Use engine.setVars() to update state. It works like Immer in practice:
- treat the callback argument as mutable
- Sugarbox records your edits into the current snapshot
- if you need to replace the entire state object, return a new object from the callback
One gotcha: snapshots only store properties you touched. If you want to represent “this thing is intentionally empty” rather than “not set in this snapshot”, use null instead of undefined.