@datamoc/mw_games 0.14.0 → 0.16.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 (71) hide show
  1. package/CHANGELOG.md +69 -1
  2. package/dist/audio/Music.d.ts +27 -0
  3. package/dist/audio/Music.d.ts.map +1 -1
  4. package/dist/audio/Music.js +70 -2
  5. package/dist/audio/Music.js.map +1 -1
  6. package/dist/audio/Orchestrator.d.ts +4 -0
  7. package/dist/audio/Orchestrator.d.ts.map +1 -1
  8. package/dist/audio/Orchestrator.js +12 -0
  9. package/dist/audio/Orchestrator.js.map +1 -1
  10. package/dist/audio/Sound.d.ts +9 -0
  11. package/dist/audio/Sound.d.ts.map +1 -1
  12. package/dist/audio/Sound.js +18 -0
  13. package/dist/audio/Sound.js.map +1 -1
  14. package/dist/core/Settings.d.ts +96 -0
  15. package/dist/core/Settings.d.ts.map +1 -0
  16. package/dist/core/Settings.js +189 -0
  17. package/dist/core/Settings.js.map +1 -0
  18. package/dist/core/index.d.ts +2 -0
  19. package/dist/core/index.d.ts.map +1 -1
  20. package/dist/core/index.js +1 -0
  21. package/dist/core/index.js.map +1 -1
  22. package/dist/mw_games.global.js +115 -115
  23. package/dist/mwl/catalog.d.ts +42 -0
  24. package/dist/mwl/catalog.d.ts.map +1 -1
  25. package/dist/mwl/catalog.js +88 -0
  26. package/dist/mwl/catalog.js.map +1 -1
  27. package/dist/mwl/index.d.ts +1 -1
  28. package/dist/mwl/index.d.ts.map +1 -1
  29. package/dist/two-d/Game.d.ts +40 -0
  30. package/dist/two-d/Game.d.ts.map +1 -1
  31. package/dist/two-d/Game.js +66 -3
  32. package/dist/two-d/Game.js.map +1 -1
  33. package/dist/two-d/QualityScaler.d.ts +63 -0
  34. package/dist/two-d/QualityScaler.d.ts.map +1 -0
  35. package/dist/two-d/QualityScaler.js +92 -0
  36. package/dist/two-d/QualityScaler.js.map +1 -0
  37. package/dist/two-d/index.d.ts +3 -1
  38. package/dist/two-d/index.d.ts.map +1 -1
  39. package/dist/two-d/index.js +1 -0
  40. package/dist/two-d/index.js.map +1 -1
  41. package/dist/two-d/render/RpgmAutotile.d.ts +217 -0
  42. package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -1
  43. package/dist/two-d/render/RpgmAutotile.js +756 -0
  44. package/dist/two-d/render/RpgmAutotile.js.map +1 -1
  45. package/dist/two-d/render/SpriteGroup.d.ts +83 -0
  46. package/dist/two-d/render/SpriteGroup.d.ts.map +1 -0
  47. package/dist/two-d/render/SpriteGroup.js +107 -0
  48. package/dist/two-d/render/SpriteGroup.js.map +1 -0
  49. package/dist/two-d/render/TileMap.d.ts +90 -0
  50. package/dist/two-d/render/TileMap.d.ts.map +1 -1
  51. package/dist/two-d/render/TileMap.js +319 -31
  52. package/dist/two-d/render/TileMap.js.map +1 -1
  53. package/dist/two-d/render/index.d.ts +5 -3
  54. package/dist/two-d/render/index.d.ts.map +1 -1
  55. package/dist/two-d/render/index.js +2 -1
  56. package/dist/two-d/render/index.js.map +1 -1
  57. package/dist/two-d/ui/Meter.d.ts +76 -0
  58. package/dist/two-d/ui/Meter.d.ts.map +1 -0
  59. package/dist/two-d/ui/Meter.js +134 -0
  60. package/dist/two-d/ui/Meter.js.map +1 -0
  61. package/dist/two-d/ui/SettingsScreen.d.ts +112 -0
  62. package/dist/two-d/ui/SettingsScreen.d.ts.map +1 -0
  63. package/dist/two-d/ui/SettingsScreen.js +338 -0
  64. package/dist/two-d/ui/SettingsScreen.js.map +1 -0
  65. package/dist/two-d/ui/index.d.ts +4 -0
  66. package/dist/two-d/ui/index.d.ts.map +1 -1
  67. package/dist/two-d/ui/index.js +2 -0
  68. package/dist/two-d/ui/index.js.map +1 -1
  69. package/dist/version.d.ts +1 -1
  70. package/dist/version.js +1 -1
  71. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,7 +5,75 @@ All notable changes to `mwg` are documented here. Format follows
