@datamoc/mw_games 0.9.0-alpha → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +4 -0
  3. package/dist/core/ActionJournal.d.ts +2 -0
  4. package/dist/core/ActionJournal.d.ts.map +1 -1
  5. package/dist/core/ActionJournal.js +6 -0
  6. package/dist/core/ActionJournal.js.map +1 -1
  7. package/dist/core/Multiplayer.d.ts +21 -4
  8. package/dist/core/Multiplayer.d.ts.map +1 -1
  9. package/dist/core/Multiplayer.js +31 -4
  10. package/dist/core/Multiplayer.js.map +1 -1
  11. package/dist/core/State.d.ts +38 -0
  12. package/dist/core/State.d.ts.map +1 -1
  13. package/dist/core/State.js +76 -0
  14. package/dist/core/State.js.map +1 -1
  15. package/dist/core/index.d.ts +3 -3
  16. package/dist/core/index.d.ts.map +1 -1
  17. package/dist/core/index.js +1 -1
  18. package/dist/core/index.js.map +1 -1
  19. package/dist/mw_games.global.js +113 -113
  20. package/dist/mwl/catalog.d.ts +7 -0
  21. package/dist/mwl/catalog.d.ts.map +1 -1
  22. package/dist/mwl/catalog.js +0 -0
  23. package/dist/mwl/catalog.js.map +1 -1
  24. package/dist/mwl/compiler.d.ts +3 -0
  25. package/dist/mwl/compiler.d.ts.map +1 -1
  26. package/dist/mwl/compiler.js +10 -3
  27. package/dist/mwl/compiler.js.map +1 -1
  28. package/dist/mwl/grammar.d.ts +8 -1
  29. package/dist/mwl/grammar.d.ts.map +1 -1
  30. package/dist/mwl/grammar.js +207 -39
  31. package/dist/mwl/grammar.js.map +1 -1
  32. package/dist/mwl/hooks.d.ts +35 -2
  33. package/dist/mwl/hooks.d.ts.map +1 -1
  34. package/dist/mwl/hooks.js +8 -6
  35. package/dist/mwl/hooks.js.map +1 -1
  36. package/dist/mwl/index.d.ts +6 -6
  37. package/dist/mwl/index.d.ts.map +1 -1
  38. package/dist/mwl/index.js +3 -3
  39. package/dist/mwl/index.js.map +1 -1
  40. package/dist/mwl/persistence.d.ts +18 -1
  41. package/dist/mwl/persistence.d.ts.map +1 -1
  42. package/dist/mwl/persistence.js +59 -3
  43. package/dist/mwl/persistence.js.map +1 -1
  44. package/dist/mwl/readers.d.ts +37 -0
  45. package/dist/mwl/readers.d.ts.map +1 -1
  46. package/dist/mwl/readers.js +69 -0
  47. package/dist/mwl/readers.js.map +1 -1
  48. package/dist/mwl/runtime.d.ts +45 -1
  49. package/dist/mwl/runtime.d.ts.map +1 -1
  50. package/dist/mwl/runtime.js +72 -8
  51. package/dist/mwl/runtime.js.map +1 -1
  52. package/dist/mwl/schema.d.ts +31 -0
  53. package/dist/mwl/schema.d.ts.map +1 -1
  54. package/dist/mwl/schema.js +57 -2
  55. package/dist/mwl/schema.js.map +1 -1
  56. package/dist/simulation/Runtime.d.ts +66 -1
  57. package/dist/simulation/Runtime.d.ts.map +1 -1
  58. package/dist/simulation/Runtime.js +131 -3
  59. package/dist/simulation/Runtime.js.map +1 -1
  60. package/dist/simulation/index.d.ts +2 -2
  61. package/dist/simulation/index.d.ts.map +1 -1
  62. package/dist/simulation/index.js +1 -1
  63. package/dist/simulation/index.js.map +1 -1
  64. package/dist/two-d/render/RpgmAutotile.d.ts +65 -0
  65. package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -0
  66. package/dist/two-d/render/RpgmAutotile.js +110 -0
  67. package/dist/two-d/render/RpgmAutotile.js.map +1 -0
  68. package/dist/two-d/render/index.d.ts +2 -0
  69. package/dist/two-d/render/index.d.ts.map +1 -1
  70. package/dist/two-d/render/index.js +1 -0
  71. package/dist/two-d/render/index.js.map +1 -1
  72. package/dist/version.d.ts +1 -1
  73. package/dist/version.d.ts.map +1 -1
  74. package/dist/version.js +1 -1
  75. package/dist/version.js.map +1 -1
  76. package/package.json +1 -1
  77. package/tools/mwl.mjs +85 -4
