mwg API
    Preparing search index...

    Class SaveSystem<T>

    Named, versioned save slots over localStorage (an in-memory store where there is none), for plain JSON state. Bump version when the state's shape changes and give migrations the step from each older version: a slot saved by an earlier release is upgraded when it loads. load returns null for a slot that is missing or damaged, so a save-select screen never meets an exception.

    import { SaveSystem } from '@datamoc/mwg/core';

    interface RunState {
    depth: number;
    gold: number;
    inventory: string[];
    }

    //version 2 added `inventory`: a slot saved at version 1 gets an empty one when it loads
    const saves = new SaveSystem<RunState>({
    namespace: 'my-game',
    version: 2,
    migrations: { 1: (old) => ({ ...(old as Omit<RunState, 'inventory'>), inventory: [] }) },
    });

    saves.save('auto', { depth: 3, gold: 40, inventory: ['rope'] }, 'Floor 3, 40 gold');

    const slot = saves.load('auto');
    if (slot) console.log(slot.state.inventory, slot.meta.preview); // ['rope'] 'Floor 3, 40 gold'
    saves.delete('auto');

    Type Parameters

    • T
    Index
    • Reads a slot back out as a portable string a player can carry to another browser or device, or hand to their own server - the counterpart to importSlot, for mwg's own save shape rather than a foreign one (importExternal covers that side). scrambleKey, when given, runs the payload through scramble first: not encryption, only enough to stop a save being hand-edited in a text editor. Returns null for a slot with no save.

      Parameters

      • slot: string
      • OptionalscrambleKey: string

      Returns string | null

    • Adopts a save this SaveSystem never wrote: normalize runs once on externalBytes, producing state at version 0, which is then carried up through the same migrations chain an ordinary load already uses to reach the current version - a game supplies one normalize per external format it wants to accept (an rpg.decodeMarshal-based one for a Game.rxdata, say), rather than hand-rolling "decode, then call save" outside the versioned pipeline every migration otherwise goes through.

      externalBytes is size-checked before normalize ever sees it - a cheap, structural guard against a truncated or hostile file, ahead of and distinct from validating whatever shape normalize itself produces.

      Parameters

      • slot: string
      • externalBytes: Uint8Array
      • normalize: (bytes: Uint8Array) => unknown
      • Optionalpreview: unknown

      Returns void

    • Writes a payload from this SaveSystem's own exportSlot back as an ordinary save, migrated up to the current version the same way load migrates an older save found locally. scrambleKey must match whatever exportSlot scrambled it with, if any.

      payload is size-checked before it is unscrambled, then read through parseInbound and the same shape check load applies; any failure throws a named Error and leaves the slot untouched.

      Parameters

      • slot: string
      • payload: string
      • OptionalscrambleKey: string

      Returns void

    • every slot holding a readable save, and its metadata - for a save-select screen

      Returns { meta: SaveMeta; slot: string }[]

    • Reads a slot, migrating it up to the current version if it was saved at an older one. Returns null for a corrupted, malformed or tampered slot the same way it already does for a missing one. The slot is read through parseInbound and a shape check, not trusted because this SaveSystem wrote it: a truncated write (an interrupted flush, a quota eviction) is possible anywhere, and under file:// Chromium shares one localStorage between every local page, so any other HTML file on the machine can rewrite it. A save-select screen should see "no usable save here", not an uncaught SyntaxError.

      Parameters

      • slot: string

      Returns SaveData<T> | null

    • Parameters

      • slot: string
      • state: T
      • Optionalpreview: unknown

      Returns void