@datamoc/mw_games 0.15.0 → 0.17.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 +154 -1
- 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/two-d/render/RpgmAutotile.d.ts +217 -0
- package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -1
- package/dist/two-d/render/RpgmAutotile.js +756 -0
- package/dist/two-d/render/RpgmAutotile.js.map +1 -1
- package/dist/two-d/render/TileMap.d.ts +90 -0
- package/dist/two-d/render/TileMap.d.ts.map +1 -1
- package/dist/two-d/render/TileMap.js +319 -31
- package/dist/two-d/render/TileMap.js.map +1 -1
- package/dist/two-d/render/index.d.ts +3 -3
- package/dist/two-d/render/index.d.ts.map +1 -1
- package/dist/two-d/render/index.js +1 -1
- package/dist/two-d/render/index.js.map +1 -1
- 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 +56 -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 +330 -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"}
|
|
@@ -62,4 +62,221 @@ export declare class RpgmAutotileAtlas {
|
|
|
62
62
|
get(tileId: number, slot: RpgmAutotileSlot, shape: number): RpgmAutotileFrame;
|
|
63
63
|
clear(): void;
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The first MV tile id of each autotile family (A1-A4): slot 0 covers
|
|
67
|
+
* 2048-2815, slot 1 covers 2816-4351, slot 2 covers 4352-5887 and slot 3
|
|
68
|
+
* covers 5888-8191. Measured against real A-sheets rather than assumed.
|
|
69
|
+
*/
|
|
70
|
+
export declare const RPGM_AUTOTILE_SLOT_BASES: readonly [2048, 2816, 4352, 5888];
|
|
71
|
+
/**
|
|
72
|
+
* How many MV tile ids each family holds: 16, 32, 32 and 48 kinds of
|
|
73
|
+
* 48 shapes each. A sheet holding fewer cells than its slot needs is a
|
|
74
|
+
* truncated custom sheet, not a different layout.
|
|
75
|
+
*/
|
|
76
|
+
export declare const RPGM_AUTOTILE_SLOT_COUNTS: readonly [768, 1536, 1536, 2304];
|
|
77
|
+
/**
|
|
78
|
+
* Which MV autotile family a raw map tile id belongs to, or null when the id
|
|
79
|
+
* is not an autotile at all (an `EMPTY` cell, a static B-E tile, an A5 tile).
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* import {
|
|
84
|
+
* rpgmAutotileSlot,
|
|
85
|
+
* RPGM_AUTOTILE_SLOT_BASES,
|
|
86
|
+
* RPGM_AUTOTILE_SLOT_COUNTS,
|
|
87
|
+
* } from '@datamoc/mw_games/two-d/render';
|
|
88
|
+
*
|
|
89
|
+
* console.log(rpgmAutotileSlot(2048)); // 0 - the first A1 tile
|
|
90
|
+
* console.log(rpgmAutotileSlot(3000)); // 1 - inside the A2 range
|
|
91
|
+
* console.log(rpgmAutotileSlot(42)); // null - a static tile, not an autotile
|
|
92
|
+
* console.log(rpgmAutotileSlot(-1)); // null - EMPTY reads as blank, never as a slot
|
|
93
|
+
* console.log(RPGM_AUTOTILE_SLOT_BASES[0]); // 2048 - where slot 0 starts
|
|
94
|
+
* console.log(RPGM_AUTOTILE_SLOT_COUNTS[0]); // 768 - 16 kinds times 48 shapes
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function rpgmAutotileSlot(tile: number): RpgmAutotileSlot | null;
|
|
98
|
+
/**
|
|
99
|
+
* The standard MV floor-autotile shape table (48 shapes), for slots 0-1:
|
|
100
|
+
* which four atlas quadrants each baked shape assembles, in 24px source
|
|
101
|
+
* cells. Entries are `[x, y]` offsets, row-major `[topLeft, topRight,
|
|
102
|
+
* bottomLeft, bottomRight]`, exactly the shape numbering MV bakes into map
|
|
103
|
+
* tile ids (`shape = (tile - base) % 48`).
|
|
104
|
+
*
|
|
105
|
+
* Functional interop data, the same category as `BLOB_SHAPES`: every game
|
|
106
|
+
* reading MV maps needs these numbers, so they live here once rather than
|
|
107
|
+
* pasted into every port.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* import { RPGM_FLOOR_AUTOTILE_TABLE, RPGM_WALL_AUTOTILE_TABLE } from '@datamoc/mw_games/two-d/render';
|
|
112
|
+
*
|
|
113
|
+
* console.log(RPGM_FLOOR_AUTOTILE_TABLE.length); // 48 - one entry per baked shape
|
|
114
|
+
* console.log(RPGM_WALL_AUTOTILE_TABLE.length); // 16 - walls cycle every 16 shapes
|
|
115
|
+
* console.log(RPGM_FLOOR_AUTOTILE_TABLE[47]); // [[0,0],[1,0],[0,1],[1,1]] - the full tile
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare const RPGM_FLOOR_AUTOTILE_TABLE: RpgmAutotileShapeTable;
|
|
119
|
+
/**
|
|
120
|
+
* The standard MV wall-autotile shape table (16 shapes), for slots 2-3.
|
|
121
|
+
* Wall shapes cycle every 16 (`table[shape % 16]`), so a wall family holds
|
|
122
|
+
* three full cycles where a floor family holds one run of 48.
|
|
123
|
+
*/
|
|
124
|
+
export declare const RPGM_WALL_AUTOTILE_TABLE: RpgmAutotileShapeTable;
|
|
125
|
+
/** one XP autotile pattern: four 16px mini-block indices, row-major `[topLeft, topRight, bottomLeft, bottomRight]` */
|
|
126
|
+
export type XpAutotilePattern = readonly [number, number, number, number];
|
|
127
|
+
/**
|
|
128
|
+
* The standard XP autotile pattern table (48 patterns). An XP autotile image
|
|
129
|
+
* is a 96 by 128 template: a 6-column grid of 16px mini-blocks, and each
|
|
130
|
+
* baked pattern assembles four of them. `tile % 48` selects the pattern;
|
|
131
|
+
* `tile / 48` (floored) selects which of the map's autotile images.
|
|
132
|
+
*
|
|
133
|
+
* Miniblock entries are 0-based here (block `n` sits at `(n % 6) * 16`,
|
|
134
|
+
* `(n / 6) * 16`). Learned from real XP autotile images and map data rather
|
|
135
|
+
* than assumed: the 6 by 8 mini-grid fits the measured 96 by 128 template
|
|
136
|
+
* exactly, and the neighbor table below reproduces baked map patterns.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* import { XP_AUTOTILE_PATTERNS, XP_NEIGHBORS_TO_PATTERN } from '@datamoc/mw_games/two-d/render';
|
|
141
|
+
*
|
|
142
|
+
* console.log(XP_AUTOTILE_PATTERNS.length); // 48 - one entry per baked pattern
|
|
143
|
+
* console.log(XP_AUTOTILE_PATTERNS[0]); // [26,27,32,33] - the filled interior tile
|
|
144
|
+
* console.log(XP_NEIGHBORS_TO_PATTERN.length); // 256 - one entry per 8-neighbour mask
|
|
145
|
+
* console.log(XP_NEIGHBORS_TO_PATTERN[255]); // 0 - surrounded on all sides is the interior
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
export declare const XP_AUTOTILE_PATTERNS: readonly XpAutotilePattern[];
|
|
149
|
+
/**
|
|
150
|
+
* Which XP pattern an 8-neighbourhood of same-autotile cells bakes to. Index
|
|
151
|
+
* with a bit mask - north `0x01`, northeast `0x02`, east `0x04`, southeast
|
|
152
|
+
* `0x08`, south `0x10`, southwest `0x20`, west `0x40`, northwest `0x80` - for
|
|
153
|
+
* games computing patterns procedurally instead of reading baked map data.
|
|
154
|
+
*/
|
|
155
|
+
export declare const XP_NEIGHBORS_TO_PATTERN: readonly number[];
|
|
156
|
+
/** an XP map cell decoded into its autotile image and baked pattern */
|
|
157
|
+
export interface XpAutotileRef {
|
|
158
|
+
/** which autotile image, 0-7 (`tile / 48` floored) */
|
|
159
|
+
index: number;
|
|
160
|
+
/** which pattern in that image, 0-47 (`tile % 48`) */
|
|
161
|
+
pattern: number;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Decodes a raw XP map cell into its autotile image and pattern, or null
|
|
165
|
+
* when the cell holds no autotile reference: `EMPTY`, a static tileset tile
|
|
166
|
+
* (384 and up), or anything outside the 1-383 autotile range.
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* import { xpAutotileRef } from '@datamoc/mw_games/two-d/render';
|
|
171
|
+
*
|
|
172
|
+
* console.log(xpAutotileRef(97)); // { index: 2, pattern: 1 } - second image, second pattern
|
|
173
|
+
* console.log(xpAutotileRef(0)); // null - EMPTY is blank, never an autotile
|
|
174
|
+
* console.log(xpAutotileRef(384)); // null - the first static tileset tile
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export declare function xpAutotileRef(tile: number): XpAutotileRef | null;
|
|
178
|
+
/**
|
|
179
|
+
* Which XP pattern a cell's 8-neighbourhood bakes to, for maps computed
|
|
180
|
+
* procedurally rather than read from baked data. `sameTerrain` is asked once
|
|
181
|
+
* per direction, with `(dx, dy)` offsets (`(0, -1)` is north); off the map is
|
|
182
|
+
* the caller's to answer (false reads as a border, the edge cell's own value
|
|
183
|
+
* clamps like the editor).
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* import { xpAutotilePattern } from '@datamoc/mw_games/two-d/render';
|
|
188
|
+
*
|
|
189
|
+
* const filled = new Set(['0,0', '1,0', '0,1', '1,1', '-1,0', '0,-1', '2,1', '1,2']);
|
|
190
|
+
* console.log(xpAutotilePattern((dx, dy) => filled.has(`${dx},${dy}`))); // 0 - the interior
|
|
191
|
+
* console.log(xpAutotilePattern(() => false)); // 46 - isolated on all sides
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
export declare function xpAutotilePattern(sameTerrain: (dx: number, dy: number) => boolean): number;
|
|
195
|
+
/**
|
|
196
|
+
* One drawn piece of an autotile cell: where to sample the source sheet and
|
|
197
|
+
* where the piece lands on the map tile, the destination in fractions of one
|
|
198
|
+
* tile (quadrant halves at `0`/`0.5` with size `0.5`, or the whole tile at
|
|
199
|
+
* `0` with size `1` for single-tile strips).
|
|
200
|
+
*/
|
|
201
|
+
export interface AutotileCellPart {
|
|
202
|
+
sourceX: number;
|
|
203
|
+
sourceY: number;
|
|
204
|
+
sourceWidth: number;
|
|
205
|
+
sourceHeight: number;
|
|
206
|
+
destX: number;
|
|
207
|
+
destY: number;
|
|
208
|
+
destWidth: number;
|
|
209
|
+
destHeight: number;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* An autotile source fully described: everything `autotileCellParts` needs
|
|
213
|
+
* except the sheet texture itself (which lives renderer-side, in the layer).
|
|
214
|
+
* `TileMap.addAutotileLayer` resolves a user-facing `AutotileSet` into one
|
|
215
|
+
* of these and validates it once with `assertAutotileLayout`, so per-cell
|
|
216
|
+
* resolution never re-checks the table.
|
|
217
|
+
*/
|
|
218
|
+
export type AutotileLayout = {
|
|
219
|
+
format: 'rpgm-mv';
|
|
220
|
+
slot: RpgmAutotileSlot;
|
|
221
|
+
table: RpgmAutotileShapeTable;
|
|
222
|
+
/** kind runs that advance together; a cell whose kind is in no run ignores the frame */
|
|
223
|
+
cycles: ReadonlyArray<ReadonlyArray<number>>;
|
|
224
|
+
} | {
|
|
225
|
+
format: 'rpgm-xp';
|
|
226
|
+
/** which autotile image, 0-7 */
|
|
227
|
+
index: number;
|
|
228
|
+
/** animation stripes in the image; frame wraps around this count */
|
|
229
|
+
frames: number;
|
|
230
|
+
/** a 32px-tall single-tile strip: one whole-tile piece per frame, patterns ignored */
|
|
231
|
+
single: boolean;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Checks a resolved autotile layout once, up front. Throws naming the first
|
|
235
|
+
* problem: a bad slot, an empty shape table, an empty animation cycle, a
|
|
236
|
+
* cycle kind outside its slot's kinds, a bad XP index, or a frame count
|
|
237
|
+
* below one.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* import {
|
|
242
|
+
* assertAutotileLayout,
|
|
243
|
+
* RPGM_FLOOR_AUTOTILE_TABLE,
|
|
244
|
+
* } from '@datamoc/mw_games/two-d/render';
|
|
245
|
+
*
|
|
246
|
+
* assertAutotileLayout({ format: 'rpgm-mv', slot: 0, table: RPGM_FLOOR_AUTOTILE_TABLE, cycles: [[0, 1, 2]] });
|
|
247
|
+
* assertAutotileLayout({ format: 'rpgm-xp', index: 2, frames: 1, single: false });
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export declare function assertAutotileLayout(layout: AutotileLayout): void;
|
|
251
|
+
/**
|
|
252
|
+
* Resolves one autotile cell to its drawn pieces: four quadrant halves for a
|
|
253
|
+
* template cell, one whole-tile piece for an XP single-tile strip, or null
|
|
254
|
+
* for a blank cell (`tile <= 0` reads as blank; `EMPTY` is -1).
|
|
255
|
+
*
|
|
256
|
+
* The layout is assumed valid (`assertAutotileLayout`); only the cell and
|
|
257
|
+
* frame are checked here. `tile` must be an integer the layout claims - an
|
|
258
|
+
* MV id in the layout's slot range, an XP id in `index * 48` to
|
|
259
|
+
* `index * 48 + 47` - and `frame` an integer at or above zero, wrapping
|
|
260
|
+
* around the animation cycles (MV) or frame stripes (XP).
|
|
261
|
+
*
|
|
262
|
+
* @example
|
|
263
|
+
* ```ts
|
|
264
|
+
* import {
|
|
265
|
+
* autotileCellParts,
|
|
266
|
+
* RPGM_FLOOR_AUTOTILE_TABLE,
|
|
267
|
+
* } from '@datamoc/mw_games/two-d/render';
|
|
268
|
+
*
|
|
269
|
+
* const parts = autotileCellParts(
|
|
270
|
+
* { format: 'rpgm-mv', slot: 0, table: RPGM_FLOOR_AUTOTILE_TABLE, cycles: [] },
|
|
271
|
+
* 2048, 0,
|
|
272
|
+
* );
|
|
273
|
+
* console.log(parts?.length); // 4 - one piece per quadrant
|
|
274
|
+
* console.log(parts?.[0].sourceWidth); // 24 - MV quadrant halves
|
|
275
|
+
* console.log(autotileCellParts(
|
|
276
|
+
* { format: 'rpgm-xp', index: 2, frames: 1, single: false },
|
|
277
|
+
* 97, 0,
|
|
278
|
+
* )?.[0].sourceWidth); // 16 - XP quadrant halves
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
export declare function autotileCellParts(layout: AutotileLayout, tile: number, frame: number): AutotileCellPart[] | null;
|
|
65
282
|
//# sourceMappingURL=RpgmAutotile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RpgmAutotile.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/RpgmAutotile.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAE7C,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACrB;AAED,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,SAAS,CAAC,oBAAoB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,oBAAoB,CAAC,CAAC;CAC7G;AAED,6EAA6E;AAC7E,MAAM,MAAM,iBAAiB,GAAG,SAAS;IACxC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,SAAS,iBAAiB,EAAE,CAAC;AA2ClE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,sBAAsB,GAC3B,iBAAiB,CAqBnB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAwC;IAC9D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAE/C,YAAY,KAAK,EAAE,sBAAsB,EAGxC;IAED,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,CAO5E;IAED,KAAK,IAAI,IAAI,CAEZ;CACD"}
|
|
1
|
+
{"version":3,"file":"RpgmAutotile.d.ts","sourceRoot":"","sources":["../../../src/two-d/render/RpgmAutotile.ts"],"names":[],"mappings":"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"}
|