@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.
Files changed (139) hide show
  1. package/CHANGELOG.md +154 -1
  2. package/README.md +21 -1
  3. package/dist/ai/lua.d.ts.map +1 -1
  4. package/dist/ai/lua.js +1 -0
  5. package/dist/ai/lua.js.map +1 -1
  6. package/dist/core/ActionJournal.d.ts +5 -0
  7. package/dist/core/ActionJournal.d.ts.map +1 -1
  8. package/dist/core/ActionJournal.js +12 -1
  9. package/dist/core/ActionJournal.js.map +1 -1
  10. package/dist/core/Clone.d.ts +31 -0
  11. package/dist/core/Clone.d.ts.map +1 -0
  12. package/dist/core/Clone.js +84 -0
  13. package/dist/core/Clone.js.map +1 -0
  14. package/dist/core/Collection.d.ts +1 -0
  15. package/dist/core/Collection.d.ts.map +1 -1
  16. package/dist/core/Collection.js +6 -2
  17. package/dist/core/Collection.js.map +1 -1
  18. package/dist/core/HttpTransport.d.ts +17 -0
  19. package/dist/core/HttpTransport.d.ts.map +1 -1
  20. package/dist/core/HttpTransport.js +61 -0
  21. package/dist/core/HttpTransport.js.map +1 -1
  22. package/dist/core/Multiplayer.d.ts +9 -0
  23. package/dist/core/Multiplayer.d.ts.map +1 -1
  24. package/dist/core/Multiplayer.js +48 -4
  25. package/dist/core/Multiplayer.js.map +1 -1
  26. package/dist/core/News.d.ts.map +1 -1
  27. package/dist/core/News.js +1 -2
  28. package/dist/core/News.js.map +1 -1
  29. package/dist/core/Sanitize.d.ts +19 -0
  30. package/dist/core/Sanitize.d.ts.map +1 -1
  31. package/dist/core/Sanitize.js +37 -0
  32. package/dist/core/Sanitize.js.map +1 -1
  33. package/dist/core/Save.d.ts +18 -9
  34. package/dist/core/Save.d.ts.map +1 -1
  35. package/dist/core/Save.js +37 -21
  36. package/dist/core/Save.js.map +1 -1
  37. package/dist/core/SaveSync.js +4 -4
  38. package/dist/core/SaveSync.js.map +1 -1
  39. package/dist/core/Settings.d.ts.map +1 -1
  40. package/dist/core/Settings.js +2 -1
  41. package/dist/core/Settings.js.map +1 -1
  42. package/dist/core/State.d.ts.map +1 -1
  43. package/dist/core/State.js +8 -7
  44. package/dist/core/State.js.map +1 -1
  45. package/dist/core/StoredValue.d.ts +1 -1
  46. package/dist/core/StoredValue.d.ts.map +1 -1
  47. package/dist/core/StoredValue.js +3 -2
  48. package/dist/core/StoredValue.js.map +1 -1
  49. package/dist/core/Telemetry.d.ts +19 -1
  50. package/dist/core/Telemetry.d.ts.map +1 -1
  51. package/dist/core/Telemetry.js +26 -1
  52. package/dist/core/Telemetry.js.map +1 -1
  53. package/dist/core/index.d.ts +2 -1
  54. package/dist/core/index.d.ts.map +1 -1
  55. package/dist/core/index.js +2 -1
  56. package/dist/core/index.js.map +1 -1
  57. package/dist/mw_games.global.js +107 -107
  58. package/dist/mwl/MapFile.js +11 -1
  59. package/dist/mwl/MapFile.js.map +1 -1
  60. package/dist/mwl/expression.js +38 -5
  61. package/dist/mwl/expression.js.map +1 -1
  62. package/dist/mwl/fengari.d.ts +8 -0
  63. package/dist/mwl/fengari.d.ts.map +1 -1
  64. package/dist/mwl/fengari.js +72 -2
  65. package/dist/mwl/fengari.js.map +1 -1
  66. package/dist/mwl/persistence.d.ts.map +1 -1
  67. package/dist/mwl/persistence.js +2 -1
  68. package/dist/mwl/persistence.js.map +1 -1
  69. package/dist/mwl/runtime.d.ts.map +1 -1
  70. package/dist/mwl/runtime.js +6 -1
  71. package/dist/mwl/runtime.js.map +1 -1
  72. package/dist/rpg/Marshal.d.ts.map +1 -1
  73. package/dist/rpg/Marshal.js +13 -0
  74. package/dist/rpg/Marshal.js.map +1 -1
  75. package/dist/simulation/Campaign.d.ts.map +1 -1
  76. package/dist/simulation/Campaign.js +9 -5
  77. package/dist/simulation/Campaign.js.map +1 -1
  78. package/dist/simulation/Harness.d.ts.map +1 -1
  79. package/dist/simulation/Harness.js +2 -1
  80. package/dist/simulation/Harness.js.map +1 -1
  81. package/dist/simulation/Runtime.d.ts +10 -0
  82. package/dist/simulation/Runtime.d.ts.map +1 -1
  83. package/dist/simulation/Runtime.js +25 -4
  84. package/dist/simulation/Runtime.js.map +1 -1
  85. package/dist/testing/index.d.ts +105 -0
  86. package/dist/testing/index.d.ts.map +1 -0
  87. package/dist/testing/index.js +134 -0
  88. package/dist/testing/index.js.map +1 -0
  89. package/dist/two-d/render/RpgmAutotile.d.ts +217 -0
  90. package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -1
  91. package/dist/two-d/render/RpgmAutotile.js +756 -0
  92. package/dist/two-d/render/RpgmAutotile.js.map +1 -1
  93. package/dist/two-d/render/TileMap.d.ts +90 -0
  94. package/dist/two-d/render/TileMap.d.ts.map +1 -1
  95. package/dist/two-d/render/TileMap.js +319 -31
  96. package/dist/two-d/render/TileMap.js.map +1 -1
  97. package/dist/two-d/render/index.d.ts +3 -3
  98. package/dist/two-d/render/index.d.ts.map +1 -1
  99. package/dist/two-d/render/index.js +1 -1
  100. package/dist/two-d/render/index.js.map +1 -1
  101. package/dist/version.d.ts +1 -1
  102. package/dist/version.js +1 -1
  103. package/package.json +90 -25
  104. package/sbom.cdx.json +5589 -0
  105. package/tools/benchmark-browser.d.mts +33 -0
  106. package/tools/benchmark-browser.mjs +163 -0
  107. package/tools/benchmark-history.d.mts +8 -0
  108. package/tools/benchmark-history.mjs +31 -0
  109. package/tools/browser-smoke.d.mts +30 -0
  110. package/tools/browser-smoke.mjs +167 -0
  111. package/tools/bundle-size.d.mts +11 -0
  112. package/tools/bundle-size.mjs +138 -0
  113. package/tools/csp.d.mts +7 -0
  114. package/tools/csp.mjs +56 -0
  115. package/tools/emit-page.d.mts +44 -0
  116. package/tools/emit-page.mjs +188 -0
  117. package/tools/extract-rgssad.d.mts +5 -0
  118. package/tools/extract-rgssad.mjs +64 -0
  119. package/tools/find-chrome.d.mts +7 -0
  120. package/tools/find-chrome.mjs +104 -0
  121. package/tools/i18n-edit.d.mts +29 -0
  122. package/tools/i18n-edit.mjs +748 -0
  123. package/tools/make-example-assets.d.mts +2 -0
  124. package/tools/make-example-assets.mjs +727 -0
  125. package/tools/multiplayer-server.d.mts +27 -0
  126. package/tools/multiplayer-server.mjs +195 -0
  127. package/tools/mwl.mjs +1 -0
  128. package/tools/sbom.d.mts +83 -0
  129. package/tools/sbom.mjs +330 -0
  130. package/tools/vendored/rgssad-wasm/LICENSE-MIT +21 -0
  131. package/tools/vendored/rgssad-wasm/README.md +15 -0
  132. package/tools/vendored/rgssad-wasm/package.json +17 -0
  133. package/tools/vendored/rgssad-wasm/rgssad_wasm.d.ts +41 -0
  134. package/tools/vendored/rgssad-wasm/rgssad_wasm.js +6 -0
  135. package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.js +399 -0
  136. package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm +0 -0
  137. package/tools/vendored/rgssad-wasm/rgssad_wasm_bg.wasm.d.ts +17 -0
  138. package/tools/vite.d.mts +17 -0
  139. 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
- historySnapshot() {
208
- return structuredClone(this.snapshot());
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":"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;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,YAAI,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,YAAI,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAWtE;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,yBAAyB,EAAE,sBAiSvC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,EAAE,sBAiGtC,CAAC;AAEF,sHAAsH;AACtH,MAAM,MAAM,iBAAiB,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,iBAAiB,EAiD5D,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,MAAM,EAUpD,CAAC;AAEF,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC7B,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAGhE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,CAW1F;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GACvB;IACA,MAAM,EAAE,SAAS,CAAC;IAClB,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,sBAAsB,CAAC;IAC9B,wFAAwF;IACxF,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;CAC5C,GACD;IACA,MAAM,EAAE,SAAS,CAAC;IAClB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,MAAM,EAAE,OAAO,CAAC;CACf,CAAC;AAKL;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAwBjE;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,IAAI,CAOhH"}