@datamoc/mw_games 0.2.0 → 0.3.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.
Files changed (97) hide show
  1. package/README.md +395 -352
  2. package/dist/assets/Streaming.d.ts +10 -4
  3. package/dist/assets/Streaming.d.ts.map +1 -1
  4. package/dist/assets/Streaming.js +17 -6
  5. package/dist/assets/Streaming.js.map +1 -1
  6. package/dist/assets/index.d.ts +10 -2
  7. package/dist/assets/index.d.ts.map +1 -1
  8. package/dist/assets/index.js +8 -4
  9. package/dist/assets/index.js.map +1 -1
  10. package/dist/audio/Music.d.ts +10 -0
  11. package/dist/audio/Music.d.ts.map +1 -1
  12. package/dist/audio/Music.js +41 -3
  13. package/dist/audio/Music.js.map +1 -1
  14. package/dist/audio/Playable.d.ts +3 -0
  15. package/dist/audio/Playable.d.ts.map +1 -1
  16. package/dist/audio/Playable.js.map +1 -1
  17. package/dist/audio/Sound.d.ts.map +1 -1
  18. package/dist/audio/Sound.js +4 -1
  19. package/dist/audio/Sound.js.map +1 -1
  20. package/dist/audio/Synth.d.ts.map +1 -1
  21. package/dist/audio/Synth.js +3 -1
  22. package/dist/audio/Synth.js.map +1 -1
  23. package/dist/core/Feedback.d.ts +3 -9
  24. package/dist/core/Feedback.d.ts.map +1 -1
  25. package/dist/core/Feedback.js +6 -18
  26. package/dist/core/Feedback.js.map +1 -1
  27. package/dist/core/HttpTransport.d.ts +22 -0
  28. package/dist/core/HttpTransport.d.ts.map +1 -0
  29. package/dist/core/HttpTransport.js +33 -0
  30. package/dist/core/HttpTransport.js.map +1 -0
  31. package/dist/core/Multiplayer.d.ts +63 -0
  32. package/dist/core/Multiplayer.d.ts.map +1 -0
  33. package/dist/core/Multiplayer.js +73 -0
  34. package/dist/core/Multiplayer.js.map +1 -0
  35. package/dist/core/SaveSync.d.ts +17 -14
  36. package/dist/core/SaveSync.d.ts.map +1 -1
  37. package/dist/core/SaveSync.js +35 -31
  38. package/dist/core/SaveSync.js.map +1 -1
  39. package/dist/core/Stats.d.ts +33 -0
  40. package/dist/core/Stats.d.ts.map +1 -0
  41. package/dist/core/Stats.js +34 -0
  42. package/dist/core/Stats.js.map +1 -0
  43. package/dist/core/Telemetry.d.ts +34 -0
  44. package/dist/core/Telemetry.d.ts.map +1 -0
  45. package/dist/core/Telemetry.js +47 -0
  46. package/dist/core/Telemetry.js.map +1 -0
  47. package/dist/core/index.d.ts +6 -0
  48. package/dist/core/index.d.ts.map +1 -1
  49. package/dist/core/index.js +3 -0
  50. package/dist/core/index.js.map +1 -1
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +1 -0
  54. package/dist/index.js.map +1 -1
  55. package/dist/mw_games.global.js +10 -9
  56. package/dist/render/Camera.d.ts.map +1 -1
  57. package/dist/render/Camera.js +4 -2
  58. package/dist/render/Camera.js.map +1 -1
  59. package/dist/render/StatusVisuals.d.ts +46 -0
  60. package/dist/render/StatusVisuals.d.ts.map +1 -0
  61. package/dist/render/StatusVisuals.js +48 -0
  62. package/dist/render/StatusVisuals.js.map +1 -0
  63. package/dist/render/index.d.ts +2 -0
  64. package/dist/render/index.d.ts.map +1 -1
  65. package/dist/render/index.js +1 -0
  66. package/dist/render/index.js.map +1 -1
  67. package/dist/simulation/Scenario.d.ts +29 -0
  68. package/dist/simulation/Scenario.d.ts.map +1 -0
  69. package/dist/simulation/Scenario.js +25 -0
  70. package/dist/simulation/Scenario.js.map +1 -0
  71. package/dist/simulation/Turns.d.ts +29 -0
  72. package/dist/simulation/Turns.d.ts.map +1 -0
  73. package/dist/simulation/Turns.js +30 -0
  74. package/dist/simulation/Turns.js.map +1 -0
  75. package/dist/simulation/index.d.ts +5 -0
  76. package/dist/simulation/index.d.ts.map +1 -0
  77. package/dist/simulation/index.js +3 -0
  78. package/dist/simulation/index.js.map +1 -0
  79. package/dist/ui/Button.d.ts +18 -1
  80. package/dist/ui/Button.d.ts.map +1 -1
  81. package/dist/ui/Button.js +15 -5
  82. package/dist/ui/Button.js.map +1 -1
  83. package/dist/ui/Label.d.ts +8 -0
  84. package/dist/ui/Label.d.ts.map +1 -1
  85. package/dist/ui/Label.js +3 -0
  86. package/dist/ui/Label.js.map +1 -1
  87. package/dist/ui/StatsScreen.d.ts +25 -0
  88. package/dist/ui/StatsScreen.d.ts.map +1 -0
  89. package/dist/ui/StatsScreen.js +27 -0
  90. package/dist/ui/StatsScreen.js.map +1 -0
  91. package/dist/ui/index.d.ts +3 -1
  92. package/dist/ui/index.d.ts.map +1 -1
  93. package/dist/ui/index.js +1 -0
  94. package/dist/ui/index.js.map +1 -1
  95. package/dist/version.d.ts +1 -1
  96. package/dist/version.js +1 -1
  97. package/package.json +147 -112
