@rydr/game-sdk 3.10.0 → 3.12.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 (81) hide show
  1. package/dist/client/PlatformClient.d.ts +15 -3
  2. package/dist/client/PlatformClient.d.ts.map +1 -1
  3. package/dist/client/PlatformClient.js +1 -1
  4. package/dist/client/PlatformClient.js.map +1 -1
  5. package/dist/conversations/index.d.ts +15 -4
  6. package/dist/conversations/index.d.ts.map +1 -1
  7. package/dist/conversations/index.js +43 -14
  8. package/dist/conversations/index.js.map +1 -1
  9. package/dist/conversations/voice-samples.d.ts +45 -0
  10. package/dist/conversations/voice-samples.d.ts.map +1 -0
  11. package/dist/conversations/voice-samples.js +244 -0
  12. package/dist/conversations/voice-samples.js.map +1 -0
  13. package/dist/conversations/voices.d.ts +33 -5
  14. package/dist/conversations/voices.d.ts.map +1 -1
  15. package/dist/conversations/voices.js +61 -31
  16. package/dist/conversations/voices.js.map +1 -1
  17. package/dist/host/PlatformHost.d.ts +4 -2
  18. package/dist/host/PlatformHost.d.ts.map +1 -1
  19. package/dist/host/PlatformHost.js +1 -1
  20. package/dist/host/PlatformHost.js.map +1 -1
  21. package/dist/protocol/conversations.d.ts +13 -2
  22. package/dist/protocol/conversations.d.ts.map +1 -1
  23. package/dist/protocol/conversations.js +14 -0
  24. package/dist/protocol/conversations.js.map +1 -1
  25. package/dist/protocol/messages.d.ts +7 -1
  26. package/dist/protocol/messages.d.ts.map +1 -1
  27. package/dist/protocol/version.d.ts +2 -2
  28. package/dist/protocol/version.d.ts.map +1 -1
  29. package/dist/protocol/version.js +7 -2
  30. package/dist/protocol/version.js.map +1 -1
  31. package/dist/sound-gallery/index.d.ts +41 -0
  32. package/dist/sound-gallery/index.d.ts.map +1 -0
  33. package/dist/sound-gallery/index.js +1264 -0
  34. package/dist/sound-gallery/index.js.map +1 -0
  35. package/dist/sounds/audio-utils.d.ts +16 -0
  36. package/dist/sounds/audio-utils.d.ts.map +1 -0
  37. package/dist/sounds/audio-utils.js +150 -0
  38. package/dist/sounds/audio-utils.js.map +1 -0
  39. package/dist/sounds/index.d.ts +23 -0
  40. package/dist/sounds/index.d.ts.map +1 -0
  41. package/dist/sounds/index.js +21 -0
  42. package/dist/sounds/index.js.map +1 -0
  43. package/dist/sounds/sound-bank.d.ts +70 -0
  44. package/dist/sounds/sound-bank.d.ts.map +1 -0
  45. package/dist/sounds/sound-bank.js +313 -0
  46. package/dist/sounds/sound-bank.js.map +1 -0
  47. package/dist/sounds/types.d.ts +88 -0
  48. package/dist/sounds/types.d.ts.map +1 -0
  49. package/dist/sounds/types.js +8 -0
  50. package/dist/sounds/types.js.map +1 -0
  51. package/dist/ui/README.md +2 -0
  52. package/dist/ui/index.d.ts +4 -1
  53. package/dist/ui/index.d.ts.map +1 -1
  54. package/dist/ui/index.js +4 -1
  55. package/dist/ui/index.js.map +1 -1
  56. package/dist/ui/power-race.d.ts +125 -0
  57. package/dist/ui/power-race.d.ts.map +1 -0
  58. package/dist/ui/power-race.js +662 -0
  59. package/dist/ui/power-race.js.map +1 -0
  60. package/dist/ui/showcase/index.d.ts.map +1 -1
  61. package/dist/ui/showcase/index.js +85 -1
  62. package/dist/ui/showcase/index.js.map +1 -1
  63. package/dist/ui/solo-labeled-diamond.d.ts +69 -0
  64. package/dist/ui/solo-labeled-diamond.d.ts.map +1 -0
  65. package/dist/ui/solo-labeled-diamond.js +168 -0
  66. package/dist/ui/solo-labeled-diamond.js.map +1 -0
  67. package/dist/ui/styles.js +24 -2
  68. package/dist/ui/styles.js.map +1 -1
  69. package/dist/ui/subtitle.d.ts +27 -0
  70. package/dist/ui/subtitle.d.ts.map +1 -0
  71. package/dist/ui/subtitle.js +77 -0
  72. package/dist/ui/subtitle.js.map +1 -0
  73. package/dist/voice-gallery/index.d.ts +31 -0
  74. package/dist/voice-gallery/index.d.ts.map +1 -0
  75. package/dist/voice-gallery/index.js +396 -0
  76. package/dist/voice-gallery/index.js.map +1 -0
  77. package/dist/voiceover-editor/index.d.ts +6 -0
  78. package/dist/voiceover-editor/index.d.ts.map +1 -1
  79. package/dist/voiceover-editor/index.js +222 -14
  80. package/dist/voiceover-editor/index.js.map +1 -1
  81. package/package.json +16 -1
