@datamoc/mw_games 0.8.2 → 0.9.0
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.
- package/CHANGELOG.md +78 -0
- package/README.md +11 -4
- package/dist/core/ActionJournal.d.ts +2 -0
- package/dist/core/ActionJournal.d.ts.map +1 -1
- package/dist/core/ActionJournal.js +6 -0
- package/dist/core/ActionJournal.js.map +1 -1
- package/dist/core/Multiplayer.d.ts +21 -4
- package/dist/core/Multiplayer.d.ts.map +1 -1
- package/dist/core/Multiplayer.js +31 -4
- package/dist/core/Multiplayer.js.map +1 -1
- package/dist/core/State.d.ts +38 -0
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +76 -0
- package/dist/core/State.js.map +1 -1
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/mw_games.global.js +107 -91
- package/dist/mwl/catalog.d.ts +7 -0
- package/dist/mwl/catalog.d.ts.map +1 -1
- package/dist/mwl/catalog.js +0 -0
- package/dist/mwl/catalog.js.map +1 -1
- package/dist/mwl/compiler.d.ts +10 -7
- package/dist/mwl/compiler.d.ts.map +1 -1
- package/dist/mwl/compiler.js +17 -10
- package/dist/mwl/compiler.js.map +1 -1
- package/dist/mwl/content.d.ts +1 -1
- package/dist/mwl/content.js +1 -1
- package/dist/mwl/grammar.d.ts +25 -8
- package/dist/mwl/grammar.d.ts.map +1 -1
- package/dist/mwl/grammar.js +408 -105
- package/dist/mwl/grammar.js.map +1 -1
- package/dist/mwl/hooks.d.ts +35 -2
- package/dist/mwl/hooks.d.ts.map +1 -1
- package/dist/mwl/hooks.js +8 -6
- package/dist/mwl/hooks.js.map +1 -1
- package/dist/mwl/index.d.ts +6 -6
- package/dist/mwl/index.d.ts.map +1 -1
- package/dist/mwl/index.js +3 -3
- package/dist/mwl/index.js.map +1 -1
- package/dist/mwl/persistence.d.ts +18 -1
- package/dist/mwl/persistence.d.ts.map +1 -1
- package/dist/mwl/persistence.js +59 -3
- package/dist/mwl/persistence.js.map +1 -1
- package/dist/mwl/readers.d.ts +39 -2
- package/dist/mwl/readers.d.ts.map +1 -1
- package/dist/mwl/readers.js +71 -2
- package/dist/mwl/readers.js.map +1 -1
- package/dist/mwl/report.d.ts +2 -2
- package/dist/mwl/report.js +2 -2
- package/dist/mwl/runtime.d.ts +46 -2
- package/dist/mwl/runtime.d.ts.map +1 -1
- package/dist/mwl/runtime.js +73 -9
- package/dist/mwl/runtime.js.map +1 -1
- package/dist/mwl/schema.d.ts +32 -1
- package/dist/mwl/schema.d.ts.map +1 -1
- package/dist/mwl/schema.js +58 -3
- package/dist/mwl/schema.js.map +1 -1
- package/dist/simulation/Runtime.d.ts +66 -1
- package/dist/simulation/Runtime.d.ts.map +1 -1
- package/dist/simulation/Runtime.js +131 -3
- package/dist/simulation/Runtime.js.map +1 -1
- package/dist/simulation/index.d.ts +2 -2
- package/dist/simulation/index.d.ts.map +1 -1
- package/dist/simulation/index.js +1 -1
- package/dist/simulation/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
- package/tools/mwl.mjs +85 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,84 @@ the public API may still change between minor versions.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.0] - 2026-09-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `core.CanonicalState` - a defensive, JSON-safe root state combined with `StateRegistry`
|
|
15
|
+
extensions, with snapshots, version migrations, transactions, and atomic restore covering
|
|
16
|
+
both pieces together (item 341).
|
|
17
|
+
- `simulation.validateSimulationReplay`, and an optional `history` option on `SimulationRuntime`:
|
|
18
|
+
replay a recorded journal from a checkpoint and compare deterministic event batches, and
|
|
19
|
+
restore complete state/scheduler/RNG/journal undo-redo checkpoints (item 341).
|
|
20
|
+
- `LockstepClient`/`createLockstepServer` carry a session seed and initial state, validate
|
|
21
|
+
game-supplied commands, and exchange per-tick state checksums, with new `onReject`/`onDesync`
|
|
22
|
+
signals reporting rejected input and diverging peers (item 341).
|
|
23
|
+
- MWL JSON5 authoring accepts schema-neutral named-node sugar (`{ unit_type: { id: 'hero' } }`
|
|
24
|
+
and repeated object children) alongside the generic `tag`/`children` envelope, lowered before
|
|
25
|
+
validation runs (item 338).
|
|
26
|
+
- `MwlDomainHook`/`MwlDomainHookRegistry`/`MwlDomainHookDeclaration` - game-declared hook
|
|
27
|
+
namespaces (`item-effect:potion-strength`) get a typed context/input/output boundary that MWG
|
|
28
|
+
validates and emits without knowing the domain's own types or rules (item 342).
|
|
29
|
+
- `HookWorld.random` - every MWL hook, built-in or domain, draws from the runtime's own seeded
|
|
30
|
+
`core.Generator` instead of `Math.random()`, via the new `MwlRuntimeOptions.random`; the draw
|
|
31
|
+
position is carried on `MwlWorld.random` and resumes exactly across save/restore (item 342).
|
|
32
|
+
Any game hand-building its own `HookWorld` (only `MwlRuntime` constructs one today) must now
|
|
33
|
+
provide this field too, the same rule item 319's `variableAt` addition already established.
|
|
34
|
+
- `MwlSaveableHookState`/`MwlHookRegistry.saveable` - a game may explicitly expose JSON-safe hook
|
|
35
|
+
state; `MwlRuntime.save()`/`restore()` round-trip it through the same save envelope (item 341).
|
|
36
|
+
- `MwlRuntime.journal`/`MwlRuntimeAction` - public runtime operations (running a trigger, firing
|
|
37
|
+
an event or a moveto watch, answering a dialogue choice) are recorded in order and persisted
|
|
38
|
+
with the save (item 341).
|
|
39
|
+
- The MWL parser and compiler retain exact JSON5 attribute and value source locations
|
|
40
|
+
(`MwlNode.attributeLocations`/`valueLocations`), used by schema, catalog, and macro
|
|
41
|
+
diagnostics instead of falling back to the owning node's own location (item 342).
|
|
42
|
+
- Unknown MWL macros and hook references are errors by default, with file/line/column
|
|
43
|
+
diagnostics; `MwlPreprocessOptions.macroPolicy: 'ignore'` restores the old silent-passthrough
|
|
44
|
+
behaviour for legacy content (item 342).
|
|
45
|
+
- `schema10`/`MWL_SCHEMA_10` - the published MWL 1.0 vocabulary: required attributes and child
|
|
46
|
+
cardinalities on top of the unchanged 0.1 tag/value contract; `mwl migrate --to 1.0` performs
|
|
47
|
+
a lossless upgrade (item 342).
|
|
48
|
+
- `validateCatalog` reports `MWL_ALIAS_CYCLE` for cycles in resolved `aliasof` chains, and the new
|
|
49
|
+
`MwlValidationOptions.mapBounds` rejects authored coordinates outside declared map dimensions
|
|
50
|
+
(item 342).
|
|
51
|
+
- `readTableMap`/`readTableIndex`/`tableKey` - typed table-row projections with collision-free
|
|
52
|
+
native composite keys, and inverse indexes that retain every matching row (items 339, 346).
|
|
53
|
+
- `mwl diagnostics`/`mwl ci` CLI modes emit stable, machine-readable JSON diagnostics; `mwl
|
|
54
|
+
format`/`mwl migrate --to 1.0` emit a deterministic canonical document (items 342, 346).
|
|
55
|
+
- `tests/random.test.ts` gained a hardcoded-output compatibility test for `core.Generator`'s
|
|
56
|
+
stream, guarding fixed seeds against a future silent algorithm change (item 342).
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- `mwl/grammar.ts`'s macro expansion, gettext rewrite, and tag-site collection now share one
|
|
61
|
+
`skipStringOrComment` scan instead of three near-identical hand-rolled copies of it.
|
|
62
|
+
- `LockstepClient.submitInput` accepts an optional per-tick checksum and an optional client-side
|
|
63
|
+
`validateInput`; rejected input reports through the new `onReject` signal instead of silently
|
|
64
|
+
going nowhere.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- `src/mwl/catalog.ts` carried a literal NUL byte, rather than an escaped `\0`, inside one
|
|
69
|
+
composite map key, which made the file register as binary to `git diff` and `grep`. Replaced
|
|
70
|
+
with the same `\0` escape already used for the identical purpose elsewhere in the file; no
|
|
71
|
+
behaviour change.
|
|
72
|
+
|
|
73
|
+
## [0.9.0-alpha] - 2026-09-13
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
|
|
77
|
+
- MWL authoring syntax is now JSON5 instead of the WML-inspired tag/`key=value`
|
|
78
|
+
form: every `.mwl` file is a top-level array of `{ tag, ...attributes, children }`
|
|
79
|
+
nodes, values are real JSON5 numbers, booleans and strings (stringified back to
|
|
80
|
+
the `Record<string, string>` the schema, compiler and runtime already see), and
|
|
81
|
+
translatable strings are marked `_("...")` via a preprocessor rewrite. The
|
|
82
|
+
`#define`/`#include`/`#ifdef` textual pass is unchanged. The `"""..."""` block
|
|
83
|
+
form (item 317) is superseded by JSON5 `\n` escapes and backslash line
|
|
84
|
+
continuations. Clean cutover: all fixtures, examples, tests and doc examples
|
|
85
|
+
are migrated, the old tag parser is deleted, and `json5` (pure JS, no native
|
|
86
|
+
build) is a runtime dependency.
|
|
87
|
+
|
|
10
88
|
## [0.8.2] - 2026-09-13
|
|
11
89
|
|
|
12
90
|
### Added
|
package/README.md
CHANGED
|
@@ -402,9 +402,12 @@ The optional 3D group is now implemented without changing the existing 2D entry
|
|
|
402
402
|
|
|
403
403
|
## MWL
|
|
404
404
|
|
|
405
|
-
MWL is the framework's declarative, WML-inspired authoring layer.
|
|
406
|
-
|
|
407
|
-
|
|
405
|
+
MWL is the framework's declarative, WML-inspired authoring layer. Content files
|
|
406
|
+
are JSON5: a top-level array of `{ tag, ...attributes, children }` nodes, with
|
|
407
|
+
real numbers and booleans for scalar values and `_("...")` marking translatable
|
|
408
|
+
strings. It describes game data and commands while `mwg` remains responsible for
|
|
409
|
+
execution, rendering, input, audio, and saves. MWL is a new language, not a WML
|
|
410
|
+
compatibility layer.
|
|
408
411
|
The Wesnoth port can nevertheless use its native `.cfg` files as build inputs:
|
|
409
412
|
the port-owned WML front end parses them, the adapter converts the supported
|
|
410
413
|
nodes to MWL, and the normal MWL compiler emits the runtime module.
|
|
@@ -415,6 +418,10 @@ time with:
|
|
|
415
418
|
|
|
416
419
|
```sh
|
|
417
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
|
|
418
425
|
npm run mwl -- build game.mwl -o generated/
|
|
419
426
|
npm run mwl -- compile game.mwl -o generated/game-data.ts
|
|
420
427
|
npm run mwl -- extract-i18n game.mwl -o generated/i18n.json
|
|
@@ -461,7 +468,7 @@ reported as warnings. The output directory is safe to regenerate: its extracted
|
|
|
461
468
|
CSS `url(data:...)` values and HTML `srcset` candidates are handled too, including
|
|
462
469
|
their density descriptors.
|
|
463
470
|
|
|
464
|
-
Translation messages are the values marked `_
|
|
471
|
+
Translation messages are the values marked `_("...")` in the source; the
|
|
465
472
|
extracted catalog matches `@datamoc/mw_games/i18n`. Hooks are referenced as
|
|
466
473
|
`type:name`, declared in a manifest, and bundled with esbuild, which a game
|
|
467
474
|
project installs itself (`npm install --save-dev esbuild`). The framework does
|
|
@@ -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;
|
|
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;
|
|
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"}
|
package/dist/core/Multiplayer.js
CHANGED
|
@@ -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.
|
|
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({
|
|
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
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"Multiplayer.js","sourceRoot":"","sources":["../../src/core/Multiplayer.ts"],"names":[],"mappings":"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"}
|
package/dist/core/State.d.ts
CHANGED
|
@@ -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
|
*
|
package/dist/core/State.d.ts.map
CHANGED
|
@@ -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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"}
|
package/dist/core/State.js
CHANGED
|
@@ -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
|
*
|
package/dist/core/State.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"State.js","sourceRoot":"","sources":["../../src/core/State.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"State.js","sourceRoot":"","sources":["../../src/core/State.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.js
CHANGED
|
@@ -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';
|
package/dist/core/index.js.map
CHANGED
|
@@ -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;
|
|
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"}
|