@@ -1,3 +1,4 @@
1
+ import type { AssetProgress } from './index.ts';
1
2
  export interface AssetBundle {
2
3
  id: string;
3
4
  paths: readonly string[];
@@ -7,7 +8,7 @@ export interface AssetBundle {
7
8
  }
8
9
  export interface AssetStreamOptions {
9
10
  budgetBytes?: number;
10
- load?: (paths: string[]) => Promise<void>;
11
+ load?: (paths: string[], onProgress?: AssetProgress) => Promise<void>;
11
12
  release?: (paths: string[]) => Promise<void>;
12
13
  }
13
14
  /**
@@ -25,9 +26,14 @@ export declare class AssetStream {
25
26
  private clock;
26
27
  constructor(options?: AssetStreamOptions);
27
28
  /** loads one bundle now, then evicts older ready bundles if its budget requires it */
28
- preload(bundle: AssetBundle): Promise<void>;
29
- /** preloads bundles in highest-priority-first order; callers may intentionally not await it */
30
- preloadLikely(bundles: readonly AssetBundle[]): Promise<void>;
29
+ preload(bundle: AssetBundle, onProgress?: AssetProgress): Promise<void>;
30
+ /**
31
+ * Preloads bundles in highest-priority-first order; callers may intentionally not await it.
32
+ * `onProgress`, when given, reports overall fraction across every bundle in `bundles` (each
33
+ * one weighted equally), for a caller that wants one progress figure across the whole list
34
+ * rather than per-bundle callbacks of its own.
35
+ */
36
+ preloadLikely(bundles: readonly AssetBundle[], onProgress?: AssetProgress): Promise<void>;
31
37
  /** marks a ready bundle as recently used at the moment a scene adopts it */
32
38
  use(id: string): boolean;
33
39
  isReady(id: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../src/assets/Streaming.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAOD;;;;;;GAMG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqC;IAChE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,KAAK,CAAK;IAElB,YAAY,OAAO,GAAE,kBAAuB,EAK3C;IAED,sFAAsF;IAChF,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhD;IAED,+FAA+F;IACzF,aAAa,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAElE;IAED,4EAA4E;IAC5E,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKvB;IAED,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE3B;IAED,8EAA8E;IACxE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtC;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;YAEa,aAAa;IAU3B,OAAO,CAAC,UAAU;CAGlB"}
1
+ {"version":3,"file":"Streaming.d.ts","sourceRoot":"","sources":["../../src/assets/Streaming.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,kBAAkB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7C;AAOD;;;;;;GAMG;AACH,qBAAa,WAAW;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiE;IAC5F,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,KAAK,CAAK;IAElB,YAAY,OAAO,GAAE,kBAAuB,EAK3C;IAED,sFAAsF;IAChF,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAc5E;IAED;;;;;OAKG;IACG,aAAa,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAM9F;IAED,4EAA4E;IAC5E,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAKvB;IAED,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE3B;IAED,8EAA8E;IACxE,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtC;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;YAEa,aAAa;IAU3B,OAAO,CAAC,UAAU;CAGlB"}
@@ -17,7 +17,7 @@ export class AssetStream {
17
17
  this.releaseAssets = options.release ?? release;
18
18
  }
19
19
  /** loads one bundle now, then evicts older ready bundles if its budget requires it */
20
- async preload(bundle) {
20
+ async preload(bundle, onProgress) {
21
21
  if (!bundle.id)
22
22
  throw new Error('asset bundle needs an id');
23
23
  if (bundle.estimatedBytes !== undefined && bundle.estimatedBytes < 0)
@@ -25,18 +25,29 @@ export class AssetStream {
25
25
  const existing = this.entries.get(bundle.id);
26
26
  if (existing?.ready) {
27
27
  existing.lastUsed = ++this.clock;
28
+ onProgress?.(1);
28
29
  return;
29
30
  }
30
31
  const paths = bundle.paths.filter((path) => !this.isRetained(path));
31
32
  if (paths.length > 0)
32
- await this.loadAssets([...paths]);
33
+ await this.loadAssets([...paths], onProgress);
34
+ else
35
+ onProgress?.(1);
33
36
  this.entries.set(bundle.id, { ...bundle, lastUsed: ++this.clock, ready: true });
34
37
  await this.enforceBudget(bundle.id);
35
38
  }
36
- /** preloads bundles in highest-priority-first order; callers may intentionally not await it */
37
- async preloadLikely(bundles) {
38
- for (const bundle of [...bundles].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0)))
39
- await this.preload(bundle);
39
+ /**
40
+ * Preloads bundles in highest-priority-first order; callers may intentionally not await it.
41
+ * `onProgress`, when given, reports overall fraction across every bundle in `bundles` (each
42
+ * one weighted equally), for a caller that wants one progress figure across the whole list
43
+ * rather than per-bundle callbacks of its own.
44
+ */
45
+ async preloadLikely(bundles, onProgress) {
46
+ const ordered = [...bundles].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
47
+ for (const [index, bundle] of ordered.entries()) {
48
+ await this.preload(bundle, onProgress && ((fraction) => onProgress((index + fraction) / ordered.length)));
49
+ }
50
+ onProgress?.(1);
40
51
  }
41
52
  /** marks a ready bundle as recently used at the moment a scene adopts it */
42
53
  use(id) {
@@ -1 +1 @@
1
- {"version":3,"file":"Streaming.js","sourceRoot":"","sources":["../../src/assets/Streaming.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Streaming.js","sourceRoot":"","sources":["../../src/assets/Streaming.ts"],"names":[],"mappings":"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"}
@@ -23,13 +23,21 @@ export declare function paths(): string[];
23
23
  export declare function has(path: string): boolean;
24
24
  /** an asset path resolved to something the browser can actually load */
25
25
  export declare function resolve(path: string): string;
26
+ /**
27
+ * 0 (started) to 1 (complete) - a count of assets finished, not a byte count. Pixi's own
28
+ * loaders do not expose bytes transferred across every asset type uniformly, so this reports
29
+ * what is actually available rather than a byte figure it cannot back with a real number.
30
+ */
31
+ export type AssetProgress = (fraction: number) => void;
26
32
  /**
27
33
  * Loads assets by path, giving each one an alias equal to its path.
28
34
  *
29
35
  * Load everything a scene needs before creating it; afterwards `texture()` is synchronous,
30
- * so game code never has to await in the middle of building a scene.
36
+ * so game code never has to await in the middle of building a scene. `onProgress`, when
37
+ * given, is item 135's `LoadQueue`/`LoadingScreen` seam for a task that would otherwise only
38
+ * ever report 0 then 1 around one opaque `await`.
31
39
  */
32
- export declare function load(paths: string[]): Promise<void>;
40
+ export declare function load(paths: string[], onProgress?: AssetProgress): Promise<void>;
33
41
  /** a loaded texture, by the same path it was loaded with */
34
42
  export declare function texture(path: string): Texture;
35
43
  /** a loaded asset of any other kind, such as parsed JSON */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;;;;;;GAUG;AAEH,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,MAAM;QACf,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACxC;CACD;AAKD,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1C;AAMD,2EAA2E;AAC3E,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,KAAK,IAAI,MAAM,EAAE,CAEhC;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGzC;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5C;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQzD;AAED,4DAA4D;AAC5D,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7C;AAED,4DAA4D;AAC5D,wBAAgB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAKtC;AAED,uFAAuF;AACvF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5D;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;;;;;;;GAUG;AAEH,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,MAAM;QACf,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACxC;CACD;AAKD,mEAAmE;AACnE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1C;AAMD,2EAA2E;AAC3E,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAED,wBAAgB,KAAK,IAAI,MAAM,EAAE,CAEhC;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGzC;AAED,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAW5C;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvD;;;;;;;GAOG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAWrF;AAED,4DAA4D;AAC5D,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAK7C;AAED,4DAA4D;AAC5D,wBAAgB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,CAKtC;AAED,uFAAuF;AACvF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C;AAED;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5D;AAED,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -34,16 +34,20 @@ export function resolve(path) {
34
34
  * Loads assets by path, giving each one an alias equal to its path.
35
35
  *
36
36
  * Load everything a scene needs before creating it; afterwards `texture()` is synchronous,
37
- * so game code never has to await in the middle of building a scene.
37
+ * so game code never has to await in the middle of building a scene. `onProgress`, when
38
+ * given, is item 135's `LoadQueue`/`LoadingScreen` seam for a task that would otherwise only
39
+ * ever report 0 then 1 around one opaque `await`.
38
40
  */
39
- export async function load(paths) {
41
+ export async function load(paths, onProgress) {
40
42
  const pending = paths.filter((path) => !Assets.cache.has(path));
41
- if (pending.length === 0)
43
+ if (pending.length === 0) {
44
+ onProgress?.(1);
42
45
  return;
46
+ }
43
47
  for (const path of pending) {
44
48
  Assets.add({ alias: path, src: resolve(path) });
45
49
  }
46
- await Assets.load(pending);
50
+ await Assets.load(pending, onProgress);
47
51
  }
48
52
  /** a loaded texture, by the same path it was loaded with */
49
53
  export function texture(path) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/assets/index.ts"],"names":[],"mappings":"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"}
@@ -12,10 +12,20 @@ export declare class Music {
12
12
  private current;
13
13
  private fades;
14
14
  private create;
15
+ private trackQueue;
16
+ private playlistFade;
15
17
  volume: number;
16
18
  constructor(options?: MusicOptions);
17
19
  /** @param fadeDuration seconds; 0 switches immediately with no crossfade */
18
20
  play(path: string, fadeDuration?: number): void;
21
+ /**
22
+ * Plays the supplied sequence repeatedly. This is deliberately small and backend-agnostic:
23
+ * callers can repeat entries to weight a track, while HTMLAudioElement's optional `onended`
24
+ * advances the queue when available.
25
+ */
26
+ playTracks(paths: readonly string[], fadeDuration?: number): void;
27
+ private startNextTrack;
28
+ private start;
19
29
  stop(fadeDuration?: number): void;
20
30
  update(dt: number): void;
21
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Music.d.ts","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW3D,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC;CACpC;AAED;;;;GAIG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAA6B;IAC3C,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,OAAO,GAAE,YAAiB,EAGrC;IAED,4EAA4E;IAC5E,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,IAAI,CA4BzC;IAED,IAAI,CAAC,YAAY,SAAI,GAAG,IAAI,CAU3B;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAevB;CACD"}
1
+ {"version":3,"file":"Music.d.ts","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW3D,MAAM,WAAW,YAAY;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC;CACpC;AAED;;;;GAIG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,YAAY,CAAK;IACzB,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,OAAO,GAAE,YAAiB,EAGrC;IAED,4EAA4E;IAC5E,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,SAAI,GAAG,IAAI,CAGzC;IAED;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,YAAY,SAAI,GAAG,IAAI,CAQ3D;IAED,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,KAAK;IAuCb,IAAI,CAAC,YAAY,SAAI,GAAG,IAAI,CAW3B;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAevB;CACD"}
@@ -8,23 +8,60 @@ export class Music {
8
8
  constructor(options = {}) {
9
9
  this.current = null;
10
10
  this.fades = [];
11
+ this.trackQueue = null;
12
+ this.playlistFade = 1;
11
13
  this.volume = options.volume ?? 1;
12
14
  this.create = options.create ?? createAudio;
13
15
  }
14
16
  /** @param fadeDuration seconds; 0 switches immediately with no crossfade */
15
17
  play(path, fadeDuration = 1) {
18
+ this.trackQueue = null;
19
+ this.start(path, fadeDuration, true);
20
+ }
21
+ /**
22
+ * Plays the supplied sequence repeatedly. This is deliberately small and backend-agnostic:
23
+ * callers can repeat entries to weight a track, while HTMLAudioElement's optional `onended`
24
+ * advances the queue when available.
25
+ */
26
+ playTracks(paths, fadeDuration = 1) {
27
+ if (paths.length === 0) {
28
+ this.stop(fadeDuration);
29
+ return;
30
+ }
31
+ this.trackQueue = [...paths];
32
+ this.playlistFade = fadeDuration;
33
+ this.startNextTrack();
34
+ }
35
+ startNextTrack() {
36
+ if (!this.trackQueue?.length)
37
+ return;
38
+ const path = this.trackQueue.shift();
39
+ this.trackQueue.push(path);
40
+ this.start(path, this.playlistFade, false);
41
+ }
42
+ start(path, fadeDuration, loop) {
16
43
  const incoming = this.create(path);
17
- incoming.loop = true;
44
+ incoming.loop = loop;
45
+ if (!loop && incoming.onended !== undefined) {
46
+ // A delayed event from a fading-out track must not advance a newer playlist.
47
+ incoming.onended = () => {
48
+ if (this.current === incoming)
49
+ this.startNextTrack();
50
+ };
51
+ }
18
52
  const previous = this.current;
19
53
  this.current = incoming;
20
54
  if (fadeDuration <= 0) {
21
55
  incoming.volume = this.volume;
22
- void incoming.play();
56
+ // a rejection here means the switch itself (or the previous.pause() right below)
57
+ // interrupted this play()'s own in-flight load - expected during a track switch,
58
+ // so swallow it the standard way rather than let it surface as unhandled.
59
+ void Promise.resolve(incoming.play()).catch(() => { });
23
60
  previous?.pause();
24
61
  return;
25
62
  }
26
63
  incoming.volume = 0;
27
- void incoming.play();
64
+ void Promise.resolve(incoming.play()).catch(() => { });
28
65
  this.fades.push({ audio: incoming, elapsed: 0, duration: fadeDuration, from: 0, to: this.volume, stopAtEnd: false });
29
66
  if (previous) {
30
67
  this.fades.push({
@@ -38,6 +75,7 @@ export class Music {
38
75
  }
39
76
  }
40
77
  stop(fadeDuration = 1) {
78
+ this.trackQueue = null;
41
79
  const audio = this.current;
42
80
  if (!audio)
43
81
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"Music.js","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAgB3D;;;;GAIG;AACH,MAAM,OAAO,KAAK;IAMjB,YAAY,OAAO,GAAiB,EAAE;QAL9B,YAAO,GAAoB,IAAI,CAAC;QAChC,UAAK,GAAW,EAAE,CAAC;QAK1B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC;IAC7C,CAAC;IAED,4EAA4E;IAC5E,IAAI,CAAC,IAAY,EAAE,YAAY,GAAG,CAAC;QAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnC,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;QAErB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;QAExB,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC9B,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;YACrB,QAAQ,EAAE,KAAK,EAAE,CAAC;YAClB,OAAO;QACR,CAAC;QAED,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QACpB,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QAErH,IAAI,QAAQ,EAAE,CAAC;YACd,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBACf,KAAK,EAAE,QAAQ;gBACf,OAAO,EAAE,CAAC;gBACV,QAAQ,EAAE,YAAY;gBACtB,IAAI,EAAE,QAAQ,CAAC,MAAM;gBACrB,EAAE,EAAE,CAAC;gBACL,SAAS,EAAE,IAAI;aACf,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,IAAI,CAAC,YAAY,GAAG,CAAC;QACpB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,OAAO;QACR,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5G,CAAC;IAED,MAAM,CAAC,EAAU;QAChB,iGAAiG;QACjG,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YACpD,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAE1D,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACZ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC/C,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACpB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;oBACnB,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;gBAC5B,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;CACD"}
1
+ {"version":3,"file":"Music.js","sourceRoot":"","sources":["../../src/audio/Music.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,9 @@ export interface Playable {
10
10
  currentTime: number;
11
11
  volume: number;
12
12
  loop: boolean;
13
+ /** Optional completion hook, matching HTMLAudioElement.onended. Backends without an
14
+ * end event can omit it; single-track Music remains fully usable there. */
15
+ onended?: ((event: Event) => unknown) | null;
13
16
  }
14
17
  /** the real thing: an `HTMLAudioElement` pointed at a resolved asset path */
15
18
  export declare function createAudio(path: string): Playable;
@@ -1 +1 @@
1
- {"version":3,"file":"Playable.d.ts","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACxB,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACd;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAElD"}
1
+ {"version":3,"file":"Playable.d.ts","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACxB,IAAI,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,KAAK,IAAI,IAAI,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd;+EAC2E;IAC3E,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,IAAI,CAAC;CAC7C;AAED,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAElD"}
@@ -1 +1 @@
1
- {"version":3,"file":"Playable.js","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAC;AAgBhD,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,IAAY;IACvC,OAAO,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"Playable.js","sourceRoot":"","sources":["../../src/audio/Playable.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAC;AAmBhD,6EAA6E;AAC7E,MAAM,UAAU,WAAW,CAAC,IAAY;IACvC,OAAO,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Sound.d.ts","sourceRoot":"","sources":["../../src/audio/Sound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG3D,MAAM,WAAW,YAAY;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC;IAEpC,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,EAMnD;IAED,IAAI,IAAI,IAAI,CASX;IAED,OAAO,IAAI,IAAI,CAKd;CACD"}
1
+ {"version":3,"file":"Sound.d.ts","sourceRoot":"","sources":["../../src/audio/Sound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG3D,MAAM,WAAW,YAAY;IAC5B,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,8FAA8F;IAC9F,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,QAAQ,CAAC;IAEpC,2FAA2F;IAC3F,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,EAMnD;IAED,IAAI,IAAI,IAAI,CAYX;IAED,OAAO,IAAI,IAAI,CAKd;CACD"}
@@ -20,7 +20,10 @@ export class Sound {
20
20
  this.next = (this.next + 1) % this.pool.length;
21
21
  audio.volume = this.volume;
22
22
  audio.currentTime = 0;
23
- void audio.play();
23
+ // play() can return a Promise that rejects if this reuse interrupts its own prior,
24
+ // still-loading play() (a real browser, not the fakes tests supply) - swallow it the
25
+ // standard way, since restarting a pooled clip mid-load is expected here, not an error.
26
+ void Promise.resolve(audio.play()).catch(() => { });
24
27
  if (this.caption)
25
28
  onCaption.dispatch({ text: this.caption });
26
29
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Sound.js","sourceRoot":"","sources":["../../src/audio/Sound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAc1C;;;;;GAKG;AACH,MAAM,OAAO,KAAK;IAMjB,YAAY,IAAY,EAAE,OAAO,GAAiB,EAAE;QAJ5C,SAAI,GAAG,CAAC,CAAC;QAKhB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC;QAC7C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAE/C,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;QACtB,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC;QAElB,IAAI,IAAI,CAAC,OAAO;YAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO;QACN,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;QACvB,CAAC;IACF,CAAC;CACD"}
1
+ {"version":3,"file":"Sound.js","sourceRoot":"","sources":["../../src/audio/Sound.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAiB,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAc1C;;;;;GAKG;AACH,MAAM,OAAO,KAAK;IAMjB,YAAY,IAAY,EAAE,OAAO,GAAiB,EAAE;QAJ5C,SAAI,GAAG,CAAC,CAAC;QAKhB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC;QAC7C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,IAAI;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAE/C,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;QACtB,mFAAmF;QACnF,qFAAqF;QACrF,wFAAwF;QACxF,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAEnD,IAAI,IAAI,CAAC,OAAO;YAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO;QACN,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,KAAK,CAAC,KAAK,EAAE,CAAC;YACd,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC;QACvB,CAAC;IACF,CAAC;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"Synth.d.ts","sourceRoot":"","sources":["../../src/audio/Synth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,WAAgB,GAAG,MAAM,CAsBhE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,WAAgB,EAAE,MAAM,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,QAAkC,GAAG,QAAQ,CAI7H"}
1
+ {"version":3,"file":"Synth.d.ts","sourceRoot":"","sources":["../../src/audio/Synth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,WAAgB,GAAG,MAAM,CAsBhE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,OAAO,GAAE,WAAgB,EAAE,MAAM,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,QAAkC,GAAG,QAAQ,CAM7H"}
@@ -34,7 +34,9 @@ export function synthesizeTone(options = {}) {
34
34
  */
35
35
  export function playTone(options = {}, create = (uri) => new Audio(uri)) {
36
36
  const playable = create(synthesizeTone(options));
37
- void playable.play();
37
+ // same rejection-swallowing as Sound.play()/Music.play(): an interrupted play() here is
38
+ // expected, not an error, and must not escape as an unhandled rejection.
39
+ void Promise.resolve(playable.play()).catch(() => { });
38
40
  return playable;
39
41
  }
40
42
  function waveSample(waveform, phase, seed, index) {
@@ -1 +1 @@
1
- {"version":3,"file":"Synth.js","sourceRoot":"","sources":["../../src/audio/Synth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Synth.js","sourceRoot":"","sources":["../../src/audio/Synth.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,16 @@
1
+ import { HttpTransport, type HttpTransportOptions } from './HttpTransport.ts';
1
2
  export interface FeedbackRequest {
2
3
  message: string;
3
4
  contact?: string;
4
5
  context?: Record<string, string | number | boolean>;
5
6
  }
6
- export interface FeedbackOptions {
7
- endpoint: string;
8
- timeoutMs?: number;
9
- fetch?: typeof globalThis.fetch;
10
- }
7
+ export type FeedbackOptions = HttpTransportOptions;
11
8
  export interface FeedbackResponse {
12
9
  ok: boolean;
13
10
  status: number;
14
11
  }
15
12
  /** Small, injectable transport for a game's own feedback endpoint. */
16
- export declare class FeedbackClient {
17
- private readonly endpoint;
18
- private readonly timeoutMs;
19
- private readonly fetchFn;
13
+ export declare class FeedbackClient extends HttpTransport {
20
14
  constructor(options: FeedbackOptions);
21
15
  submit(request: FeedbackRequest): Promise<FeedbackResponse>;
22
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Feedback.d.ts","sourceRoot":"","sources":["../../src/core/Feedback.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACpD;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CACf;AAED,sEAAsE;AACtE,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAElD,YAAY,OAAO,EAAE,eAAe,EAOnC;IAEK,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAgBhE;CACD"}
1
+ {"version":3,"file":"Feedback.d.ts","sourceRoot":"","sources":["../../src/core/Feedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,MAAM,WAAW,eAAe;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACpD;AAED,MAAM,MAAM,eAAe,GAAG,oBAAoB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CACf;AAED,sEAAsE;AACtE,qBAAa,cAAe,SAAQ,aAAa;IAChD,YAAY,OAAO,EAAE,eAAe,EAEnC;IAEK,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAYhE;CACD"}
@@ -1,35 +1,23 @@
1
+ import { HttpTransport } from './HttpTransport.js';
1
2
  /** Small, injectable transport for a game's own feedback endpoint. */
2
- export class FeedbackClient {
3
+ export class FeedbackClient extends HttpTransport {
3
4
  constructor(options) {
4
- if (!options.endpoint)
5
- throw new Error('feedback endpoint is required');
6
- this.endpoint = options.endpoint;
7
- this.timeoutMs = options.timeoutMs ?? 10000;
8
- if (!(this.timeoutMs > 0))
9
- throw new Error('feedback timeout must be positive');
10
- this.fetchFn = options.fetch ?? globalThis.fetch;
11
- if (!this.fetchFn)
12
- throw new Error('fetch is unavailable; provide FeedbackOptions.fetch');
5
+ super(options, 'feedback');
13
6
  }
14
7
  async submit(request) {
15
8
  if (!request.message?.trim())
16
9
  throw new Error('feedback message cannot be empty');
17
- const controller = new AbortController();
18
- const timer = setTimeout(() => controller.abort(), this.timeoutMs);
19
- try {
10
+ return this.withTimeout(async (signal) => {
20
11
  const response = await this.fetchFn(this.endpoint, {
21
12
  method: 'POST',
22
13
  headers: { 'content-type': 'application/json' },
23
14
  body: JSON.stringify(request),
24
- signal: controller.signal,
15
+ signal,
25
16
  });
26
17
  if (!response.ok)
27
18
  throw new Error(`feedback request failed with HTTP ${response.status}`);
28
19
  return { ok: true, status: response.status };
29
- }
30
- finally {
31
- clearTimeout(timer);
32
- }
20
+ });
33
21
  }
34
22
  }
35
23
  //# sourceMappingURL=Feedback.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Feedback.js","sourceRoot":"","sources":["../../src/core/Feedback.ts"],"names":[],"mappings":"AAiBA,sEAAsE;AACtE,MAAM,OAAO,cAAc;IAK1B,YAAY,OAAwB;QACnC,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACxE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;QAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAChF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IAC3F,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAwB;QACpC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClF,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACnE,IAAI,CAAC;YACJ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAClD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,MAAM,EAAE,UAAU,CAAC,MAAM;aACzB,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9C,CAAC;gBAAS,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;CACD"}
1
+ {"version":3,"file":"Feedback.js","sourceRoot":"","sources":["../../src/core/Feedback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA6B,MAAM,oBAAoB,CAAC;AAe9E,sEAAsE;AACtE,MAAM,OAAO,cAAe,SAAQ,aAAa;IAChD,YAAY,OAAwB;QACnC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAwB;QACpC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE;gBAClD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,MAAM;aACN,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1F,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9C,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}
@@ -0,0 +1,22 @@
1
+ export interface HttpTransportOptions {
2
+ endpoint: string;
3
+ timeoutMs?: number;
4
+ fetch?: typeof globalThis.fetch;
5
+ }
6
+ /**
7
+ * The constructor validation and timeout-wrapped fetch shared by every injectable HTTPS
8
+ * transport here (`FeedbackClient`, `SaveSyncClient`, `TelemetryClient`) - each one is a
9
+ * plain request/response against a game's own endpoint, differing only in what they send and
10
+ * expect back, not in how the endpoint/timeout/fetch options are validated or how a request
11
+ * is aborted after `timeoutMs`. `label` names the concrete client in its own error messages
12
+ * ("feedback endpoint is required", not a generic one that would leave a game guessing which
13
+ * of several clients threw).
14
+ */
15
+ export declare abstract class HttpTransport {
16
+ protected readonly endpoint: string;
17
+ protected readonly timeoutMs: number;
18
+ protected readonly fetchFn: typeof globalThis.fetch;
19
+ constructor(options: HttpTransportOptions, label: string);
20
+ protected withTimeout<T>(run: (signal: AbortSignal) => Promise<T>): Promise<T>;
21
+ }
22
+ //# sourceMappingURL=HttpTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpTransport.d.ts","sourceRoot":"","sources":["../../src/core/HttpTransport.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAChC;AAED;;;;;;;;GAQG;AACH,8BAAsB,aAAa;IAClC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IACpC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IACrC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IAEpD,YAAY,OAAO,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,EAOvD;IAED,UAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQnF;CACD"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The constructor validation and timeout-wrapped fetch shared by every injectable HTTPS
3
+ * transport here (`FeedbackClient`, `SaveSyncClient`, `TelemetryClient`) - each one is a
4
+ * plain request/response against a game's own endpoint, differing only in what they send and
5
+ * expect back, not in how the endpoint/timeout/fetch options are validated or how a request
6
+ * is aborted after `timeoutMs`. `label` names the concrete client in its own error messages
7
+ * ("feedback endpoint is required", not a generic one that would leave a game guessing which
8
+ * of several clients threw).
9
+ */
10
+ export class HttpTransport {
11
+ constructor(options, label) {
12
+ if (!options.endpoint)
13
+ throw new Error(`${label} endpoint is required`);
14
+ this.endpoint = options.endpoint;
15
+ this.timeoutMs = options.timeoutMs ?? 10000;
16
+ if (!(this.timeoutMs > 0))
17
+ throw new Error(`${label} timeout must be positive`);
18
+ this.fetchFn = options.fetch ?? globalThis.fetch;
19
+ if (!this.fetchFn)
20
+ throw new Error(`fetch is unavailable; provide ${label}Options.fetch`);
21
+ }
22
+ async withTimeout(run) {
23
+ const controller = new AbortController();
24
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
25
+ try {
26
+ return await run(controller.signal);
27
+ }
28
+ finally {
29
+ clearTimeout(timer);
30
+ }
31
+ }
32
+ }
33
+ //# sourceMappingURL=HttpTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpTransport.js","sourceRoot":"","sources":["../../src/core/HttpTransport.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,MAAM,OAAgB,aAAa;IAKlC,YAAY,OAA6B,EAAE,KAAa;QACvD,IAAI,CAAC,OAAO,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,uBAAuB,CAAC,CAAC;QACxE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;QAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,2BAA2B,CAAC,CAAC;QAChF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,eAAe,CAAC,CAAC;IAC3F,CAAC;IAES,KAAK,CAAC,WAAW,CAAI,GAAwC;QACtE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACnE,IAAI,CAAC;YACJ,OAAO,MAAM,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACrC,CAAC;gBAAS,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACF,CAAC;CACD"}
@@ -0,0 +1,63 @@
1
+ import { Signal } from './Signal.ts';
2
+ /** the subset of the DOM/Node `WebSocket` this needs - injectable so a test never opens a real socket */
3
+ export interface WebSocketLike {
4
+ readyState: number;
5
+ send(data: string): void;
6
+ close(): void;
7
+ onopen: ((event: unknown) => void) | null;
8
+ onclose: ((event: unknown) => void) | null;
9
+ onerror: ((event: unknown) => void) | null;
10
+ onmessage: ((event: {
11
+ data: string;
12
+ }) => void) | null;
13
+ }
14
+ export interface LockstepClientOptions {
15
+ url: string;
16
+ /** defaults to the global `WebSocket`; inject a fake in tests, or `ws`'s own client in Node */
17
+ create?: (url: string) => WebSocketLike;
18
+ }
19
+ export interface TickEvent {
20
+ tick: number;
21
+ /** this room's every client id mapped to its input for `tick`, or `null` if it missed the deadline */
22
+ inputs: Record<string, unknown>;
23
+ }
24
+ /**
25
+ * A client for this project's own reference lockstep server (`tools/multiplayer-server.mjs`):
26
+ * the transport, identity, and tick-authority piece item 129 asked for, without `mwg`
27
+ * inventing a full prediction/rollback netcode a real game would likely want to replace
28
+ * anyway. Every connected client submits at most one input per tick; the server broadcasts a
29
+ * `tick` message once every client in its room has submitted for that tick, or once a
30
+ * configured timeout elapses, substituting `null` for whoever is still missing - lockstep,
31
+ * the model turn-driven and RTS-shaped games have used for this for decades, chosen because
32
+ * it needs no client-side prediction to already be correct. A game wanting prediction or
33
+ * interpolation on top of this still can: `onTick` hands over the same ordered, authoritative
34
+ * input stream a prediction layer would reconcile against.
35
+ *
36
+ * This is deliberately the only network surface in `mwg` that assumes a server exists rather
37
+ * than a game's own endpoint - `FeedbackClient`/`NewsClient`/`SaveSyncClient` all assume the
38
+ * opposite, a one-shot request/response a game points at its own backend. Real-time
39
+ * multiplayer has no one-shot shape to hide a server behind, which is why `mwg` ships a
40
+ * reference one (`tools/multiplayer-server.mjs`) rather than assuming a game brings its own,
41
+ * the same reasoning that decided this the moment the item was sized.
42
+ */
43
+ export declare class LockstepClient {
44
+ readonly onWelcome: Signal<{
45
+ id: string;
46
+ }>;
47
+ readonly onTick: Signal<TickEvent>;
48
+ readonly onClose: Signal<void>;
49
+ private socket;
50
+ private readonly url;
51
+ private readonly createSocket;
52
+ private _id;
53
+ constructor(options: LockstepClientOptions);
54
+ /** this client's own id, assigned by the server's `welcome` message; `null` before it arrives */
55
+ get id(): string | null;
56
+ get connected(): boolean;
57
+ connect(): void;
58
+ /** submits this client's input for the current tick; a no-op before the connection is open */
59
+ submitInput(payload: unknown): void;
60
+ close(): void;
61
+ private handleMessage;
62
+ }
63
+ //# sourceMappingURL=Multiplayer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Multiplayer.d.ts","sourceRoot":"","sources":["../../src/core/Multiplayer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,yGAAyG;AACzG,MAAM,WAAW,aAAa;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CACtD;AAID,MAAM,WAAW,qBAAqB;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,+FAA+F;IAC/F,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;CACxC;AAED,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,sGAAsG;IACtG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;IAC1B,QAAQ,CAAC,SAAS;YAAoB,MAAM;OAAM;IAClD,QAAQ,CAAC,MAAM,oBAA2B;IAC1C,QAAQ,CAAC,OAAO,eAAsB;IAEtC,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAC9D,OAAO,CAAC,GAAG,CAAuB;IAElC,YAAY,OAAO,EAAE,qBAAqB,EAIzC;IAED,iGAAiG;IACjG,IAAI,EAAE,IAAI,MAAM,GAAG,IAAI,CAEtB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,OAAO,IAAI,IAAI,CAUd;IAED,8FAA8F;IAC9F,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGlC;IAED,KAAK,IAAI,IAAI,CAEZ;IAED,OAAO,CAAC,aAAa;CASrB"}