@datamoc/mw_games 0.8.1 → 0.9.0-alpha
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 +56 -0
- package/MWG - Best Practices.md +97 -0
- package/MWG - Deep Code and Architecture Review.md +238 -0
- package/README.md +7 -4
- package/dist/core/Sanitize.d.ts +8 -0
- package/dist/core/Sanitize.d.ts.map +1 -1
- package/dist/core/Sanitize.js +20 -0
- package/dist/core/Sanitize.js.map +1 -1
- package/dist/core/Save.d.ts +8 -1
- package/dist/core/Save.d.ts.map +1 -1
- package/dist/core/Save.js +26 -7
- package/dist/core/Save.js.map +1 -1
- package/dist/mw_games.global.js +107 -91
- package/dist/mwl/compiler.d.ts +7 -7
- package/dist/mwl/compiler.js +7 -7
- package/dist/mwl/content.d.ts +1 -1
- package/dist/mwl/content.js +1 -1
- package/dist/mwl/grammar.d.ts +18 -8
- package/dist/mwl/grammar.d.ts.map +1 -1
- package/dist/mwl/grammar.js +227 -92
- package/dist/mwl/grammar.js.map +1 -1
- package/dist/mwl/persistence.d.ts +4 -1
- package/dist/mwl/persistence.d.ts.map +1 -1
- package/dist/mwl/persistence.js +6 -1
- package/dist/mwl/persistence.js.map +1 -1
- package/dist/mwl/readers.d.ts +2 -2
- package/dist/mwl/readers.js +2 -2
- package/dist/mwl/report.d.ts +2 -2
- package/dist/mwl/report.js +2 -2
- package/dist/mwl/runtime.d.ts +30 -1
- package/dist/mwl/runtime.d.ts.map +1 -1
- package/dist/mwl/runtime.js +204 -209
- package/dist/mwl/runtime.js.map +1 -1
- package/dist/mwl/schema.d.ts +1 -1
- package/dist/mwl/schema.js +1 -1
- package/dist/two-d/Game.d.ts +10 -4
- package/dist/two-d/Game.d.ts.map +1 -1
- package/dist/two-d/Game.js.map +1 -1
- package/dist/two-d/render/Types2D.d.ts +6 -4
- package/dist/two-d/render/Types2D.d.ts.map +1 -1
- package/dist/two-d/render/Types2D.js +6 -4
- package/dist/two-d/render/Types2D.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,62 @@ the public API may still change between minor versions.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.0-alpha] - 2026-09-13
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- MWL authoring syntax is now JSON5 instead of the WML-inspired tag/`key=value`
|
|
15
|
+
form: every `.mwl` file is a top-level array of `{ tag, ...attributes, children }`
|
|
16
|
+
nodes, values are real JSON5 numbers, booleans and strings (stringified back to
|
|
17
|
+
the `Record<string, string>` the schema, compiler and runtime already see), and
|
|
18
|
+
translatable strings are marked `_("...")` via a preprocessor rewrite. The
|
|
19
|
+
`#define`/`#include`/`#ifdef` textual pass is unchanged. The `"""..."""` block
|
|
20
|
+
form (item 317) is superseded by JSON5 `\n` escapes and backslash line
|
|
21
|
+
continuations. Clean cutover: all fixtures, examples, tests and doc examples
|
|
22
|
+
are migrated, the old tag parser is deleted, and `json5` (pure JS, no native
|
|
23
|
+
build) is a runtime dependency.
|
|
24
|
+
|
|
25
|
+
## [0.8.2] - 2026-09-13
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- `tests/builtin-pipes.test.ts`: regression coverage confirming `TiledSprite`/`NinePatch`
|
|
30
|
+
resolve to Pixi's own registered `tilingSprite`/`nineSliceSprite` pipes, a guarantee previously
|
|
31
|
+
verified only by a downstream consumer's own uncommitted script (item 336).
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- `mwl/runtime.ts`'s `executeNode` (a 226-line `switch` over 28 command tags, its own case
|
|
36
|
+
bodies inline) is now a `commandHandlers` dispatch table plus one small, independently-named
|
|
37
|
+
private method per command. No public API or behaviour change: `API_REPORT.md`'s diff is
|
|
38
|
+
purely additive private-method stubs, and all 166 `mwl-*.test.ts` tests pass unmodified
|
|
39
|
+
(item 337).
|
|
40
|
+
- `DEVELOPMENT.md` documents why `coverage`/`coverage:check` exclude `Game.ts`,
|
|
41
|
+
`ColorTransformBatcher.ts`, `Minimap.ts`, `three-d/Vox.ts`, `DialogueStage.ts`,
|
|
42
|
+
`EventDialogue.ts` and `two-d/ui/**` (Pixi rendering/layout, verified by the visual smokes
|
|
43
|
+
instead of a coverage percentage), and why `core` holds optional network-facing clients
|
|
44
|
+
alongside always-needed primitives (item 333, item 334).
|
|
45
|
+
- `GameOptions.extensions`'s doc comment now names `TiledSprite`/`NinePatch` alongside
|
|
46
|
+
`TintedSprite` as self-registering their Pixi render pipe automatically, closing a
|
|
47
|
+
documentation gap that likely explains why a cautious consumer wasn't confident enough to rely
|
|
48
|
+
on it (item 336).
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- `mwl`'s `validateWorld` rejects a `__proto__`/`constructor`/`prototype` key anywhere in a
|
|
53
|
+
decoded save (item 335): `MwlRuntime.restore` merges a decoded save into its own world with
|
|
54
|
+
`Object.assign`, which honours such a key as a prototype substitution rather than an ordinary
|
|
55
|
+
value. `core/Sanitize.ts` gains `assertNoForbiddenKeys`, the same rejection `validateSchema`
|
|
56
|
+
already applied to fixed-shape data, generalised to `mwl`'s dynamic, arbitrarily-nested world
|
|
57
|
+
shape.
|
|
58
|
+
- `SaveSystem.load` returns `null` for a corrupted or malformed slot instead of throwing an
|
|
59
|
+
uncaught `SyntaxError`, the same outcome a missing slot already produced; `importSlot` throws a
|
|
60
|
+
labelled `SaveSystem.importSlot: payload is not valid save data` error instead of a bare parse
|
|
61
|
+
error (item 331).
|
|
62
|
+
- `Container2D`/`Texture2D` in `two-d/render/Types2D.ts` each carried two adjacent JSDoc blocks,
|
|
63
|
+
so only the generic, less useful one reached generated documentation; merged into one comment
|
|
64
|
+
each (item 332).
|
|
65
|
+
|
|
10
66
|
## [0.8.1] - 2026-09-12
|
|
11
67
|
|
|
12
68
|
### Added
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# MWG: Best Practices
|
|
2
|
+
|
|
3
|
+
Practical guidance for someone starting a real project with `mwg` today: how to work with the
|
|
4
|
+
grain of the framework instead of against it. Pair this with
|
|
5
|
+
[MWG: Deep Code and Architecture Review](MWG%20-%20Deep%20Code%20and%20Architecture%20Review.md)
|
|
6
|
+
for the *why* behind each of these; this document is the *how*.
|
|
7
|
+
|
|
8
|
+
## Start from a working example, not a blank page
|
|
9
|
+
|
|
10
|
+
The shipped examples (colour-transform, interface, dialogue/stage, roguelike dungeon) are
|
|
11
|
+
real, buildable, `file://`-verified projects, not snippets. Copy the one closest to your game
|
|
12
|
+
and grow it, rather than assembling a project from the API reference alone. Decide early which
|
|
13
|
+
of the two install paths in the getting-started guide you actually need (a bundler-based
|
|
14
|
+
project with npm, or a plain `<script>` tag with no build step at all) and verify your own
|
|
15
|
+
project reaches a working `file://` page under that path before you build much on top of it.
|
|
16
|
+
|
|
17
|
+
## Reach for the typed facade first, the escape hatch second
|
|
18
|
+
|
|
19
|
+
Ordinary sprites, shapes, text, and containers go through `Sprite2D`/`Shape2D`/`Text2D`/
|
|
20
|
+
`TiledSprite`/`Gradient`. None of that requires your own code to name `pixi.js` anywhere. Only
|
|
21
|
+
reach for `two-d/pixi-interop` when you need a specific Pixi capability the facade doesn't
|
|
22
|
+
cover, and keep that usage confined to as few files as you can, the same way `mwg` itself
|
|
23
|
+
confines all Pixi-internal knowledge to one file. Two concrete benefits, not just tidiness:
|
|
24
|
+
your project stays portable if you ever need the Babylon path instead, and `pixi.js` is an
|
|
25
|
+
optional peer dependency, so code that never touches the escape hatch never has to install it.
|
|
26
|
+
|
|
27
|
+
## Keep game logic renderer-free where you can
|
|
28
|
+
|
|
29
|
+
Model state and rules in plain data and `core`/`simulation`-level terms (stable entity ids via
|
|
30
|
+
`EntityRegistry`, not live object references) rather than reaching into a sprite or a scene
|
|
31
|
+
from inside game logic. Code written this way can be tested with Node's own test runner with
|
|
32
|
+
no renderer, no browser, and no ticker in the loop at all, the same separation that lets `mwg`
|
|
33
|
+
run the identical scene-lifecycle and save-system code under either a Pixi or a Babylon game.
|
|
34
|
+
|
|
35
|
+
## Load once per scene, then stay synchronous
|
|
36
|
+
|
|
37
|
+
Call `load(paths)` up front for a scene and treat everything after that as synchronous code.
|
|
38
|
+
Scattering `await` through per-frame or per-action logic is a sign an asset load has drifted
|
|
39
|
+
into the wrong place; move it back to scene setup, using the `optional`/`onMissing` path if a
|
|
40
|
+
particular asset is allowed to be missing.
|
|
41
|
+
|
|
42
|
+
## Trust your own data, validate everything else
|
|
43
|
+
|
|
44
|
+
Use `SaveSystem.load()` for a save this same process previously wrote. For anything that
|
|
45
|
+
crossed a device or a network boundary, a pasted save code, a cloud sync, a value a server
|
|
46
|
+
handed back, use `importSlot`/`importExternal` instead, and validate the *shape* of what comes
|
|
47
|
+
back, not just that it parsed as JSON. Apply the same split in your own persistence code even
|
|
48
|
+
outside `SaveSystem`: "this process wrote it a moment ago" and "this arrived from somewhere
|
|
49
|
+
else" are different trust levels, and worth two different code paths, not one path with an
|
|
50
|
+
optimistic cast.
|
|
51
|
+
|
|
52
|
+
## Test the way `mwg` tests itself
|
|
53
|
+
|
|
54
|
+
Plain `.ts` sources under Node's built-in test runner, no framework, is a deliberate choice
|
|
55
|
+
here: it keeps the dependency list short and the tests portable. A green test suite and a
|
|
56
|
+
clean typecheck are necessary, not sufficient, verify anything visual (layout, a window's
|
|
57
|
+
position, whether choice text is legible against its background) by building an example and
|
|
58
|
+
actually looking at it. If you can't check a UI change visually yourself, say so plainly rather
|
|
59
|
+
than calling it done on the strength of the typechecker alone.
|
|
60
|
+
|
|
61
|
+
## Verify from `file://`, not only from a dev server
|
|
62
|
+
|
|
63
|
+
The entire point of this framework is a game that opens by double-clicking a local file, no
|
|
64
|
+
server. A feature that only works against a bundler's dev server has not been verified against
|
|
65
|
+
the target it's actually meant to ship to. Build, then open the built page directly, before
|
|
66
|
+
calling a feature finished.
|
|
67
|
+
|
|
68
|
+
## Only pull in the renderer you actually use
|
|
69
|
+
|
|
70
|
+
`three-d` is kept off the root barrel specifically so a 2D project never pays for Babylon; a
|
|
71
|
+
Babylon project likewise never needs to pull in Pixi. Import `two-d` or `3d`, not both, unless
|
|
72
|
+
your game genuinely mixes both kinds of scenes.
|
|
73
|
+
|
|
74
|
+
## Keep your own vocabulary out of your own shared code
|
|
75
|
+
|
|
76
|
+
`mwg` holds no rule, value, or vocabulary belonging to any single reference game, only the
|
|
77
|
+
generic mechanic shape; your own game's specific numbers, names, and content stay in your own
|
|
78
|
+
game layer, supplied to `mwg`'s generic primitives as data. If your project grows multiple
|
|
79
|
+
internal systems, campaigns, or a modding surface, apply the same discipline one level up: keep
|
|
80
|
+
the genuinely generic mechanics generic, and keep any one system's specific content as data
|
|
81
|
+
that mechanic consumes, rather than baking it into the mechanic itself.
|
|
82
|
+
|
|
83
|
+
## Don't build for the reuse you don't have yet
|
|
84
|
+
|
|
85
|
+
Favour plain data and composition over an early abstraction layer, a manager class, an event
|
|
86
|
+
bus, a plugin system, before you have a second real call site that actually needs it. `mwg`'s
|
|
87
|
+
own modules lean this way on purpose (`StatBlock`'s fixed modifier order over a rule engine,
|
|
88
|
+
`EntityTemplate`'s plain content rows over a generic component system) and it's a good default
|
|
89
|
+
for your own game code too: an abstraction with exactly one caller costs a future reader a hop
|
|
90
|
+
and buys nothing until a second caller actually shows up.
|
|
91
|
+
|
|
92
|
+
## Verify an API claim before building on it
|
|
93
|
+
|
|
94
|
+
`mwg` is pre-alpha and still adding surface between releases. Check REFERENCE.md (or the
|
|
95
|
+
generated API docs) for the actual current name and signature of something before assuming it
|
|
96
|
+
matches a similar-sounding API from a different framework you've used before, especially for
|
|
97
|
+
anything not yet covered by the API-stability guarantee that starts at 1.0.
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# MWG: Deep Code and Architecture Review
|
|
2
|
+
|
|
3
|
+
This is an architecture deep-dive for developers building with `mwg`: not what exists
|
|
4
|
+
(that's [REFERENCE.md](https://github.com/datamoc/mwg/blob/main/REFERENCE.md)'s job) or what
|
|
5
|
+
it's for (that's `README.md`'s), but how the pieces fit together and why they're shaped the
|
|
6
|
+
way they are. Read it once before you structure a non-trivial project, then use it as a map
|
|
7
|
+
when you need to decide where new code of your own belongs.
|
|
8
|
+
|
|
9
|
+
`mwg` is pre-alpha (`0.y.z`): the public API documented in REFERENCE.md and API_REPORT.md is
|
|
10
|
+
meant to be stable from 1.0 on, and anything not yet there carries an `@experimental` tag.
|
|
11
|
+
Nothing below hides that status behind confident prose; where a design choice is a deliberate
|
|
12
|
+
trade-off rather than a finished guarantee, it's said so.
|
|
13
|
+
|
|
14
|
+
## The constraint that shapes everything: `file://`
|
|
15
|
+
|
|
16
|
+
A game built with `mwg` is meant to run by double-clicking a local HTML file. No server, no
|
|
17
|
+
install step, nothing to download at runtime. That single requirement cascades into most of
|
|
18
|
+
the framework's less obvious decisions:
|
|
19
|
+
|
|
20
|
+
- `fetch()`, XHR, and `<script type="module">` are all blocked from `file://`, and Chrome
|
|
21
|
+
treats even a same-folder `<img>` as cross-origin for WebGL. So every asset a build touches
|
|
22
|
+
is compiled into a `data:` URI ahead of time, not fetched at runtime.
|
|
23
|
+
- The standalone library build is a classic IIFE, not ES modules, so it can load from a plain
|
|
24
|
+
`<script>` tag with no bundler at all.
|
|
25
|
+
- A build's last step rewrites the bundler's `<script type="module">` entry tag to a classic
|
|
26
|
+
deferred script and inlines the compiled asset data before it, in document order.
|
|
27
|
+
|
|
28
|
+
If you only take one thing from this document: verify a change by opening the *built* page
|
|
29
|
+
from `file://`, not just by trusting a dev server. A feature that only works under Vite's dev
|
|
30
|
+
server is not finished.
|
|
31
|
+
|
|
32
|
+
## Module map and dependency direction
|
|
33
|
+
|
|
34
|
+
Every module is its own barrel (`import { X } from '@datamoc/mw_games/core'`, or the matching
|
|
35
|
+
subpath), plus a root re-export. Two rendering worlds sit side by side over one renderer-free
|
|
36
|
+
core, and nothing in that core knows either exists:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
+------------------------------------------+
|
|
40
|
+
| core (renderer-free, imports nothing) |
|
|
41
|
+
| Scene lifecycle, SceneStack, Signal, |
|
|
42
|
+
| Random, Input, SaveSystem, Session |
|
|
43
|
+
+------------------------------------------+
|
|
44
|
+
^ ^
|
|
45
|
+
| |
|
|
46
|
+
+---------------+----------------+ +----------+---------------+
|
|
47
|
+
| two-d (PixiJS) | | three-d (Babylon.js, |
|
|
48
|
+
| Game, Scene2D, Camera, | | optional, off the root |
|
|
49
|
+
| TileMap, Sprite2D/Shape2D/ | | barrel so a 2D game |
|
|
50
|
+
| Text2D facade, ui, stage | | never pays for it) |
|
|
51
|
+
+----------------------------------+ +--------------------------+
|
|
52
|
+
|
|
53
|
+
renderer-free alongside core: i18n, actors, world, battle, simulation,
|
|
54
|
+
roguelike, board, audio, rpg, ai, mwl, assets/paths
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`core` importing no other module (and no renderer) is what lets the same scene-lifecycle and
|
|
58
|
+
save-system code run under a Babylon game as under a Pixi one. This isn't a documentation
|
|
59
|
+
claim taken on faith: `tests/renderer-isolation.test.ts` walks the real import graph in both
|
|
60
|
+
directions (nothing under `two-d` reaches Babylon, nothing under `three-d` reaches Pixi, no
|
|
61
|
+
example names `pixi.js`/`@babylonjs/*` directly) and fails the build if the boundary slips.
|
|
62
|
+
`roguelike` adds only `rot-js`; `pixi.js`, `@babylonjs/core`/`@babylonjs/loaders`, and
|
|
63
|
+
`@capacitor/core` are all optional peer dependencies rather than installed ones, so a project
|
|
64
|
+
brings in exactly the renderer it draws with, no more.
|
|
65
|
+
|
|
66
|
+
## Execution model
|
|
67
|
+
|
|
68
|
+
`Game` (`two-d`) owns one Pixi `Application`, a `SceneStack<Scene2D>`, and the frame loop,
|
|
69
|
+
which normally runs off Pixi's own ticker. `core.Scene` is lifecycle only
|
|
70
|
+
(`create`/`update`/`resize`/`onSuspend`/`onResume`/`destroy`) and owns no display node at all;
|
|
71
|
+
`two-d.Scene2D` adds exactly one field, a `stage` container, on top of it. `SceneStack` is
|
|
72
|
+
generic over that lifecycle type alone, which is what lets it be reused unchanged on the
|
|
73
|
+
Babylon side.
|
|
74
|
+
|
|
75
|
+
Scene changes go through `switchScene`, which queues a request and drains it at the start of
|
|
76
|
+
the *next* frame, so a frame never updates a scene that was just asked to leave. Only the top
|
|
77
|
+
of the stack receives `update`, but every scene in the stack still renders, which is what
|
|
78
|
+
makes a translucent pause menu over live gameplay work without special-casing it.
|
|
79
|
+
|
|
80
|
+
`Game.step(dt)` drives exactly one frame synchronously, bypassing the ticker. Reach for it in
|
|
81
|
+
headless contexts (tests) and when a backgrounded browser tab has throttled
|
|
82
|
+
`requestAnimationFrame` down to a rate that makes a game look frozen for reasons that have
|
|
83
|
+
nothing to do with your code.
|
|
84
|
+
|
|
85
|
+
## Rendering model
|
|
86
|
+
|
|
87
|
+
`Camera` never moves "the camera": it moves a `world` container under a fixed viewport,
|
|
88
|
+
including for rotation, which turns the whole layer once about the view centre rather than
|
|
89
|
+
transforming tiles individually. Grid maps render through a chunked `TileMap`, so off-screen
|
|
90
|
+
chunks can be culled as a block instead of tile by tile.
|
|
91
|
+
|
|
92
|
+
Per-sprite additive colour (a poison tint, a hit-flash) needs both a multiply *and* an add in
|
|
93
|
+
the same pass, which Pixi's built-in `tint` (multiply only) can't express. `mwg` implements
|
|
94
|
+
that as a custom batcher, `ColorTransformBatcher`, extending Pixi's own `Batcher` so the extra
|
|
95
|
+
math rides in the same draw call rather than costing a separate filter pass per sprite. This
|
|
96
|
+
is also the one place in the entire framework allowed to import Pixi's batcher or shader
|
|
97
|
+
internals; nothing else does. You don't opt into any of this by hand: importing `TintedSprite`
|
|
98
|
+
(directly, or via `TileMap`/`DialogueStage`/`AnimatedSprite`, all built on it) registers the
|
|
99
|
+
colour-transform pipe at module load time, before your own code runs.
|
|
100
|
+
|
|
101
|
+
## The PixiJS boundary
|
|
102
|
+
|
|
103
|
+
The design intent (recorded as ADR-001, "a game consumes `mwg`, not PixiJS or Babylon.js
|
|
104
|
+
directly, in ordinary use") is a genuine constraint, not a suggestion, and it's enforced the
|
|
105
|
+
same way the module boundary is: by a test that scans the real API surface, not by convention.
|
|
106
|
+
It has three tiers:
|
|
107
|
+
|
|
108
|
+
1. **The typed facade** - `Container2D`/`Texture2D`/`Rect`/`TextureRegion`
|
|
109
|
+
(`two-d/render/Types2D.ts`) and `Node2D`/`Shape2D`/`Text2D`/`Sprite2D`/`TiledSprite`/
|
|
110
|
+
`Gradient` (`two-d/render/Shape2D.ts`). Ordinary sprites, shapes, text, and containers all
|
|
111
|
+
go through here, and none of it requires your code to name `pixi.js` anywhere, in a type
|
|
112
|
+
position or a value position.
|
|
113
|
+
2. **One documented escape hatch** - `two-d/pixi-interop.ts`, published at
|
|
114
|
+
`@datamoc/mw_games/two-d/pixi-interop`, a small, explicit re-export of the handful of Pixi
|
|
115
|
+
symbols the facade doesn't (yet) cover. If you genuinely need a Pixi capability the facade
|
|
116
|
+
doesn't expose, this is where that dependency belongs, confined to as few files in your own
|
|
117
|
+
project as you can manage, the same discipline `mwg` holds `ColorTransformBatcher.ts` to
|
|
118
|
+
internally.
|
|
119
|
+
3. **`pixi.js` itself is an optional peer dependency**, not a direct one. A project that never
|
|
120
|
+
touches the escape hatch never installs Pixi's actual package; only code that imports
|
|
121
|
+
`pixi-interop` does.
|
|
122
|
+
|
|
123
|
+
Why go to this trouble: it's what makes the Babylon path (`three-d`) possible as more than a
|
|
124
|
+
parallel rewrite, and it's what keeps a 2D-only project from paying for a 3D engine it never
|
|
125
|
+
loads, or vice versa. Prefer the facade by default. Reach for the escape hatch deliberately,
|
|
126
|
+
not reflexively, and keep that usage visible and narrow rather than scattered through your
|
|
127
|
+
rendering code.
|
|
128
|
+
|
|
129
|
+
## Simulation and time
|
|
130
|
+
|
|
131
|
+
Two renderer-free authorities sit underneath both rendering paths:
|
|
132
|
+
|
|
133
|
+
- **`roguelike.Scheduler`** is the sole authority on logical, turn-based time (ADR-003):
|
|
134
|
+
energy-cost ordering, fractional costs, a documented tie-break, `postpone` for delaying an
|
|
135
|
+
actor other than the current one, and a deterministic `toJSON`/`restore` snapshot.
|
|
136
|
+
- **`simulation.SimulationRuntime`** is renderer-free and transactional (ADR-002): a command
|
|
137
|
+
produces its complete logical result, and charges the scheduler, synchronously, *before* any
|
|
138
|
+
presentation plays. `core.Presentation`'s `PresentationQueue` then lets rendering consume the
|
|
139
|
+
resulting events at its own pace, decoupled from when the logic actually happened. This is
|
|
140
|
+
proven, not just structured that way: running the same commands against three different
|
|
141
|
+
presentation-duration functions produces identical simulation state and events every time.
|
|
142
|
+
|
|
143
|
+
A simulation's logical snapshot is deliberately a different thing from `core.SaveSystem`'s
|
|
144
|
+
storage format (ADR-006): `SimulationSnapshot<State>` is plain JSON-safe data that `SaveSystem`
|
|
145
|
+
stores as an opaque payload, never the reverse. Compose the two rather than reinventing either.
|
|
146
|
+
|
|
147
|
+
## Entity identity and "something happened"
|
|
148
|
+
|
|
149
|
+
Logical entities are referenced by a stable id, not held by object reference (ADR-004,
|
|
150
|
+
`core.Entity`'s `EntityRegistry`). That id is what you pass into `Scheduler.toJSON`'s or
|
|
151
|
+
`SimulationRuntime.snapshot`'s `actorId`, so identity composes cleanly with both authorities
|
|
152
|
+
above without either needing to know about the other.
|
|
153
|
+
|
|
154
|
+
Three distinct shapes exist for "something happened," on purpose, so one word doesn't have to
|
|
155
|
+
mean three things depending on context (ADR-005):
|
|
156
|
+
|
|
157
|
+
- **`GameEvent`** - an ordered *output* of a transition. Something a rule produced, never
|
|
158
|
+
something a global bus dispatches to drive other rules.
|
|
159
|
+
- **`Hook`** (`HookRegistry`) - a synchronous, mid-calculation modification point.
|
|
160
|
+
- **`Signal`** - a plain notification with no bearing on any rule at all.
|
|
161
|
+
|
|
162
|
+
## Persistence
|
|
163
|
+
|
|
164
|
+
`core.SaveSystem` gives named, versioned save slots over `localStorage`, with an in-memory
|
|
165
|
+
fallback where storage isn't available, scoped deliberately to plain JSON-serialisable state
|
|
166
|
+
rather than arbitrary object graphs. The API draws a real line between two kinds of input:
|
|
167
|
+
`load()` trusts data this same process already wrote, while `importSlot`/`importExternal` are
|
|
168
|
+
the path for anything that crossed a device or a network boundary, and validate size and
|
|
169
|
+
content before accepting it. Follow that same split in your own save-adjacent code: trust what
|
|
170
|
+
your own process just wrote, validate anything a player pastes in, syncs from elsewhere, or
|
|
171
|
+
receives from a server, and don't assume "it's valid JSON" already means "it's valid data."
|
|
172
|
+
|
|
173
|
+
`Session` reuses the same storage abstraction for exactly one counter, how many times a game
|
|
174
|
+
has launched, so a native wrapper can decide when to ask for a rating. `mwg` counts; it never
|
|
175
|
+
prompts on its own.
|
|
176
|
+
|
|
177
|
+
## Assets
|
|
178
|
+
|
|
179
|
+
`assets/paths.ts` resolves a path with no renderer in reach at all, which is what lets `two-d`
|
|
180
|
+
and `three-d` share one compiled-asset map. `assets/loader.ts` is the half that actually needs
|
|
181
|
+
Pixi. In development, paths are served normally; in a compiled build, resolution looks paths up
|
|
182
|
+
in a global asset map that the build's own compile step populates. Call `load(paths)` once per
|
|
183
|
+
scene; everything after that is meant to be synchronous, so don't scatter `await` through
|
|
184
|
+
per-frame or per-action code. `load` also accepts an `optional` path list with a per-path
|
|
185
|
+
`onMissing` callback, so one missing decal doesn't have to abort an otherwise-successful batch.
|
|
186
|
+
|
|
187
|
+
## Framework scope discipline
|
|
188
|
+
|
|
189
|
+
Two decisions worth understanding even though they don't change any API you call directly,
|
|
190
|
+
because they set correct expectations for whether `mwg` will fit *your* game:
|
|
191
|
+
|
|
192
|
+
- **No rule, value, or vocabulary specific to any one reference game lives in `mwg`** (ADR-007).
|
|
193
|
+
Every primitive is generic over a game-supplied type parameter; hunger values, weapon
|
|
194
|
+
formulas, faction rules, and the like stay in the game that needs them. If you come to `mwg`
|
|
195
|
+
from studying one of its reference games (Shattered Pixel Dungeon, ADOM, RPG Maker-style
|
|
196
|
+
projects, and others README.md names as capability targets), expect the mechanic's *shape*
|
|
197
|
+
to be there and the specific numbers not to be.
|
|
198
|
+
- **`mwg` provides the mechanism for semantic messaging and localisation; your game supplies
|
|
199
|
+
the vocabulary** (ADR-008). `i18n.SemanticMessage`/`MessageChannel`/`MessageFormatter` build
|
|
200
|
+
on the existing catalog/plural/Fluent machinery; `mwg` holds no message type name, catalog
|
|
201
|
+
key, or translated string of its own anywhere in that path.
|
|
202
|
+
|
|
203
|
+
In practice this means `mwg` will feel intentionally unopinionated about *what* your game says
|
|
204
|
+
and *how much* damage a sword does, while still being opinionated about *how* time, identity,
|
|
205
|
+
events, and persistence work underneath it.
|
|
206
|
+
|
|
207
|
+
## Extension points
|
|
208
|
+
|
|
209
|
+
`GameOptions.extensions` takes an array of registration functions, run once before Pixi's
|
|
210
|
+
`app.init()` builds the renderer, for registering *your own* Pixi extension the same way `mwg`
|
|
211
|
+
registers its colour-transform pipe internally. You won't need this for ordinary rendering
|
|
212
|
+
work; it exists specifically for the case where your game needs its own custom Pixi-level
|
|
213
|
+
behaviour alongside what `mwg` already provides.
|
|
214
|
+
|
|
215
|
+
## Testing and verification philosophy
|
|
216
|
+
|
|
217
|
+
`mwg`'s own test suite runs directly under Node's built-in test runner against `.ts` sources,
|
|
218
|
+
no test framework, which is a stated feature, not an accident: the dependency list staying
|
|
219
|
+
short is treated as part of the product. Worth adopting the same discipline in your own tests
|
|
220
|
+
where it fits.
|
|
221
|
+
|
|
222
|
+
Typechecking and unit tests verify correctness, not what a player actually sees. A window
|
|
223
|
+
placed off-screen or choices rendered over text will not show up in `npm run check` or a green
|
|
224
|
+
test suite; building an example and actually looking at it will. If you can't visually verify a
|
|
225
|
+
UI change yourself, say so explicitly rather than reporting it done.
|
|
226
|
+
|
|
227
|
+
## Status and where to go next
|
|
228
|
+
|
|
229
|
+
- **REFERENCE.md** - the API index: every export, one line each, plus the generated
|
|
230
|
+
parameter-level documentation.
|
|
231
|
+
- **The example games** (colour-transform, interface, dialogue/stage, roguelike dungeon) -
|
|
232
|
+
working, buildable, `file://`-verified starting points; closer to how to structure a real
|
|
233
|
+
project than any written description can be.
|
|
234
|
+
- **`MWG: Best Practices.md`** - the companion to this document: concrete guidance for
|
|
235
|
+
structuring a new project well from day one, rather than how the framework itself is built.
|
|
236
|
+
- **ROADMAP.md and ADR.md** (on the project's GitHub) - the full, numbered build history and
|
|
237
|
+
the reasoning behind the architectural decisions summarised above, for anyone who wants the
|
|
238
|
+
complete record rather than the digest.
|
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.
|
|
@@ -461,7 +464,7 @@ reported as warnings. The output directory is safe to regenerate: its extracted
|
|
|
461
464
|
CSS `url(data:...)` values and HTML `srcset` candidates are handled too, including
|
|
462
465
|
their density descriptors.
|
|
463
466
|
|
|
464
|
-
Translation messages are the values marked `_
|
|
467
|
+
Translation messages are the values marked `_("...")` in the source; the
|
|
465
468
|
extracted catalog matches `@datamoc/mw_games/i18n`. Hooks are referenced as
|
|
466
469
|
`type:name`, declared in a manifest, and bundled with esbuild, which a game
|
|
467
470
|
project installs itself (`npm install --save-dev esbuild`). The framework does
|
package/dist/core/Sanitize.d.ts
CHANGED
|
@@ -69,6 +69,14 @@ export type Schema = {
|
|
|
69
69
|
items: Schema;
|
|
70
70
|
maxLength?: number;
|
|
71
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Recursively rejects `__proto__`/`constructor`/`prototype` as an own key anywhere in `value`,
|
|
74
|
+
* for data too dynamic for `validateSchema`'s fixed field list (a free-form variable bag, a
|
|
75
|
+
* dictionary keyed by content-chosen ids, both common in a save format). Reuses the same
|
|
76
|
+
* `FORBIDDEN_KEYS` set `validateSchema` enforces for fixed-shape objects; use this one instead
|
|
77
|
+
* when the shape itself isn't known ahead of time.
|
|
78
|
+
*/
|
|
79
|
+
export declare function assertNoForbiddenKeys(value: unknown, path?: string): void;
|
|
72
80
|
/** throws with a path-qualified message at the first field that does not match `schema` */
|
|
73
81
|
export declare function validateSchema(value: unknown, schema: Schema, path?: string): void;
|
|
74
82
|
//# sourceMappingURL=Sanitize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sanitize.d.ts","sourceRoot":"","sources":["../../src/core/Sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,gBAAgB;IAChC,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,2GAA2G;AAC3G,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAIzF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAU3D;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAIxF;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,GACf;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAI5E,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,IAAI,CAsC/E"}
|
|
1
|
+
{"version":3,"file":"Sanitize.d.ts","sourceRoot":"","sources":["../../src/core/Sanitize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,WAAW,gBAAgB;IAChC,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,2GAA2G;AAC3G,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAIzF;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAU3D;AAED,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAIxF;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,MAAM,GACf;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAI5E;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAM,GAAG,IAAI,CAWtE;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,IAAI,CAsC/E"}
|
package/dist/core/Sanitize.js
CHANGED
|
@@ -56,6 +56,26 @@ export function sanitizeInboundText(text, options = {}) {
|
|
|
56
56
|
return text;
|
|
57
57
|
}
|
|
58
58
|
const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
59
|
+
/**
|
|
60
|
+
* Recursively rejects `__proto__`/`constructor`/`prototype` as an own key anywhere in `value`,
|
|
61
|
+
* for data too dynamic for `validateSchema`'s fixed field list (a free-form variable bag, a
|
|
62
|
+
* dictionary keyed by content-chosen ids, both common in a save format). Reuses the same
|
|
63
|
+
* `FORBIDDEN_KEYS` set `validateSchema` enforces for fixed-shape objects; use this one instead
|
|
64
|
+
* when the shape itself isn't known ahead of time.
|
|
65
|
+
*/
|
|
66
|
+
export function assertNoForbiddenKeys(value, path = '$') {
|
|
67
|
+
if (Array.isArray(value)) {
|
|
68
|
+
value.forEach((item, index) => assertNoForbiddenKeys(item, `${path}[${index}]`));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (value !== null && typeof value === 'object') {
|
|
72
|
+
for (const key of Object.keys(value)) {
|
|
73
|
+
if (FORBIDDEN_KEYS.has(key))
|
|
74
|
+
throw new Error(`${path} contains a forbidden key "${key}"`);
|
|
75
|
+
assertNoForbiddenKeys(value[key], `${path}.${key}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
59
79
|
/** throws with a path-qualified message at the first field that does not match `schema` */
|
|
60
80
|
export function validateSchema(value, schema, path = '$') {
|
|
61
81
|
if (value === undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sanitize.js","sourceRoot":"","sources":["../../src/core/Sanitize.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Sanitize.js","sourceRoot":"","sources":["../../src/core/Sanitize.ts"],"names":[],"mappings":"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"}
|
package/dist/core/Save.d.ts
CHANGED
|
@@ -33,7 +33,14 @@ export declare class SaveSystem<T> {
|
|
|
33
33
|
constructor(options: SaveSystemOptions);
|
|
34
34
|
private key;
|
|
35
35
|
save(slot: string, state: T, preview?: unknown): void;
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Reads a slot, migrating it up to the current version if it was saved at an older one.
|
|
38
|
+
* Returns `null` for a corrupted or malformed slot the same way it already does for a
|
|
39
|
+
* missing one - a slot this `SaveSystem` wrote itself is trusted, but a truncated write
|
|
40
|
+
* (an interrupted browser storage flush, a quota eviction, a hand-edited value) is still
|
|
41
|
+
* possible, and a save-select screen should see "no usable save here", not an uncaught
|
|
42
|
+
* `SyntaxError`.
|
|
43
|
+
*/
|
|
37
44
|
load(slot: string): SaveData<T> | null;
|
|
38
45
|
/**
|
|
39
46
|
* Adopts a save this `SaveSystem` never wrote: `normalize` runs once on `externalBytes`,
|
package/dist/core/Save.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Save.d.ts","sourceRoot":"","sources":["../../src/core/Save.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,QAAQ;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAEhB,6FAA6F;IAC7F,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,CAAC,CAAC;CACT;AAED,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,MAAM,EAAE,CAAC;CACjB;AAuBD,qGAAqG;AACrG,wBAAgB,cAAc,IAAI,WAAW,CAS5C;AAED,MAAM,WAAW,iBAAiB;IACjC,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAEhB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC;IACzD,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,qBAAa,UAAU,CAAC,CAAC;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,OAAO,CAAc;IAE7B,YAAY,OAAO,EAAE,iBAAiB,EAKrC;IAED,OAAO,CAAC,GAAG;IAIX,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAGpD;IAED
|
|
1
|
+
{"version":3,"file":"Save.d.ts","sourceRoot":"","sources":["../../src/core/Save.ts"],"names":[],"mappings":"AAuBA,MAAM,WAAW,QAAQ;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAEhB,6FAA6F;IAC7F,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,CAAC,CAAC;CACT;AAED,iGAAiG;AACjG,MAAM,WAAW,WAAW;IAC3B,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,IAAI,MAAM,EAAE,CAAC;CACjB;AAuBD,qGAAqG;AACrG,wBAAgB,cAAc,IAAI,WAAW,CAS5C;AAED,MAAM,WAAW,iBAAiB;IACjC,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAEhB,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC;IACzD,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,qBAAa,UAAU,CAAC,CAAC;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,OAAO,CAAc;IAE7B,YAAY,OAAO,EAAE,iBAAiB,EAKrC;IAED,OAAO,CAAC,GAAG;IAIX,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAGpD;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAcrC;IAED;;;;;;;;;;;OAWG;IACH,cAAc,CACb,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,UAAU,EACzB,SAAS,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,EACzC,OAAO,CAAC,EAAE,OAAO,GACf,IAAI,CASN;IAED,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEzB;IAED;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI5D;IAED;;;;;;;;OAQG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAiBpE;IAED,0EAA0E;IAC1E,IAAI,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAY9C;CACD"}
|
package/dist/core/Save.js
CHANGED
|
@@ -63,17 +63,29 @@ export class SaveSystem {
|
|
|
63
63
|
const data = { meta: { version: this.version, savedAt: Date.now(), preview }, state };
|
|
64
64
|
this.storage.write(this.key(slot), JSON.stringify(data));
|
|
65
65
|
}
|
|
66
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* Reads a slot, migrating it up to the current version if it was saved at an older one.
|
|
68
|
+
* Returns `null` for a corrupted or malformed slot the same way it already does for a
|
|
69
|
+
* missing one - a slot this `SaveSystem` wrote itself is trusted, but a truncated write
|
|
70
|
+
* (an interrupted browser storage flush, a quota eviction, a hand-edited value) is still
|
|
71
|
+
* possible, and a save-select screen should see "no usable save here", not an uncaught
|
|
72
|
+
* `SyntaxError`.
|
|
73
|
+
*/
|
|
67
74
|
load(slot) {
|
|
68
75
|
const raw = this.storage.read(this.key(slot));
|
|
69
76
|
if (!raw)
|
|
70
77
|
return null;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
try {
|
|
79
|
+
const data = JSON.parse(raw);
|
|
80
|
+
let state = data.state;
|
|
81
|
+
for (let v = data.meta.version; v < this.version; v++) {
|
|
82
|
+
state = (this.migrations[v] ?? ((s) => s))(state);
|
|
83
|
+
}
|
|
84
|
+
return { meta: { ...data.meta, version: this.version }, state: state };
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
return null;
|
|
75
88
|
}
|
|
76
|
-
return { meta: { ...data.meta, version: this.version }, state: state };
|
|
77
89
|
}
|
|
78
90
|
/**
|
|
79
91
|
* Adopts a save this `SaveSystem` never wrote: `normalize` runs once on `externalBytes`,
|
|
@@ -124,7 +136,14 @@ export class SaveSystem {
|
|
|
124
136
|
importSlot(slot, payload, scrambleKey) {
|
|
125
137
|
checkSize(payload);
|
|
126
138
|
const raw = scrambleKey ? unscramble(payload, scrambleKey) : payload;
|
|
127
|
-
const
|
|
139
|
+
const sanitized = sanitizeInboundText(raw);
|
|
140
|
+
let data;
|
|
141
|
+
try {
|
|
142
|
+
data = JSON.parse(sanitized);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
throw new Error('SaveSystem.importSlot: payload is not valid save data (not parseable JSON)');
|
|
146
|
+
}
|
|
128
147
|
let state = data.state;
|
|
129
148
|
for (let v = data.meta.version; v < this.version; v++) {
|
|
130
149
|
state = (this.migrations[v] ?? ((s) => s))(state);
|
package/dist/core/Save.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Save.js","sourceRoot":"","sources":["../../src/core/Save.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAuB/D,uFAAuF;AACvF,MAAM,aAAa;IAAnB;QACS,SAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IAiB1C,CAAC;IAfA,IAAI,CAAC,GAAW;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,KAAa;QAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,GAAW;QACjB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,IAAI;QACH,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9B,CAAC;CACD;AAED,qGAAqG;AACrG,MAAM,UAAU,cAAc;IAC7B,IAAI,OAAO,YAAY,KAAK,WAAW;QAAE,OAAO,IAAI,aAAa,EAAE,CAAC;IAEpE,OAAO;QACN,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC;QACxC,KAAK,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC;QACvD,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC;QAC7C,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;KACrC,CAAC;AACH,CAAC;AAYD,MAAM,OAAO,UAAU;IAMtB,YAAY,OAA0B;QACrC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,cAAc,EAAE,CAAC;IACpD,CAAC;IAEO,GAAG,CAAC,IAAY;QACvB,OAAO,YAAY,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,IAAI,CAAC,IAAY,EAAE,KAAQ,EAAE,OAAiB;QAC7C,MAAM,IAAI,GAAgB,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC;QACnG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"Save.js","sourceRoot":"","sources":["../../src/core/Save.ts"],"names":[],"mappings":"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"}
|