# Save games Snapshots carry durable world state between processes. Use them for save games, checkpoints, replay buffers, and hot reload. ```nupp local save = world:saveSnapshot() world:loadSnapshot(save) ``` ## Snapshot contents `saveSnapshot()` returns a detached, format-neutral record. It preserves entity IDs and generations, component names and values, relationships, the state stack, and named custom data. Store or encode this value using Nupp's file and data APIs. The fixed accumulator and enabled phase state are preserved too. ```nupp local snapshot = world:saveSnapshot() -- Later, with the same component and state definitions registered: local prelude = world:loadSnapshot(snapshot) print(prelude.entityCount) ``` Use binary output for checkpoints and save files with native components: ```nupp local buffer = require("string.buffer") local output = buffer.new() local saved = world:saveSnapshot({format = "binary", buffer = output}) world:loadSnapshot(saved) world:loadSnapshot(output:tostring()) ``` The optional `path` writes binary output to a file and still returns the buffer. Reusing a buffer replaces its prior snapshot; loading a buffer does not consume it. The version-one framing uses native double ID arrays and column-major FFI copies. Matching raw layouts copy directly into their final columns without constructing a value per row. Changed scalar layouts use saved fingerprints for field-name migration. Custom codecs always take the codec path. Loading accepts detached tables, column-indexed tables, tagged table/binary outputs, byte strings and buffers. Install the named component and state definitions before loading. Save and load may run inside an active system after leaving any query loop; they reject publication callbacks and attempts to operate on another suspended dispatch. `filterQuery` selects archetypes, and `layers` selects Transform2D layers from zero through 31. Entities without Transform2D pass the layer filter. A snapshot without a filter includes disabled and paused entities. ## Durable world state Persist game meaning: entity relationships, health, inventory, animation state, and authored identity. `EntityKey` lets setup code rediscover individual entities after load without keeping an old row address. ## Runtime state Systems, queries, observers, component definitions, and resource values are runtime setup. Install them before loading. Snapshots do not serialize functions or the world's execution machinery. ## Component durability Record components may supply `save(value)` and `load(saved)` callbacks. Use them when the in-memory record holds handles or a different durable representation. Keep persisted component names stable across code and module moves. Use `deserialize(world, saved)` instead of `load` when decoding needs destination world resources. Both component and relationship codecs accept this form. It runs during validation, before entity replacement. A serializer returning nil omits that component on the decoded path and never invokes its loader. ## Transient components Set `transient = true` for projections such as native handles or caches. The snapshot omits that component while retaining the entity. Rebuild projections from durable state after loading. ## Snapshot handlers Register a handler for durable resource state outside component columns: ```nupp local SCORE: nupp.store.Key = nupp.store.newKey("game.score") world.resources:set(SCORE, 0) world:addSnapshotHandler({ name = "game.score", save = function(exclusive world: tecs.ecs.World): number return world.resources:get(SCORE) or 0 end, load = function(exclusive world: tecs.ecs.World, value: any): nil world.resources:set(SCORE, value as number) end, }) ``` Handler names are persisted keys. `finish(world, prelude)` runs after entity and handler restoration, when derived state can resolve restored identities. `tecs.random`, `__tecs.pipeline` and `__tecs.stateStack` are reserved metadata keys. ## Snapshot lifecycle observation `OnSnapshotSave` fires at address zero before entity selection. Its `addData` method attaches metadata; `exclude(Component)` excludes whole derived entities, unlike a transient component, which only omits its own column. `StartSnapshotLoad` fires after entity restoration and before metadata dispatch. Register `onData(key, callback)` handlers on this event for this load only. Multiple listeners receive a key in registration order. `FinishSnapshotLoad` carries the prelude after metadata handlers finish. Mutations staged by load callbacks publish before `loadSnapshot` returns. ## State setup Create every state with its policy before loading. Snapshots preserve the stack and state tags; policy functions stay in game code. See [State stack](states.md).