@@ -0,0 +1,313 @@
1
+ import { SOUND_CATEGORIES } from "./types.js";
2
+ const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
3
+ const dbToGain = (db) => Math.pow(10, db / 20);
4
+ /** Uniform in [-mag, +mag]. Deterministic-free; variation only needs perceptual jitter. */
5
+ const jitter = (mag) => (mag > 0 ? (Math.random() * 2 - 1) * mag : 0);
6
+ /**
7
+ * A shuffle-bag: deals every item once (shuffled) before repeating, and never repeats the last item
8
+ * across a reshuffle — so an N-clip event cycles through all N with no immediate repeat. Beats
9
+ * `Math.random()` picking, which is what makes repeated SFX sound repetitive.
10
+ */
11
+ class Bag {
12
+ size;
13
+ order = [];
14
+ last = -1;
15
+ constructor(size) {
16
+ this.size = size;
17
+ }
18
+ next() {
19
+ if (this.size <= 1)
20
+ return 0;
21
+ if (this.order.length === 0) {
22
+ this.order = Array.from({ length: this.size }, (_, i) => i);
23
+ for (let i = this.order.length - 1; i > 0; i--) {
24
+ const j = Math.floor(Math.random() * (i + 1));
25
+ const a = this.order[i];
26
+ this.order[i] = this.order[j];
27
+ this.order[j] = a;
28
+ }
29
+ if (this.order[0] === this.last && this.order.length > 1) {
30
+ const a = this.order[0];
31
+ this.order[0] = this.order[1];
32
+ this.order[1] = a;
33
+ }
34
+ }
35
+ const idx = this.order.pop();
36
+ this.last = idx;
37
+ return idx;
38
+ }
39
+ }
40
+ export function createSoundBank(opts = {}) {
41
+ const ownsContext = !opts.context;
42
+ let ctx = opts.context ?? null;
43
+ let master = null;
44
+ const buses = new Map();
45
+ const busTargetDb = new Map(); // pre-duck level, so unduck returns here
46
+ const events = new Map();
47
+ const bags = new Map();
48
+ const lastPlayedAt = new Map();
49
+ const live = new Map();
50
+ const bufferCache = new Map();
51
+ let assetList = [];
52
+ function ensureGraph() {
53
+ if (ctx && master)
54
+ return ctx;
55
+ const AC = typeof window !== "undefined"
56
+ ? window.AudioContext ?? window.webkitAudioContext
57
+ : undefined;
58
+ if (!ctx) {
59
+ if (!AC)
60
+ return null;
61
+ ctx = new AC();
62
+ }
63
+ master = ctx.createGain();
64
+ let tail = master;
65
+ if (opts.limiter !== false) {
66
+ const lim = ctx.createDynamicsCompressor();
67
+ lim.threshold.value = -3;
68
+ lim.knee.value = 0;
69
+ lim.ratio.value = 20;
70
+ lim.attack.value = 0.002;
71
+ lim.release.value = 0.15;
72
+ master.connect(lim);
73
+ tail = lim;
74
+ }
75
+ tail.connect(ctx.destination);
76
+ for (const cat of SOUND_CATEGORIES) {
77
+ const g = ctx.createGain();
78
+ g.connect(master);
79
+ buses.set(cat, g);
80
+ busTargetDb.set(cat, 0);
81
+ }
82
+ return ctx;
83
+ }
84
+ function busFor(cat) {
85
+ ensureGraph();
86
+ return buses.get(cat) ?? null;
87
+ }
88
+ async function decode(url) {
89
+ const cached = bufferCache.get(url);
90
+ if (cached)
91
+ return cached;
92
+ const p = (async () => {
93
+ const c = ensureGraph();
94
+ if (!c)
95
+ return null;
96
+ try {
97
+ const res = await fetch(url);
98
+ if (!res.ok)
99
+ return null;
100
+ const bytes = await res.arrayBuffer();
101
+ return await c.decodeAudioData(bytes);
102
+ }
103
+ catch {
104
+ return null;
105
+ }
106
+ })();
107
+ bufferCache.set(url, p);
108
+ return p;
109
+ }
110
+ function trackVoice(key, voice, maxVoices) {
111
+ const arr = live.get(key) ?? [];
112
+ arr.push(voice);
113
+ if (maxVoices && arr.length > maxVoices) {
114
+ const stolen = arr.shift();
115
+ try {
116
+ stolen?.stop();
117
+ }
118
+ catch {
119
+ /* already ended */
120
+ }
121
+ }
122
+ live.set(key, arr);
123
+ }
124
+ function untrackVoice(key, voice) {
125
+ const arr = live.get(key);
126
+ if (!arr)
127
+ return;
128
+ const i = arr.indexOf(voice);
129
+ if (i >= 0)
130
+ arr.splice(i, 1);
131
+ }
132
+ function pickClip(asset) {
133
+ if (asset.clips.length === 0)
134
+ return null;
135
+ if (asset.clips.length === 1)
136
+ return asset.clips[0] ?? null;
137
+ let bag = bags.get(asset.key);
138
+ if (!bag) {
139
+ bag = new Bag(asset.clips.length);
140
+ bags.set(asset.key, bag);
141
+ }
142
+ return asset.clips[bag.next()] ?? null;
143
+ }
144
+ function playStream(asset, clip, bus, c, o) {
145
+ if (typeof Audio === "undefined")
146
+ return null;
147
+ const media = new Audio();
148
+ media.crossOrigin = "anonymous";
149
+ media.src = clip.url;
150
+ media.loop = o.loop ?? (asset.category === "music" || asset.category === "ambience");
151
+ const src = c.createMediaElementSource(media);
152
+ const g = c.createGain();
153
+ g.gain.value = dbToGain((asset.gainDb ?? 0) + (o.gainDb ?? 0) + jitter(asset.variation?.volumeDb ?? 0));
154
+ src.connect(g).connect(bus);
155
+ void media.play().catch(() => undefined);
156
+ const voice = {
157
+ stop: () => {
158
+ media.pause();
159
+ try {
160
+ src.disconnect();
161
+ }
162
+ catch {
163
+ /* noop */
164
+ }
165
+ untrackVoice(asset.key, voice);
166
+ },
167
+ };
168
+ media.addEventListener("ended", () => voice.stop());
169
+ trackVoice(asset.key, voice, asset.variation?.maxVoices);
170
+ return { key: asset.key, stop: voice.stop };
171
+ }
172
+ return {
173
+ async load() {
174
+ let manifest = opts.manifest ?? null;
175
+ if (!manifest && opts.manifestUrl) {
176
+ try {
177
+ const res = await fetch(opts.manifestUrl, { cache: "no-cache" });
178
+ if (res.ok)
179
+ manifest = (await res.json());
180
+ }
181
+ catch {
182
+ manifest = null;
183
+ }
184
+ }
185
+ assetList = manifest?.sounds ?? [];
186
+ events.clear();
187
+ for (const a of assetList)
188
+ events.set(a.key, a);
189
+ },
190
+ async preload(keys) {
191
+ const targets = (keys ? keys.map((k) => events.get(k)) : assetList).filter((a) => !!a && !a.stream);
192
+ await Promise.all(targets.flatMap((a) => a.clips.map((cl) => decode(cl.url))));
193
+ },
194
+ play(key, o = {}) {
195
+ const asset = events.get(key);
196
+ if (!asset)
197
+ return null;
198
+ const now = typeof performance !== "undefined" ? performance.now() : Date.now();
199
+ const cd = asset.variation?.cooldownMs ?? 0;
200
+ if (cd > 0 && now - (lastPlayedAt.get(key) ?? -Infinity) < cd)
201
+ return null;
202
+ lastPlayedAt.set(key, now);
203
+ const c = ensureGraph();
204
+ if (!c)
205
+ return null;
206
+ if (c.state === "suspended")
207
+ void c.resume().catch(() => undefined);
208
+ const bus = busFor(asset.category);
209
+ if (!bus)
210
+ return null;
211
+ const clip = pickClip(asset);
212
+ if (!clip)
213
+ return null;
214
+ if (asset.stream)
215
+ return playStream(asset, clip, bus, c, o);
216
+ // Decode-to-memory path (SFX): fire-and-forget; the buffer is cached after first play.
217
+ const handle = { stopped: false, voice: null };
218
+ void decode(clip.url).then((buf) => {
219
+ if (!buf || handle.stopped)
220
+ return;
221
+ const src = c.createBufferSource();
222
+ src.buffer = buf;
223
+ src.loop = o.loop ?? false;
224
+ src.detune.value = jitter(asset.variation?.pitchCents ?? 0) + (o.detuneCents ?? 0);
225
+ const g = c.createGain();
226
+ g.gain.value = dbToGain((asset.gainDb ?? 0) + (o.gainDb ?? 0) + jitter(asset.variation?.volumeDb ?? 0));
227
+ src.connect(g).connect(bus);
228
+ const voice = {
229
+ stop: () => {
230
+ try {
231
+ src.stop();
232
+ }
233
+ catch {
234
+ /* already stopped */
235
+ }
236
+ untrackVoice(asset.key, voice);
237
+ },
238
+ };
239
+ src.addEventListener("ended", () => untrackVoice(asset.key, voice));
240
+ trackVoice(asset.key, voice, asset.variation?.maxVoices);
241
+ handle.voice = voice;
242
+ src.start();
243
+ });
244
+ return {
245
+ key,
246
+ stop: () => {
247
+ handle.stopped = true;
248
+ handle.voice?.stop();
249
+ },
250
+ };
251
+ },
252
+ stop(key) {
253
+ const arr = live.get(key);
254
+ if (!arr)
255
+ return;
256
+ for (const v of [...arr]) {
257
+ try {
258
+ v.stop();
259
+ }
260
+ catch {
261
+ /* noop */
262
+ }
263
+ }
264
+ live.set(key, []);
265
+ },
266
+ setBusVolume(category, db) {
267
+ busTargetDb.set(category, db);
268
+ const g = busFor(category);
269
+ if (g && ctx)
270
+ g.gain.setTargetAtTime(dbToGain(db), ctx.currentTime, 0.01);
271
+ },
272
+ setMasterVolume(db) {
273
+ ensureGraph();
274
+ if (master && ctx)
275
+ master.gain.setTargetAtTime(dbToGain(clamp(db, -60, 6)), ctx.currentTime, 0.01);
276
+ },
277
+ duck(category, db, ms = 120) {
278
+ const g = busFor(category);
279
+ if (!g || !ctx)
280
+ return;
281
+ const target = (busTargetDb.get(category) ?? 0) - Math.abs(db);
282
+ g.gain.setTargetAtTime(dbToGain(target), ctx.currentTime, Math.max(0.005, ms / 1000 / 3));
283
+ },
284
+ unduck(category, ms = 250) {
285
+ const g = busFor(category);
286
+ if (!g || !ctx)
287
+ return;
288
+ g.gain.setTargetAtTime(dbToGain(busTargetDb.get(category) ?? 0), ctx.currentTime, Math.max(0.005, ms / 1000 / 3));
289
+ },
290
+ keys: () => [...events.keys()],
291
+ assets: () => assetList.slice(),
292
+ dispose() {
293
+ for (const key of live.keys()) {
294
+ for (const v of live.get(key) ?? []) {
295
+ try {
296
+ v.stop();
297
+ }
298
+ catch {
299
+ /* noop */
300
+ }
301
+ }
302
+ }
303
+ live.clear();
304
+ bufferCache.clear();
305
+ if (ownsContext && ctx)
306
+ void ctx.close().catch(() => undefined);
307
+ ctx = null;
308
+ master = null;
309
+ buses.clear();
310
+ },
311
+ };
312
+ }
313
+ //# sourceMappingURL=sound-bank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sound-bank.js","sourceRoot":"","sources":["../../src/sounds/sound-bank.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA4B9C,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAU,EAAE,EAAU,EAAU,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3F,MAAM,QAAQ,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;AAC/D,2FAA2F;AAC3F,MAAM,MAAM,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEtF;;;;GAIG;AACH,MAAM,GAAG;IAGsB;IAFrB,KAAK,GAAa,EAAE,CAAC;IACrB,IAAI,GAAG,CAAC,CAAC,CAAC;IAClB,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;IAAG,CAAC;IAC7C,IAAI;QACF,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QAC7B,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;YAC5D,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC;gBAClC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC;gBACxC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;YACD,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzD,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC;gBAClC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC;gBACxC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAY,CAAC;QACvC,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;QAChB,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AA+BD,MAAM,UAAU,eAAe,CAAC,OAAyB,EAAE;IACzD,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;IAClC,IAAI,GAAG,GAAwB,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;IACpD,IAAI,MAAM,GAAoB,IAAI,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA2B,CAAC;IACjD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAyB,CAAC,CAAC,yCAAyC;IAE/F,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC5C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC5C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuC,CAAC;IACnE,IAAI,SAAS,GAAiB,EAAE,CAAC;IAEjC,SAAS,WAAW;QAClB,IAAI,GAAG,IAAI,MAAM;YAAE,OAAO,GAAG,CAAC;QAC9B,MAAM,EAAE,GACN,OAAO,MAAM,KAAK,WAAW;YAC3B,CAAC,CAAC,MAAM,CAAC,YAAY,IAAK,MAAkE,CAAC,kBAAkB;YAC/G,CAAC,CAAC,SAAS,CAAC;QAChB,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YACrB,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC;QACjB,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;QAC1B,IAAI,IAAI,GAAc,MAAM,CAAC;QAC7B,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,GAAG,CAAC,wBAAwB,EAAE,CAAC;YAC3C,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACzB,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;YACzB,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC;YACzB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACpB,IAAI,GAAG,GAAG,CAAC;QACb,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;YAC3B,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAClB,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,SAAS,MAAM,CAAC,GAAkB;QAChC,WAAW,EAAE,CAAC;QACd,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IAChC,CAAC;IAED,KAAK,UAAU,MAAM,CAAC,GAAW;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,MAAM,CAAC,GAAG,CAAC,KAAK,IAAiC,EAAE;YACjD,MAAM,CAAC,GAAG,WAAW,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC7B,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,OAAO,IAAI,CAAC;gBACzB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;gBACtC,OAAO,MAAM,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACxB,OAAO,CAAC,CAAC;IACX,CAAC;IAED,SAAS,UAAU,CAAC,GAAW,EAAE,KAAgB,EAAE,SAAkB;QACnE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChB,IAAI,SAAS,IAAI,GAAG,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC;gBACH,MAAM,EAAE,IAAI,EAAE,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,mBAAmB;YACrB,CAAC;QACH,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,SAAS,YAAY,CAAC,GAAW,EAAE,KAAgB;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC;YAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,SAAS,QAAQ,CAAC,KAAiB;QACjC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC5D,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC;IACzC,CAAC;IAED,SAAS,UAAU,CAAC,KAAiB,EAAE,IAAe,EAAE,GAAa,EAAE,CAAe,EAAE,CAAc;QACpG,IAAI,OAAO,KAAK,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9C,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;QAC1B,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;QAChC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;QACrB,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,IAAI,KAAK,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC;QACrF,MAAM,GAAG,GAAG,CAAC,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;QACzB,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC;QACxG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,KAAK,GAAc;YACvB,IAAI,EAAE,GAAG,EAAE;gBACT,KAAK,CAAC,KAAK,EAAE,CAAC;gBACd,IAAI,CAAC;oBACH,GAAG,CAAC,UAAU,EAAE,CAAC;gBACnB,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU;gBACZ,CAAC;gBACD,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACjC,CAAC;SACF,CAAC;QACF,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACpD,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACzD,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAI;YACR,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;YACrC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClC,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;oBACjE,IAAI,GAAG,CAAC,EAAE;wBAAE,QAAQ,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;gBACpE,CAAC;gBAAC,MAAM,CAAC;oBACP,QAAQ,GAAG,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;YACD,SAAS,GAAG,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC;YACnC,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,KAAK,MAAM,CAAC,IAAI,SAAS;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAClD,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,IAAe;YAC3B,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CACxE,CAAC,CAAC,EAAmB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CACzC,CAAC;YACF,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACjF,CAAC;QAED,IAAI,CAAC,GAAW,EAAE,IAAiB,EAAE;YACnC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9B,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC;YAExB,MAAM,GAAG,GAAG,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAChF,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,UAAU,IAAI,CAAC,CAAC;YAC5C,IAAI,EAAE,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;gBAAE,OAAO,IAAI,CAAC;YAC3E,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAE3B,MAAM,CAAC,GAAG,WAAW,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;YACpB,IAAI,CAAC,CAAC,KAAK,KAAK,WAAW;gBAAE,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACpE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,CAAC;YACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC;YAEvB,IAAI,KAAK,CAAC,MAAM;gBAAE,OAAO,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAE5D,uFAAuF;YACvF,MAAM,MAAM,GAAkD,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;YAC9F,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;gBACjC,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO;oBAAE,OAAO;gBACnC,MAAM,GAAG,GAAG,CAAC,CAAC,kBAAkB,EAAE,CAAC;gBACnC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;gBACjB,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC;gBAC3B,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;gBACnF,MAAM,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC;gBACzB,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC;gBACxG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAC5B,MAAM,KAAK,GAAc;oBACvB,IAAI,EAAE,GAAG,EAAE;wBACT,IAAI,CAAC;4BACH,GAAG,CAAC,IAAI,EAAE,CAAC;wBACb,CAAC;wBAAC,MAAM,CAAC;4BACP,qBAAqB;wBACvB,CAAC;wBACD,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;oBACjC,CAAC;iBACF,CAAC;gBACF,GAAG,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;gBACpE,UAAU,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBACzD,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;gBACrB,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;YAEH,OAAO;gBACL,GAAG;gBACH,IAAI,EAAE,GAAG,EAAE;oBACT,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;oBACtB,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;gBACvB,CAAC;aACF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,GAAW;YACd,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC1B,IAAI,CAAC,GAAG;gBAAE,OAAO;YACjB,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC;oBACH,CAAC,CAAC,IAAI,EAAE,CAAC;gBACX,CAAC;gBAAC,MAAM,CAAC;oBACP,UAAU;gBACZ,CAAC;YACH,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACpB,CAAC;QAED,YAAY,CAAC,QAAuB,EAAE,EAAU;YAC9C,WAAW,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,GAAG;gBAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC5E,CAAC;QAED,eAAe,CAAC,EAAU;YACxB,WAAW,EAAE,CAAC;YACd,IAAI,MAAM,IAAI,GAAG;gBAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACrG,CAAC;QAED,IAAI,CAAC,QAAuB,EAAE,EAAU,EAAE,EAAE,GAAG,GAAG;YAChD,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG;gBAAE,OAAO;YACvB,MAAM,MAAM,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/D,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5F,CAAC;QACD,MAAM,CAAC,QAAuB,EAAE,EAAE,GAAG,GAAG;YACtC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG;gBAAE,OAAO;YACvB,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACpH,CAAC;QAED,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE;QAE/B,OAAO;YACL,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC9B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;oBACpC,IAAI,CAAC;wBACH,CAAC,CAAC,IAAI,EAAE,CAAC;oBACX,CAAC;oBAAC,MAAM,CAAC;wBACP,UAAU;oBACZ,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,WAAW,CAAC,KAAK,EAAE,CAAC;YACpB,IAAI,WAAW,IAAI,GAAG;gBAAE,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAChE,GAAG,GAAG,IAAI,CAAC;YACX,MAAM,GAAG,IAAI,CAAC;YACd,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Sound-library data types — owned by the SDK (like world/character types), so the platform's
3
+ * `SoundService`/gallery and every game's `SoundBank` share ONE shape. A "sound" is modelled as an
4
+ * **event** (a stable key + a pool of clips + behaviour), not a bare file — so variation and the
5
+ * hardware-driven adaptive layer are additive later with no schema migration.
6
+ */
7
+ /** Mixer bus + organisational category. Each maps to an independently-controllable gain bus. */
8
+ export type SoundCategory = "sfx" | "music" | "ambience" | "ui" | "voice";
9
+ export declare const SOUND_CATEGORIES: readonly SoundCategory[];
10
+ /** One audio file in an event's pool. */
11
+ export interface SoundClip {
12
+ /** Public R2 URL of the audio (wav/mp3/ogg). */
13
+ url: string;
14
+ /** Original upload filename (display only). */
15
+ filename?: string;
16
+ /** Duration in seconds, measured at ingest. */
17
+ durationSec?: number;
18
+ }
19
+ /** Per-play randomisation. The runtime honours it on every {@link SoundBank.play}; all optional. */
20
+ export interface SoundVariation {
21
+ /** ± random detune per play, in cents (100 = one semitone). 0/undefined = none. */
22
+ pitchCents?: number;
23
+ /** ± random gain per play, in dB. 0/undefined = none. */
24
+ volumeDb?: number;
25
+ /** Drop retriggers of this event faster than this many ms (anti-machine-gun). */
26
+ cooldownMs?: number;
27
+ /** Cap simultaneous live voices of this event; the oldest is stolen. undefined = unlimited. */
28
+ maxVoices?: number;
29
+ }
30
+ /** Loudness measured at ingest — the input to future normalisation (P2). */
31
+ export interface SoundLoudness {
32
+ integratedLufs?: number;
33
+ peakDb?: number;
34
+ }
35
+ /** Provenance/attribution, e.g. for Freesound packs — feeds a future credits manifest. */
36
+ export interface SoundLicense {
37
+ source?: string;
38
+ author?: string;
39
+ url?: string;
40
+ note?: string;
41
+ }
42
+ /** A library entry: a named, foldered, taggable sound event games play by its stable {@link key}. */
43
+ export interface SoundAsset {
44
+ /** Stable play key AND Supabase row id (unique within the library): `sounds.play(key)`. */
45
+ key: string;
46
+ name: string;
47
+ label?: string;
48
+ category: SoundCategory;
49
+ /** Id of the {@link SoundFolder} this sound is filed under (authoring-only). null/undefined = unfiled. */
50
+ folderId?: string | null;
51
+ /** @deprecated Legacy free-text folder path; superseded by {@link folderId}. Kept for back-compat. */
52
+ folder?: string;
53
+ tags?: string[];
54
+ /** Clip pool. One entry today; many enables the random-container variation (P2). */
55
+ clips: SoundClip[];
56
+ /** Per-play randomisation. */
57
+ variation?: SoundVariation;
58
+ /** Static designer trim applied to every play, in dB. */
59
+ gainDb?: number;
60
+ /** Stream (music/ambience) instead of decoding fully into memory (sfx). */
61
+ stream?: boolean;
62
+ loudness?: SoundLoudness;
63
+ license?: SoundLicense;
64
+ /** Downsampled |amplitude| in 0..1 for instant waveform rendering in the gallery. */
65
+ peaks?: number[];
66
+ /** Epoch ms of last save. */
67
+ updatedAt?: number;
68
+ }
69
+ /**
70
+ * A folder in the authoring hierarchy — a first-class entity (stable id + parent), NOT a derived
71
+ * path. Sounds reference it by {@link SoundAsset.folderId}. Renaming touches one record; moving a
72
+ * subtree reparents one record. Folders are authoring-only and never published to games.
73
+ */
74
+ export interface SoundFolder {
75
+ id: string;
76
+ name: string;
77
+ /** Parent folder id, or null for a root folder. */
78
+ parentId: string | null;
79
+ }
80
+ /** The published, game-facing library snapshot (R2 `sounds/library.json`). */
81
+ export interface SoundLibraryManifest {
82
+ /** Epoch ms of the last Publish, or null if never published. */
83
+ generatedAt: number | null;
84
+ /** Bumped on each Publish — lets a SoundBank cache-bust. */
85
+ version?: number;
86
+ sounds: SoundAsset[];
87
+ }
88
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sounds/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,gGAAgG;AAChG,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC;AAC1E,eAAO,MAAM,gBAAgB,EAAE,SAAS,aAAa,EAAgD,CAAC;AAEtG,yCAAyC;AACzC,MAAM,WAAW,SAAS;IACxB,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,oGAAoG;AACpG,MAAM,WAAW,cAAc;IAC7B,mFAAmF;IACnF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0FAA0F;AAC1F,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,qGAAqG;AACrG,MAAM,WAAW,UAAU;IACzB,2FAA2F;IAC3F,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,aAAa,CAAC;IACxB,0GAA0G;IAC1G,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,sGAAsG;IACtG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,oFAAoF;IACpF,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,qFAAqF;IACrF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,8EAA8E;AAC9E,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Sound-library data types — owned by the SDK (like world/character types), so the platform's
3
+ * `SoundService`/gallery and every game's `SoundBank` share ONE shape. A "sound" is modelled as an
4
+ * **event** (a stable key + a pool of clips + behaviour), not a bare file — so variation and the
5
+ * hardware-driven adaptive layer are additive later with no schema migration.
6
+ */
7
+ export const SOUND_CATEGORIES = ["sfx", "music", "ambience", "ui", "voice"];
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sounds/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,MAAM,gBAAgB,GAA6B,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC"}
package/dist/ui/README.md CHANGED
@@ -44,8 +44,10 @@ feed its `{x, y, onScreen}` into `setScreenPos`/`setVisible` — don't compute p
44
44
  | `mountActionDiamond(host, opts)` | fn | The full 4-button A/B/Y/Z diamond with per-button labels/actions. |
