@datamoc/mw_games 0.26.1 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +77 -0
- package/api-surface.json +474 -0
- package/dist/ai/Suggest.d.ts +54 -0
- package/dist/ai/Suggest.d.ts.map +1 -0
- package/dist/ai/Suggest.js +48 -0
- package/dist/ai/Suggest.js.map +1 -0
- package/dist/ai/index.d.ts +2 -0
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +1 -0
- package/dist/ai/index.js.map +1 -1
- package/dist/core/Random.d.ts +32 -5
- package/dist/core/Random.d.ts.map +1 -1
- package/dist/core/Random.js.map +1 -1
- package/dist/core/Replay.d.ts +28 -4
- package/dist/core/Replay.d.ts.map +1 -1
- package/dist/core/Replay.js +38 -9
- package/dist/core/Replay.js.map +1 -1
- package/dist/core/ReplayFile.d.ts +197 -0
- package/dist/core/ReplayFile.d.ts.map +1 -0
- package/dist/core/ReplayFile.js +257 -0
- package/dist/core/ReplayFile.js.map +1 -0
- package/dist/core/index.d.ts +4 -2
- 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 +113 -113
- package/dist/simulation/Training.d.ts +77 -0
- package/dist/simulation/Training.d.ts.map +1 -1
- package/dist/simulation/Training.js +87 -0
- package/dist/simulation/Training.js.map +1 -1
- package/dist/simulation/index.d.ts +2 -2
- package/dist/simulation/index.d.ts.map +1 -1
- package/dist/simulation/index.js +1 -1
- package/dist/simulation/index.js.map +1 -1
- package/dist/two-d/render/Beam.d.ts +93 -0
- package/dist/two-d/render/Beam.d.ts.map +1 -0
- package/dist/two-d/render/Beam.js +154 -0
- package/dist/two-d/render/Beam.js.map +1 -0
- package/dist/two-d/render/Flights.d.ts +79 -0
- package/dist/two-d/render/Flights.d.ts.map +1 -0
- package/dist/two-d/render/Flights.js +120 -0
- package/dist/two-d/render/Flights.js.map +1 -0
- package/dist/two-d/render/Particles.d.ts +48 -0
- package/dist/two-d/render/Particles.d.ts.map +1 -1
- package/dist/two-d/render/Particles.js +59 -1
- package/dist/two-d/render/Particles.js.map +1 -1
- package/dist/two-d/render/index.d.ts +5 -1
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +2 -0
- package/dist/two-d/render/index.js.map +1 -1
- package/dist/two-d/ui/MessageLog.d.ts +28 -0
- package/dist/two-d/ui/MessageLog.d.ts.map +1 -1
- package/dist/two-d/ui/MessageLog.js +23 -6
- package/dist/two-d/ui/MessageLog.js.map +1 -1
- package/dist/two-d/ui/TextPrompt.d.ts +115 -0
- package/dist/two-d/ui/TextPrompt.d.ts.map +1 -0
- package/dist/two-d/ui/TextPrompt.js +227 -0
- package/dist/two-d/ui/TextPrompt.js.map +1 -0
- package/dist/two-d/ui/index.d.ts +4 -2
- package/dist/two-d/ui/index.d.ts.map +1 -1
- package/dist/two-d/ui/index.js +2 -1
- package/dist/two-d/ui/index.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { Recorder, Player } from './Replay.ts';
|
|
2
|
+
import type { ReplayEvent } from './Replay.ts';
|
|
3
|
+
import { type SaveStorage } from './Save.ts';
|
|
4
|
+
import type { Signal } from './Signal.ts';
|
|
5
|
+
/**
|
|
6
|
+
* A run made durable: the recording `core` already takes, in a shape that survives a page
|
|
7
|
+
* reload, crosses machines, and refuses to play against a build it was not recorded on.
|
|
8
|
+
*
|
|
9
|
+
* `Recorder`/`Player` record and replay in memory; this file is everything around that:
|
|
10
|
+
* a self-describing file format (export and import), the newest recording kept in storage
|
|
11
|
+
* (last-run capture), and a mid-run checkpoint pairing the partial recording with the
|
|
12
|
+
* game state beside it. The `file://` rule shapes the plumbing: an export is a download and
|
|
13
|
+
* an import is a file picker, `fetch()` is never used, and Node-side tools read and write
|
|
14
|
+
* the same file directly.
|
|
15
|
+
*/
|
|
16
|
+
/** The self-describing envelope a recorded run is exported as. */
|
|
17
|
+
export interface ReplayFile {
|
|
18
|
+
format: 'mwg-replay';
|
|
19
|
+
version: 1;
|
|
20
|
+
/** the framework build the run was recorded against - `version` from the package root */
|
|
21
|
+
framework: string;
|
|
22
|
+
/** the game's own identity, so a replay of one game is refused by another by name */
|
|
23
|
+
game: string;
|
|
24
|
+
/** the run's seed, so a seeded environment walks the same trajectory on import */
|
|
25
|
+
seed?: number;
|
|
26
|
+
/** wall-clock moment of export, for a file listing; playback never reads it */
|
|
27
|
+
recordedAt?: number;
|
|
28
|
+
events: readonly ReplayEvent[];
|
|
29
|
+
}
|
|
30
|
+
/** What `exportReplayFile` stamps into the envelope beside the recording itself. */
|
|
31
|
+
export interface ReplayFileMeta {
|
|
32
|
+
framework: string;
|
|
33
|
+
game: string;
|
|
34
|
+
seed?: number;
|
|
35
|
+
recordedAt?: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Wraps a recording in the versioned, self-describing envelope, as a JSON string ready to
|
|
39
|
+
* save as a file. The events are validated and copied, so the exported file cannot drift
|
|
40
|
+
* with a recording that keeps running.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* import { exportReplayFile, Recorder, Signal, version } from '@datamoc/mw_games';
|
|
45
|
+
*
|
|
46
|
+
* declare const recorder: Recorder;
|
|
47
|
+
* const file = exportReplayFile(recorder.toJSON(), {
|
|
48
|
+
* framework: version,
|
|
49
|
+
* game: 'my-game',
|
|
50
|
+
* recordedAt: Date.now(),
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function exportReplayFile(events: readonly ReplayEvent[], meta: ReplayFileMeta): string;
|
|
55
|
+
/**
|
|
56
|
+
* Parses and checks a replay file, refusing by name anything that is not this game on this
|
|
57
|
+
* framework: a replay from another build does not fail somewhere mid-playback, it is
|
|
58
|
+
* rejected at the door with what it actually carries.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* import { importReplayFile, version } from '@datamoc/mw_games';
|
|
63
|
+
*
|
|
64
|
+
* declare const json: string; // read from a file, see readReplayFile
|
|
65
|
+
* const file = importReplayFile(json, { framework: version, game: 'my-game' });
|
|
66
|
+
* console.log(file.events.length, file.seed);
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export declare function importReplayFile(json: string, expect: {
|
|
70
|
+
framework: string;
|
|
71
|
+
game: string;
|
|
72
|
+
}): ReplayFile;
|
|
73
|
+
/** The kept newest recording, as `LastRun.load` hands it back. */
|
|
74
|
+
export interface LastRunData {
|
|
75
|
+
version: 1;
|
|
76
|
+
seed?: number;
|
|
77
|
+
events: readonly ReplayEvent[];
|
|
78
|
+
}
|
|
79
|
+
export interface LastRunOptions {
|
|
80
|
+
/** namespaces the kept recording, so two games sharing an origin never collide */
|
|
81
|
+
namespace: string;
|
|
82
|
+
storage?: SaveStorage;
|
|
83
|
+
/** once a recording holds more events than this, the newest are kept; default 10000 */
|
|
84
|
+
maxEvents?: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The newest recording, always kept, bounded: what "watch the previous run" reads. One
|
|
88
|
+
* recording deep by design (the newest replaces the older one), stored through the same
|
|
89
|
+
* `SaveStorage` a `SaveSystem` slot uses, so it survives a reload and lands in the
|
|
90
|
+
* in-memory fallback under `file://`.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* import { LastRun, Recorder } from '@datamoc/mw_games/core';
|
|
95
|
+
*
|
|
96
|
+
* declare const recorder: Recorder;
|
|
97
|
+
* const last = new LastRun({ namespace: 'my-game' });
|
|
98
|
+
* last.keep(recorder.toJSON());
|
|
99
|
+
* const kept = last.load();
|
|
100
|
+
* console.log(kept ? kept.events.length : 'no run yet');
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare class LastRun {
|
|
104
|
+
private readonly store;
|
|
105
|
+
private readonly maxEvents;
|
|
106
|
+
constructor(options: LastRunOptions);
|
|
107
|
+
/** Keeps the newest recording, replacing any previous one. An oversized tail keeps its newest events. */
|
|
108
|
+
keep(events: readonly ReplayEvent[], seed?: number): void;
|
|
109
|
+
/** The kept recording, or null when no run has been kept yet. Corrupt storage throws by name. */
|
|
110
|
+
load(): LastRunData | null;
|
|
111
|
+
/** Drops the kept recording. */
|
|
112
|
+
clear(): void;
|
|
113
|
+
}
|
|
114
|
+
/** A run in progress, checkpointed: the partial recording beside the game state it captured. */
|
|
115
|
+
export interface RunCheckpoint<T> {
|
|
116
|
+
version: 1;
|
|
117
|
+
/** the frame count the recording reached, so playback resumes mid-run */
|
|
118
|
+
frame: number;
|
|
119
|
+
events: readonly ReplayEvent[];
|
|
120
|
+
state: T;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Pairs a live recording with the state a save already captured, as plain data a
|
|
124
|
+
* `SaveSystem` slot stores: restoring the slot restores the run, not just the numbers.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* import { runCheckpoint, Recorder } from '@datamoc/mw_games/core';
|
|
129
|
+
*
|
|
130
|
+
* declare const recorder: Recorder;
|
|
131
|
+
* const checkpoint = runCheckpoint(recorder, { depth: 4, hp: 9 });
|
|
132
|
+
* console.log(checkpoint.frame, checkpoint.state.hp);
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export declare function runCheckpoint<T>(recorder: Recorder, state: T): RunCheckpoint<T>;
|
|
136
|
+
/**
|
|
137
|
+
* The playback half of a restored checkpoint: a `Player` that continues the recording from
|
|
138
|
+
* the checkpoint's frame, skipping the events before it, so the run resumes rather than
|
|
139
|
+
* restarting. The restored state and the resumed playback travel together: the game loads
|
|
140
|
+
* the slot, then starts this player against the same frame signal it records on.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* import { resumeRunPlayer, runCheckpoint, Recorder, Signal } from '@datamoc/mw_games/core';
|
|
145
|
+
*
|
|
146
|
+
* declare const recorder: Recorder;
|
|
147
|
+
* const checkpoint = runCheckpoint(recorder, { hp: 9 });
|
|
148
|
+
* const onFrame = new Signal<number>();
|
|
149
|
+
* const player = resumeRunPlayer(checkpoint, (action) => console.log(action), onFrame);
|
|
150
|
+
* player.stop();
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export declare function resumeRunPlayer<T>(checkpoint: RunCheckpoint<T>, dispatch: (action: string) => void, frames: Signal<number>): Player;
|
|
154
|
+
/**
|
|
155
|
+
* Saves a replay file locally: a Blob download, which works from a `file://` page with no
|
|
156
|
+
* server and no `fetch()`. Nothing is read back; the file is the export.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```ts
|
|
160
|
+
* import { downloadReplayFile, exportReplayFile } from '@datamoc/mw_games/core';
|
|
161
|
+
*
|
|
162
|
+
* const json = exportReplayFile([], { framework: '0.26.1', game: 'my-game' });
|
|
163
|
+
* downloadReplayFile(json, 'run-1.mwgreplay.json');
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export declare function downloadReplayFile(json: string, filename: string): void;
|
|
167
|
+
/**
|
|
168
|
+
* Reads a chosen file (or any Blob) as text, headless and in the browser alike: the
|
|
169
|
+
* browser half of an import is the picker, this is the rest. `Blob.text()` needs no DOM,
|
|
170
|
+
* so the same function reads a `node:fs` buffer's Blob in a tool.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* import { importReplayFile, readReplayFile, version } from '@datamoc/mw_games';
|
|
175
|
+
*
|
|
176
|
+
* declare const file: Blob; // from pickReplayFile, or a Node-side Blob
|
|
177
|
+
* const json = await readReplayFile(file);
|
|
178
|
+
* const replay = importReplayFile(json, { framework: version, game: 'my-game' });
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export declare function readReplayFile(file: Blob): Promise<string>;
|
|
182
|
+
/**
|
|
183
|
+
* Opens a file picker for one replay file, resolving null when the player cancels. The
|
|
184
|
+
* `file://` import path: no `fetch()`, no drag-drop wiring to get wrong.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* import { importReplayFile, pickReplayFile, readReplayFile, version } from '@datamoc/mw_games';
|
|
189
|
+
*
|
|
190
|
+
* const picked = await pickReplayFile();
|
|
191
|
+
* if (picked) {
|
|
192
|
+
* const replay = importReplayFile(await readReplayFile(picked), { framework: version, game: 'my-game' });
|
|
193
|
+
* }
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export declare function pickReplayFile(accept?: string): Promise<Blob | null>;
|
|
197
|
+
//# sourceMappingURL=ReplayFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReplayFile.d.ts","sourceRoot":"","sources":["../../src/core/ReplayFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { Recorder, Player, parseReplayEvents } from './Replay.js';
|
|
2
|
+
import { defaultStorage } from './Save.js';
|
|
3
|
+
import { StoredValue } from './StoredValue.js';
|
|
4
|
+
import { checkSize, parseInbound } from './Sanitize.js';
|
|
5
|
+
function checkIdentity(kind, value) {
|
|
6
|
+
if (typeof value !== 'string' || !value.length)
|
|
7
|
+
throw new TypeError(`a replay file needs a non-empty ${kind}`);
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
function checkSeed(seed) {
|
|
11
|
+
const value = seed;
|
|
12
|
+
if (!Number.isInteger(value) || value < 0 || value > 0xffffffff)
|
|
13
|
+
throw new RangeError('a replay seed must be uint32');
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Wraps a recording in the versioned, self-describing envelope, as a JSON string ready to
|
|
18
|
+
* save as a file. The events are validated and copied, so the exported file cannot drift
|
|
19
|
+
* with a recording that keeps running.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { exportReplayFile, Recorder, Signal, version } from '@datamoc/mw_games';
|
|
24
|
+
*
|
|
25
|
+
* declare const recorder: Recorder;
|
|
26
|
+
* const file = exportReplayFile(recorder.toJSON(), {
|
|
27
|
+
* framework: version,
|
|
28
|
+
* game: 'my-game',
|
|
29
|
+
* recordedAt: Date.now(),
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function exportReplayFile(events, meta) {
|
|
34
|
+
const framework = checkIdentity('framework', meta.framework);
|
|
35
|
+
const game = checkIdentity('game', meta.game);
|
|
36
|
+
const file = {
|
|
37
|
+
format: 'mwg-replay',
|
|
38
|
+
version: 1,
|
|
39
|
+
framework,
|
|
40
|
+
game,
|
|
41
|
+
events: parseReplayEvents(events),
|
|
42
|
+
};
|
|
43
|
+
if (meta.seed !== undefined)
|
|
44
|
+
file.seed = checkSeed(meta.seed);
|
|
45
|
+
if (meta.recordedAt !== undefined) {
|
|
46
|
+
if (typeof meta.recordedAt !== 'number' || !Number.isFinite(meta.recordedAt))
|
|
47
|
+
throw new TypeError('recordedAt must be a finite number');
|
|
48
|
+
file.recordedAt = meta.recordedAt;
|
|
49
|
+
}
|
|
50
|
+
return JSON.stringify(file);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Parses and checks a replay file, refusing by name anything that is not this game on this
|
|
54
|
+
* framework: a replay from another build does not fail somewhere mid-playback, it is
|
|
55
|
+
* rejected at the door with what it actually carries.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* import { importReplayFile, version } from '@datamoc/mw_games';
|
|
60
|
+
*
|
|
61
|
+
* declare const json: string; // read from a file, see readReplayFile
|
|
62
|
+
* const file = importReplayFile(json, { framework: version, game: 'my-game' });
|
|
63
|
+
* console.log(file.events.length, file.seed);
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function importReplayFile(json, expect) {
|
|
67
|
+
const parsed = parseInbound(json, { label: 'replay file' });
|
|
68
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
69
|
+
throw new Error('a replay file must be a JSON object');
|
|
70
|
+
if (parsed.format !== 'mwg-replay')
|
|
71
|
+
throw new Error(`not a replay file: expected format "mwg-replay", found ${JSON.stringify(parsed.format)}`);
|
|
72
|
+
if (parsed.version !== 1)
|
|
73
|
+
throw new Error(`replay file version ${JSON.stringify(parsed.version)} is not supported (this build reads 1)`);
|
|
74
|
+
if (parsed.game !== expect.game)
|
|
75
|
+
throw new Error(`a replay of ${JSON.stringify(parsed.game)} cannot be imported into ${JSON.stringify(expect.game)}`);
|
|
76
|
+
if (parsed.framework !== expect.framework)
|
|
77
|
+
throw new Error(`a replay recorded against mwg ${JSON.stringify(parsed.framework)} cannot be imported into ${JSON.stringify(expect.framework)}`);
|
|
78
|
+
const events = parseReplayEvents(parsed.events);
|
|
79
|
+
return {
|
|
80
|
+
format: 'mwg-replay',
|
|
81
|
+
version: 1,
|
|
82
|
+
framework: parsed.framework,
|
|
83
|
+
game: parsed.game,
|
|
84
|
+
...(parsed.seed === undefined ? {} : { seed: checkSeed(parsed.seed) }),
|
|
85
|
+
...(parsed.recordedAt === undefined ? {} : { recordedAt: parsed.recordedAt }),
|
|
86
|
+
events,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The newest recording, always kept, bounded: what "watch the previous run" reads. One
|
|
91
|
+
* recording deep by design (the newest replaces the older one), stored through the same
|
|
92
|
+
* `SaveStorage` a `SaveSystem` slot uses, so it survives a reload and lands in the
|
|
93
|
+
* in-memory fallback under `file://`.
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* import { LastRun, Recorder } from '@datamoc/mw_games/core';
|
|
98
|
+
*
|
|
99
|
+
* declare const recorder: Recorder;
|
|
100
|
+
* const last = new LastRun({ namespace: 'my-game' });
|
|
101
|
+
* last.keep(recorder.toJSON());
|
|
102
|
+
* const kept = last.load();
|
|
103
|
+
* console.log(kept ? kept.events.length : 'no run yet');
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export class LastRun {
|
|
107
|
+
constructor(options) {
|
|
108
|
+
if (typeof options.namespace !== 'string' || !options.namespace.length)
|
|
109
|
+
throw new TypeError('a last-run store needs a non-empty namespace');
|
|
110
|
+
const maxEvents = options.maxEvents ?? 10000;
|
|
111
|
+
if (!Number.isInteger(maxEvents) || maxEvents < 1 || maxEvents > 1_000_000)
|
|
112
|
+
throw new RangeError('last-run maxEvents must be in 1..1000000');
|
|
113
|
+
this.maxEvents = maxEvents;
|
|
114
|
+
this.store = new StoredValue(options.storage ?? defaultStorage(), `mwg-last-run:${options.namespace}`);
|
|
115
|
+
}
|
|
116
|
+
/** Keeps the newest recording, replacing any previous one. An oversized tail keeps its newest events. */
|
|
117
|
+
keep(events, seed) {
|
|
118
|
+
let all = parseReplayEvents(events);
|
|
119
|
+
if (all.length > this.maxEvents)
|
|
120
|
+
all = all.slice(all.length - this.maxEvents);
|
|
121
|
+
const data = seed === undefined ? { version: 1, events: all } : { version: 1, seed: checkSeed(seed), events: all };
|
|
122
|
+
checkSize(JSON.stringify(data));
|
|
123
|
+
this.store.write(data);
|
|
124
|
+
}
|
|
125
|
+
/** The kept recording, or null when no run has been kept yet. Corrupt storage throws by name. */
|
|
126
|
+
load() {
|
|
127
|
+
const data = this.store.read(null);
|
|
128
|
+
if (data === null)
|
|
129
|
+
return null;
|
|
130
|
+
if (data?.version !== 1)
|
|
131
|
+
throw new Error('the kept last-run recording is not version 1; clear() it and record again');
|
|
132
|
+
return {
|
|
133
|
+
version: 1,
|
|
134
|
+
...(data.seed === undefined ? {} : { seed: checkSeed(data.seed) }),
|
|
135
|
+
events: parseReplayEvents(data.events),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/** Drops the kept recording. */
|
|
139
|
+
clear() {
|
|
140
|
+
this.store.remove();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Pairs a live recording with the state a save already captured, as plain data a
|
|
145
|
+
* `SaveSystem` slot stores: restoring the slot restores the run, not just the numbers.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* import { runCheckpoint, Recorder } from '@datamoc/mw_games/core';
|
|
150
|
+
*
|
|
151
|
+
* declare const recorder: Recorder;
|
|
152
|
+
* const checkpoint = runCheckpoint(recorder, { depth: 4, hp: 9 });
|
|
153
|
+
* console.log(checkpoint.frame, checkpoint.state.hp);
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
export function runCheckpoint(recorder, state) {
|
|
157
|
+
return { version: 1, frame: recorder.frame, events: recorder.toJSON(), state };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The playback half of a restored checkpoint: a `Player` that continues the recording from
|
|
161
|
+
* the checkpoint's frame, skipping the events before it, so the run resumes rather than
|
|
162
|
+
* restarting. The restored state and the resumed playback travel together: the game loads
|
|
163
|
+
* the slot, then starts this player against the same frame signal it records on.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* import { resumeRunPlayer, runCheckpoint, Recorder, Signal } from '@datamoc/mw_games/core';
|
|
168
|
+
*
|
|
169
|
+
* declare const recorder: Recorder;
|
|
170
|
+
* const checkpoint = runCheckpoint(recorder, { hp: 9 });
|
|
171
|
+
* const onFrame = new Signal<number>();
|
|
172
|
+
* const player = resumeRunPlayer(checkpoint, (action) => console.log(action), onFrame);
|
|
173
|
+
* player.stop();
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export function resumeRunPlayer(checkpoint, dispatch, frames) {
|
|
177
|
+
if (typeof checkpoint !== 'object' || checkpoint === null || checkpoint.version !== 1)
|
|
178
|
+
throw new Error('a run checkpoint must be { version: 1, frame, events, state }');
|
|
179
|
+
return new Player(parseReplayEvents(checkpoint.events), dispatch, frames, { fromFrame: checkpoint.frame });
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Saves a replay file locally: a Blob download, which works from a `file://` page with no
|
|
183
|
+
* server and no `fetch()`. Nothing is read back; the file is the export.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* import { downloadReplayFile, exportReplayFile } from '@datamoc/mw_games/core';
|
|
188
|
+
*
|
|
189
|
+
* const json = exportReplayFile([], { framework: '0.26.1', game: 'my-game' });
|
|
190
|
+
* downloadReplayFile(json, 'run-1.mwgreplay.json');
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
export function downloadReplayFile(json, filename) {
|
|
194
|
+
if (typeof document === 'undefined')
|
|
195
|
+
throw new Error('downloadReplayFile needs a browser document');
|
|
196
|
+
const anchor = document.createElement('a');
|
|
197
|
+
anchor.href = URL.createObjectURL(new Blob([json], { type: 'application/json' }));
|
|
198
|
+
anchor.download = filename;
|
|
199
|
+
document.body.appendChild(anchor);
|
|
200
|
+
anchor.click();
|
|
201
|
+
anchor.remove();
|
|
202
|
+
setTimeout(() => URL.revokeObjectURL(anchor.href), 0);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Reads a chosen file (or any Blob) as text, headless and in the browser alike: the
|
|
206
|
+
* browser half of an import is the picker, this is the rest. `Blob.text()` needs no DOM,
|
|
207
|
+
* so the same function reads a `node:fs` buffer's Blob in a tool.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```ts
|
|
211
|
+
* import { importReplayFile, readReplayFile, version } from '@datamoc/mw_games';
|
|
212
|
+
*
|
|
213
|
+
* declare const file: Blob; // from pickReplayFile, or a Node-side Blob
|
|
214
|
+
* const json = await readReplayFile(file);
|
|
215
|
+
* const replay = importReplayFile(json, { framework: version, game: 'my-game' });
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
export async function readReplayFile(file) {
|
|
219
|
+
return await file.text();
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Opens a file picker for one replay file, resolving null when the player cancels. The
|
|
223
|
+
* `file://` import path: no `fetch()`, no drag-drop wiring to get wrong.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```ts
|
|
227
|
+
* import { importReplayFile, pickReplayFile, readReplayFile, version } from '@datamoc/mw_games';
|
|
228
|
+
*
|
|
229
|
+
* const picked = await pickReplayFile();
|
|
230
|
+
* if (picked) {
|
|
231
|
+
* const replay = importReplayFile(await readReplayFile(picked), { framework: version, game: 'my-game' });
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export async function pickReplayFile(accept = '.json') {
|
|
236
|
+
if (typeof document === 'undefined')
|
|
237
|
+
throw new Error('pickReplayFile needs a browser document');
|
|
238
|
+
return await new Promise((resolve) => {
|
|
239
|
+
const input = document.createElement('input');
|
|
240
|
+
input.type = 'file';
|
|
241
|
+
input.accept = accept;
|
|
242
|
+
input.style.display = 'none';
|
|
243
|
+
let settled = false;
|
|
244
|
+
const done = (value) => {
|
|
245
|
+
if (settled)
|
|
246
|
+
return;
|
|
247
|
+
settled = true;
|
|
248
|
+
input.remove();
|
|
249
|
+
resolve(value);
|
|
250
|
+
};
|
|
251
|
+
input.addEventListener('change', () => done(input.files?.[0] ?? null));
|
|
252
|
+
input.addEventListener('cancel', () => done(null));
|
|
253
|
+
document.body.appendChild(input);
|
|
254
|
+
input.click();
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=ReplayFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReplayFile.js","sourceRoot":"","sources":["../../src/core/ReplayFile.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export * as Input from './Input.ts';
|
|
|
17
17
|
export { PlayerInput } from './PlayerInput.ts';
|
|
18
18
|
export type { PlayerInputOptions } from './PlayerInput.ts';
|
|
19
19
|
export { Generator, MersenneTwister, RandomStreams } from './Random.ts';
|
|
20
|
-
export type { MersenneTwisterState, RandomSource } from './Random.ts';
|
|
20
|
+
export type { FloatSource, MersenneTwisterState, RandomSource } from './Random.ts';
|
|
21
21
|
export { JavaRandom } from './JavaRandom.ts';
|
|
22
22
|
export type { JavaRandomDraw, JavaRandomOptions } from './JavaRandom.ts';
|
|
23
23
|
export { SaveSystem } from './Save.ts';
|
|
@@ -41,8 +41,10 @@ export { checkSize, checkNoControlCharacters, parseInbound, sanitizeInboundText,
|
|
|
41
41
|
export type { SizeLimitOptions, Schema } from './Sanitize.ts';
|
|
42
42
|
export { Collection } from './Collection.ts';
|
|
43
43
|
export type { DbRecord, CollectionOptions } from './Collection.ts';
|
|
44
|
-
export { Recorder, Player, serializeReplay, deserializeReplay } from './Replay.ts';
|
|
44
|
+
export { Recorder, Player, parseReplayEvents, serializeReplay, deserializeReplay } from './Replay.ts';
|
|
45
45
|
export type { ReplayEvent } from './Replay.ts';
|
|
46
|
+
export { exportReplayFile, importReplayFile, LastRun, runCheckpoint, resumeRunPlayer, downloadReplayFile, readReplayFile, pickReplayFile, } from './ReplayFile.ts';
|
|
47
|
+
export type { ReplayFile, ReplayFileMeta, LastRunData, LastRunOptions, RunCheckpoint } from './ReplayFile.ts';
|
|
46
48
|
export { ActionJournal } from './ActionJournal.ts';
|
|
47
49
|
export { cloneData, uncloneablePath } from './Clone.ts';
|
|
48
50
|
export type { ActionJournalEntry } from './ActionJournal.ts';
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACxE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.js
CHANGED
|
@@ -22,7 +22,8 @@ export { TelemetryClient } from './Telemetry.js';
|
|
|
22
22
|
export { NewsClient, NewsSeenTracker } from './News.js';
|
|
23
23
|
export { checkSize, checkNoControlCharacters, parseInbound, sanitizeInboundText, validateSchema } from './Sanitize.js';
|
|
24
24
|
export { Collection } from './Collection.js';
|
|
25
|
-
export { Recorder, Player, serializeReplay, deserializeReplay } from './Replay.js';
|
|
25
|
+
export { Recorder, Player, parseReplayEvents, serializeReplay, deserializeReplay } from './Replay.js';
|
|
26
|
+
export { exportReplayFile, importReplayFile, LastRun, runCheckpoint, resumeRunPlayer, downloadReplayFile, readReplayFile, pickReplayFile, } from './ReplayFile.js';
|
|
26
27
|
export { ActionJournal } from './ActionJournal.js';
|
|
27
28
|
export { cloneData, uncloneablePath } from './Clone.js';
|
|
28
29
|
export { Achievements } from './Achievements.js';
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAQ3D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,wBAAwB,EAAE,YAAY,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
|