@datamoc/mw_games 0.16.0 → 0.17.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.
- package/CHANGELOG.md +162 -0
- package/README.md +21 -1
- package/dist/ai/lua.d.ts.map +1 -1
- package/dist/ai/lua.js +1 -0
- package/dist/ai/lua.js.map +1 -1
- package/dist/core/ActionJournal.d.ts +5 -0
- package/dist/core/ActionJournal.d.ts.map +1 -1
- package/dist/core/ActionJournal.js +12 -1
- package/dist/core/ActionJournal.js.map +1 -1
- package/dist/core/Clone.d.ts +31 -0
- package/dist/core/Clone.d.ts.map +1 -0
- package/dist/core/Clone.js +84 -0
- package/dist/core/Clone.js.map +1 -0
- package/dist/core/Collection.d.ts +1 -0
- package/dist/core/Collection.d.ts.map +1 -1
- package/dist/core/Collection.js +6 -2
- package/dist/core/Collection.js.map +1 -1
- package/dist/core/HttpTransport.d.ts +17 -0
- package/dist/core/HttpTransport.d.ts.map +1 -1
- package/dist/core/HttpTransport.js +61 -0
- package/dist/core/HttpTransport.js.map +1 -1
- package/dist/core/Multiplayer.d.ts +9 -0
- package/dist/core/Multiplayer.d.ts.map +1 -1
- package/dist/core/Multiplayer.js +48 -4
- package/dist/core/Multiplayer.js.map +1 -1
- package/dist/core/News.d.ts.map +1 -1
- package/dist/core/News.js +1 -2
- package/dist/core/News.js.map +1 -1
- package/dist/core/Sanitize.d.ts +19 -0
- package/dist/core/Sanitize.d.ts.map +1 -1
- package/dist/core/Sanitize.js +37 -0
- package/dist/core/Sanitize.js.map +1 -1
- package/dist/core/Save.d.ts +18 -9
- package/dist/core/Save.d.ts.map +1 -1
- package/dist/core/Save.js +37 -21
- package/dist/core/Save.js.map +1 -1
- package/dist/core/SaveSync.js +4 -4
- package/dist/core/SaveSync.js.map +1 -1
- package/dist/core/Settings.d.ts.map +1 -1
- package/dist/core/Settings.js +2 -1
- package/dist/core/Settings.js.map +1 -1
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +8 -7
- package/dist/core/State.js.map +1 -1
- package/dist/core/StoredValue.d.ts +1 -1
- package/dist/core/StoredValue.d.ts.map +1 -1
- package/dist/core/StoredValue.js +3 -2
- package/dist/core/StoredValue.js.map +1 -1
- package/dist/core/Telemetry.d.ts +19 -1
- package/dist/core/Telemetry.d.ts.map +1 -1
- package/dist/core/Telemetry.js +26 -1
- package/dist/core/Telemetry.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/mw_games.global.js +107 -107
- package/dist/mwl/MapFile.js +11 -1
- package/dist/mwl/MapFile.js.map +1 -1
- package/dist/mwl/expression.js +38 -5
- package/dist/mwl/expression.js.map +1 -1
- package/dist/mwl/fengari.d.ts +8 -0
- package/dist/mwl/fengari.d.ts.map +1 -1
- package/dist/mwl/fengari.js +72 -2
- package/dist/mwl/fengari.js.map +1 -1
- package/dist/mwl/persistence.d.ts.map +1 -1
- package/dist/mwl/persistence.js +2 -1
- package/dist/mwl/persistence.js.map +1 -1
- package/dist/mwl/runtime.d.ts.map +1 -1
- package/dist/mwl/runtime.js +6 -1
- package/dist/mwl/runtime.js.map +1 -1
- package/dist/rpg/Marshal.d.ts.map +1 -1
- package/dist/rpg/Marshal.js +13 -0
- package/dist/rpg/Marshal.js.map +1 -1
- package/dist/simulation/Campaign.d.ts.map +1 -1
- package/dist/simulation/Campaign.js +9 -5
- package/dist/simulation/Campaign.js.map +1 -1
- package/dist/simulation/Harness.d.ts.map +1 -1
- package/dist/simulation/Harness.js +2 -1
- package/dist/simulation/Harness.js.map +1 -1
- package/dist/simulation/Runtime.d.ts +10 -0
- package/dist/simulation/Runtime.d.ts.map +1 -1
- package/dist/simulation/Runtime.js +25 -4
- package/dist/simulation/Runtime.js.map +1 -1
- package/dist/testing/index.d.ts +105 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +134 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +90 -25
- package/sbom.cdx.json +5589 -0
- package/tools/benchmark-browser.d.mts +33 -0
- package/tools/benchmark-browser.mjs +163 -0
- package/tools/benchmark-history.d.mts +8 -0
- package/tools/benchmark-history.mjs +31 -0
- package/tools/browser-smoke.d.mts +30 -0
- package/tools/browser-smoke.mjs +167 -0
- package/tools/bundle-size.d.mts +11 -0
- package/tools/bundle-size.mjs +138 -0
- package/tools/csp.d.mts +7 -0
- package/tools/csp.mjs +65 -0
- package/tools/emit-page.d.mts +44 -0
- package/tools/emit-page.mjs +188 -0
- package/tools/extract-rgssad.d.mts +5 -0
- package/tools/extract-rgssad.mjs +64 -0
- package/tools/find-chrome.d.mts +7 -0
- package/tools/find-chrome.mjs +104 -0
- package/tools/i18n-edit.d.mts +29 -0
- package/tools/i18n-edit.mjs +748 -0
- package/tools/make-example-assets.d.mts +2 -0
- package/tools/make-example-assets.mjs +727 -0
- package/tools/multiplayer-server.d.mts +27 -0
- package/tools/multiplayer-server.mjs +195 -0
- package/tools/mwl.mjs +1 -0
- package/tools/sbom.d.mts +83 -0
- package/tools/sbom.mjs +332 -0
- package/tools/vendored/rgssad-wasm/LICENSE-MIT +21 -0
- package/tools/vendored/rgssad-wasm/README.md +15 -0
- package/tools/vendored/rgssad-wasm/package.json +17 -0
- package/tools/vendored/rgssad-wasm/rgssad_wasm.d.ts +41 -0
- package/tools/vendored/rgssad-wasm/rgssad_wasm.js +6 -0
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.js +399 -0
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm +0 -0
- package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm.d.ts +17 -0
- package/tools/vite.d.mts +17 -0
- package/tools/vite.mjs +83 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,168 @@ All notable changes to `mwg` are documented here. Format follows
|
|
|
5
5
|
[Semantic Versioning](https://semver.org/) as of this first release - a 0.y.z version means
|
|
6
6
|
the public API may still change between minor versions.
|
|
7
7
|
|
|
8
|
+
## [0.17.1] - 2026-09-25
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- A page built on a Windows checkout refused its own inline script. The HTML parser turns
|
|
13
|
+
newlines into LF before it hashes an inline script, while `contentSecurityPolicy` hashed the
|
|
14
|
+
CRLF bytes a `core.autocrlf=true` checkout hands over, so Chrome computed a different hash
|
|
15
|
+
from the one the policy allowed. The page logged a Content-Security-Policy violation that
|
|
16
|
+
`mwg-smoke`, the visual smoke and `mwg-bench` read as a page error, the source-page fallback
|
|
17
|
+
script never ran, and the same build on Linux stayed quiet - which is why no browser job had
|
|
18
|
+
caught it. Inline scripts are now hashed after CRLF and lone CR become LF; the standalone
|
|
19
|
+
page's unpacker scripts stay hashed as written, since no parser touches those. A CRLF
|
|
20
|
+
checkout and an LF checkout now produce the same policy, pinned by a test.
|
|
21
|
+
- The committed-artifact checks no longer read the checkout's line endings. `api:check`,
|
|
22
|
+
`stats:check`, `sbom:check` and the committed-SBOM test compared generated text against the
|
|
23
|
+
committed file byte for byte, so a Windows clone failed them on a tree `git diff` called
|
|
24
|
+
clean; `bundle.distRaw` summed the bytes `tsc` copies out of a source file's comments, which
|
|
25
|
+
recorded who generated the file rather than what ships.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- The `check` job runs on `windows-latest` alongside `ubuntu-latest`, so the two failures above
|
|
30
|
+
fail the push instead of reaching a Windows contributor. The gates themselves are unchanged,
|
|
31
|
+
and `fail-fast` is off so one OS failing still shows the other.
|
|
32
|
+
|
|
33
|
+
## [0.17.0] - 2026-09-25
|
|
34
|
+
|
|
35
|
+
### Security
|
|
36
|
+
|
|
37
|
+
- One inbound pipeline, on by default (item 372). `core.parseInbound` runs the size cap,
|
|
38
|
+
the control-character check and a `JSON.parse` that refuses `__proto__`/`constructor`/
|
|
39
|
+
`prototype` at any depth. `SaveSystem.load`/`list`/`importSlot`, `Collection`, the stored
|
|
40
|
+
values behind `PlayerStats`/`RunHistory`/`NewsSeenTracker`, `Settings`, `NewsClient` and
|
|
41
|
+
`LockstepClient` all use it, with no call for a game to add. The reason: under `file://`,
|
|
42
|
+
Chromium shares one `localStorage` between every local page, so any HTML file opened on
|
|
43
|
+
the same machine can read or rewrite a game's saves. `load` now returns `null`, and `list`
|
|
44
|
+
skips the slot, for a tampered or malformed slot (a corrupt slot used to make `list`
|
|
45
|
+
throw). `importSlot` checks the `meta` shape and throws a named error.
|
|
46
|
+
`LockstepClient` caps server messages at `maxMessageBytes` (1 MB), type-checks `welcome`/
|
|
47
|
+
`tick`/`rejected`, and reports anything else on the new `onProtocolError` signal instead of
|
|
48
|
+
throwing out of `onmessage`. An unknown message type, which was silently ignored, is
|
|
49
|
+
reported there too.
|
|
50
|
+
- The Lua host bounds memory, not only instructions (item 373): `memoryLimit` (32 MB by
|
|
51
|
+
default, also accepted by `LuaAI`) charges every string and buffer a call allocates, so
|
|
52
|
+
`string.rep("x", 2^28)` or a doubling `s = s .. s` loop fails with "Lua memory limit
|
|
53
|
+
exceeded" in milliseconds instead of allocating hundreds of megabytes and freezing the tab.
|
|
54
|
+
A script-level `pcall` cannot swallow it. `getmetatable("")` no longer exposes the string
|
|
55
|
+
library.
|
|
56
|
+
- Every page `emitPage` finishes carries a Content-Security-Policy (item 374), so every
|
|
57
|
+
example and every game built through `mwgPage()`/`mwg-emit` gets it with no configuration:
|
|
58
|
+
`default-src 'none'`, scripts from the page's own folder plus hashes of its inline scripts
|
|
59
|
+
(including the scripts a compressed standalone page unpacks), images/fonts/media from
|
|
60
|
+
`data:`/`blob:` only, and `connect-src` limited to `data:`/`blob:` plus the origins a game
|
|
61
|
+
declares (`csp: { connect: [...] }`). Measured in Chromium from `file://`: a `fetch`, an image
|
|
62
|
+
beacon, a remote script and an injected inline script are all refused, and all 22 examples
|
|
63
|
+
and both standalone variants still start. `'unsafe-eval'` stays allowed, because Pixi 8
|
|
64
|
+
refuses to start without it unless the game imports `pixi.js/unsafe-eval` (`eval: false`
|
|
65
|
+
then drops it). `csp: false` leaves the policy out.
|
|
66
|
+
- Transport defaults (item 375): `FeedbackClient`, `NewsClient`, `SaveSyncClient`,
|
|
67
|
+
`TelemetryClient` and `LockstepClient` throw at construction for an `http:`/`ws:` url to
|
|
68
|
+
anything but this machine, unless `allowInsecure: true`. Response bodies stream through
|
|
69
|
+
`maxResponseBytes` (10 MB), checked against `content-length` first and cancelled as soon as
|
|
70
|
+
they pass it. `SaveSyncClient.download`/`list` parsed their JSON envelope with a bare
|
|
71
|
+
`response.json()`; they now go through `parseInbound` like every other reader.
|
|
72
|
+
- The reference lockstep server could be stopped by any one client (item 385): `ws` reports
|
|
73
|
+
an oversized or malformed frame as an `error` event on the socket, and with no listener that
|
|
74
|
+
event threw and ended the process, every room with it. It now has a listener, caps messages
|
|
75
|
+
at `maxMessageBytes` (64 KB, where `ws` accepted 100 MiB), reads them through `parseInbound`
|
|
76
|
+
(an input carrying `__proto__` counts as missing), closes a connection naming an invalid
|
|
77
|
+
room (1008) or a full one (`maxClientsPerRoom`, 64; 1013).
|
|
78
|
+
- `TelemetryClient` bounds what leaves the machine (item 378): strings (event name, property
|
|
79
|
+
names and values) are cut at `maxStringLength` (256), at most `maxProperties` (32) are sent,
|
|
80
|
+
and `allowedProperties`, when given, drops every other name. A path or an error message
|
|
81
|
+
passed by mistake leaves as a bounded fragment.
|
|
82
|
+
- README and `SaveSystem`'s doc state the rule item 377 settled on: under `file://`, any local
|
|
83
|
+
page shares a game's `localStorage`, so nothing in a save is private and no secret belongs
|
|
84
|
+
there.
|
|
85
|
+
- CI hardening (item 379): every GitHub Action is pinned to a commit SHA (the tag kept as a
|
|
86
|
+
comment), `ci.yml` and `benchmark-browser.yml` run with a read-only token, and Dependabot
|
|
87
|
+
keeps both the action pins and the npm dependencies current. `tests/workflows.test.ts`
|
|
88
|
+
fails on an unpinned action or a workflow without `permissions`.
|
|
89
|
+
- `extract-rgssad` wrote each entry to `path.join(outDir, name)` with the name taken from the
|
|
90
|
+
archive, so a crafted entry (`../x`, or `..\x` on Windows) could write outside the output
|
|
91
|
+
folder. Entry names are now normalised and refused unless they resolve inside it (item 389).
|
|
92
|
+
- Seeded fuzzing of every decoder that reads outside input (item 376) found four defects, all
|
|
93
|
+
fixed: `mwl.parseExpression` overflowed the stack on 13 000 nested parentheses (now bounded at
|
|
94
|
+
256 levels and 4096 operators, which also bounds `evaluateExpression`'s recursion, and it no
|
|
95
|
+
longer copies the rest of the source for every token); `parseMapFile` trimmed lines with a
|
|
96
|
+
backtracking `/[,\s]+$/` that took a second on 28 000 spaces; `parseTerrain` spread every row
|
|
97
|
+
into `Math.max`, which overflows past about 100 000 rows, and had no size bound (now 1024x1024
|
|
98
|
+
cells); and `rpg.decodeMarshal` overflowed the stack on nested arrays (now 1000 levels).
|
|
99
|
+
|
|
100
|
+
### Added
|
|
101
|
+
|
|
102
|
+
- The build step a game needs, shipped (item 381): `@datamoc/mw_games/tools/vite`'s
|
|
103
|
+
`mwgPage(options)` plugin makes `vite build` alone produce a page that opens from
|
|
104
|
+
`file://` (IIFE `game.js`, `base: './'`, `assets/` served in dev and compiled into the
|
|
105
|
+
build, raw copies left out, optional `singleFile`/`compress`/`toWebp`).
|
|
106
|
+
`@datamoc/mw_games/tools/emit-page` exports the underlying `emitPage(options)`, which every
|
|
107
|
+
example here still uses through its command line. The getting-started page's step 10 is
|
|
108
|
+
now that one plugin line; it used to tell users to make the edit by hand.
|
|
109
|
+
- `mwg-size dist` (`@datamoc/mw_games/tools/bundle-size`, item 386): the size budget this
|
|
110
|
+
repository gates its own build with, for a game's build. Every file a player receives, raw and
|
|
111
|
+
gzipped, plus the total, against `size-budget.json` (written on first run or with `--update`),
|
|
112
|
+
failing past `--tolerance` (2 %).
|
|
113
|
+
- `mwg-bench <page | dist>` (`@datamoc/mw_games/tools/benchmark-browser`'s `measurePage`, item
|
|
114
|
+
387): a game's own frame-rate gate in headless Chrome, with mean fps, 95th-percentile frame
|
|
115
|
+
time, an optional history compared against its best run, and the software-WebGL switch for a
|
|
116
|
+
runner with no GPU.
|
|
117
|
+
- `@datamoc/mw_games/testing` (item 388): `memoryStorage`, `fakeAudio`/`fakeAudioWithEnded`,
|
|
118
|
+
`FakeSocket`, `fakeFetch` and `fakeGamepad`, the doubles for the seams mwg takes by injection. Off the root
|
|
119
|
+
barrel, renderer-free. This repository's own tests now use them, which removed twelve copies
|
|
120
|
+
of the same in-memory storage, six of the same fake audio element, two fake sockets and two fake gamepads.
|
|
121
|
+
`core.MemoryStorage`, the fallback `defaultStorage()` already used, is exported.
|
|
122
|
+
- Two developer tools ship (item 389): `mwg-placeholder-assets <folder>` writes the generated,
|
|
123
|
+
licence-free placeholder set the examples use (refusing to overwrite without `--force`), and
|
|
124
|
+
`mwg-extract-rgssad <archive> <outDir>` unpacks an RPG Maker XP/VX archive through the
|
|
125
|
+
vendored MIT decoder, now in the package with its licence.
|
|
126
|
+
- The translation editor ships (item 384): `npx mwg-i18n <base> <target> [--check]`
|
|
127
|
+
(`@datamoc/mw_games/tools/i18n-edit`) runs from an installed package, loading `dist` there
|
|
128
|
+
and the TypeScript sources inside this repository, so a game's CI can gate its translations
|
|
129
|
+
with `--check`.
|
|
130
|
+
- The reference lockstep server ships (item 385): `npx mwg-lockstep-server [port]
|
|
131
|
+
[--host=]` (`@datamoc/mw_games/tools/multiplayer-server`), with `ws` an optional peer. The
|
|
132
|
+
command listens on 127.0.0.1 unless `--host` says otherwise.
|
|
133
|
+
- CycloneDX SBOMs for a game (item 380): `mwgPage()` writes `dist/sbom.cdx.json`, the SBOM
|
|
134
|
+
of what the build ships (the packages vite's module graph put in the bundle, with versions
|
|
135
|
+
and licences, and every shipped file with its SHA-256; `sbom: false` skips it). For a small
|
|
136
|
+
consumer project, 8 packages and 3 files, where its lockfile lists 60 components.
|
|
137
|
+
`mwg-sbom [folder]` (`@datamoc/mw_games/tools/sbom`) writes the lockfile SBOM of any
|
|
138
|
+
project, an `application` when the project is `private`. The framework's own
|
|
139
|
+
`sbom.cdx.json` now ships in the package.
|
|
140
|
+
- `mwg-smoke <page | dist>` and `@datamoc/mw_games/tools/browser-smoke`'s `smokePage` (item
|
|
141
|
+
383): a game's CI can prove its build still opens from `file://` (no page error, a ready game
|
|
142
|
+
on a WebGL/WebGPU canvas, non-blank pixels, a screenshot), exiting non-zero otherwise.
|
|
143
|
+
`playwright-core` is an optional peer. The Chrome lookup now also finds the newest Chromium
|
|
144
|
+
Playwright installed, whatever its revision, and knows the macOS install paths, so a
|
|
145
|
+
container or CI image no longer needs `CHROME_PATH`.
|
|
146
|
+
- `bin` entries (item 382): `mwg-emit <folder> [--dist=] [--assets=]` and `mwg-mwl`, so `npx`
|
|
147
|
+
runs them instead of a `node node_modules/...` path.
|
|
148
|
+
- `core.cloneData`/`core.uncloneablePath` - `structuredClone` whose failure names the first
|
|
149
|
+
value that cannot be copied and where it sits (`action.target.reactions.rules[0].when`),
|
|
150
|
+
plus that path lookup on its own for a game to assert its commands are plain data.
|
|
151
|
+
|
|
152
|
+
### Fixed
|
|
153
|
+
|
|
154
|
+
- `SimulationRuntime.dispatch` committed a command's state and scheduler cost before
|
|
155
|
+
journalling it, so a command that could not be copied (one carrying a live actor that owns
|
|
156
|
+
a `ReactionTable`, say) threw a bare `DataCloneError` after the turn had already
|
|
157
|
+
happened. It now copies the event batch, the command and (with `history`) the checkpoint
|
|
158
|
+
state first, and on failure throws a `TypeError` naming the path and restores the random
|
|
159
|
+
stream, leaving state, scheduler and journal untouched. The plain-data contract for
|
|
160
|
+
`Command`, `Event` and `State` is now stated on the class.
|
|
161
|
+
- `ActionJournal.append` stored the caller's action object by reference, so mutating it
|
|
162
|
+
afterwards rewrote history; the action is now copied like the events, and a refused
|
|
163
|
+
append no longer consumes a sequence number.
|
|
164
|
+
- `Campaign.completeCurrent` assigned the carried-over state before copying the level's
|
|
165
|
+
result, so a result that could not be copied left the new state applied and the result
|
|
166
|
+
missing. Both are copied first now. `CanonicalState`, `StateRegistry`, `Campaign`,
|
|
167
|
+
`runHeadlessScenario` and the MWL save reader copy incoming values through
|
|
168
|
+
`core.cloneData`, so a non-data value names its path there too.
|
|
169
|
+
|
|
8
170
|
## [0.16.0] - 2026-09-19
|
|
9
171
|
|
|
10
172
|
### Added
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ playable in the browser with no download, plus the generated API reference.
|
|
|
15
15
|
planning or porting a demanding game with mwg, with links to the [mwg reference](https://github.com/datamoc/mwg/blob/main/REFERENCE.md)
|
|
16
16
|
and the [mwg Pixel Dungeon study](https://datamoc.github.io/mwg-pixel-dungeon/).
|
|
17
17
|
|
|
18
|
-
> **Status: pre-alpha (v0.
|
|
18
|
+
> **Status: pre-alpha (v0.17.1).** Every module in the shared floor below, plus optional
|
|
19
19
|
> 3D, mobile (Capacitor) and desktop (WebView2) packaging, is built and tested - see
|
|
20
20
|
> [ROADMAP.md](https://github.com/datamoc/mwg/blob/main/ROADMAP.md) for open work, and
|
|
21
21
|
> [CLOSED.md](https://github.com/datamoc/mwg/blob/main/CLOSED.md) for the full, numbered shipped history.
|
|
@@ -160,6 +160,26 @@ finds no such tag - the guard against running it against an unbuilt dev template
|
|
|
160
160
|
The bundle itself still has to already be a classic script (an IIFE or UMD build, not further
|
|
161
161
|
ES module output); this only rewrites the tag pointing at it.
|
|
162
162
|
|
|
163
|
+
With Vite, none of that is by hand: `@datamoc/mw_games/tools/vite`'s `mwgPage()` plugin sets
|
|
164
|
+
the classic-script configuration and, when `vite build` finishes, compiles `assets/`, rewrites
|
|
165
|
+
the tag and precompresses the output (item 381). The same finishing step is `emitPage` from
|
|
166
|
+
`@datamoc/mw_games/tools/emit-page`, or the `mwg-emit` command, for another bundler.
|
|
167
|
+
|
|
168
|
+
The finished page also carries a Content-Security-Policy, with nothing to configure (item 374):
|
|
169
|
+
scripts only from its own folder and its own hashed inline scripts, no network request except to
|
|
170
|
+
origins the game declares (`mwgPage({ csp: { connect: ['https://news.example'] } })`), and no
|
|
171
|
+
image, font or media URL but `data:`/`blob:`. A compromised dependency can run, but cannot send
|
|
172
|
+
a save or anything else off the machine. `'unsafe-eval'` stays allowed because Pixi 8 refuses
|
|
173
|
+
to start without it unless a game imports `pixi.js/unsafe-eval` (then pass `csp: { eval: false }`).
|
|
174
|
+
|
|
175
|
+
One consequence of `file://` a game has to design around: **Chromium gives every local page one
|
|
176
|
+
shared `localStorage`**. Any other HTML file opened on the same machine can read a game's saves
|
|
177
|
+
and settings, and rewrite them. mwg treats that storage as outside input (`SaveSystem.load`
|
|
178
|
+
rejects a tampered slot rather than loading it, item 372), but no checksum can make it
|
|
179
|
+
private or trustworthy, since the page that rewrites a save can recompute any checksum too. So
|
|
180
|
+
never put a secret in a save or in settings (an account token, a password, a licence key), and
|
|
181
|
+
treat a save as the player's own editable file, which it is.
|
|
182
|
+
|
|
163
183
|
## Capability spec
|
|
164
184
|
|
|
165
185
|
The definition of done for 1.0, drawn from what each of the nine references actually
|
package/dist/ai/lua.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lua.d.ts","sourceRoot":"","sources":["../../src/ai/lua.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAmB,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEvH,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED,MAAM,WAAW,YAAa,SAAQ,wBAAwB;IAC7D,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,IAAI,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmE;IAC1F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAE5C,YAAY,OAAO,GAAE,YAAiB,
|
|
1
|
+
{"version":3,"file":"lua.d.ts","sourceRoot":"","sources":["../../src/ai/lua.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EAAmB,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEvH,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;CACxC;AAED,MAAM,WAAW,YAAa,SAAQ,wBAAwB;IAC7D,QAAQ,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,IAAI,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;IAClE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmE;IAC1F,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAE5C,YAAY,OAAO,GAAE,YAAiB,EASrC;IAED,QAAQ,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAK1C;IAED,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,UAAU,CAkD1D;IAED;;;;OAIG;IACH,MAAM,CACL,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,YAAY,EAAE,OAAO,EACnC,OAAO,EAAE,gBAAgB,GACvB,eAAe,CAAC,OAAO,YAAY,EAAE,OAAO,EAAE,OAAO,YAAY,EAAE,OAAO,CAAC,CA4B7E;IAED,WAAW,IAAI,eAAe,CAE7B;IAED,WAAW,CAAC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAM3C;IAED,OAAO,IAAI,IAAI,CAKd;CACD;AA0ED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,YAAiB,GAAG,KAAK,CAE7D;AAED,YAAY,EAAE,iBAAiB,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/ai/lua.js
CHANGED
package/dist/ai/lua.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lua.js","sourceRoot":"","sources":["../../src/ai/lua.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lua.js","sourceRoot":"","sources":["../../src/ai/lua.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,11 @@ export interface ActionJournalEntry<Action, Event> {
|
|
|
9
9
|
* debugging. It does not interpret actions or events: the game decides how to reapply an
|
|
10
10
|
* action, while the journal preserves the exact order and resulting event batch.
|
|
11
11
|
*
|
|
12
|
+
* Actions and events are copied with `structuredClone` on the way in, so both must be plain
|
|
13
|
+
* data. An action that carries a live object holding callbacks (an actor with a
|
|
14
|
+
* `ReactionTable`, say) is refused by `append` with the path of the first value that cannot be
|
|
15
|
+
* copied; carry that object's id instead.
|
|
16
|
+
*
|
|
12
17
|
* @example
|
|
13
18
|
* ```ts
|
|
14
19
|
* import { ActionJournal } from '@datamoc/mw_games/core';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionJournal.d.ts","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ActionJournal.d.ts","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"AAEA,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;;;;;;;;;;;;;;;;;;;GAmBG;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,CASvF;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"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import { cloneData } from './Clone.js';
|
|
1
2
|
/**
|
|
2
3
|
* A serializable, append-only action log for replay, undo checkpoints, synchronization and
|
|
3
4
|
* debugging. It does not interpret actions or events: the game decides how to reapply an
|
|
4
5
|
* action, while the journal preserves the exact order and resulting event batch.
|
|
5
6
|
*
|
|
7
|
+
* Actions and events are copied with `structuredClone` on the way in, so both must be plain
|
|
8
|
+
* data. An action that carries a live object holding callbacks (an actor with a
|
|
9
|
+
* `ReactionTable`, say) is refused by `append` with the path of the first value that cannot be
|
|
10
|
+
* copied; carry that object's id instead.
|
|
11
|
+
*
|
|
6
12
|
* @example
|
|
7
13
|
* ```ts
|
|
8
14
|
* import { ActionJournal } from '@datamoc/mw_games/core';
|
|
@@ -19,7 +25,12 @@ export class ActionJournal {
|
|
|
19
25
|
this.nextSequence = 0;
|
|
20
26
|
}
|
|
21
27
|
append(action, events = []) {
|
|
22
|
-
const entry = {
|
|
28
|
+
const entry = {
|
|
29
|
+
sequence: this.nextSequence,
|
|
30
|
+
action: cloneData(action, 'action'),
|
|
31
|
+
events: cloneData([...events], 'events'),
|
|
32
|
+
};
|
|
33
|
+
this.nextSequence++;
|
|
23
34
|
this.entries.push(entry);
|
|
24
35
|
return structuredClone(entry);
|
|
25
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionJournal.js","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ActionJournal.js","sourceRoot":"","sources":["../../src/core/ActionJournal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AASvC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,aAAa;IAA1B;QACS,YAAO,GAAwC,EAAE,CAAC;QAClD,iBAAY,GAAG,CAAC,CAAC;IA+D1B,CAAC;IA7DA,MAAM,CAAC,MAAc,EAAE,MAAM,GAAqB,EAAE;QACnD,MAAM,KAAK,GAAG;YACb,QAAQ,EAAE,IAAI,CAAC,YAAY;YAC3B,MAAM,EAAE,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC;YACnC,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,QAAQ,CAAC;SACxC,CAAC;QACF,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where `structuredClone` would fail inside `value`, as a readable path (`command.attacker.
|
|
3
|
+
* reactions.rules[0].when`), or null when the whole value clones. A function, a symbol, a
|
|
4
|
+
* `WeakMap`/`WeakSet`, a `Promise` or a DOM node all fail; a class instance on its own does
|
|
5
|
+
* not (its own fields are copied and its prototype dropped), so the path points at the first
|
|
6
|
+
* field that actually cannot be copied rather than at the object holding it.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { uncloneablePath } from '@datamoc/mw_games/core';
|
|
11
|
+
*
|
|
12
|
+
* uncloneablePath({ target: { id: 'king', onHit: () => {} } }, 'command'); // 'command.target.onHit'
|
|
13
|
+
* uncloneablePath({ targetId: 'king' }, 'command'); // null
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function uncloneablePath(value: unknown, root?: string): string | null;
|
|
17
|
+
/**
|
|
18
|
+
* `structuredClone`, with a failure that names what could not be copied and where, instead of
|
|
19
|
+
* the bare `DataCloneError` a journal or undo checkpoint would otherwise surface far from the
|
|
20
|
+
* code that put a live object there.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { cloneData } from '@datamoc/mw_games/core';
|
|
25
|
+
*
|
|
26
|
+
* const checkpoint = cloneData({ turn: 3, hp: { king: 12 } }, 'state');
|
|
27
|
+
* cloneData({ onHit: () => {} }, 'command'); // throws: command.onHit cannot be structured-cloned ...
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function cloneData<T>(value: T, label: string): T;
|
|
31
|
+
//# sourceMappingURL=Clone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Clone.d.ts","sourceRoot":"","sources":["../../src/core/Clone.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,SAAU,GAAG,MAAM,GAAG,IAAI,CAE7E;AAiCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAavD"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where `structuredClone` would fail inside `value`, as a readable path (`command.attacker.
|
|
3
|
+
* reactions.rules[0].when`), or null when the whole value clones. A function, a symbol, a
|
|
4
|
+
* `WeakMap`/`WeakSet`, a `Promise` or a DOM node all fail; a class instance on its own does
|
|
5
|
+
* not (its own fields are copied and its prototype dropped), so the path points at the first
|
|
6
|
+
* field that actually cannot be copied rather than at the object holding it.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* import { uncloneablePath } from '@datamoc/mw_games/core';
|
|
11
|
+
*
|
|
12
|
+
* uncloneablePath({ target: { id: 'king', onHit: () => {} } }, 'command'); // 'command.target.onHit'
|
|
13
|
+
* uncloneablePath({ targetId: 'king' }, 'command'); // null
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export function uncloneablePath(value, root = 'value') {
|
|
17
|
+
return find(value, root, new Set());
|
|
18
|
+
}
|
|
19
|
+
function find(value, path, seen) {
|
|
20
|
+
if (typeof value === 'function' || typeof value === 'symbol')
|
|
21
|
+
return path;
|
|
22
|
+
if (value === null || typeof value !== 'object' || seen.has(value))
|
|
23
|
+
return null;
|
|
24
|
+
seen.add(value);
|
|
25
|
+
if (clones(value))
|
|
26
|
+
return null;
|
|
27
|
+
const children = [];
|
|
28
|
+
if (value instanceof Map) {
|
|
29
|
+
for (const [key, item] of value)
|
|
30
|
+
children.push([`${path}.get(${JSON.stringify(key) ?? String(key)})`, item]);
|
|
31
|
+
}
|
|
32
|
+
else if (value instanceof Set) {
|
|
33
|
+
for (const item of value)
|
|
34
|
+
children.push([`${path}.item`, item]);
|
|
35
|
+
}
|
|
36
|
+
else if (Array.isArray(value)) {
|
|
37
|
+
value.forEach((item, index) => children.push([`${path}[${index}]`, item]));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
for (const [key, item] of Object.entries(value))
|
|
41
|
+
children.push([`${path}.${key}`, item]);
|
|
42
|
+
}
|
|
43
|
+
for (const [childPath, child] of children) {
|
|
44
|
+
const found = find(child, childPath, seen);
|
|
45
|
+
if (found)
|
|
46
|
+
return found;
|
|
47
|
+
}
|
|
48
|
+
return path;
|
|
49
|
+
}
|
|
50
|
+
function clones(value) {
|
|
51
|
+
try {
|
|
52
|
+
structuredClone(value);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* `structuredClone`, with a failure that names what could not be copied and where, instead of
|
|
61
|
+
* the bare `DataCloneError` a journal or undo checkpoint would otherwise surface far from the
|
|
62
|
+
* code that put a live object there.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { cloneData } from '@datamoc/mw_games/core';
|
|
67
|
+
*
|
|
68
|
+
* const checkpoint = cloneData({ turn: 3, hp: { king: 12 } }, 'state');
|
|
69
|
+
* cloneData({ onHit: () => {} }, 'command'); // throws: command.onHit cannot be structured-cloned ...
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export function cloneData(value, label) {
|
|
73
|
+
try {
|
|
74
|
+
return structuredClone(value);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
const path = uncloneablePath(value, label) ?? label;
|
|
78
|
+
throw new TypeError(`${path} cannot be structured-cloned (${error instanceof Error ? error.message : String(error)}). ` +
|
|
79
|
+
'Journals, snapshots and undo checkpoints copy their contents with structuredClone, so they ' +
|
|
80
|
+
'must hold plain data: refer to a live object (an actor, anything carrying callbacks such as ' +
|
|
81
|
+
'a ReactionTable) by its id and resolve it inside the rule.', { cause: error });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=Clone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Clone.js","sourceRoot":"","sources":["../../src/core/Clone.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/core/Collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../../src/core/Collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAG7D;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IACjC,yFAAyF;IACzF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iFAAiF;IACjF,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IAEtC,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,EAIxD;IAED,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,uCAAuC;IACvC,GAAG,IAAI,QAAQ,EAAE,CAEhB;IAED,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAGpC;IAED,sDAAsD;IACtD,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAQ1B;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAEvB;IAED,6FAA6F;IAC7F,KAAK,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,QAAQ,KAAK,OAAO,GAAG,QAAQ,EAAE,CAE1D;IAED,oEAAoE;IACpE,KAAK,IAAI,IAAI,CAEZ;IAED,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,KAAK;CAGb"}
|
package/dist/core/Collection.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defaultStorage } from './Save.js';
|
|
2
|
+
import { parseInbound } from './Sanitize.js';
|
|
2
3
|
/**
|
|
3
4
|
* A named collection of records, queried and filtered - the shape `SaveSystem`
|
|
4
5
|
* does not cover. A save slot is one blob loaded wholesale; a collection is many
|
|
@@ -39,7 +40,7 @@ export class Collection {
|
|
|
39
40
|
}
|
|
40
41
|
get(id) {
|
|
41
42
|
const raw = this.storage.read(this.prefix + id);
|
|
42
|
-
return raw === null ? undefined :
|
|
43
|
+
return raw === null ? undefined : this.parse(raw, this.prefix + id);
|
|
43
44
|
}
|
|
44
45
|
/** inserts or replaces the record with the same id */
|
|
45
46
|
put(record) {
|
|
@@ -67,7 +68,10 @@ export class Collection {
|
|
|
67
68
|
return this.storage.keys().filter((key) => key.startsWith(this.prefix));
|
|
68
69
|
}
|
|
69
70
|
read(key) {
|
|
70
|
-
return
|
|
71
|
+
return this.parse(this.storage.read(key), key);
|
|
72
|
+
}
|
|
73
|
+
parse(raw, key) {
|
|
74
|
+
return parseInbound(raw, { label: `record "${key}"` });
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
//# sourceMappingURL=Collection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Collection.js","sourceRoot":"","sources":["../../src/core/Collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAoB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Collection.js","sourceRoot":"","sources":["../../src/core/Collection.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,18 @@ export interface HttpTransportOptions {
|
|
|
2
2
|
endpoint: string;
|
|
3
3
|
timeoutMs?: number;
|
|
4
4
|
fetch?: typeof globalThis.fetch;
|
|
5
|
+
/** largest response body read, in bytes; defaults to 10 MB */
|
|
6
|
+
maxResponseBytes?: number;
|
|
7
|
+
/** accept `http://` to a host other than this machine; off by default */
|
|
8
|
+
allowInsecure?: boolean;
|
|
5
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Throws unless `url` is encrypted (`https:`/`wss:`) or stays on this machine (`localhost`,
|
|
12
|
+
* `127.0.0.1`, `[::1]`), or `allowInsecure` says otherwise. A save, a telemetry event or a
|
|
13
|
+
* multiplayer input sent in clear text is readable and alterable by anyone on the path; a
|
|
14
|
+
* relative url inherits the page's own scheme, so it is accepted as is.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assertSecureUrl(url: string, label: string, allowInsecure?: boolean): void;
|
|
6
17
|
/**
|
|
7
18
|
* The constructor validation and timeout-wrapped fetch shared by every injectable HTTPS
|
|
8
19
|
* transport here (`FeedbackClient`, `NewsClient`, `SaveSyncClient`, `TelemetryClient`) - each one is a
|
|
@@ -16,7 +27,13 @@ export declare abstract class HttpTransport {
|
|
|
16
27
|
protected readonly endpoint: string;
|
|
17
28
|
protected readonly timeoutMs: number;
|
|
18
29
|
protected readonly fetchFn: typeof globalThis.fetch;
|
|
30
|
+
protected readonly maxResponseBytes: number;
|
|
31
|
+
private readonly label;
|
|
19
32
|
constructor(options: HttpTransportOptions, label: string);
|
|
20
33
|
protected withTimeout<T>(run: (signal: AbortSignal) => Promise<T>): Promise<T>;
|
|
34
|
+
/** the response body as text, refused as soon as it passes `maxResponseBytes` rather than after it is all in memory */
|
|
35
|
+
protected readText(response: Response): Promise<string>;
|
|
36
|
+
/** `readText`, then `parseInbound` */
|
|
37
|
+
protected readJson(response: Response, what: string): Promise<unknown>;
|
|
21
38
|
}
|
|
22
39
|
//# sourceMappingURL=HttpTransport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HttpTransport.d.ts","sourceRoot":"","sources":["../../src/core/HttpTransport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HttpTransport.d.ts","sourceRoot":"","sources":["../../src/core/HttpTransport.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAChC,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAID;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,UAAQ,GAAG,IAAI,CAQvF;AAED;;;;;;;;GAQG;AACH,8BAAsB,aAAa;IAClC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IACrC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACpD,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B,YAAY,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,EAUvD;IAED,UAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQnF;IAED,uHAAuH;IACvH,UAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B5D;IAED,sCAAsC;IACtC,UAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK3E;CACD"}
|
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
import { checkSize, parseInbound } from './Sanitize.js';
|
|
2
|
+
const LOCAL_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
3
|
+
/**
|
|
4
|
+
* Throws unless `url` is encrypted (`https:`/`wss:`) or stays on this machine (`localhost`,
|
|
5
|
+
* `127.0.0.1`, `[::1]`), or `allowInsecure` says otherwise. A save, a telemetry event or a
|
|
6
|
+
* multiplayer input sent in clear text is readable and alterable by anyone on the path; a
|
|
7
|
+
* relative url inherits the page's own scheme, so it is accepted as is.
|
|
8
|
+
*/
|
|
9
|
+
export function assertSecureUrl(url, label, allowInsecure = false) {
|
|
10
|
+
if (allowInsecure || !/^[a-z][a-z0-9+.-]*:/i.test(url))
|
|
11
|
+
return;
|
|
12
|
+
const parsed = new URL(url);
|
|
13
|
+
if (parsed.protocol === 'https:' || parsed.protocol === 'wss:')
|
|
14
|
+
return;
|
|
15
|
+
if ((parsed.protocol === 'http:' || parsed.protocol === 'ws:') && LOCAL_HOSTS.has(parsed.hostname))
|
|
16
|
+
return;
|
|
17
|
+
throw new Error(`${label} url must use https: or wss: (got ${parsed.protocol}//${parsed.host}); pass allowInsecure: true to accept it`);
|
|
18
|
+
}
|
|
1
19
|
/**
|
|
2
20
|
* The constructor validation and timeout-wrapped fetch shared by every injectable HTTPS
|
|
3
21
|
* transport here (`FeedbackClient`, `NewsClient`, `SaveSyncClient`, `TelemetryClient`) - each one is a
|
|
@@ -11,7 +29,10 @@ export class HttpTransport {
|
|
|
11
29
|
constructor(options, label) {
|
|
12
30
|
if (!options.endpoint)
|
|
13
31
|
throw new Error(`${label} endpoint is required`);
|
|
32
|
+
assertSecureUrl(options.endpoint, `${label} endpoint`, options.allowInsecure);
|
|
14
33
|
this.endpoint = options.endpoint;
|
|
34
|
+
this.label = label;
|
|
35
|
+
this.maxResponseBytes = options.maxResponseBytes ?? 10 * 1024 * 1024;
|
|
15
36
|
this.timeoutMs = options.timeoutMs ?? 10000;
|
|
16
37
|
if (!(this.timeoutMs > 0))
|
|
17
38
|
throw new Error(`${label} timeout must be positive`);
|
|
@@ -29,5 +50,45 @@ export class HttpTransport {
|
|
|
29
50
|
clearTimeout(timer);
|
|
30
51
|
}
|
|
31
52
|
}
|
|
53
|
+
/** the response body as text, refused as soon as it passes `maxResponseBytes` rather than after it is all in memory */
|
|
54
|
+
async readText(response) {
|
|
55
|
+
const limit = this.maxResponseBytes;
|
|
56
|
+
const declared = Number(response.headers?.get?.('content-length'));
|
|
57
|
+
if (declared > limit)
|
|
58
|
+
throw new Error(`${this.label} response exceeds the ${limit}-byte limit (${declared} bytes)`);
|
|
59
|
+
if (!response.body) {
|
|
60
|
+
const text = await response.text();
|
|
61
|
+
checkSize(text, { maxBytes: limit });
|
|
62
|
+
return text;
|
|
63
|
+
}
|
|
64
|
+
const reader = response.body.getReader();
|
|
65
|
+
const chunks = [];
|
|
66
|
+
let size = 0;
|
|
67
|
+
for (;;) {
|
|
68
|
+
const { done, value } = await reader.read();
|
|
69
|
+
if (done)
|
|
70
|
+
break;
|
|
71
|
+
size += value.byteLength;
|
|
72
|
+
if (size > limit) {
|
|
73
|
+
await reader.cancel();
|
|
74
|
+
throw new Error(`${this.label} response exceeds the ${limit}-byte limit`);
|
|
75
|
+
}
|
|
76
|
+
chunks.push(value);
|
|
77
|
+
}
|
|
78
|
+
const bytes = new Uint8Array(size);
|
|
79
|
+
let offset = 0;
|
|
80
|
+
for (const chunk of chunks) {
|
|
81
|
+
bytes.set(chunk, offset);
|
|
82
|
+
offset += chunk.byteLength;
|
|
83
|
+
}
|
|
84
|
+
return new TextDecoder().decode(bytes);
|
|
85
|
+
}
|
|
86
|
+
/** `readText`, then `parseInbound` */
|
|
87
|
+
async readJson(response, what) {
|
|
88
|
+
return parseInbound(await this.readText(response), {
|
|
89
|
+
maxBytes: this.maxResponseBytes,
|
|
90
|
+
label: `${this.label} ${what}`,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
32
93
|
}
|
|
33
94
|
//# sourceMappingURL=HttpTransport.js.map
|