45
45
  | `mountLabeledDiamond(host, opts)` | fn | A diamond floating over a point with labels around it (the "actions on offer" affordance). |
46
46
  | `mountDialogueCard(host, opts)` | fn | An NPC dialogue box: speaker name, typed-out line, advance cue (A). |
47
+ | `mountSubtitle(host, opts)` | fn | A boxless, self-dismissing caption (the voice-over "auto" look): big centred line + speaker name, no frame. `anchor`/`offset` place it; `showName` toggles the name. |
47
48
  | `mountChoiceCard(host, opts)` | fn | A player choice menu: prompt + highlighted option list (▲▼ move, A confirm). |
48
49
  | `mountRarityCard(host, opts)` / `buildRarityCard(opts)` | fn | A generic rarity-tinted item/creature card. |
50
+ | `createPowerRace(opts)` | fn | A timed **power-vs-deadline race** overlay — the "push NOW or lose it" beat. A charge bar (∫power dt) races a clock; first to 100% wins. `start()` then `setPower(w)`+`tick(dt)` per frame; `won`/`lost` via `onResolve`. Recolour with `theme`, relabel with `text`. |
49
51
  | `injectCss()` | fn | Force the `.rydr-ui-*` CSS into `<head>` early (components call it for you). |
50
52
 