package/CHANGELOG.md CHANGED
@@ -7,6 +7,77 @@ the public API may still change between minor versions.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.9.1] - 2026-09-14
11
+
12
+ ### Added
13
+
14
+ - `rpgmAutotileFrame` and `RpgmAutotileAtlas` - renderer-neutral RPG Maker MV autotile
15
+ atlas geometry, including four-slot decoding, quadrant selection, validation, and cached
16
+ frame descriptions (roadmap item 348).
17
+
18
+ ## [0.9.0] - 2026-09-13
19
+
20
+ ### Added
21
+
22
+ - `core.CanonicalState` - a defensive, JSON-safe root state combined with `StateRegistry`
23
+ extensions, with snapshots, version migrations, transactions, and atomic restore covering
24
+ both pieces together (item 341).
25
+ - `simulation.validateSimulationReplay`, and an optional `history` option on `SimulationRuntime`:
26
+ replay a recorded journal from a checkpoint and compare deterministic event batches, and
27
+ restore complete state/scheduler/RNG/journal undo-redo checkpoints (item 341).
28
+ - `LockstepClient`/`createLockstepServer` carry a session seed and initial state, validate
29
+ game-supplied commands, and exchange per-tick state checksums, with new `onReject`/`onDesync`
30
+ signals reporting rejected input and diverging peers (item 341).
31
+ - MWL JSON5 authoring accepts schema-neutral named-node sugar (`{ unit_type: { id: 'hero' } }`
32
+ and repeated object children) alongside the generic `tag`/`children` envelope, lowered before
33
+ validation runs (item 338).
34
+ - `MwlDomainHook`/`MwlDomainHookRegistry`/`MwlDomainHookDeclaration` - game-declared hook
35
+ namespaces (`item-effect:potion-strength`) get a typed context/input/output boundary that MWG
36
+ validates and emits without knowing the domain's own types or rules (item 342).
37
+ - `HookWorld.random` - every MWL hook, built-in or domain, draws from the runtime's own seeded
38
+ `core.Generator` instead of `Math.random()`, via the new `MwlRuntimeOptions.random`; the draw
39
+ position is carried on `MwlWorld.random` and resumes exactly across save/restore (item 342).
40
+ Any game hand-building its own `HookWorld` (only `MwlRuntime` constructs one today) must now
41
+ provide this field too, the same rule item 319's `variableAt` addition already established.
42
+ - `MwlSaveableHookState`/`MwlHookRegistry.saveable` - a game may explicitly expose JSON-safe hook
43
+ state; `MwlRuntime.save()`/`restore()` round-trip it through the same save envelope (item 341).
44
+ - `MwlRuntime.journal`/`MwlRuntimeAction` - public runtime operations (running a trigger, firing
45
+ an event or a moveto watch, answering a dialogue choice) are recorded in order and persisted
46
+ with the save (item 341).
47
+ - The MWL parser and compiler retain exact JSON5 attribute and value source locations
48
+ (`MwlNode.attributeLocations`/`valueLocations`), used by schema, catalog, and macro
49
+ diagnostics instead of falling back to the owning node's own location (item 342).
50
+ - Unknown MWL macros and hook references are errors by default, with file/line/column
51
+ diagnostics; `MwlPreprocessOptions.macroPolicy: 'ignore'` restores the old silent-passthrough
52
+ behaviour for legacy content (item 342).
53
+ - `schema10`/`MWL_SCHEMA_10` - the published MWL 1.0 vocabulary: required attributes and child
54
+ cardinalities on top of the unchanged 0.1 tag/value contract; `mwl migrate --to 1.0` performs
55
+ a lossless upgrade (item 342).
56
+ - `validateCatalog` reports `MWL_ALIAS_CYCLE` for cycles in resolved `aliasof` chains, and the new
57
+ `MwlValidationOptions.mapBounds` rejects authored coordinates outside declared map dimensions
58
+ (item 342).
59
+ - `readTableMap`/`readTableIndex`/`tableKey` - typed table-row projections with collision-free
60
+ native composite keys, and inverse indexes that retain every matching row (items 339, 346).
61
+ - `mwl diagnostics`/`mwl ci` CLI modes emit stable, machine-readable JSON diagnostics; `mwl
62
+ format`/`mwl migrate --to 1.0` emit a deterministic canonical document (items 342, 346).
63
+ - `tests/random.test.ts` gained a hardcoded-output compatibility test for `core.Generator`'s
64
+ stream, guarding fixed seeds against a future silent algorithm change (item 342).
65
+
66
+ ### Changed
67
+
68
+ - `mwl/grammar.ts`'s macro expansion, gettext rewrite, and tag-site collection now share one
69
+ `skipStringOrComment` scan instead of three near-identical hand-rolled copies of it.
70
+ - `LockstepClient.submitInput` accepts an optional per-tick checksum and an optional client-side
71
+ `validateInput`; rejected input reports through the new `onReject` signal instead of silently
72
+ going nowhere.
73
+
74
+ ### Fixed
75
+
76
+ - `src/mwl/catalog.ts` carried a literal NUL byte, rather than an escaped `\0`, inside one
77
+ composite map key, which made the file register as binary to `git diff` and `grep`. Replaced
78
+ with the same `\0` escape already used for the identical purpose elsewhere in the file; no
79
+ behaviour change.
80
+
10
81
  ## [0.9.0-alpha] - 2026-09-13
