Recipes
Saves persistence player progress and data stores
Anything that must outlive the current match or session: score, inventory, unlocked levels, best time, checkpoint. Durable values live in the data warehouse, addressed by store, record, and field.
engine v1.0.234since script-semantic-patch-ops.v1, action-catalog.v1.0.232, persistence.v1Copy for LLM
Use this for
saving score, inventory, unlocks, and progress that survives across sessions; per-player durable state; a game data store
Not for
transient in-match values that need not persist (a plain script variable is enough); replicated motion (see multiplayer-replication-and-rooms)
Pairs with: Collectibles pickups scoring and win condition, Combat damage health and respawn scripting, UI HUD panels widgets and world nameplates, Spawn points checkpoints and respawn flow
The recipe
- Declare the store with
project_create_data_store(project.data_store.create) so the game has a durable place for records. - Address a value with three coordinates used by every warehouse op:
storeKey(defaultsprogress),recordKey(defaultsplayer), andfield. - Read into a script binding:
readTypedStateValue{ "scope":{"kind":"handler","handlerRef":<key>}, "storeKey":"progress", "recordKey":"player", "field":"coins", "valueType":"number", "assignTo":"coins", "defaultValue": 0 }.valueTypeis a Script IR value type (number,boolean,string,vector3,json, ...). - Write a value:
writeTypedStateValuewith the same coordinates plusvalue. Increment a counter atomically:incrementNumericState{ "field":"coins", "by": 1 }. Flip a flag:setBooleanState{ "field":"tutorialDone", "value": true }. - From a GessaScript body (
replaceScriptFromGessaScript) the full warehouse surface is available:ctx.warehouse.get,set,update,increment,append,query,create,delete. - Surface a saved value in the HUD with
wireHudStateBinding(see ui-hud-panels-and-widgets); it reads the same store/record/field.
Pitfalls
writeTypedStateValue,incrementNumericState, andsetBooleanStatecarrywriteState+durable+requiresAuthority: they run server-authoritatively and persist. Do not treat them as client-local scratch.readTypedStateValueisreadState+durable; give it adefaultValueso a missing record does not read as undefined.- The
valueTypemust match how the field is written elsewhere; reading a number field asbooleanwill not coerce. persistence.v1guardspersistence.prefetch_onlyandpersistence.drain_auditmean reads are prefetched and writes audited; keep per-tick warehouse traffic bounded.
Verify
simulation_run(qa.run.start) to confirm a written value reads back after a reload path.project_get_graph_snapshotto confirm the data store and the warehouse-op handlers exist.