51
53
  Types: `ButtonLetter` (`"A"\|"B"\|"Y"\|"Z"`), `DirButton`, `KeycapVariant` (`"full"\|"solo"`),
@@ -2,7 +2,7 @@
2
2
  * `@rydr/game-sdk/ui` — the reusable controller-button UI: a DOM/CSS keycap of the A/B/Y/Z face
3
3
  * buttons and the UP/DOWN/LEFT/RIGHT d-pad, plus higher-level pieces built from it (a dark glass card
4
4
  * with a content slot, an action card, the full A/B/Y/Z move diamond, an NPC dialogue card, a player
5
- * choice menu, a labeled diamond, and a generic rarity card). Games use it to show "which button to
5
+ * choice menu, a labeled diamond, a solo labeled diamond, and a generic rarity card). Games use it to show "which button to
6
6
  * press" in one consistent visual language across the library.
7
7
  *
8
8
  * Self-contained, like `@rydr/game-sdk/three`'s perf-overlay: it injects its own scoped `.rydr-ui-*`
@@ -26,7 +26,10 @@ export * from "./card.js";
26
26
  export * from "./action-card.js";
27
27
  export * from "./action-diamond.js";
28
28
  export * from "./dialogue-card.js";
29
+ export * from "./subtitle.js";
29
30
  export * from "./choice-card.js";