11
82
 
12
83
  ### Changed
package/README.md CHANGED
@@ -418,6 +418,10 @@ time with:
418
418
 
419
419
  ```sh
420
420
  npm run mwl -- validate game.mwl
421
+ npm run mwl -- diagnostics game.mwl
422
+ npm run mwl -- ci game.mwl
423
+ npm run mwl -- format game.mwl -o generated/game.mwl
424
+ npm run mwl -- migrate game.mwl --to 1.0 -o generated/game-1.0.mwl
421
425
  npm run mwl -- build game.mwl -o generated/
422
426
  npm run mwl -- compile game.mwl -o generated/game-data.ts
423
427
  npm run mwl -- extract-i18n game.mwl -o generated/i18n.json
@@ -31,6 +31,8 @@ export declare class ActionJournal<Action, Event> {
31
31
  /** Drops entries at and after a checkpoint, as an undo operation would. */
32
32
  truncate(sequence: number): void;
33
33
  toJSON(): ActionJournalEntry<Action, Event>[];
34
+ /** Replaces the log from a validated snapshot, preserving contiguous sequence numbers. */
35
+ replace(entries: readonly ActionJournalEntry<Action, Event>[]): void;
34
36
  static fromJSON<Action, Event>(entries: readonly ActionJournalEntry<Action, Event>[]): ActionJournal<Action, Event>;
35
37
  }
36
38
  //# sourceMappingURL=ActionJournal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActionJournal.d.ts","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,WAAW,kBAAkB,CAAC,MAAM,EAAE,KAAK;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;CAClC;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAa,CAAC,MAAM,EAAE,KAAK;IACvC,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,YAAY,CAAK;IAEzB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,SAAS,KAAK,EAAO,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAIvF;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,GAAG,IAAI,SAAS,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAEtD;IAED,gFAAgF;IAChF,IAAI,IAAI,MAAM,CAEb;IAED,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAE3D;IAED,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAG/B;IAED,MAAM,IAAI,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAE5C;IAED,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAC5B,OAAO,EAAE,SAAS,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GACnD,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAa9B;CACD"}
1
+ {"version":3,"file":"ActionJournal.d.ts","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,MAAM,WAAW,kBAAkB,CAAC,MAAM,EAAE,KAAK;IAChD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;CAClC;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,aAAa,CAAC,MAAM,EAAE,KAAK;IACvC,OAAO,CAAC,OAAO,CAA2C;IAC1D,OAAO,CAAC,YAAY,CAAK;IAEzB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,SAAS,KAAK,EAAO,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAIvF;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,GAAG,IAAI,SAAS,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAEtD;IAED,gFAAgF;IAChF,IAAI,IAAI,MAAM,CAEb;IAED,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAE3D;IAED,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAG/B;IAED,MAAM,IAAI,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAE5C;IAED,0FAA0F;IAC1F,OAAO,CAAC,OAAO,EAAE,SAAS,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,CAInE;IAED,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAC5B,OAAO,EAAE,SAAS,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,GACnD,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAa9B;CACD"}
@@ -44,6 +44,12 @@ export class ActionJournal {
44
44
  toJSON() {
45
45
  return this.all;
46
46
  }
47
+ /** Replaces the log from a validated snapshot, preserving contiguous sequence numbers. */
48
+ replace(entries) {
49
+ const restored = ActionJournal.fromJSON(entries);
50
+ this.entries = restored.entries;
51
+ this.nextSequence = restored.nextSequence;
52
+ }
47
53
  static fromJSON(entries) {
48
54
  const journal = new ActionJournal();
49
55
  let expected = 0;
@@ -1 +1 @@
1
- {"version":3,"file":"ActionJournal.js","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,aAAa;IAA1B;QACS,YAAO,GAAwC,EAAE,CAAC;QAClD,iBAAY,GAAG,CAAC,CAAC;IAmD1B,CAAC;IAjDA,MAAM,CAAC,MAAc,EAAE,MAAM,GAAqB,EAAE;QACnD,MAAM,KAAK,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC;QAC9F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,IAAI;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,IAAI,GAAG;QACN,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,gFAAgF;IAChF,IAAI;QACH,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAgB;QACrB,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,QAAgB;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC;QACzE,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAED,MAAM;QACL,OAAO,IAAI,CAAC,GAA0C,CAAC;IACxD,CAAC;IAED,MAAM,CAAC,QAAQ,CACd,OAAqD;QAErD,MAAM,OAAO,GAAG,IAAI,aAAa,EAAiB,CAAC;QACnD,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;gBACvE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAC1E,OAAO,CAAC,OAAO,CAAC,IAAI,CACnB,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAC9F,CAAC;YACF,QAAQ,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,YAAY,GAAG,QAAQ,CAAC;QAChC,OAAO,OAAO,CAAC;IAChB,CAAC;CACD"}
1
+ {"version":3,"file":"ActionJournal.js","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,aAAa;IAA1B;QACS,YAAO,GAAwC,EAAE,CAAC;QAClD,iBAAY,GAAG,CAAC,CAAC;IA0D1B,CAAC;IAxDA,MAAM,CAAC,MAAc,EAAE,MAAM,GAAqB,EAAE;QACnD,MAAM,KAAK,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC;QAC9F,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzB,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,IAAI;QACP,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,IAAI,GAAG;QACN,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,gFAAgF;IAChF,IAAI;QACH,OAAO,IAAI,CAAC,YAAY,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,QAAgB;QACrB,OAAO,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,2EAA2E;IAC3E,QAAQ,CAAC,QAAgB;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC;QACzE,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;IAC9B,CAAC;IAED,MAAM;QACL,OAAO,IAAI,CAAC,GAA0C,CAAC;IACxD,CAAC;IAED,0FAA0F;IAC1F,OAAO,CAAC,OAAqD;QAC5D,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,QAAQ,CACd,OAAqD;QAErD,MAAM,OAAO,GAAG,IAAI,aAAa,EAAiB,CAAC;QACnD,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;gBACvE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;YAC1E,OAAO,CAAC,OAAO,CAAC,IAAI,CACnB,eAAe,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAC9F,CAAC;YACF,QAAQ,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,YAAY,GAAG,QAAQ,CAAC;QAChC,OAAO,OAAO,CAAC;IAChB,CAAC;CACD"}
@@ -15,11 +15,22 @@ export interface LockstepClientOptions {
15
15
  url: string;
16
16
  /** defaults to the global `WebSocket`; inject a fake in tests, or `ws`'s own client in Node */
17
17
  create?: (url: string) => WebSocketLike;
18
+ /** Optional client-side command contract. Returning a string rejects with that reason. */
19
+ validateInput?: (payload: unknown) => boolean | string;
20
+ }
21
+ export interface LockstepWelcome {
22
+ id: string;
23
+ /** The room seed, when the server configured one. */
24
+ seed?: number;
25
+ /** The JSON-safe state from which every peer must start, when configured. */
26
+ initialState?: unknown;
18
27
  }
19
28
  export interface TickEvent {
20
29
  tick: number;
21
30
  /** this room's every client id mapped to its input for `tick`, or `null` if it missed the deadline */
22
31
  inputs: Record<string, unknown>;
32
+ /** state checksums reported by peers after applying this tick, when supplied */
33
+ checksums?: Record<string, number>;
23
34
  }
24
35
  /**
25
36
  * A client for this project's own reference lockstep server (`tools/multiplayer-server.mjs`):
@@ -53,14 +64,20 @@ export interface TickEvent {
53
64
  * ```
