narraleaf-react 0.23.0 → 0.23.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.
- package/dist/game/nlcore/common/game.d.ts +4 -4
- package/dist/game/nlcore/game/audioBus.d.ts +41 -2
- package/dist/game/nlcore/game.d.ts +7 -6
- package/dist/game/player/elements/player/PreferenceUpdateAnnouncer.d.ts +11 -5
- package/dist/game/player/lib/AudioManager.d.ts +0 -15
- package/dist/main.js +36 -36
- package/package.json +115 -115
|
@@ -3,11 +3,11 @@ import { GameState } from "../../player/gameState";
|
|
|
3
3
|
import { Storable, Namespace } from "../elements/persistent/storable";
|
|
4
4
|
import { LiveGame } from "../game/liveGame";
|
|
5
5
|
import { Preference } from "../game/preference";
|
|
6
|
-
import { AudioBusError, AudioBusMixer, AudioBusTree, DefaultAudioBusIds, MaxAudioBusDepth, acceptsAudioBus, getActiveAudioBusTree } from "../game/audioBus";
|
|
7
|
-
import type { AudioBusDeclaration, AudioBusNode, AudioBusState } from "../game/audioBus";
|
|
6
|
+
import { AudioBusError, AudioBusMixer, AudioBusTree, DefaultAudioBusIds, MaxAudioBusDepth, SeededBusPreferenceKeys, acceptsAudioBus, getActiveAudioBusTree } from "../game/audioBus";
|
|
7
|
+
import type { AudioBusAlias, AudioBusDeclaration, AudioBusNode, AudioBusState } from "../game/audioBus";
|
|
8
8
|
import type { StorableChange, StorableRestore } from "../elements/persistent/storable";
|
|
9
9
|
import type { SavedGame } from "../gameTypes";
|
|
10
10
|
import type { StackSnapshot, StackFrameSnapshot } from "../action/stackModel";
|
|
11
11
|
import { KeyMap } from "../game/keyMap";
|
|
12
|
-
export { LiveGame, GameState, Game, Storable, Namespace, Preference, KeyMap, AudioBusError, AudioBusMixer, AudioBusTree, DefaultAudioBusIds, MaxAudioBusDepth, acceptsAudioBus, getActiveAudioBusTree, };
|
|
13
|
-
export type { AudioBusDeclaration, AudioBusNode, AudioBusState, SavedGame, StackSnapshot, StackFrameSnapshot, StorableChange, StorableRestore, };
|
|
12
|
+
export { LiveGame, GameState, Game, Storable, Namespace, Preference, KeyMap, AudioBusError, AudioBusMixer, AudioBusTree, DefaultAudioBusIds, MaxAudioBusDepth, SeededBusPreferenceKeys, acceptsAudioBus, getActiveAudioBusTree, };
|
|
13
|
+
export type { AudioBusAlias, AudioBusDeclaration, AudioBusNode, AudioBusState, SavedGame, StackSnapshot, StackFrameSnapshot, StorableChange, StorableRestore, };
|
|
@@ -174,6 +174,33 @@ export declare function acceptsAudioBus(busId: string, ancestorIds: readonly str
|
|
|
174
174
|
type AudioBusEvents = {
|
|
175
175
|
"event:audioBus.volumeChange": [string, number, number];
|
|
176
176
|
};
|
|
177
|
+
/**
|
|
178
|
+
* Somewhere other than the mixer that already stores a bus's player volume.
|
|
179
|
+
*
|
|
180
|
+
* There is exactly one of these in the engine: the three volume preferences. `voiceVolume` is not
|
|
181
|
+
* a number that gets *copied* onto the voice bus, it **is** the voice bus's player volume, reached
|
|
182
|
+
* through this. A bus with an alias has no entry in the mixer's own map at all, so there is one
|
|
183
|
+
* store and one writer and nothing can overwrite anything.
|
|
184
|
+
*
|
|
185
|
+
* Structural on purpose - `audioBus.ts` stays free of imports, and a test can hand it a real
|
|
186
|
+
* `Preference` and exercise exactly what `Game` wires up.
|
|
187
|
+
*/
|
|
188
|
+
export type AudioBusAlias = {
|
|
189
|
+
get(): number;
|
|
190
|
+
set(volume: number): void;
|
|
191
|
+
/** Fires when the backing store changes by any route, including one that bypasses the mixer. */
|
|
192
|
+
subscribe(listener: (volume: number) => void): {
|
|
193
|
+
cancel: () => void;
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* The preference key that *is* each seeded bus's player volume.
|
|
198
|
+
*/
|
|
199
|
+
export declare const SeededBusPreferenceKeys: {
|
|
200
|
+
readonly bgm: "bgmVolume";
|
|
201
|
+
readonly sound: "soundVolume";
|
|
202
|
+
readonly voice: "voiceVolume";
|
|
203
|
+
};
|
|
177
204
|
/**
|
|
178
205
|
* The per-game mixer: the declared tree, plus what the player has done to it.
|
|
179
206
|
*
|
|
@@ -200,14 +227,22 @@ export declare class AudioBusMixer {
|
|
|
200
227
|
readonly "event:audioBus.volumeChange": "event:audioBus.volumeChange";
|
|
201
228
|
};
|
|
202
229
|
readonly events: EventDispatcher<AudioBusEvents>;
|
|
203
|
-
/**
|
|
230
|
+
/**
|
|
231
|
+
* The player's half, for buses that do not have an alias. Absent means "untouched", which is
|
|
232
|
+
* 1 — not 0, and not the declaration.
|
|
233
|
+
*/
|
|
204
234
|
private readonly overrides;
|
|
235
|
+
private readonly aliases;
|
|
236
|
+
private readonly aliasTokens;
|
|
205
237
|
private tree;
|
|
206
238
|
/**
|
|
207
239
|
* @param declarations - Read lazily, so a host that calls `configure()` between constructing
|
|
208
240
|
* the `Game` and mounting the player still gets the tree it declared.
|
|
241
|
+
* @param aliases - Buses whose player volume is stored somewhere else, by bus id. See
|
|
242
|
+
* {@link AudioBusAlias}; in the engine this is the three volume preferences and nothing else.
|
|
209
243
|
*/
|
|
210
|
-
constructor(declarations: () => readonly AudioBusDeclaration[]);
|
|
244
|
+
constructor(declarations: () => readonly AudioBusDeclaration[], aliases?: Record<string, AudioBusAlias>);
|
|
245
|
+
private announce;
|
|
211
246
|
/**
|
|
212
247
|
* The resolved tree, resolving it on first use and caching it afterwards.
|
|
213
248
|
*
|
|
@@ -244,6 +279,10 @@ export declare class AudioBusMixer {
|
|
|
244
279
|
* A bus the player has never touched reads 1 whatever the author declared, which is what makes
|
|
245
280
|
* a slider bound to this sit at maximum on a fresh install and what makes the persisted value
|
|
246
281
|
* mean "what the player did" rather than "what the game shipped with".
|
|
282
|
+
*
|
|
283
|
+
* For the three seeded buses this reads the corresponding volume preference, because that
|
|
284
|
+
* preference *is* this number. `mixer.getVolume("voice")` and `getPreference("voiceVolume")`
|
|
285
|
+
* cannot disagree; there is only one of them.
|
|
247
286
|
*/
|
|
248
287
|
getVolume(id: string): number;
|
|
249
288
|
/**
|
|
@@ -74,17 +74,18 @@ export declare class Game {
|
|
|
74
74
|
* at any point after `new Game(...)` is safe; if the channels do not exist yet the value is
|
|
75
75
|
* applied the moment they do.
|
|
76
76
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* declared.
|
|
77
|
+
* `bgmVolume`, `soundVolume` and `voiceVolume` **are** the player's half of the three seeded
|
|
78
|
+
* buses — not numbers copied onto them. `game.audioBuses.getVolume("voice")` and
|
|
79
|
+
* `game.preference.getPreference("voiceVolume")` read the same storage and cannot disagree,
|
|
80
|
+
* and writing either drives the audio graph immediately, mounted or not. Both surfaces stay
|
|
81
|
+
* supported; use whichever suits, and use this one for buses the host declared.
|
|
82
|
+
* (`globalVolume` is the master output, not a bus, and is unchanged.)
|
|
82
83
|
*
|
|
83
84
|
* @example
|
|
84
85
|
* ```ts
|
|
85
86
|
* // persist the player's half only - the author's mix comes back with the game
|
|
86
87
|
* localStorage.setItem("mixer", JSON.stringify(game.audioBuses.getVolumes()));
|
|
87
|
-
* // restore, any time after `new Game(...)`
|
|
88
|
+
* // restore, any time after `new Game(...)` - no ordering requirement, seeded or not
|
|
88
89
|
* game.audioBuses.setVolumes(JSON.parse(localStorage.getItem("mixer") ?? "{}"));
|
|
89
90
|
* ```
|
|
90
91
|
*/
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { GameState } from "../../../../game/nlcore/common/game";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Carries `globalVolume` — and only `globalVolume` — from the preferences to the audio subsystem.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* The three *bus* volumes used to be pushed from here too, one `useEffect` each. They are gone, and
|
|
6
|
+
* their absence is the point: `bgmVolume`/`soundVolume`/`voiceVolume` **are** the player's half of
|
|
7
|
+
* the three seeded buses now, read straight through by `game.audioBuses`, so there is nothing left
|
|
8
|
+
* to copy. Copying them from a mounted component is what broke the feature twice — the effects fire
|
|
9
|
+
* on mount with whatever the preference happens to hold, which erased first the author's declared
|
|
10
|
+
* mix and then a player override the host had restored a moment earlier. It also meant a preference
|
|
11
|
+
* written while no player was mounted reached the graph only on the next mount.
|
|
12
|
+
*
|
|
13
|
+
* `globalVolume` stays because it is the master output rather than a bus — it has no declared half
|
|
14
|
+
* and no gain node in the tree.
|
|
9
15
|
*/
|
|
10
16
|
export default function PreferenceUpdateAnnouncer({ gameState }: Readonly<{
|
|
11
17
|
gameState: GameState;
|
|
@@ -263,19 +263,4 @@ export declare class AudioManager {
|
|
|
263
263
|
setGlobalVolume(volume: number): void;
|
|
264
264
|
getGlobalVolume(): number;
|
|
265
265
|
destroy(): void;
|
|
266
|
-
/**
|
|
267
|
-
* The three volume preferences are aliases onto the three seeded buses, and this is the alias.
|
|
268
|
-
*
|
|
269
|
-
* They stay the way a player's music/sfx/voice sliders are driven - widening the preference key
|
|
270
|
-
* union to cover arbitrary bus ids is not possible without reshaping `GamePreference`, and is
|
|
271
|
-
* not needed: a host bus is driven through {@link AudioManager.setBusVolume} instead.
|
|
272
|
-
*
|
|
273
|
-
* They write the **player's** half only. This used to write the bus's whole gain, and because
|
|
274
|
-
* these preferences default to 1 it meant that a host declaring `{id: "sound", volume: 0.6}`
|
|
275
|
-
* had its mix silently overwritten with 1 the moment the audio subsystem started - the author
|
|
276
|
-
* set SFX to 60% and every player heard 100%. Custom buses were unaffected because nothing
|
|
277
|
-
* aliases them, so the three buses every existing project uses were the only ones that ignored
|
|
278
|
-
* the declaration. Now `soundVolume: 1` means "do not attenuate further" and 0.6 survives.
|
|
279
|
-
*/
|
|
280
|
-
private setupGroupVolume;
|
|
281
266
|
}
|