30
31
  export * from "./labeled-diamond.js";
32
+ export * from "./solo-labeled-diamond.js";
31
33
  export * from "./rarity-card.js";
34
+ export * from "./power-race.js";
32
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC"}
package/dist/ui/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * `@rydr/game-sdk/ui` — the reusable controller-button UI: a DOM/CSS keycap of the A/B/Y/Z face
3
3
  * buttons and the UP/DOWN/LEFT/RIGHT d-pad, plus higher-level pieces built from it (a dark glass card
4
4
  * with a content slot, an action card, the full A/B/Y/Z move diamond, an NPC dialogue card, a player
5
- * choice menu, a labeled diamond, and a generic rarity card). Games use it to show "which button to
5
+ * choice menu, a labeled diamond, a solo labeled diamond, and a generic rarity card). Games use it to show "which button to
6
6
  * press" in one consistent visual language across the library.
7
7
  *
8
8
  * Self-contained, like `@rydr/game-sdk/three`'s perf-overlay: it injects its own scoped `.rydr-ui-*`
@@ -26,7 +26,10 @@ export * from "./card.js";
26
26
  export * from "./action-card.js";
27
27
  export * from "./action-diamond.js";
28
28
  export * from "./dialogue-card.js";
29
+ export * from "./subtitle.js";
29
30
  export * from "./choice-card.js";