54
65
  */
55
66
  export declare class LockstepClient {
56
- readonly onWelcome: Signal<{
57
- id: string;
58
- }>;
67
+ readonly onWelcome: Signal<LockstepWelcome>;
59
68
  readonly onTick: Signal<TickEvent>;
69
+ readonly onReject: Signal<{
70
+ reason: string;
71
+ }>;
72
+ readonly onDesync: Signal<{
73
+ tick: number;
74
+ checksums: Record<string, number>;
75
+ }>;
60
76
  readonly onClose: Signal<void>;
61
77
  private socket;
62
78
  private readonly url;
63
79
  private readonly createSocket;
80
+ private readonly validateInput?;
64
81
  private _id;
65
82
  constructor(options: LockstepClientOptions);
66
83
  /** this client's own id, assigned by the server's `welcome` message; `null` before it arrives */
@@ -68,7 +85,7 @@ export declare class LockstepClient {
68
85
  get connected(): boolean;
69
86
  connect(): void;
70
87
  /** submits this client's input for the current tick; a no-op before the connection is open */
71
- submitInput(payload: unknown): void;
88
+ submitInput(payload: unknown, checksum?: number): void;
72
89
  close(): void;
73
90
  private handleMessage;
74
91
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Multiplayer.d.ts","sourceRoot":"","sources":["../../src/core/Multiplayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,yGAAyG;AACzG,MAAM,WAAW,aAAa;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CACtD;AAID,MAAM,WAAW,qBAAqB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,+FAA+F;IAC/F,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;CACxC;AAED,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,sGAAsG;IACtG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,cAAc;IAC1B,QAAQ,CAAC,SAAS;YAAoB,MAAM;OAAM;IAClD,QAAQ,CAAC,MAAM,oBAA2B;IAC1C,QAAQ,CAAC,OAAO,eAAsB;IAEtC,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAC9D,OAAO,CAAC,GAAG,CAAuB;IAElC,YAAY,OAAO,EAAE,qBAAqB,EAIzC;IAED,iGAAiG;IACjG,IAAI,EAAE,IAAI,MAAM,GAAG,IAAI,CAEtB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,OAAO,IAAI,IAAI,CAUd;IAED,8FAA8F;IAC9F,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGlC;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,OAAO,CAAC,aAAa;CAcrB"}
1
+ {"version":3,"file":"Multiplayer.d.ts","sourceRoot":"","sources":["../../src/core/Multiplayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,yGAAyG;AACzG,MAAM,WAAW,aAAa;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CACtD;AAID,MAAM,WAAW,qBAAqB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,+FAA+F;IAC/F,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;IACxC,0FAA0F;IAC1F,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,GAAG,MAAM,CAAC;CACvD;AAED,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,sGAAsG;IACtG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,cAAc;IAC1B,QAAQ,CAAC,SAAS,0BAAiC;IACnD,QAAQ,CAAC,MAAM,oBAA2B;IAC1C,QAAQ,CAAC,QAAQ;gBAAwB,MAAM;OAAM;IACrD,QAAQ,CAAC,QAAQ;cAAsB,MAAM;mBAAa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;OAAM;IACtF,QAAQ,CAAC,OAAO,eAAsB;IAEtC,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAyC;IACxE,OAAO,CAAC,GAAG,CAAuB;IAElC,YAAY,OAAO,EAAE,qBAAqB,EAKzC;IAED,iGAAiG;IACjG,IAAI,EAAE,IAAI,MAAM,GAAG,IAAI,CAEtB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,OAAO,IAAI,IAAI,CAUd;IAED,8FAA8F;IAC9F,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAUrD;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,OAAO,CAAC,aAAa;CAkCrB"}
@@ -35,6 +35,8 @@ export class LockstepClient {
35
35
  constructor(options) {
36
36
  this.onWelcome = new Signal();
37
37
  this.onTick = new Signal();
38
+ this.onReject = new Signal();
39
+ this.onDesync = new Signal();
38
40
  this.onClose = new Signal();
39
41
  this.socket = null;
40
42
  this._id = null;
@@ -42,6 +44,7 @@ export class LockstepClient {
42
44
  throw new Error('lockstep client url is required');
43
45
  this.url = options.url;
44
46
  this.createSocket = options.create ?? ((url) => new WebSocket(url));
47
+ this.validateInput = options.validateInput;
45
48
  }
46
49
  /** this client's own id, assigned by the server's `welcome` message; `null` before it arrives */
47
50
  get id() {
@@ -63,10 +66,17 @@ export class LockstepClient {
63
66
  this.socket = socket;
64
67
  }
65
68
  /** submits this client's input for the current tick; a no-op before the connection is open */
66
- submitInput(payload) {
69
+ submitInput(payload, checksum) {
67
70
  if (!this.connected)
68
71
  return;
69
- this.socket?.send(JSON.stringify({ type: 'input', payload }));
72
+ const validation = this.validateInput?.(payload);
73
+ if (validation === false || typeof validation === 'string') {
74
+ this.onReject.dispatch({
75
+ reason: validation === false ? 'input rejected by client validation' : validation,
76
+ });
77
+ return;
78
+ }
79
+ this.socket?.send(JSON.stringify({ type: 'input', payload, ...(checksum === undefined ? {} : { checksum }) }));
70
80
  }
71
81
  close() {
72
82
  this.socket?.close();
@@ -75,10 +85,27 @@ export class LockstepClient {
75
85
  const message = JSON.parse(raw);
76
86
  if (message.type === 'welcome' && message.id !== undefined) {
77
87
  this._id = message.id;
78
- this.onWelcome.dispatch({ id: message.id });
88
+ this.onWelcome.dispatch({
89
+ id: message.id,
90
+ ...(message.seed === undefined ? {} : { seed: message.seed }),
91
+ ...(message.initialState === undefined ? {} : { initialState: message.initialState }),
92
+ });
79
93
  }
80
94
  else if (message.type === 'tick' && message.tick !== undefined && message.inputs !== undefined) {
81
- this.onTick.dispatch({ tick: message.tick, inputs: message.inputs });
95
+ const event = {
96
+ tick: message.tick,
97
+ inputs: message.inputs,
98
+ ...(message.checksums === undefined ? {} : { checksums: message.checksums }),
99
+ };
100
+ this.onTick.dispatch(event);
101
+ if (message.checksums) {
102
+ const checksums = Object.values(message.checksums);
103
+ if (checksums.some((checksum) => checksum !== checksums[0]))
104
+ this.onDesync.dispatch({ tick: message.tick, checksums: message.checksums });
105
+ }
106
+ }
107
+ else if (message.type === 'rejected') {
108
+ this.onReject.dispatch({ reason: message.reason ?? 'input rejected by server' });
82
109
  }
83
110
  }
84
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Multiplayer.js","sourceRoot":"","sources":["../../src/core/Multiplayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAarC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,wFAAwF;AAcxG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,cAAc;IAU1B,YAAY,OAA8B;QATjC,cAAS,GAAG,IAAI,MAAM,EAAkB,CAAC;QACzC,WAAM,GAAG,IAAI,MAAM,EAAa,CAAC;QACjC,YAAO,GAAG,IAAI,MAAM,EAAQ,CAAC;QAE9B,WAAM,GAAyB,IAAI,CAAC;QAGpC,QAAG,GAAkB,IAAI,CAAC;QAGjC,IAAI,CAAC,OAAO,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,GAAG,CAA6B,CAAC,CAAC;IACjG,CAAC;IAED,iGAAiG;IACjG,IAAI,EAAE;QACL,OAAO,IAAI,CAAC,GAAG,CAAC;IACjB,CAAC;IAED,IAAI,SAAS;QACZ,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC;IAChE,CAAC;IAED,OAAO;QACN,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;YACrB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACzB,CAAC,CAAC;QACF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;IAED,8FAA8F;IAC9F,WAAW,CAAC,OAAgB;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5B,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IACtB,CAAC;IAEO,aAAa,CAAC,GAAW;QAChC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAK7B,CAAC;QACF,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC5D,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC;YACtB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7C,CAAC;aAAM,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAClG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACtE,CAAC;IACF,CAAC;CACD"}
1
+ {"version":3,"file":"Multiplayer.js","sourceRoot":"","sources":["../../src/core/Multiplayer.ts"],"names":[],"mappings":"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"}
@@ -28,6 +28,44 @@ export interface StateRestoreDiagnostic {
28
28
  readonly to: number;
29
29
  readonly status: 'migrated' | 'unchanged' | 'reset' | 'removed';
30
30
  }
31
+ export interface CanonicalStateSnapshot<State extends StateValue = StateValue> {
32
+ readonly version: number;
33
+ readonly state: State;
34
+ readonly extensions: Readonly<Record<string, StateValue>>;
35
+ readonly extensionVersions?: Readonly<Record<string, number>>;
36
+ }
37
+ /**
38
+ * A single JSON-safe source of truth for a game's logical state. The root value belongs to the
39
+ * game, while framework or game subsystems register independent versioned extensions beside it.
40
+ * Reads and writes clone values, so a renderer cannot mutate authoritative state accidentally.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { CanonicalState } from '@datamoc/mw_games/core';
45
+ *
46
+ * const state = new CanonicalState({ turn: 1, gold: 10 });
47
+ * state.update((current) => ({ ...current, gold: current.gold - 3 }));
48
+ * const save = state.snapshot();
49
+ * state.restore(save);
50
+ * ```
51
+ */
52
+ export declare class CanonicalState<State extends StateValue> {
53
+ private _state;
54
+ private readonly version;
55
+ private readonly migrations;
56
+ readonly extensions: StateRegistry;
57
+ constructor(initial: State, options?: {
58
+ readonly version?: number;
59
+ readonly migrations?: Readonly<Record<number, (state: StateValue) => State>>;
60
+ readonly extensions?: StateRegistry;
61
+ });
62
+ get state(): State;
63
+ set(next: State): void;
64
+ update(transform: (current: State) => State): State;
65
+ snapshot(): CanonicalStateSnapshot<State>;
66
+ restore(snapshot: CanonicalStateSnapshot<State>, options?: Parameters<StateRegistry['restore']>[1]): readonly StateRestoreDiagnostic[];
67
+ transaction<T>(work: (state: CanonicalState<State>) => T): T;
68
+ }
31
69
  /**
32
70
  * Coordinates game-owned save state without knowing its schema.
33
71
  *
@@ -1 +1 @@
1
- {"version":3,"file":"State.d.ts","sourceRoot":"","sources":["../../src/core/State.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,EAAE,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,CAAC;AAElH,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,UAAU,GAAG,UAAU;IAChE,yCAAyC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACrC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC;IACzE,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,uFAAuF;IACvF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;CAChE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,aAAa;IACzB,OAAO,CAAC,UAAU,CAAqC;IAEvD,QAAQ,CAAC,CAAC,SAAS,UAAU,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAcvE;IAED,QAAQ,IAAI,aAAa,CAMxB;IAED,OAAO,CACN,QAAQ,EAAE,aAAa,EACvB,OAAO,GAAE;QACR,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;QAC/C,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,sBAAsB,KAAK,IAAI,CAAC;KAChE,GACJ,SAAS,sBAAsB,EAAE,CAiCnC;IAED,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAQ/B;CACD"}
1
+ {"version":3,"file":"State.d.ts","sourceRoot":"","sources":["../../src/core/State.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,79 @@
1
+ /**
2
+ * A single JSON-safe source of truth for a game's logical state. The root value belongs to the
3
+ * game, while framework or game subsystems register independent versioned extensions beside it.
4
+ * Reads and writes clone values, so a renderer cannot mutate authoritative state accidentally.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * import { CanonicalState } from '@datamoc/mw_games/core';
9
+ *
10
+ * const state = new CanonicalState({ turn: 1, gold: 10 });
11
+ * state.update((current) => ({ ...current, gold: current.gold - 3 }));
12
+ * const save = state.snapshot();
13
+ * state.restore(save);
14
+ * ```
15
+ */
16
+ export class CanonicalState {
17
+ constructor(initial, options = {}) {
18
+ this._state = structuredClone(initial);
19
+ this.version = options.version ?? 1;
20
+ this.migrations = options.migrations ?? {};
21
+ this.extensions = options.extensions ?? new StateRegistry();
22
+ }
23
+ get state() {
24
+ return structuredClone(this._state);
25
+ }
26
+ set(next) {
27
+ this._state = structuredClone(next);
28
+ }
29
+ update(transform) {
30
+ const next = transform(this.state);
31
+ this.set(next);
32
+ return this.state;
33
+ }
34
+ snapshot() {
35
+ const extensions = this.extensions.snapshot();
36
+ return {
37
+ version: this.version,
38
+ state: this.state,
39
+ extensions: extensions.extensions,
40
+ extensionVersions: extensions.versions,
41
+ };
42
+ }
43
+ restore(snapshot, options = {}) {
44
+ if (!Number.isSafeInteger(snapshot.version) || snapshot.version < 1)
45
+ throw new Error('canonical state snapshot version must be a positive integer');
46
+ if (snapshot.version > this.version)
47
+ throw new Error(`canonical state snapshot version ${snapshot.version} is newer than ${this.version}`);
48
+ const before = this.snapshot();
49
+ try {
50
+ let state = structuredClone(snapshot.state);
51
+ for (let version = snapshot.version; version < this.version; version++) {
52
+ const migration = this.migrations[version + 1];
53
+ if (!migration)
54
+ throw new Error(`missing canonical state migration to version ${version + 1}`);
55
+ state = migration(state);
56
+ }
57
+ this._state = structuredClone(state);
58
+ return this.extensions.restore({ extensions: snapshot.extensions, versions: snapshot.extensionVersions }, options);
59
+ }
60
+ catch (error) {
61
+ this._state = structuredClone(before.state);
62
+ this.extensions.restore({ extensions: before.extensions, versions: before.extensionVersions }, { missing: 'keep' });
63
+ throw error;
64
+ }
65
+ }
66
+ transaction(work) {
67
+ const before = this.snapshot();
68
+ try {
69
+ return work(this);
70
+ }
71
+ catch (error) {
72
+ this.restore(before);
73
+ throw error;
74
+ }
75
+ }
76
+ }
1
77
  /**
2
78
  * Coordinates game-owned save state without knowing its schema.
3
79
  *
@@ -1 +1 @@
1
- {"version":3,"file":"State.js","sourceRoot":"","sources":["../../src/core/State.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"State.js","sourceRoot":"","sources":["../../src/core/State.ts"],"names":[],"mappings":"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"}
@@ -18,13 +18,13 @@ export { Generator, MersenneTwister, RandomStreams } from './Random.ts';
18
18
  export type { MersenneTwisterState } from './Random.ts';
19
19
  export { SaveSystem } from './Save.ts';
20
20
  export type { SaveMeta, SaveData, SaveStorage, SaveSystemOptions } from './Save.ts';
21
- export { StateRegistry } from './State.ts';
22
- export type { StateValue, StateExtension, StateSnapshot, StateRestoreDiagnostic } from './State.ts';
21
+ export { CanonicalState, StateRegistry } from './State.ts';
22
+ export type { CanonicalStateSnapshot, StateValue, StateExtension, StateSnapshot, StateRestoreDiagnostic, } from './State.ts';
23
23
  export { scramble, unscramble } from './Scramble.ts';
24
24
  export { SaveSyncClient } from './SaveSync.ts';
25
25
  export type { SaveSyncOptions, SaveSyncResponse } from './SaveSync.ts';
26
26
  export { LockstepClient } from './Multiplayer.ts';
27
- export type { WebSocketLike, LockstepClientOptions, TickEvent } from './Multiplayer.ts';
27
+ export type { WebSocketLike, LockstepClientOptions, LockstepWelcome, TickEvent } from './Multiplayer.ts';
28
28
  export { RunHistory } from './RunHistory.ts';
29
29
  export type { RunHistoryEntry, RunHistoryOptions } from './RunHistory.ts';
30
30
  export { PlayerStats } from './Stats.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ export * as Input from './Input.js';
10
10
  export { PlayerInput } from './PlayerInput.js';
11
11
  export { Generator, MersenneTwister, RandomStreams } from './Random.js';
12
12
  export { SaveSystem } from './Save.js';
13
- export { StateRegistry } from './State.js';
13
+ export { CanonicalState, StateRegistry } from './State.js';
14
14
  export { scramble, unscramble } from './Scramble.js';
15
15
  export { SaveSyncClient } from './SaveSync.js';
16
16
  export { LockstepClient } from './Multiplayer.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEzG,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhG,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAQ3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEzG,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEnF,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEhG,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAExH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC"}