5
5
  [Semantic Versioning](https://semver.org/) as of this first release - a 0.y.z version means
6
6
  the public API may still change between minor versions.
7
7
 
8
- ## [Unreleased]
8
+ ## [0.16.0] - 2026-09-19
9
+
10
+ ### Added
11
+
12
+ - First-class autotile layers on `TileMap` (item 370): `addAutotileLayer` takes raw
13
+ MV tile ids or XP tile values plus one `AutotileSet` per family slot (MV) or image
14
+ index (XP), and the map assembles each cell's quadrant halves straight from the
15
+ source sheet, no prebuilt atlas canvas in between. `setAutotileFrame`/
16
+ `getAutotileFrame` advance and read the animation frame (MV kind cycles, XP frame
17
+ stripes, wrapping); `setTile`/`getTile` keep working with raw ids. The standard MV
18
+ floor/wall shape tables ship as `RPGM_FLOOR_AUTOTILE_TABLE`/
19
+ `RPGM_WALL_AUTOTILE_TABLE` with the family address facts
20
+ (`RPGM_AUTOTILE_SLOT_BASES`/`RPGM_AUTOTILE_SLOT_COUNTS`, `rpgmAutotileSlot`), and
21
+ the XP side ships `XP_AUTOTILE_PATTERNS`/`XP_NEIGHBORS_TO_PATTERN` with
22
+ `xpAutotileRef` (baked cells) and `xpAutotilePattern` (procedural neighbourhoods);
23
+ `autotileCellParts`/`assertAutotileLayout` resolve and validate one cell
24
+ renderer-free.
25
+
26
+ ## [0.15.0] - 2026-09-19
27
+
28
+ ### Added
29
+
30
+ - `mwl.MwlTableReference` and `MwlValidationOptions.tableReferences` - declarative
31
+ cross-table reference checks (item 362, from the Pixel Dungeon study's proposal P21). A
32
+ table column declares `references: { table, column }` or `oneOf: [...]`, and
33
+ `validateCatalog` checks every cell once for all tables, reporting `MWL_TABLE_REFERENCE`
34
+ with the table, the row, and the offending value. The declarations' contents (which column
35
+ points where, which set is legal) stay game data in the consuming repository; absent or
36
+ empty cells are skipped and a `list` cell checks each entry under the table's own
37
+ delimiter.
38
+
39
+ - `core.Settings`/`GameSettings`/`SettingsOptions`/`CustomSettingValue` - persisted
40
+ player settings (item 363): music and sound-effect levels, master mute, zoom
41
+ preference, key bindings applied to `Input` on load, and a game-defined `custom` bag
42
+ (`hints`, `violence`, ...). `defaultSettings` names the fresh-game values,
43
+ `effectiveMusicVolume`/`effectiveSfxVolume` read 0 while muted, and corrupt storage
44
+ reads as defaults.
45
+
46
+ - `two-d/ui.SettingsScreen`/`SettingsCustomRow` - a ready-made settings screen over
47
+ `core.Settings` (item 364): music/sfx sliders, mute checkbox, zoom slider, one row
48
+ per `custom` descriptor (boolean/number/choice), an embedded controls page that
49
+ writes rebinds back into `Settings` on exit, and a reset row.
50
+
51
+ - Auto-pause and auto-mute on page hide (item 365): `Game` suspends the loop and
52
+ silences its `audio` rig while hidden and resumes both on show (`autoPause`, on by
53
+ default), via `suspend`/`resume` that park the clock at 0 and route through the top
54
+ scene's `onSuspend`/`onResume`. `Music`/`Sound`/`Orchestrator` gain matching
55
+ `suspend`/`resume`, and the player's own mute setting is never touched.
56
+
57
+ - Frame-time quality scaling over the static device fit (item 366): a `QualityScaler`
58
+ steps the backing-store ratio down after sustained over-budget frames and back up
59
+ only after a much longer streak inside budget, wired to `Game` via the
60
+ `qualityScaling` option (off unless given) with the fitted ratio as its ceiling.
61
+
62
+ - Audio ducking for dialogue and menus (item 367): `Music.duck` glides to an
63
+ attenuated level until `unduck`, through the existing fade path, with tracks started
64
+ while ducked starting ducked and pending fades retargeted. `Sound` is untouched.
65
+
66
+ - A discrete meter widget, `two-d/ui.Meter` (item 368): N icons with a value filled,
67
+ the heart row or star rating to `Bar`'s continuous fill. Fractions clip mid-icon
68
+ through a mask, so halves need no extra art; flat theme pips by default, a
69
+ game-supplied filled/empty texture pair otherwise.
70
+
71
+ - Animate only what is on screen, `two-d/render.SpriteGroup`/`isOnScreen` (item 369):
72
+ `update(camera, dt)` advances the members inside `camera.view` (plus `margin`) and leaves
73
+ the rest on their current frame. Members are `AnimatedSprite`s, `ParticleEmitter`s, or
74
+ anything with `x`/`y` in world units plus `update(dt)`; skipped members resume where they
75
+ left off, and a rotated camera tests the same over-inclusive box `TileMap.cull` uses, so
76
+ nothing visible ever freezes.
9
77
 
10
78
  ## [0.14.0] - 2026-09-15
11
79
 
@@ -26,6 +26,8 @@ export declare class Music {
26
26
  private trackQueue;
27
27
  private playlistFade;
28
28
  volume: number;
29
+ private suspended_;
30
+ private duckLevel_;
29
31
  constructor(options?: MusicOptions);
30
32
  /** @param fadeDuration seconds; 0 switches immediately with no crossfade */
31
33
  play(path: string, fadeDuration?: number): void;
@@ -38,6 +40,31 @@ export declare class Music {
38
40
  private startNextTrack;
39
41
  private start;
40
42
  stop(fadeDuration?: number): void;
43
+ /**
44
+ * Silences everything for a page hide: pauses the current track and every fading one,
45
+ * and freezes `update` until `resume`, so a crossfade mid-flight continues where it
46
+ * stopped rather than finishing inaudibly in a background tab. Idempotent.
47
+ */
48
+ suspend(): void;
49
+ /**
50
+ * The counterpart to `suspend`: restarts the current track where it paused. A track
51
+ * stopped (not suspended) while hidden stays stopped - resume only resumes.
52
+ */
53
+ resume(): void;
54
+ /**
55
+ * Ducks the music under dialogue or a menu: the current track glides to
56
+ * `volume * level` over `fadeDuration` and stays there until `unduck`, and tracks
57
+ * started while ducked start ducked. Pending fades are retargeted proportionally, so
58
+ * ducking mid-crossfade still lands quiet. `Sound` is untouched. Idempotent.
59
+ *
60
+ * @param level 0 (silent) to 1 (full); clamped, 0.5 by default
61
+ */
62
+ duck(level?: number, fadeDuration?: number): void;
63
+ /** releases a `duck` back to full volume through the same fade path */
64
+ unduck(fadeDuration?: number): void;
65
+ /** the held duck attenuation, 1 when full */
66
+ get duckLevel(): number;
67
+ get isSuspended(): boolean;
41
68
  update(dt: number): void;
42
69
  }
43
70
  //# sourceMappingURL=Music.d.ts.map
@@ -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;;;;;;;;;;;;;;;GAeG;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;IA8Cb,IAAI,CAAC,YAAY,SAAI,GAAG,IAAI,CAW3B;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;;;;;;;;;;;;;;;GAeG;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;IACf,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAK;IAEvB,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;IA8Cb,IAAI,CAAC,YAAY,SAAI,GAAG,IAAI,CAW3B;IAED;;;;OAIG;IACH,OAAO,IAAI,IAAI,CAId;IAED;;;OAGG;IACH,MAAM,IAAI,IAAI,CAIb;IAED;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,SAAM,EAAE,YAAY,SAAM,GAAG,IAAI,CAqB1C;IAED,uEAAuE;IACvE,MAAM,CAAC,YAAY,SAAM,GAAG,IAAI,CAE/B;IAED,6CAA6C;IAC7C,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAgBvB;CACD"}
@@ -21,6 +21,8 @@ export class Music {
21
21
  this.fades = [];
22
22
  this.trackQueue = null;
23
23
  this.playlistFade = 1;
24
+ this.suspended_ = false;
25
+ this.duckLevel_ = 1;
24
26
  this.volume = options.volume ?? 1;
25
27
  this.create = options.create ?? createAudio;
26
28
  }
@@ -63,7 +65,7 @@ export class Music {
63
65
  const previous = this.current;
64
66
  this.current = incoming;
65
67
  if (fadeDuration <= 0) {
66
- incoming.volume = this.volume;
68
+ incoming.volume = this.volume * this.duckLevel_;
67
69
  // a rejection here means the switch itself (or the previous.pause() right below)
68
70
  // interrupted this play()'s own in-flight load - expected during a track switch,
69
71
  // so swallow it the standard way rather than let it surface as unhandled.
@@ -78,7 +80,7 @@ export class Music {
78
80
  elapsed: 0,
79
81
  duration: fadeDuration,
80
82
  from: 0,
81
- to: this.volume,
83
+ to: this.volume * this.duckLevel_,
82
84
  stopAtEnd: false,
83
85
  });
84
86
  if (previous) {
@@ -104,7 +106,73 @@ export class Music {
104
106
  }
105
107
  this.fades.push({ audio, elapsed: 0, duration: fadeDuration, from: audio.volume, to: 0, stopAtEnd: true });
106
108
  }
109
+ /**
110
+ * Silences everything for a page hide: pauses the current track and every fading one,
111
+ * and freezes `update` until `resume`, so a crossfade mid-flight continues where it
112
+ * stopped rather than finishing inaudibly in a background tab. Idempotent.
113
+ */
114
+ suspend() {
115
+ this.suspended_ = true;
116
+ this.current?.pause();
117
+ for (const fade of this.fades)
118
+ fade.audio.pause();
119
+ }
120
+ /**
121
+ * The counterpart to `suspend`: restarts the current track where it paused. A track
122
+ * stopped (not suspended) while hidden stays stopped - resume only resumes.
123
+ */
124
+ resume() {
125
+ if (!this.suspended_)
126
+ return;
127
+ this.suspended_ = false;
128
+ if (this.current)
129
+ void Promise.resolve(this.current.play()).catch(() => { });
130
+ }
131
+ /**
132
+ * Ducks the music under dialogue or a menu: the current track glides to
133
+ * `volume * level` over `fadeDuration` and stays there until `unduck`, and tracks
134
+ * started while ducked start ducked. Pending fades are retargeted proportionally, so
135
+ * ducking mid-crossfade still lands quiet. `Sound` is untouched. Idempotent.
136
+ *
137
+ * @param level 0 (silent) to 1 (full); clamped, 0.5 by default
138
+ */
139
+ duck(level = 0.5, fadeDuration = 0.5) {
140
+ const next = Number.isFinite(level) ? Math.max(0, Math.min(1, level)) : 1;
141
+ const previous = this.duckLevel_;
142
+ this.duckLevel_ = next;
143
+ for (const fade of this.fades) {
144
+ fade.to = previous > 0 ? (fade.to / previous) * next : this.volume * next;
145
+ }
146
+ if (this.current) {
147
+ const target = this.volume * next;
148
+ if (fadeDuration <= 0)
149
+ this.current.volume = target;
150
+ else {
151
+ this.fades.push({
152
+ audio: this.current,
153
+ elapsed: 0,
154
+ duration: fadeDuration,
155
+ from: this.current.volume,
156
+ to: target,
157
+ stopAtEnd: false,
158
+ });
159
+ }
160
+ }
161
+ }
162
+ /** releases a `duck` back to full volume through the same fade path */
163
+ unduck(fadeDuration = 0.5) {
164
+ this.duck(1, fadeDuration);
165
+ }
166
+ /** the held duck attenuation, 1 when full */
167
+ get duckLevel() {
168
+ return this.duckLevel_;
169
+ }
170
+ get isSuspended() {
171
+ return this.suspended_;
172
+ }
107
173
  update(dt) {
174
+ if (this.suspended_)
175
+ return;
108
176
  //iterate a copy: a fade finishing may not touch the list, but this stays safe if one day it does
109
177
  for (const fade of [...this.fades]) {
110
178
  fade.elapsed += dt;
@@ -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;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,KAAK;IAQjB,YAAY,OAAO,GAAiB,EAAE;QAP9B,YAAO,GAAoB,IAAI,CAAC;QAChC,UAAK,GAAW,EAAE,CAAC;QAEnB,eAAU,GAAoB,IAAI,CAAC;QACnC,iBAAY,GAAG,CAAC,CAAC;QAIxB,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,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,KAAwB,EAAE,YAAY,GAAG,CAAC;QACpD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACxB,OAAO;QACR,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,cAAc,EAAE,CAAC;IACvB,CAAC;IAEO,cAAc;QACrB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM;YAAE,OAAO;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAG,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,IAAY,EAAE,YAAoB,EAAE,IAAa;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACnC,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC7C,6EAA6E;YAC7E,QAAQ,CAAC,OAAO,GAAG,GAAG,EAAE;gBACvB,IAAI,IAAI,CAAC,OAAO,KAAK,QAAQ;oBAAE,IAAI,CAAC,cAAc,EAAE,CAAC;YACtD,CAAC,CAAC;QACH,CAAC;QAED,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,iFAAiF;YACjF,iFAAiF;YACjF,0EAA0E;YAC1E,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YACtD,QAAQ,EAAE,KAAK,EAAE,CAAC;YAClB,OAAO;QACR,CAAC;QAED,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QACpB,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;YACf,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,YAAY;YACtB,IAAI,EAAE,CAAC;YACP,EAAE,EAAE,IAAI,CAAC,MAAM;YACf,SAAS,EAAE,KAAK;SAChB,CAAC,CAAC;QAEH,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,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,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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"}
@@ -50,5 +50,9 @@ export declare class Orchestrator {
50
50
  on(event: string, cue: Sound): void;
51
51
  /** plays the sound registered for `event`, if any; silently does nothing otherwise */
52
52
  trigger(event: string): void;
53
+ /** suspends the music and every cue - the rig a `Game` silences on page hide */
54
+ suspend(): void;
55
+ /** resumes the music and every cue after `suspend` */
56
+ resume(): void;
53
57
  }
54
58
  //# sourceMappingURL=Orchestrator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Orchestrator.d.ts","sourceRoot":"","sources":["../../src/audio/Orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,2GAA2G;AAC3G,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,KAAK,CAAQ;IAErB,YAAY,KAAK,EAAE,KAAK,EAEvB;IAED,oDAAoD;IACpD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAEtD;IAED,yFAAyF;IACzF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQzB;IAED,8DAA8D;IAC9D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAElC;IAED,sFAAsF;IACtF,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE3B;CACD"}
1
+ {"version":3,"file":"Orchestrator.d.ts","sourceRoot":"","sources":["../../src/audio/Orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,2GAA2G;AAC3G,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,KAAK,CAAQ;IAErB,YAAY,KAAK,EAAE,KAAK,EAEvB;IAED,oDAAoD;IACpD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAEtD;IAED,yFAAyF;IACzF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAQzB;IAED,8DAA8D;IAC9D,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAElC;IAED,sFAAsF;IACtF,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE3B;IAED,gFAAgF;IAChF,OAAO,IAAI,IAAI,CAGd;IAED,sDAAsD;IACtD,MAAM,IAAI,IAAI,CAGb;CACD"}
@@ -58,5 +58,17 @@ export class Orchestrator {
58
58
  trigger(event) {
59
59
  this.cues.get(event)?.play();
60
60
  }
61
+ /** suspends the music and every cue - the rig a `Game` silences on page hide */
62
+ suspend() {
63
+ this.music.suspend();
64
+ for (const cue of this.cues.values())
65
+ cue.suspend();
66
+ }
67
+ /** resumes the music and every cue after `suspend` */
68
+ resume() {
69
+ this.music.resume();
70
+ for (const cue of this.cues.values())
71
+ cue.resume();
72
+ }
61
73
  }
62
74
  //# sourceMappingURL=Orchestrator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Orchestrator.js","sourceRoot":"","sources":["../../src/audio/Orchestrator.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,YAAY;IAMxB,YAAY,KAAY;QALhB,WAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;QAC9C,SAAI,GAAG,IAAI,GAAG,EAAiB,CAAC;QAChC,iBAAY,GAAkB,IAAI,CAAC;QAI1C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAED,oDAAoD;IACpD,MAAM,CAAC,KAAa,EAAE,OAA0B;QAC/C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,yFAAyF;IACzF,KAAK,CAAC,KAAa;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,GAAG,CAAC,CAAC;QAE/E,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY;YAAE,OAAO;QAEhD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;IACnC,CAAC;IAED,8DAA8D;IAC9D,EAAE,CAAC,KAAa,EAAE,GAAU;QAC3B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,sFAAsF;IACtF,OAAO,CAAC,KAAa;QACpB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;CACD"}
1
+ {"version":3,"file":"Orchestrator.js","sourceRoot":"","sources":["../../src/audio/Orchestrator.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAO,YAAY;IAMxB,YAAY,KAAY;QALhB,WAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;QAC9C,SAAI,GAAG,IAAI,GAAG,EAAiB,CAAC;QAChC,iBAAY,GAAkB,IAAI,CAAC;QAI1C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAED,oDAAoD;IACpD,MAAM,CAAC,KAAa,EAAE,OAA0B;QAC/C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,yFAAyF;IACzF,KAAK,CAAC,KAAa;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,KAAK,GAAG,CAAC,CAAC;QAE/E,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,YAAY;YAAE,OAAO;QAEhD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;IACnC,CAAC;IAED,8DAA8D;IAC9D,EAAE,CAAC,KAAa,EAAE,GAAU;QAC3B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,sFAAsF;IACtF,OAAO,CAAC,KAAa;QACpB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED,gFAAgF;IAChF,OAAO;QACN,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACrB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAAE,GAAG,CAAC,OAAO,EAAE,CAAC;IACrD,CAAC;IAED,sDAAsD;IACtD,MAAM;QACL,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YAAE,GAAG,CAAC,MAAM,EAAE,CAAC;IACpD,CAAC;CACD"}
@@ -26,6 +26,7 @@ export declare class Sound {
26
26
  private pool;
27
27
  private next;
28
28
  private caption?;
29
+ private suspended_;
29
30
  volume: number;
30
31
  constructor(path: string, options?: SoundOptions);
31
32
  /**
@@ -42,5 +43,13 @@ export declare class Sound {
42
43
  */
43
44
  play(gain?: number, pitch?: number): void;
44
45
  stopAll(): void;
46
+ /**
47
+ * Cuts in-flight one-shots and silences later `play` calls until `resume` - the page-hide
48
+ * half of `Music.suspend`. One-shots have nothing to restart, so resume only re-enables.
49
+ */
50
+ suspend(): void;
51
+ /** re-enables `play` after `suspend` */
52
+ resume(): void;
53
+ get isSuspended(): boolean;
45
54
  }
46
55
  //# sourceMappingURL=Sound.d.ts.map
@@ -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;;;;;;;;;;;;;GAaG;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;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,IAAI,SAAI,EAAE,KAAK,SAAI,GAAG,IAAI,CAa9B;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;;;;;;;;;;;;;GAaG;AACH,qBAAa,KAAK;IACjB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,OAAO,CAAC,CAAS;IACzB,OAAO,CAAC,UAAU,CAAS;IAC3B,MAAM,EAAE,MAAM,CAAC;IAEf,YAAY,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,EAMnD;IAED;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,IAAI,SAAI,EAAE,KAAK,SAAI,GAAG,IAAI,CAc9B;IAED,OAAO,IAAI,IAAI,CAKd;IAED;;;OAGG;IACH,OAAO,IAAI,IAAI,CAGd;IAED,wCAAwC;IACxC,MAAM,IAAI,IAAI,CAEb;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;CACD"}
@@ -17,6 +17,7 @@ import { onCaption } from './Captions.js';
17
17
  export class Sound {
18
18
  constructor(path, options = {}) {
19
19
  this.next = 0;
20
+ this.suspended_ = false;
20
21
  const size = Math.max(1, options.poolSize ?? 4);
21
22
  const create = options.create ?? createAudio;
22
23
  this.volume = options.volume ?? 1;
@@ -36,6 +37,8 @@ export class Sound {
36
37
  * than own a panner node a game does not necessarily want - the same reasoning applies here.
37
38
  */
38
39
  play(gain = 1, pitch = 1) {
40
+ if (this.suspended_)
41
+ return;
39
42
  const audio = this.pool[this.next];
40
43
  this.next = (this.next + 1) % this.pool.length;
41
44
  audio.volume = this.volume * gain;
@@ -54,5 +57,20 @@ export class Sound {
54
57
  audio.currentTime = 0;
55
58
  }
56
59
  }
60
+ /**
61
+ * Cuts in-flight one-shots and silences later `play` calls until `resume` - the page-hide
62
+ * half of `Music.suspend`. One-shots have nothing to restart, so resume only re-enables.
63
+ */
64
+ suspend() {
65
+ this.suspended_ = true;
66
+ this.stopAll();
67
+ }
68
+ /** re-enables `play` after `suspend` */
69
+ resume() {
70
+ this.suspended_ = false;
71
+ }
72
+ get isSuspended() {
73
+ return this.suspended_;
74
+ }
57
75
  }
58
76
  //# sourceMappingURL=Sound.js.map
@@ -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;;;;;;;;;;;;;GAaG;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;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC;QACvB,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,GAAG,IAAI,CAAC;QAClC,KAAK,CAAC,YAAY,GAAG,KAAK,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
+ {"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;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,KAAK;IAOjB,YAAY,IAAY,EAAE,OAAO,GAAiB,EAAE;QAL5C,SAAI,GAAG,CAAC,CAAC;QAET,eAAU,GAAG,KAAK,CAAC;QAI1B,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;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC;QACvB,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,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,GAAG,IAAI,CAAC;QAClC,KAAK,CAAC,YAAY,GAAG,KAAK,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;IAED;;;OAGG;IACH,OAAO;QACN,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,OAAO,EAAE,CAAC;IAChB,CAAC;IAED,wCAAwC;IACxC,MAAM;QACL,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;CACD"}
@@ -0,0 +1,96 @@
1
+ import { type SaveStorage } from './Save.ts';
2
+ import { type Action } from './Input.ts';
3
+ /** a game-defined value: hints on/off, a violence level, anything JSON-flat */
4
+ export type CustomSettingValue = string | number | boolean;
5
+ /** the player-facing values `Settings` persists; everything is renderer-free on purpose */
6
+ export interface GameSettings {
7
+ /** background-music level, 0 to 1 */
8
+ musicVolume: number;
9
+ /** sound-effect level, 0 to 1 */
10
+ sfxVolume: number;
11
+ /** master mute: both effective volumes read 0 while true, levels are kept */
12
+ muted: boolean;
13
+ /** the zoom a game applies to its own `Camera`; never below 0.01, like `Camera` itself */
14
+ zoom: number;
15
+ /** key bindings, in the shape `Input.exportBindings` writes and `importBindings` reads */
16
+ bindings: Record<Action, string[]>;
17
+ /** game-defined values beyond the built-ins above (`hints`, `violence`, ...), keyed by name */
18
+ custom: Record<string, CustomSettingValue>;
19
+ }
20
+ export interface SettingsOptions {
21
+ /** namespaces the storage key, so two games sharing an origin never collide */
22
+ namespace?: string;
23
+ storage?: SaveStorage;
24
+ }
25
+ /**
26
+ * The values a fresh game starts with: full volume, unmuted, zoom 1, default bindings.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { defaultSettings } from '@datamoc/mw_games/core';
31
+ *
32
+ * console.log(defaultSettings().zoom); // 1
33
+ * ```
34
+ */
35
+ export declare function defaultSettings(): GameSettings;
36
+ /** what a game hands its own audio objects: 0 while muted, the stored level otherwise */
37
+ export declare function effectiveMusicVolume(settings: Pick<GameSettings, 'musicVolume' | 'muted'>): number;
38
+ /** what a game hands its own sound effects: 0 while muted, the stored level otherwise */
39
+ export declare function effectiveSfxVolume(settings: Pick<GameSettings, 'sfxVolume' | 'muted'>): number;
40
+ /**
41
+ * Persisted player settings: music and sound-effect levels, master mute, zoom preference,
42
+ * and key bindings, read back on the next launch.
43
+ *
44
+ * The values live in `core` so they stay renderer-free; the wiring stays with the game,
45
+ * which assigns them onto its own `Music`/`Sound`/`Camera` (see the example). Bindings are
46
+ * the exception: they are applied to `Input` on load and on every bindings mutation,
47
+ * since persisted keys that a game must remember to apply would silently do nothing.
48
+ *
49
+ * Corrupt storage reads as defaults rather than throwing: a settings screen should show
50
+ * the defaults, not a crash.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * import { Settings, effectiveMusicVolume, effectiveSfxVolume } from '@datamoc/mw_games/core';
55
+ *
56
+ * const settings = new Settings({ namespace: 'my-game' });
57
+ * settings.update({ musicVolume: 0.7, zoom: 2 });
58
+ * settings.setCustom('hints', true);
59
+ *
60
+ * const music = { volume: 1 };
61
+ * const camera = { zoom: 1 };
62
+ * music.volume = effectiveMusicVolume(settings.current);
63
+ * camera.zoom = settings.current.zoom;
64
+ * console.log(effectiveSfxVolume(settings.current), settings.getCustom('hints', false));
65
+ * ```
66
+ */
67
+ export declare class Settings {
68
+ private readonly storage;
69
+ private readonly key;
70
+ private value;
71
+ constructor(options?: SettingsOptions);
72
+ /** a copy of the current values; mutating it writes nothing back, use the setters */
73
+ get current(): GameSettings;
74
+ /** a game-defined value (`hints`, `violence`, ...), or `fallback` when never set */
75
+ getCustom(key: string, fallback: CustomSettingValue): CustomSettingValue;
76
+ /** stores a game-defined value and persists it */
77
+ setCustom(key: string, value: CustomSettingValue): void;
78
+ setMusicVolume(volume: number): void;
79
+ setSfxVolume(volume: number): void;
80
+ setMuted(muted: boolean): void;
81
+ setZoom(zoom: number): void;
82
+ setBindings(bindings: Readonly<Record<Action, readonly string[]>>): void;
83
+ update(patch: {
84
+ musicVolume?: number;
85
+ sfxVolume?: number;
86
+ muted?: boolean;
87
+ zoom?: number;
88
+ bindings?: Readonly<Record<Action, readonly string[]>>;
89
+ custom?: Readonly<Record<string, CustomSettingValue>>;
90
+ }): void;
91
+ /** re-applies the stored bindings to `Input`, for a game that installed its own after this was built */
92
+ applyBindings(): void;
93
+ /** back to full volume, unmuted, zoom 1 and the default bindings, persisted */
94
+ reset(): void;
95
+ }
96
+ //# sourceMappingURL=Settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Settings.d.ts","sourceRoot":"","sources":["../../src/core/Settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAoC,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAG3E,+EAA+E;AAC/E,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,2FAA2F;AAC3F,MAAM,WAAW,YAAY;IAC5B,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,KAAK,EAAE,OAAO,CAAC;IACf,0FAA0F;IAC1F,IAAI,EAAE,MAAM,CAAC;IACb,0FAA0F;IAC1F,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACnC,+FAA+F;IAC/F,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC/B,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAS9C;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,OAAO,CAAC,GAAG,MAAM,CAElG;AAED,yFAAyF;AACzF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,MAAM,CAE9F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,QAAQ;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,KAAK,CAAe;IAE5B,YAAY,OAAO,GAAE,eAAoB,EAKxC;IAED,qFAAqF;IACrF,IAAI,OAAO,IAAI,YAAY,CAE1B;IAED,oFAAoF;IACpF,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,kBAAkB,CAEvE;IAED,kDAAkD;IAClD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAGtD;IAED,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEnC;IAED,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEjC;IAED,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE7B;IAED,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAE1B;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,GAAG,IAAI,CAEvE;IAED,MAAM,CAAC,KAAK,EAAE;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;KACtD,GAAG,IAAI,CAWP;IAED,wGAAwG;IACxG,aAAa,IAAI,IAAI,CAEpB;IAED,+EAA+E;IAC/E,KAAK,IAAI,IAAI,CAIZ;CACD"}