30
31
  export * from "./labeled-diamond.js";
32
+ export * from "./solo-labeled-diamond.js";
31
33
  export * from "./rarity-card.js";
34
+ export * from "./power-race.js";
32
35
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * `createPowerRace` — a timed power-race HUD: two bars race each other.
3
+ *
4
+ * · deadline bar — fills at a constant rate over `durationS` (the clock closing in).
5
+ * · charge bar — fills from accumulated effort (∫ power dt) toward
6
+ * `requiredJoules = targetFtpPct × ftp × durationS`.
7
+ *
8
+ * If the charge bar reaches 100% before the deadline bar does, the rider **wins**; otherwise the
9
+ * clock **wins** (the rider loses). Pacing is free — only total work matters. This is the canonical
10
+ * "push NOW or lose it" beat: a surge you must out-pedal before a timer runs out. It began as
11
+ * Tower-Defense's nuke-intercept mini-game and VIVAX's Vivapierre charge; both are the same widget.
12
+ *
13
+ * Pass `mode: "charge"` for the **no-rival** variant — a solo "charge this up" with no deadline bar and
14
+ * no clock that can beat you (it only resolves `won`, on fill). Same visuals, calmer framing.
15
+ *
16
+ * Self-contained DOM/CSS (no three.js), like the rest of `@rydr/game-sdk/ui`: it injects its own
17
+ * scoped `.rpr-*` stylesheet once into `<head>`. It takes **power values**, not a `session` — the
18
+ * game owns its loop and feeds watts in. FTP-relative by construction (`ftp` sets the bar to clear),
19
+ * so a 150 W and a 350 W rider face the same challenge — never hard-code a raw-watt threshold.
20
+ *
21
+ * ── Sizing contract (same as the rest of the kit) ──────────────────────────────────────────────
22
+ * Tuned for a trainer screen viewed from a few feet away while pedaling. Don't restyle the `.rpr-*`
23
+ * type sizes / dimensions or wrap it in `transform: scale()`. Recolour it with the `theme` option and
24
+ * relabel it with `text` — those are the customization surface; the layout is fixed.
25
+ * ────────────────────────────────────────────────────────────────────────────────────────────────
26
+ *
27
+ * Driving it: `start()`, then pump `setPower(w)` + `tick(dt)` every frame. The HUD self-resolves to
28
+ * `won` / `lost` when either bar crosses 100%; poll `getPhase()` or pass `onResolve`. Drive external
29
+ * VFX (a glow, a light) off `getProgress().charge`.
30
+ */
31
+ /** Layout of the two bars. Both drive the same class hooks. */
32
+ export type PowerRaceVariant = "twin-stacked" | "twin-towers";
33
+ /** Where the live precision % sits (or `null` to hide it). */
34
+ export type PowerRaceScoreVariant = "tip" | "impact" | "above" | "infill";
35
+ /** The internal phase machine; `won`/`lost` are the resolved outcomes. */
36
+ export type PowerRacePhase = "idle" | "priming-warning" | "priming-prompt" | "priming-bars" | "racing" | "won" | "lost";
37
+ /** The two terminal outcomes. */
38
+ export type PowerRaceOutcome = "won" | "lost";
39
+ /** Total intro duration in seconds. */
40
+ export declare const INTRO_TOTAL_S: number;
41
+ /**
42
+ * The six palette colours, driven into the component as CSS custom properties. Each bar is a
43
+ * `deep → bright` gradient; the win state recolours the charge bar green. The default is the original
44
+ * "alert" skin (red clock, cyan effort, green win); pass a `theme` (any subset) to recolour.
45
+ */
46
+ export interface PowerRaceTheme {
47
+ /** Deadline (clock) bar bright end + all its labels/glows. */
48
+ deadline: string;
49
+ /** Deadline bar gradient dark end. */
50
+ deadlineDeep: string;
51
+ /** Charge (effort) bar bright end + its label/glow. */
52
+ charge: string;
53
+ /** Charge bar gradient dark end. */
54
+ chargeDeep: string;
55
+ /** Win state bright end (the charge bar on a win + the "won" stamp). */
56
+ win: string;
57
+ /** Win state gradient dark end. */
58
+ winDeep: string;
59
+ }
60
+ /** The built-in "alert" skin — the proven Tower-Defense look. Default when no `theme` is passed. */
61
+ export declare const DEFAULT_POWER_RACE_THEME: Required<PowerRaceTheme>;
62
+ /** Every user-facing string. Defaults reproduce the original alert copy; override per game. */
63
+ export interface PowerRaceText {
64
+ heading?: string;
65
+ prompt?: string;
66
+ deadlineLabel?: string;
67
+ chargeLabel?: string;
68
+ win?: string;
69
+ lose?: string;
70
+ }
71
+ export interface PowerRaceOpts {
72
+ /** Rider FTP — sets the effort target (`requiredJoules`). Always FTP-relative; never a raw threshold. */
73
+ ftp?: number;
74
+ /** How long the deadline bar takes to fill (seconds). Default 5. */
75
+ durationS?: number;
76
+ /** Effort target as a fraction of FTP: `requiredJoules = targetFtpPct × ftp × durationS`. Default 1.1. */
77
+ targetFtpPct?: number;
78
+ /**
79
+ * `"race"` (default) — a rival **deadline** bar races you; you lose if it fills first (the "push NOW
80
+ * or lose it" beat). `"charge"` — **no rival**: you just fill the charge bar (a solo "charge this
81
+ * up"). In charge mode the deadline bar is hidden, the alarm framing is calmed (no red klaxon
82
+ * strobe), and the widget only ever resolves `won` on its own (charge → 100%). There's no built-in
83
+ * clock, so a rider can charge at their own pace; a game that wants a *failure* (e.g. the rider was
84
+ * downed, or a scene timeout) drives it with `showResolution("lost")`. `durationS` still sets how
85
+ * much work fills the bar (`requiredJoules`); it just isn't a losing clock. Relabel the alarm copy
86
+ * for a charge with `text` (e.g. `heading: "CHARGING"`, `prompt: "PUSH TO CHARGE"`).
87
+ */
88
+ mode?: "race" | "charge";
89
+ /** Bar layout. Default `twin-stacked`. */
90
+ variant?: PowerRaceVariant;
91
+ /** Live precision-% placement, or `null`/omitted to hide it. */
92
+ scoreVariant?: PowerRaceScoreVariant | null;
93
+ /** All user-facing strings (any subset). */
94
+ text?: PowerRaceText;
95
+ /** Palette override (any subset). Defaults to {@link DEFAULT_POWER_RACE_THEME}. */
96
+ theme?: Partial<PowerRaceTheme>;
97
+ /** Called once when the race resolves. Same signal as polling `getPhase()`. */
98
+ onResolve?: (outcome: PowerRaceOutcome) => void;
99
+ }
100
+ export interface PowerRaceHud {
101
+ /** The overlay root — append it to your HUD layer. */
102
+ element: HTMLElement;
103
+ /** Begin the priming intro, then the race. */
104
+ start(): void;
105
+ /** Feed the current power (watts) each frame. */
106
+ setPower(w: number): void;
107
+ /** Current phase; `won`/`lost` once resolved. */
108
+ getPhase(): PowerRacePhase;
109
+ /** Live bar fills 0..1 — drive external VFX (e.g. a glow) off `charge`. */
110
+ getProgress(): {
111
+ deadline: number;
112
+ charge: number;
113
+ };
114
+ /** Advance one frame; returns the (possibly new) phase. Self-resolves + fires `onResolve`. */
115
+ tick(dt: number): PowerRacePhase;
116
+ /** Force a resolution (e.g. an externally decided outcome), optionally auto-hiding after `durationS`. */
117
+ showResolution(outcome: PowerRaceOutcome, opts?: {
118
+ durationS?: number;
119
+ }): void;
120
+ /** Back to idle (hidden, bars cleared) for reuse. */
121
+ reset(): void;
122
+ dispose(): void;
123
+ }
124
+ export declare function createPowerRace(opts?: PowerRaceOpts): PowerRaceHud;
125
+ //# sourceMappingURL=power-race.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"power-race.d.ts","sourceRoot":"","sources":["../../src/ui/power-race.ts"],"names":[],"mappings":"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"}