@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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Generator } from '../core/Random.js';
|
|
2
2
|
import { ActionJournal } from '../core/ActionJournal.js';
|
|
3
|
+
import { cloneData } from '../core/Clone.js';
|
|
3
4
|
import { stateChecksum } from '../core/SyncGuard.js';
|
|
4
5
|
import { UndoHistory } from '../core/UndoHistory.js';
|
|
5
6
|
import { Scheduler } from '../roguelike/Scheduler.js';
|
|
@@ -85,6 +86,15 @@ export function validateSimulationReplay(initial, entries, options) {
|
|
|
85
86
|
* automatic-actor loop and fixed-command replay respectively; a game composes both against
|
|
86
87
|
* the same `scheduler` rather than choosing one over the other.
|
|
87
88
|
*
|
|
89
|
+
* Every command and event batch is journalled, and with `history` every committed state is
|
|
90
|
+
* checkpointed, all through `structuredClone`: `Command`, `Event` and `State` must be plain data.
|
|
91
|
+
* A command naming its target as a live actor object (one that owns a `ReactionTable`, or any
|
|
92
|
+
* other callback) cannot be copied, so carry the actor's id and resolve it in the rule. A
|
|
93
|
+
* `dispatch` whose command, events or checkpoint cannot be copied throws a `TypeError` naming
|
|
94
|
+
* the offending path and commits nothing: state, scheduler, random stream and journal stay as
|
|
95
|
+
* they were before the call. The type system cannot enforce this, since a class instance with
|
|
96
|
+
* methods is perfectly cloneable while a plain object with one function field is not.
|
|
97
|
+
*
|
|
88
98
|
* @example
|
|
89
99
|
* ```ts
|
|
90
100
|
* import { SimulationRuntime, type SimulationRuntimeRule } from '@datamoc/mw_games/simulation';
|
|
@@ -142,13 +152,23 @@ export class SimulationRuntime {
|
|
|
142
152
|
/** Runs one command through the rule, commits the resulting state, and charges its cost
|
|
143
153
|
* to the scheduler's current actor when one is given. */
|
|
144
154
|
dispatch(command) {
|
|
155
|
+
const random = this.random.getState();
|
|
145
156
|
const outcome = this.rule(this._state, command, { random: this.random, scheduler: this._scheduler });
|
|
157
|
+
let checkpoint;
|
|
158
|
+
try {
|
|
159
|
+
checkpoint = this.history ? cloneData(outcome.state, 'state') : null;
|
|
160
|
+
// Last fallible step, so a refused command or event batch leaves the journal unchanged.
|
|
161
|
+
this.journal.append(command, outcome.events);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
this.random.setState(random);
|
|
165
|
+
throw error;
|
|
166
|
+
}
|
|
146
167
|
this._state = outcome.state;
|
|
147
168
|
if (outcome.cost != null)
|
|
148
169
|
this._scheduler.spend(outcome.cost);
|
|
149
|
-
this.journal.append(command, outcome.events);
|
|
150
170
|
if (this.history)
|
|
151
|
-
this.history.push(this.historySnapshot());
|
|
171
|
+
this.history.push(this.historySnapshot(checkpoint));
|
|
152
172
|
return outcome;
|
|
153
173
|
}
|
|
154
174
|
get canUndo() {
|
|
@@ -204,8 +224,9 @@ export class SimulationRuntime {
|
|
|
204
224
|
actorId: options.actorId,
|
|
205
225
|
});
|
|
206
226
|
}
|
|
207
|
-
|
|
208
|
-
|
|
227
|
+
/** `snapshot()` already copies the scheduler, random state and journal; only state is live. */
|
|
228
|
+
historySnapshot(state = cloneData(this._state, 'state')) {
|
|
229
|
+
return { ...this.snapshot(), state };
|
|
209
230
|
}
|
|
210
231
|
restoreCheckpoint(snapshot) {
|
|
211
232
|
if (!this.actorOf)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Runtime.js","sourceRoot":"","sources":["../../src/simulation/Runtime.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Runtime.js","sourceRoot":"","sources":["../../src/simulation/Runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { type SaveStorage } from '../core/Save.ts';
|
|
2
|
+
import type { WebSocketLike } from '../core/Multiplayer.ts';
|
|
3
|
+
import type { Playable } from '../audio/Playable.ts';
|
|
4
|
+
/**
|
|
5
|
+
* Test doubles for the seams mwg already takes by injection, so a game's tests (and this
|
|
6
|
+
* repository's own) do not each rewrite them: a storage for `SaveSystem`, `Settings`,
|
|
7
|
+
* `Collection` and the stored counters, a `Playable` for `Sound`/`Music`'s `create`, a socket for
|
|
8
|
+
* `LockstepClient`'s `create`, and a `fetch` for every `HttpTransport` client. Renderer-free and
|
|
9
|
+
* dependency-free, and kept off the root barrel, so nothing here reaches a shipped game unless
|
|
10
|
+
* a test imports it.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { SaveSystem } from '@datamoc/mw_games/core';
|
|
15
|
+
* import { memoryStorage } from '@datamoc/mw_games/testing';
|
|
16
|
+
*
|
|
17
|
+
* const saves = new SaveSystem<{ gold: number }>({ namespace: 'test', version: 1, storage: memoryStorage() });
|
|
18
|
+
* saves.save('slot1', { gold: 3 });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function memoryStorage(): SaveStorage;
|
|
22
|
+
/** a `Playable` that records how often it was played */
|
|
23
|
+
export interface FakePlayable extends Playable {
|
|
24
|
+
playCount: number;
|
|
25
|
+
paused: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A `Playable` for `Sound`/`Music`'s `create` option (`create: fakeAudio` works as is):
|
|
29
|
+
* `play()` counts and unpauses, `pause()` pauses.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { Sound } from '@datamoc/mw_games/audio';
|
|
34
|
+
* import { fakeAudio } from '@datamoc/mw_games/testing';
|
|
35
|
+
*
|
|
36
|
+
* const audio = fakeAudio();
|
|
37
|
+
* const sound = new Sound('hit.wav', { poolSize: 1, create: () => audio });
|
|
38
|
+
* sound.play();
|
|
39
|
+
* console.log(audio.playCount); // 1
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function fakeAudio(): FakePlayable;
|
|
43
|
+
/**
|
|
44
|
+
* `fakeAudio` with an `onended` slot, which is how a backend that reports the end of a track
|
|
45
|
+
* looks to the audio classes; `audio.onended?.(new Event('ended'))` ends it.
|
|
46
|
+
*/
|
|
47
|
+
export declare function fakeAudioWithEnded(): FakePlayable;
|
|
48
|
+
/**
|
|
49
|
+
* A `WebSocketLike` for `LockstepClient`'s `create` option: `sent` holds what the client sent,
|
|
50
|
+
* `receive(message)` delivers a server message as JSON (`receiveRaw` delivers text as is), and
|
|
51
|
+
* `close()` fires `onclose`.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* import { LockstepClient } from '@datamoc/mw_games/core';
|
|
56
|
+
* import { FakeSocket } from '@datamoc/mw_games/testing';
|
|
57
|
+
*
|
|
58
|
+
* const socket = new FakeSocket();
|
|
59
|
+
* const client = new LockstepClient({ url: 'wss://example.test', create: () => socket });
|
|
60
|
+
* client.connect();
|
|
61
|
+
* socket.receive({ type: 'welcome', id: 'p1' });
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare class FakeSocket implements WebSocketLike {
|
|
65
|
+
readyState: number;
|
|
66
|
+
readonly sent: string[];
|
|
67
|
+
onopen: ((event: unknown) => void) | null;
|
|
68
|
+
onclose: ((event: unknown) => void) | null;
|
|
69
|
+
onerror: ((event: unknown) => void) | null;
|
|
70
|
+
onmessage: ((event: {
|
|
71
|
+
data: string;
|
|
72
|
+
}) => void) | null;
|
|
73
|
+
send(data: string): void;
|
|
74
|
+
close(): void;
|
|
75
|
+
receive(message: unknown): void;
|
|
76
|
+
receiveRaw(data: string): void;
|
|
77
|
+
}
|
|
78
|
+
/** one request a `fakeFetch` received */
|
|
79
|
+
export interface FakeFetchCall {
|
|
80
|
+
url: string;
|
|
81
|
+
init?: RequestInit;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A `fetch` for any `HttpTransport` client's `fetch` option: `respond` answers each request,
|
|
85
|
+
* with a `Response` or with a plain value sent as a JSON body, and `calls` records them in order.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { NewsClient } from '@datamoc/mw_games/core';
|
|
90
|
+
* import { fakeFetch } from '@datamoc/mw_games/testing';
|
|
91
|
+
*
|
|
92
|
+
* const fetch = fakeFetch(() => [{ id: '1', title: 'Patch notes', body: 'Fixed things.' }]);
|
|
93
|
+
* const news = new NewsClient({ endpoint: 'https://example.test/news', fetch });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function fakeFetch(respond: (url: string, init?: RequestInit) => unknown): typeof globalThis.fetch & {
|
|
97
|
+
calls: FakeFetchCall[];
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* A `Gamepad` for `Input`/`PlayerInput` tests: `buttons` are values from 0 to 1 (pressed above
|
|
101
|
+
* 0.5), `axes` from -1 to 1. Hand it to the code under test the way `navigator.getGamepads()`
|
|
102
|
+
* would.
|
|
103
|
+
*/
|
|
104
|
+
export declare function fakeGamepad(index: number, buttons?: number[], axes?: number[]): Gamepad;
|
|
105
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,IAAI,WAAW,CAE3C;AAED,wDAAwD;AACxD,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,IAAI,YAAY,CAexC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAEjD;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,UAAW,YAAW,aAAa;IAC/C,UAAU,SAAK;IACf,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAM;IAC7B,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACjD,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAClD,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAClD,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAE7D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEvB;IAED,KAAK,IAAI,IAAI,CAGZ;IAED,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE9B;IAED,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE7B;CACD;AAED,yCAAyC;AACzC,MAAM,WAAW,aAAa;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,WAAW,CAAC;CACnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CACxB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,GACnD,OAAO,UAAU,CAAC,KAAK,GAAG;IAAE,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,CAStD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,EAAO,EAAE,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAM/F"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { MemoryStorage } from '../core/Save.js';
|
|
2
|
+
/**
|
|
3
|
+
* Test doubles for the seams mwg already takes by injection, so a game's tests (and this
|
|
4
|
+
* repository's own) do not each rewrite them: a storage for `SaveSystem`, `Settings`,
|
|
5
|
+
* `Collection` and the stored counters, a `Playable` for `Sound`/`Music`'s `create`, a socket for
|
|
6
|
+
* `LockstepClient`'s `create`, and a `fetch` for every `HttpTransport` client. Renderer-free and
|
|
7
|
+
* dependency-free, and kept off the root barrel, so nothing here reaches a shipped game unless
|
|
8
|
+
* a test imports it.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { SaveSystem } from '@datamoc/mw_games/core';
|
|
13
|
+
* import { memoryStorage } from '@datamoc/mw_games/testing';
|
|
14
|
+
*
|
|
15
|
+
* const saves = new SaveSystem<{ gold: number }>({ namespace: 'test', version: 1, storage: memoryStorage() });
|
|
16
|
+
* saves.save('slot1', { gold: 3 });
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export function memoryStorage() {
|
|
20
|
+
return new MemoryStorage();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A `Playable` for `Sound`/`Music`'s `create` option (`create: fakeAudio` works as is):
|
|
24
|
+
* `play()` counts and unpauses, `pause()` pauses.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { Sound } from '@datamoc/mw_games/audio';
|
|
29
|
+
* import { fakeAudio } from '@datamoc/mw_games/testing';
|
|
30
|
+
*
|
|
31
|
+
* const audio = fakeAudio();
|
|
32
|
+
* const sound = new Sound('hit.wav', { poolSize: 1, create: () => audio });
|
|
33
|
+
* sound.play();
|
|
34
|
+
* console.log(audio.playCount); // 1
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function fakeAudio() {
|
|
38
|
+
return {
|
|
39
|
+
playCount: 0,
|
|
40
|
+
paused: true,
|
|
41
|
+
volume: 1,
|
|
42
|
+
currentTime: 0,
|
|
43
|
+
loop: false,
|
|
44
|
+
play() {
|
|
45
|
+
this.playCount++;
|
|
46
|
+
this.paused = false;
|
|
47
|
+
},
|
|
48
|
+
pause() {
|
|
49
|
+
this.paused = true;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* `fakeAudio` with an `onended` slot, which is how a backend that reports the end of a track
|
|
55
|
+
* looks to the audio classes; `audio.onended?.(new Event('ended'))` ends it.
|
|
56
|
+
*/
|
|
57
|
+
export function fakeAudioWithEnded() {
|
|
58
|
+
return { ...fakeAudio(), onended: null };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A `WebSocketLike` for `LockstepClient`'s `create` option: `sent` holds what the client sent,
|
|
62
|
+
* `receive(message)` delivers a server message as JSON (`receiveRaw` delivers text as is), and
|
|
63
|
+
* `close()` fires `onclose`.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { LockstepClient } from '@datamoc/mw_games/core';
|
|
68
|
+
* import { FakeSocket } from '@datamoc/mw_games/testing';
|
|
69
|
+
*
|
|
70
|
+
* const socket = new FakeSocket();
|
|
71
|
+
* const client = new LockstepClient({ url: 'wss://example.test', create: () => socket });
|
|
72
|
+
* client.connect();
|
|
73
|
+
* socket.receive({ type: 'welcome', id: 'p1' });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export class FakeSocket {
|
|
77
|
+
constructor() {
|
|
78
|
+
this.readyState = 1;
|
|
79
|
+
this.sent = [];
|
|
80
|
+
this.onopen = null;
|
|
81
|
+
this.onclose = null;
|
|
82
|
+
this.onerror = null;
|
|
83
|
+
this.onmessage = null;
|
|
84
|
+
}
|
|
85
|
+
send(data) {
|
|
86
|
+
this.sent.push(data);
|
|
87
|
+
}
|
|
88
|
+
close() {
|
|
89
|
+
this.readyState = 3;
|
|
90
|
+
this.onclose?.(undefined);
|
|
91
|
+
}
|
|
92
|
+
receive(message) {
|
|
93
|
+
this.receiveRaw(JSON.stringify(message));
|
|
94
|
+
}
|
|
95
|
+
receiveRaw(data) {
|
|
96
|
+
this.onmessage?.({ data });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* A `fetch` for any `HttpTransport` client's `fetch` option: `respond` answers each request,
|
|
101
|
+
* with a `Response` or with a plain value sent as a JSON body, and `calls` records them in order.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* import { NewsClient } from '@datamoc/mw_games/core';
|
|
106
|
+
* import { fakeFetch } from '@datamoc/mw_games/testing';
|
|
107
|
+
*
|
|
108
|
+
* const fetch = fakeFetch(() => [{ id: '1', title: 'Patch notes', body: 'Fixed things.' }]);
|
|
109
|
+
* const news = new NewsClient({ endpoint: 'https://example.test/news', fetch });
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export function fakeFetch(respond) {
|
|
113
|
+
const calls = [];
|
|
114
|
+
const fetch = async (input, init) => {
|
|
115
|
+
const url = String(input);
|
|
116
|
+
calls.push({ url, init });
|
|
117
|
+
const answer = await respond(url, init);
|
|
118
|
+
return answer instanceof Response ? answer : new Response(JSON.stringify(answer), { status: 200 });
|
|
119
|
+
};
|
|
120
|
+
return Object.assign(fetch, { calls });
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* A `Gamepad` for `Input`/`PlayerInput` tests: `buttons` are values from 0 to 1 (pressed above
|
|
124
|
+
* 0.5), `axes` from -1 to 1. Hand it to the code under test the way `navigator.getGamepads()`
|
|
125
|
+
* would.
|
|
126
|
+
*/
|
|
127
|
+
export function fakeGamepad(index, buttons = [], axes = []) {
|
|
128
|
+
return {
|
|
129
|
+
index,
|
|
130
|
+
buttons: buttons.map((value) => ({ pressed: value > 0.5, touched: value > 0.5, value })),
|
|
131
|
+
axes,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAoB,MAAM,iBAAiB,CAAC;AAIlE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa;IAC5B,OAAO,IAAI,aAAa,EAAE,CAAC;AAC5B,CAAC;AAQD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS;IACxB,OAAO;QACN,SAAS,EAAE,CAAC;QACZ,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,CAAC;QACT,WAAW,EAAE,CAAC;QACd,IAAI,EAAE,KAAK;QACX,IAAI;YACH,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACrB,CAAC;QACD,KAAK;YACJ,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACpB,CAAC;KACD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IACjC,OAAO,EAAE,GAAG,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,UAAU;IAAvB;QACC,eAAU,GAAG,CAAC,CAAC;QACN,SAAI,GAAa,EAAE,CAAC;QAC7B,WAAM,GAAsC,IAAI,CAAC;QACjD,YAAO,GAAsC,IAAI,CAAC;QAClD,YAAO,GAAsC,IAAI,CAAC;QAClD,cAAS,GAA+C,IAAI,CAAC;IAkB9D,CAAC;IAhBA,IAAI,CAAC,IAAY;QAChB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,OAAgB;QACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU,CAAC,IAAY;QACtB,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5B,CAAC;CACD;AAQD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,SAAS,CACxB,OAAqD;IAErD,MAAM,KAAK,GAAoB,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,EAAE,KAAwB,EAAE,IAAkB,EAAE,EAAE;QACpE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACxC,OAAO,MAAM,YAAY,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IACpG,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,KAAgC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AACnE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAAO,GAAa,EAAE,EAAE,IAAI,GAAa,EAAE;IACrF,OAAO;QACN,KAAK;QACL,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,GAAG,GAAG,EAAE,OAAO,EAAE,KAAK,GAAG,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;QACxF,IAAI;KACkB,CAAC;AACzB,CAAC"}
|
package/dist/version.d.ts
CHANGED
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
* this from `package.json` automatically, chosen because this project's own build already
|
|
10
10
|
* has no step before `tsc`/`vite` that this would need to run ahead of.
|
|
11
11
|
*/
|
|
12
|
-
export declare const version = "0.
|
|
12
|
+
export declare const version = "0.17.1";
|
|
13
13
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
* this from `package.json` automatically, chosen because this project's own build already
|
|
10
10
|
* has no step before `tsc`/`vite` that this would need to run ahead of.
|
|
11
11
|
*/
|
|
12
|
-
export const version = '0.
|
|
12
|
+
export const version = '0.17.1';
|
|
13
13
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datamoc/mw_games",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "A local-file game framework: renderer-free game logic, drawn through PixiJS in 2D or Babylon.js in 3D, with mobile and desktop packaging.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -33,6 +33,18 @@
|
|
|
33
33
|
"./dist/three-d/TileGrid3D.js",
|
|
34
34
|
"./dist/two-d/render/TintedSprite.js"
|
|
35
35
|
],
|
|
36
|
+
"bin": {
|
|
37
|
+
"mwg-bench": "tools/benchmark-browser.mjs",
|
|
38
|
+
"mwg-emit": "tools/emit-page.mjs",
|
|
39
|
+
"mwg-extract-rgssad": "tools/extract-rgssad.mjs",
|
|
40
|
+
"mwg-i18n": "tools/i18n-edit.mjs",
|
|
41
|
+
"mwg-lockstep-server": "tools/multiplayer-server.mjs",
|
|
42
|
+
"mwg-mwl": "tools/mwl.mjs",
|
|
43
|
+
"mwg-placeholder-assets": "tools/make-example-assets.mjs",
|
|
44
|
+
"mwg-sbom": "tools/sbom.mjs",
|
|
45
|
+
"mwg-size": "tools/bundle-size.mjs",
|
|
46
|
+
"mwg-smoke": "tools/browser-smoke.mjs"
|
|
47
|
+
},
|
|
36
48
|
"publishConfig": {
|
|
37
49
|
"access": "public"
|
|
38
50
|
},
|
|
@@ -48,9 +60,37 @@
|
|
|
48
60
|
"tools/compress-dist.d.mts",
|
|
49
61
|
"tools/classic-html.mjs",
|
|
50
62
|
"tools/classic-html.d.mts",
|
|
63
|
+
"tools/sbom.mjs",
|
|
64
|
+
"tools/sbom.d.mts",
|
|
65
|
+
"sbom.cdx.json",
|
|
51
66
|
"tools/single-file.mjs",
|
|
52
67
|
"tools/single-file.d.mts",
|
|
68
|
+
"tools/make-example-assets.mjs",
|
|
69
|
+
"tools/make-example-assets.d.mts",
|
|
70
|
+
"tools/multiplayer-server.mjs",
|
|
71
|
+
"tools/multiplayer-server.d.mts",
|
|
53
72
|
"tools/mwl.mjs",
|
|
73
|
+
"tools/benchmark-browser.mjs",
|
|
74
|
+
"tools/benchmark-browser.d.mts",
|
|
75
|
+
"tools/benchmark-history.mjs",
|
|
76
|
+
"tools/benchmark-history.d.mts",
|
|
77
|
+
"tools/browser-smoke.mjs",
|
|
78
|
+
"tools/bundle-size.mjs",
|
|
79
|
+
"tools/bundle-size.d.mts",
|
|
80
|
+
"tools/browser-smoke.d.mts",
|
|
81
|
+
"tools/csp.mjs",
|
|
82
|
+
"tools/csp.d.mts",
|
|
83
|
+
"tools/emit-page.mjs",
|
|
84
|
+
"tools/emit-page.d.mts",
|
|
85
|
+
"tools/extract-rgssad.mjs",
|
|
86
|
+
"tools/extract-rgssad.d.mts",
|
|
87
|
+
"tools/vendored/rgssad-wasm",
|
|
88
|
+
"tools/find-chrome.mjs",
|
|
89
|
+
"tools/i18n-edit.mjs",
|
|
90
|
+
"tools/i18n-edit.d.mts",
|
|
91
|
+
"tools/find-chrome.d.mts",
|
|
92
|
+
"tools/vite.mjs",
|
|
93
|
+
"tools/vite.d.mts",
|
|
54
94
|
"LICENSE",
|
|
55
95
|
"CHANGELOG.md",
|
|
56
96
|
"README.md",
|
|
@@ -134,11 +174,28 @@
|
|
|
134
174
|
"types": "./dist/ai/lua.d.ts",
|
|
135
175
|
"import": "./dist/ai/lua.js"
|
|
136
176
|
},
|
|
177
|
+
"./testing": {
|
|
178
|
+
"types": "./dist/testing/index.d.ts",
|
|
179
|
+
"import": "./dist/testing/index.js"
|
|
180
|
+
},
|
|
181
|
+
"./tools/benchmark-browser": "./tools/benchmark-browser.mjs",
|
|
182
|
+
"./tools/benchmark-history": "./tools/benchmark-history.mjs",
|
|
183
|
+
"./tools/browser-smoke": "./tools/browser-smoke.mjs",
|
|
184
|
+
"./tools/bundle-size": "./tools/bundle-size.mjs",
|
|
137
185
|
"./tools/classic-html": "./tools/classic-html.mjs",
|
|
138
186
|
"./tools/compile-resources": "./tools/compile-resources.mjs",
|
|
139
187
|
"./tools/compress-dist": "./tools/compress-dist.mjs",
|
|
188
|
+
"./tools/csp": "./tools/csp.mjs",
|
|
189
|
+
"./tools/emit-page": "./tools/emit-page.mjs",
|
|
140
190
|
"./tools/extract-html": "./tools/extract-html.mjs",
|
|
191
|
+
"./tools/extract-rgssad": "./tools/extract-rgssad.mjs",
|
|
192
|
+
"./tools/find-chrome": "./tools/find-chrome.mjs",
|
|
193
|
+
"./tools/i18n-edit": "./tools/i18n-edit.mjs",
|
|
194
|
+
"./tools/sbom": "./tools/sbom.mjs",
|
|
195
|
+
"./tools/make-example-assets": "./tools/make-example-assets.mjs",
|
|
196
|
+
"./tools/multiplayer-server": "./tools/multiplayer-server.mjs",
|
|
141
197
|
"./tools/single-file": "./tools/single-file.mjs",
|
|
198
|
+
"./tools/vite": "./tools/vite.mjs",
|
|
142
199
|
"./tools/webp-convert": "./tools/webp-convert.mjs",
|
|
143
200
|
"./two-d": {
|
|
144
201
|
"types": "./dist/two-d/index.d.ts",
|
|
@@ -184,7 +241,7 @@
|
|
|
184
241
|
"sbom:check": "node tools/sbom.mjs --check",
|
|
185
242
|
"ci:status": "node tools/ci-status.mjs",
|
|
186
243
|
"example": "vite --config examples/colour-transform/vite.config.ts",
|
|
187
|
-
"example:build": "vite build --config examples/colour-transform/vite.config.ts && node tools/emit-page.mjs examples/colour-transform",
|
|
244
|
+
"example:build": "vite build --config examples/colour-transform/vite.config.ts && node tools/emit-page.mjs examples/colour-transform --assets=examples/assets",
|
|
188
245
|
"test": "node --test \"tests/**/*.test.ts\"",
|
|
189
246
|
"coverage": "node --test --experimental-test-coverage --test-coverage-exclude=src/two-d/Game.ts --test-coverage-exclude=src/two-d/render/ColorTransformBatcher.ts --test-coverage-exclude=src/two-d/render/Minimap.ts --test-coverage-exclude=src/three-d/Vox.ts --test-coverage-exclude=src/two-d/stage/DialogueStage.ts --test-coverage-exclude=src/two-d/stage/EventDialogue.ts --test-coverage-exclude=src/two-d/ui/** --test-coverage-exclude=tools/** \"tests/**/*.test.ts\"",
|
|
190
247
|
"coverage:check": "node --test --experimental-test-coverage --test-coverage-lines=88 --test-coverage-branches=89 --test-coverage-functions=82 --test-coverage-exclude=src/two-d/Game.ts --test-coverage-exclude=src/two-d/render/ColorTransformBatcher.ts --test-coverage-exclude=src/two-d/render/Minimap.ts --test-coverage-exclude=src/three-d/Vox.ts --test-coverage-exclude=src/two-d/stage/DialogueStage.ts --test-coverage-exclude=src/two-d/stage/EventDialogue.ts --test-coverage-exclude=src/two-d/ui/** --test-coverage-exclude=tools/** \"tests/**/*.test.ts\"",
|
|
@@ -195,47 +252,47 @@
|
|
|
195
252
|
"i18n:edit": "node tools/i18n-edit.mjs",
|
|
196
253
|
"i18n:check": "node tools/i18n-edit.mjs --check",
|
|
197
254
|
"example:ui": "vite --config examples/interface/vite.config.ts",
|
|
198
|
-
"example:ui:build": "vite build --config examples/interface/vite.config.ts && node tools/emit-page.mjs examples/interface",
|
|
255
|
+
"example:ui:build": "vite build --config examples/interface/vite.config.ts && node tools/emit-page.mjs examples/interface --assets=examples/assets",
|
|
199
256
|
"example:dialogue": "vite --config examples/dialogue/vite.config.ts",
|
|
200
|
-
"example:dialogue:build": "vite build --config examples/dialogue/vite.config.ts && node tools/emit-page.mjs examples/dialogue",
|
|
257
|
+
"example:dialogue:build": "vite build --config examples/dialogue/vite.config.ts && node tools/emit-page.mjs examples/dialogue --assets=examples/assets",
|
|
201
258
|
"example:dungeon": "vite --config examples/dungeon/vite.config.ts",
|
|
202
|
-
"example:dungeon:build": "vite build --config examples/dungeon/vite.config.ts && node tools/emit-page.mjs examples/dungeon",
|
|
259
|
+
"example:dungeon:build": "vite build --config examples/dungeon/vite.config.ts && node tools/emit-page.mjs examples/dungeon --assets=examples/assets",
|
|
203
260
|
"example:village": "vite --config examples/village/vite.config.ts",
|
|
204
|
-
"example:village:build": "vite build --config examples/village/vite.config.ts && node tools/emit-page.mjs examples/village",
|
|
261
|
+
"example:village:build": "vite build --config examples/village/vite.config.ts && node tools/emit-page.mjs examples/village --assets=examples/assets",
|
|
205
262
|
"example:battle": "vite --config examples/battle/vite.config.ts",
|
|
206
|
-
"example:battle:build": "npm run mwl -- build examples/battle/content -o examples/battle/generated && vite build --config examples/battle/vite.config.ts && node tools/emit-page.mjs examples/battle",
|
|
263
|
+
"example:battle:build": "npm run mwl -- build examples/battle/content -o examples/battle/generated && vite build --config examples/battle/vite.config.ts && node tools/emit-page.mjs examples/battle --assets=examples/assets",
|
|
207
264
|
"example:minigame": "vite --config examples/minigame/vite.config.ts",
|
|
208
|
-
"example:minigame:build": "vite build --config examples/minigame/vite.config.ts && node tools/emit-page.mjs examples/minigame",
|
|
265
|
+
"example:minigame:build": "vite build --config examples/minigame/vite.config.ts && node tools/emit-page.mjs examples/minigame --assets=examples/assets",
|
|
209
266
|
"example:multi-turn-beam": "vite --config examples/multi-turn-beam/vite.config.ts",
|
|
210
|
-
"example:multi-turn-beam:build": "vite build --config examples/multi-turn-beam/vite.config.ts && node tools/emit-page.mjs examples/multi-turn-beam",
|
|
267
|
+
"example:multi-turn-beam:build": "vite build --config examples/multi-turn-beam/vite.config.ts && node tools/emit-page.mjs examples/multi-turn-beam --assets=examples/assets",
|
|
211
268
|
"example:chess": "vite --config examples/chess/vite.config.ts",
|
|
212
|
-
"example:chess:build": "vite build --config examples/chess/vite.config.ts && node tools/emit-page.mjs examples/chess",
|
|
269
|
+
"example:chess:build": "vite build --config examples/chess/vite.config.ts && node tools/emit-page.mjs examples/chess --assets=examples/assets",
|
|
213
270
|
"example:tower-defense": "vite --config examples/tower-defense/vite.config.ts",
|
|
214
|
-
"example:tower-defense:build": "vite build --config examples/tower-defense/vite.config.ts && node tools/emit-page.mjs examples/tower-defense",
|
|
271
|
+
"example:tower-defense:build": "vite build --config examples/tower-defense/vite.config.ts && node tools/emit-page.mjs examples/tower-defense --assets=examples/assets",
|
|
215
272
|
"example:3d": "vite --config examples/three-d/vite.config.ts",
|
|
216
|
-
"example:3d:build": "vite build --config examples/three-d/vite.config.ts && node tools/emit-page.mjs examples/three-d",
|
|
273
|
+
"example:3d:build": "vite build --config examples/three-d/vite.config.ts && node tools/emit-page.mjs examples/three-d --assets=examples/assets",
|
|
217
274
|
"example:loading": "vite --config examples/loading/vite.config.ts",
|
|
218
|
-
"example:loading:build": "vite build --config examples/loading/vite.config.ts && node tools/emit-page.mjs examples/loading",
|
|
275
|
+
"example:loading:build": "vite build --config examples/loading/vite.config.ts && node tools/emit-page.mjs examples/loading --assets=examples/assets",
|
|
219
276
|
"example:hello-world": "vite --config examples/hello-world/vite.config.ts",
|
|
220
|
-
"example:hello-world:build": "vite build --config examples/hello-world/vite.config.ts && node tools/emit-page.mjs examples/hello-world",
|
|
277
|
+
"example:hello-world:build": "vite build --config examples/hello-world/vite.config.ts && node tools/emit-page.mjs examples/hello-world --assets=examples/assets",
|
|
221
278
|
"example:movement": "vite --config examples/movement/vite.config.ts",
|
|
222
|
-
"example:movement:build": "vite build --config examples/movement/vite.config.ts && node tools/emit-page.mjs examples/movement",
|
|
279
|
+
"example:movement:build": "vite build --config examples/movement/vite.config.ts && node tools/emit-page.mjs examples/movement --assets=examples/assets",
|
|
223
280
|
"example:save-load": "vite --config examples/save-load/vite.config.ts",
|
|
224
|
-
"example:save-load:build": "vite build --config examples/save-load/vite.config.ts && node tools/emit-page.mjs examples/save-load",
|
|
281
|
+
"example:save-load:build": "vite build --config examples/save-load/vite.config.ts && node tools/emit-page.mjs examples/save-load --assets=examples/assets",
|
|
225
282
|
"example:audio": "vite --config examples/audio/vite.config.ts",
|
|
226
|
-
"example:audio:build": "vite build --config examples/audio/vite.config.ts && node tools/emit-page.mjs examples/audio",
|
|
283
|
+
"example:audio:build": "vite build --config examples/audio/vite.config.ts && node tools/emit-page.mjs examples/audio --assets=examples/assets",
|
|
227
284
|
"example:i18n": "vite --config examples/i18n/vite.config.ts",
|
|
228
|
-
"example:i18n:build": "vite build --config examples/i18n/vite.config.ts && node tools/emit-page.mjs examples/i18n",
|
|
285
|
+
"example:i18n:build": "vite build --config examples/i18n/vite.config.ts && node tools/emit-page.mjs examples/i18n --assets=examples/assets",
|
|
229
286
|
"example:string-editor": "vite --config examples/string-editor/vite.config.ts",
|
|
230
|
-
"example:string-editor:build": "vite build --config examples/string-editor/vite.config.ts && node tools/emit-page.mjs examples/string-editor",
|
|
287
|
+
"example:string-editor:build": "vite build --config examples/string-editor/vite.config.ts && node tools/emit-page.mjs examples/string-editor --assets=examples/assets",
|
|
231
288
|
"example:world-transition": "vite --config examples/world-transition/vite.config.ts",
|
|
232
|
-
"example:world-transition:build": "vite build --config examples/world-transition/vite.config.ts && node tools/emit-page.mjs examples/world-transition",
|
|
289
|
+
"example:world-transition:build": "vite build --config examples/world-transition/vite.config.ts && node tools/emit-page.mjs examples/world-transition --assets=examples/assets",
|
|
233
290
|
"example:event-system": "vite --config examples/event-system/vite.config.ts",
|
|
234
|
-
"example:event-system:build": "vite build --config examples/event-system/vite.config.ts && node tools/emit-page.mjs examples/event-system",
|
|
291
|
+
"example:event-system:build": "vite build --config examples/event-system/vite.config.ts && node tools/emit-page.mjs examples/event-system --assets=examples/assets",
|
|
235
292
|
"example:headless": "vite --config examples/headless/vite.config.ts",
|
|
236
|
-
"example:headless:build": "vite build --config examples/headless/vite.config.ts && node tools/emit-page.mjs examples/headless",
|
|
293
|
+
"example:headless:build": "vite build --config examples/headless/vite.config.ts && node tools/emit-page.mjs examples/headless --assets=examples/assets",
|
|
237
294
|
"example:mwl-content": "vite --config examples/mwl-content/vite.config.ts",
|
|
238
|
-
"example:mwl-content:build": "npm run mwl -- build examples/mwl-content/content -o examples/mwl-content/generated && vite build --config examples/mwl-content/vite.config.ts && node tools/emit-page.mjs examples/mwl-content",
|
|
295
|
+
"example:mwl-content:build": "npm run mwl -- build examples/mwl-content/content -o examples/mwl-content/generated && vite build --config examples/mwl-content/vite.config.ts && node tools/emit-page.mjs examples/mwl-content --assets=examples/assets",
|
|
239
296
|
"benchmark:browser": "npm run example:dungeon:build && node tools/benchmark-browser.mjs",
|
|
240
297
|
"benchmark:3d": "npm run example:3d:build && node tools/benchmark-browser.mjs examples/three-d/dist/index.html",
|
|
241
298
|
"benchmark:tower-defense": "npm run example:tower-defense:build && node tools/benchmark-browser.mjs examples/tower-defense/dist/index.html",
|
|
@@ -250,7 +307,7 @@
|
|
|
250
307
|
"webpage:examples": "node tools/build-webpage-examples.mjs",
|
|
251
308
|
"webpage:docs": "node tools/build-webpage-docs.mjs",
|
|
252
309
|
"webpage:diagrams": "node tools/make-example-diagrams.mjs && node tools/make-architecture-diagrams.mjs",
|
|
253
|
-
"mobile:build": "vite build --config examples/tower-defense/vite.config.ts && node tools/emit-page.mjs examples/tower-defense --no-compress",
|
|
310
|
+
"mobile:build": "vite build --config examples/tower-defense/vite.config.ts && node tools/emit-page.mjs examples/tower-defense --assets=examples/assets --no-compress",
|
|
254
311
|
"cap:cli": "node --require ./tools/capacitor-node-workaround.cjs ./node_modules/@capacitor/cli/bin/capacitor",
|
|
255
312
|
"cap:add:android": "npm run mobile:build && npm run cap:cli -- add android",
|
|
256
313
|
"cap:add:ios": "npm run mobile:build && npm run cap:cli -- add ios",
|
|
@@ -271,7 +328,9 @@
|
|
|
271
328
|
"@babylonjs/core": "^9.25.0",
|
|
272
329
|
"@babylonjs/loaders": "^9.25.0",
|
|
273
330
|
"@capacitor/core": "^7.4.4",
|
|
274
|
-
"pixi.js": "^8.20.1"
|
|
331
|
+
"pixi.js": "^8.20.1",
|
|
332
|
+
"playwright-core": "^1.62.1",
|
|
333
|
+
"ws": "^8.21.3"
|
|
275
334
|
},
|
|
276
335
|
"peerDependenciesMeta": {
|
|
277
336
|
"@babylonjs/core": {
|
|
@@ -285,6 +344,12 @@
|
|
|
285
344
|
},
|
|
286
345
|
"pixi.js": {
|
|
287
346
|
"optional": true
|
|
347
|
+
},
|
|
348
|
+
"playwright-core": {
|
|
349
|
+
"optional": true
|
|
350
|
+
},
|
|
351
|
+
"ws": {
|
|
352
|
+
"optional": true
|
|
288
353
|
}
|
|
289
354
|
},
|
|
290
355
|
"devDependencies": {
|