@jgengine/shell 0.31.0 → 0.32.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.
- package/CHANGELOG.md +19 -0
- package/dist/Shell3dPresentation.js +1 -1
- package/dist/ShellChrome.d.ts +3 -1
- package/dist/ShellChrome.js +3 -2
- package/dist/ShellHudPresentation.js +1 -1
- package/dist/audio/CaptionOverlay.d.ts +15 -0
- package/dist/audio/CaptionOverlay.js +50 -0
- package/dist/audio/FeedbackHost.d.ts +14 -0
- package/dist/audio/FeedbackHost.js +42 -0
- package/dist/audio/audioEngine.d.ts +25 -0
- package/dist/audio/audioEngine.js +166 -8
- package/dist/audio/audioProbe.d.ts +22 -0
- package/dist/audio/audioProbe.js +20 -0
- package/dist/audio/busMix.d.ts +4 -0
- package/dist/audio/busMix.js +7 -0
- package/dist/audio/captions.d.ts +48 -0
- package/dist/audio/captions.js +77 -0
- package/dist/audio/eventFeedback.d.ts +127 -0
- package/dist/audio/eventFeedback.js +268 -0
- package/dist/audio/gestureResume.d.ts +10 -0
- package/dist/audio/gestureResume.js +25 -0
- package/dist/audio/playableAudio.d.ts +1 -1
- package/dist/audio/playableAudio.js +3 -1
- package/dist/settings/appliedSettings.js +3 -0
- package/dist/settings/settingsController.js +15 -0
- package/package.json +4 -4
- package/skills/jgengine/api.md +3 -2
- package/skills/jgengine-ui/SKILL.md +1 -0
- package/skills/jgengine-ui/api.md +50 -1
- package/skills/jgengine-ui/capabilities.md +32 -0
- package/skills/jgengine-ui/reference.md +1 -1
- package/skills/jgengine-world/api.md +14 -4
- package/skills/jgengine-world/capabilities.md +4 -0
|
@@ -2139,15 +2139,64 @@
|
|
|
2139
2139
|
- `EntityAudioEmitters` (function): function EntityAudioEmitters({ engine, entitySounds, }: { engine: AudioEngine; entitySounds: Record<string, string> | undefined; }): null — ⚠ undocumented
|
|
2140
2140
|
- `ObjectAudioEmitters` (function): function ObjectAudioEmitters({ engine, objectSounds, }: { engine: AudioEngine; objectSounds: Record<string, string> | undefined; }): null — ⚠ undocumented
|
|
2141
2141
|
|
|
2142
|
+
## @jgengine/shell/audio/CaptionOverlay
|
|
2143
|
+
|
|
2144
|
+
- `CaptionOverlay` (function): function CaptionOverlay({ feed, max = 2, zIndex = 84, }: { feed: CaptionFeed; /** How many lines to show at once. Default 2. */ max?: number; zIndex?: number; }): ReactNode — The captions line: a bounded, bottom-centred stack that renders only while the accessibility captions setting is on. Reads HudTheme tokens, so a game's theme reskins it, and lives in the same overlay layer as the notice stack.
|
|
2145
|
+
|
|
2146
|
+
## @jgengine/shell/audio/FeedbackHost
|
|
2147
|
+
|
|
2148
|
+
- `FeedbackHost` (function): function FeedbackHost({ ctx, engine }: { ctx: GameContext; engine: AudioEngine }): ReactNode — Mounts the engine's feel layer for one game: announced events become a sound, a gamepad pulse, a camera kick and a caption line; the audio context unlocks on the first gesture; and the caption stack follows the accessibility setting. Games supply sounds, never the rules.
|
|
2149
|
+
|
|
2142
2150
|
## @jgengine/shell/audio/audioEngine
|
|
2143
2151
|
|
|
2144
2152
|
- `AudioEmitterHandle` (interface): interface AudioEmitterHandle { isPlaying?(): boolean; setPosition(position: Vec3): void; setRate(rate: number): void; setGain(gain: number): void; setLowpass(hz: number): void; setHighpass(hz: number): void; setVelocity(velocity: Vec3): void; stop(): void } — ⚠ undocumented
|
|
2145
|
-
- `AudioEngine` (interface): interface AudioEngine { setListenerPose(pose: ListenerPose | Vec3): void; setVoiceLimit(maxTotal: number, overflow?: VoiceAllocatorConfig["overflow"]): void;
|
|
2153
|
+
- `AudioEngine` (interface): interface AudioEngine { setListenerPose(pose: ListenerPose | Vec3): void; setVoiceLimit(maxTotal: number, overflow?: VoiceAllocatorConfig["overflow"]): void; play(soundId: string, position?: Vec3): void; playOneShot(soundId: string, position?: Vec3): void; playL… — ⚠ undocumented · used by `createAudioEngine`: Game-owned sound catalog playback with bounded SFX reservations, spatial panning, and shared buses.
|
|
2154
|
+
- `AudioLevel` (interface): interface AudioLevel — Master-output level, `0..1`. Pooled by {@link AudioEngine.measure} - read it, don't retain it.
|
|
2146
2155
|
- `AudioSceneConfig` (interface): interface AudioSceneConfig { sounds?: Record<string, SoundDef>; maxVoices?: number; voiceOverflow?: VoiceAllocatorConfig["overflow"]; voiceAllocator?: VoiceAllocator; buses?: Record<string, AudioBusDef>; music?: Record<string, MusicTheme>; musicBus?: string } — ⚠ undocumented · used by `createAudioEngine`: Game-owned sound catalog playback with bounded SFX reservations, spatial panning, and shared buses.
|
|
2147
2156
|
- `ListenerPose` (interface): interface ListenerPose — Position and orientation for a spatial-audio listener.
|
|
2157
|
+
- `MAX_PENDING_CUES` (const): const MAX_PENDING_CUES: 16 — Cues held while the browser keeps the audio context suspended, before any user gesture.
|
|
2148
2158
|
- `Vec3` (interface): interface Vec3 { x: number; y: number; z: number } — ⚠ undocumented · used by `coverPoints` (@jgengine/core/ai/tacticalQueries): Returns boundary locations that are hidden from a threat.
|
|
2149
2159
|
- `createAudioEngine` (function): function createAudioEngine(config: AudioSceneConfig = {}): AudioEngine — Game-owned sound catalog playback with bounded SFX reservations, spatial panning, and shared buses.
|
|
2150
2160
|
|
|
2161
|
+
## @jgengine/shell/audio/audioProbe
|
|
2162
|
+
|
|
2163
|
+
- `AudioProbe` (interface): interface AudioProbe — The read-only handle a capture script or devtools uses to prove the mix is producing sound.
|
|
2164
|
+
- `installAudioProbe` (function): function installAudioProbe(engine: AudioEngine): () => void — Publish the audio engine's own level readout on `window.__jgengineAudio`, so a headless capture can state a measured RMS instead of guessing from a screenshot. Reads only; it never plays or changes a bus.
|
|
2165
|
+
|
|
2166
|
+
## @jgengine/shell/audio/busMix
|
|
2167
|
+
|
|
2168
|
+
- `MASTER_MUTE_SETTING_ID` (const): const MASTER_MUTE_SETTING_ID: "sound.muted" — Persisted mute for the whole mix, next to `sound.master`.
|
|
2169
|
+
- `busMuteSettingId` (function): function busMuteSettingId(busId: string): string — Persisted mute for one bus, next to its `busVolumeSettingId(busId)` volume.
|
|
2170
|
+
|
|
2171
|
+
## @jgengine/shell/audio/captions
|
|
2172
|
+
|
|
2173
|
+
- `Caption` (interface): interface Caption — One caption line as the overlay renders it.
|
|
2174
|
+
- `CaptionFeed` (interface): interface CaptionFeed — A capped, self-expiring list of caption lines that the accessibility captions setting turns on.
|
|
2175
|
+
- `CaptionFeedConfig` (interface): interface CaptionFeedConfig — Tunables for {@link createCaptionFeed}; all retunable at runtime.
|
|
2176
|
+
- `createCaptionFeed` (function): function createCaptionFeed(config: CaptionFeedConfig = {}): CaptionFeed — The caption list the feedback seam writes to and the HUD overlay reads: bounded, self-expiring, and deduped so three hits read as "Hit x3" rather than three copies. Pure state with an injected clock, so it runs headless.
|
|
2177
|
+
|
|
2178
|
+
## @jgengine/shell/audio/eventFeedback
|
|
2179
|
+
|
|
2180
|
+
- `AnyFeedbackBinding` (type): type AnyFeedbackBinding = { [Name in FeedbackEventName]: FeedbackBinding<Name> }[FeedbackEventName] — Any row of the event mapping, whichever event it binds.
|
|
2181
|
+
- `DEFAULT_FEEDBACK_BINDINGS` (const): const DEFAULT_FEEDBACK_BINDINGS: readonly AnyFeedbackBinding[] — The default mapping: each engine-announced gameplay event to the cue it raises. Damage to the local player reads as hurt, damage anywhere else as a hit; a wave start has no event of its own, so a game announces it through `notify("wave")` or `attachWaveFeedback`.
|
|
2182
|
+
- `DEFAULT_FEEDBACK_REACTIONS` (const): const DEFAULT_FEEDBACK_REACTIONS: Readonly<Record<FeedbackCue, FeedbackReaction>> — The default reactions. They are data: a game overrides one through `audio.feedbackCues` (sound) or `createEventFeedback({ reactions })` (haptics, shake, caption), and replaces the mapping through `bindings` without touching the shell.
|
|
2183
|
+
- `EventFeedback` (interface): interface EventFeedback — The event-to-reaction seam. One instance per running world.
|
|
2184
|
+
- `EventFeedbackOptions` (interface): interface EventFeedbackOptions — Options a game or host may override.
|
|
2185
|
+
- `FeedbackAnnouncer` (interface): interface FeedbackAnnouncer — The slice of `ctx.game.feedback` a wave runner needs, so this runs headless in a test.
|
|
2186
|
+
- `FeedbackBinding` (type): type FeedbackBinding<Name extends FeedbackEventName = FeedbackEventName> = { event: Name; cue: FeedbackCue; /** Default `"any"`. `"local"` only fires for the local player's own target/user/refusal. */ scope?: FeedbackScope; /** Overrides the cue's caption for this event, e.g. "You died". */ caption?… — One row of the event mapping: `event` announces, `cue` reacts.
|
|
2187
|
+
- `FeedbackDeps` (interface): interface FeedbackDeps — Everything the feedback seam reaches outside itself. Injected so it runs headless.
|
|
2188
|
+
- `FeedbackEventName` (type): type FeedbackEventName = | "combat.damage" | "entity.died" | "worldItem.picked_up" | "quest.completed" | "stat.levelUp" | "command.refused" — Event names the default mapping listens to; a game may add its own through `bindings`.
|
|
2189
|
+
- `FeedbackReaction` (interface): interface FeedbackReaction — One cue's reaction: what plays, what the hand feels, what the screen does, and what a caption says.
|
|
2190
|
+
- `FeedbackScope` (type): type FeedbackScope = "local" | "remote" | "any" — Which side of an event a binding reacts to: the local player's, someone else's, or either.
|
|
2191
|
+
- `ResolvedFeedback` (interface): interface ResolvedFeedback — A resolved trigger: pooled per binding, so a busy event stream allocates nothing to decide.
|
|
2192
|
+
- `attachEventFeedback` (function): function attachEventFeedback(events: Pick<GameEvents, "on">, feedback: EventFeedback, eventsToBind: readonly FeedbackEventName[] = Object.keys( DEFAULT_FEEDBACK_BINDINGS.reduce<Record<string, true>>((names, binding) => { names[binding.event] = true; return names; }, {}), ) as FeedbackEventName[]): (… — Subscribe the feedback seam to a game's event bus, including `feedback.cue` for moments the game announces itself. Returns the detach function; the mapping and reactions stay override-able through the seam's `retune`.
|
|
2193
|
+
- `attachWaveFeedback` (function): function attachWaveFeedback(runner: Pick<WaveRunner, "state" | "subscribe">, announce: FeedbackAnnouncer): () => void — Announce each new wave a {@link WaveRunner} starts as the `wave` cue, once per boundary. A wave has no event of its own, so this is the engine-side hookup for tower defense and wave survival games: `attachWaveFeedback(runner, ctx.game.feedback)`. Nothing is polled, the runner's own notification drives it, and one `update` that crosses two waves still fires once - the cue has a cooldown and the next boundary is announced by the next crossing.
|
|
2194
|
+
- `createEventFeedback` (function): function createEventFeedback(deps: FeedbackDeps, options: EventFeedbackOptions = {}): EventFeedback — Build the event-to-sound/haptic/shake/caption seam. The mapping is data ({@link DEFAULT_FEEDBACK_BINDINGS}), reactions are data ({@link DEFAULT_FEEDBACK_REACTIONS}), and the resolved trigger for each binding is allocated once - handling an event allocates only the caption string it actually shows, never per frame.
|
|
2195
|
+
|
|
2196
|
+
## @jgengine/shell/audio/gestureResume
|
|
2197
|
+
|
|
2198
|
+
- `installGestureResume` (function): function installGestureResume(engine: Pick<AudioEngine, "resume">, target: Pick<Document, "addEventListener" | "removeEventListener"> | null = typeof document === "undefined" ? null : document): () => void — Resume the audio context on the first real user gesture. Chrome keeps a freshly created `AudioContext` suspended until the page sees a trusted input, so pressing a key, tapping or clicking is the only moment sound may start; the engine then flushes any cue it held. One listener set per game, removed on unmount.
|
|
2199
|
+
|
|
2151
2200
|
## @jgengine/shell/audio/loopParams
|
|
2152
2201
|
|
|
2153
2202
|
- `MAX_LOOP_CUTOFF` (const): const MAX_LOOP_CUTOFF: 22050 — Highest live filter cutoff, Hz; the engine also caps it at the context's Nyquist frequency.
|
|
@@ -64,6 +64,18 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
64
64
|
|
|
65
65
|
- `readModelAnimationParams` (function) · `import { readModelAnimationParams } from "@jgengine/shell/render/useModelAnimation"`
|
|
66
66
|
|
|
67
|
+
## attach-event-feedback — one call wires every announced combat/loot/objective/refusal event to its reaction
|
|
68
|
+
|
|
69
|
+
- `attachEventFeedback` (function) · `import { attachEventFeedback } from "@jgengine/shell/audio/eventFeedback"`
|
|
70
|
+
|
|
71
|
+
## attach-wave-feedback — fire the wave cue once whenever a wave runner crosses into a new wave
|
|
72
|
+
|
|
73
|
+
- `attachWaveFeedback` (function) · `import { attachWaveFeedback } from "@jgengine/shell/audio/eventFeedback"`
|
|
74
|
+
|
|
75
|
+
## audio-probe — read the live master RMS/peak and bus gains from a running page for capture and diagnostics
|
|
76
|
+
|
|
77
|
+
- `installAudioProbe` (function) · `import { installAudioProbe } from "@jgengine/shell/audio/audioProbe"`
|
|
78
|
+
|
|
67
79
|
## authored-flocks — render authored habitat agents through caller-selected animated species models with velocity orientation and bounded model lifetime
|
|
68
80
|
|
|
69
81
|
- `AuthoredFlocks` (function) · `import { AuthoredFlocks } from "@jgengine/shell/world/AuthoredFlocks"`
|
|
@@ -114,6 +126,14 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
114
126
|
|
|
115
127
|
- `isCameraOccluderTransparent` (function) · `import { isCameraOccluderTransparent } from "@jgengine/shell/camera"`
|
|
116
128
|
|
|
129
|
+
## caption-feed — bounded, self-expiring, deduped caption lines for the accessibility captions overlay
|
|
130
|
+
|
|
131
|
+
- `createCaptionFeed` (function) · `import { createCaptionFeed } from "@jgengine/shell/audio/captions"`
|
|
132
|
+
|
|
133
|
+
## caption-overlay — render the caption feed as a themed, screen-reader-announced line stack gated by the captions accessibility setting
|
|
134
|
+
|
|
135
|
+
- `CaptionOverlay` (function) · `import { CaptionOverlay } from "@jgengine/shell/audio/CaptionOverlay"`
|
|
136
|
+
|
|
117
137
|
## capture-canvas — read the live R3F frame to a PNG data URL (needs preserveDrawingBuffer)
|
|
118
138
|
|
|
119
139
|
- `captureCanvas` (function) · `import { captureCanvas } from "@jgengine/shell/render/sceneCapture"`
|
|
@@ -285,6 +305,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
285
305
|
|
|
286
306
|
- `EntitySummary` (function) · `import { EntitySummary } from "@jgengine/react"`
|
|
287
307
|
|
|
308
|
+
## event-feedback — map announced gameplay events (damage, kill, pickup, objective, wave, refusal) to a sound, gamepad pulse, camera shake and caption through one data mapping
|
|
309
|
+
|
|
310
|
+
- `createEventFeedback` (function) · `import { createEventFeedback } from "@jgengine/shell/audio/eventFeedback"`
|
|
311
|
+
|
|
288
312
|
## event-meter-hud — render a core event/heat meter's live value, fraction, tier, and ready state in a HUD gauge
|
|
289
313
|
|
|
290
314
|
- `useEventMeter` (function) · `import { useEventMeter } from "@jgengine/react"`
|
|
@@ -293,6 +317,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
293
317
|
|
|
294
318
|
- `FastTravelMenu` (function) · `import { FastTravelMenu } from "@jgengine/react"`
|
|
295
319
|
|
|
320
|
+
## feedback-host — mount event feedback, gesture-gated audio and captions for a running game in one component
|
|
321
|
+
|
|
322
|
+
- `FeedbackHost` (function) · `import { FeedbackHost } from "@jgengine/shell/audio/FeedbackHost"`
|
|
323
|
+
|
|
296
324
|
## floating-text — overlay that renders on-screen floating combat text with per-kind color, alpha, and pop-in scale
|
|
297
325
|
|
|
298
326
|
- `FloatingText` (function) · `import { FloatingText } from "@jgengine/react"`
|
|
@@ -309,6 +337,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
309
337
|
|
|
310
338
|
- `GameContextBridge` (function) · `import { GameContextBridge } from "@jgengine/react"`
|
|
311
339
|
|
|
340
|
+
## gesture-resume — unlock the audio context on the first pointer/key/touch gesture, so pre-gesture cues play instead of vanishing
|
|
341
|
+
|
|
342
|
+
- `installGestureResume` (function) · `import { installGestureResume } from "@jgengine/shell/audio/gestureResume"`
|
|
343
|
+
|
|
312
344
|
## ground-edge-fade — fade merged ground layers into the terrain at their outer edge, keeping inner seams crisp
|
|
313
345
|
|
|
314
346
|
- `applyGroundEdgeFade` (function) · `import { applyGroundEdgeFade } from "@jgengine/shell/terrain"`
|
|
@@ -351,7 +351,7 @@ Canyon Chase is the worked example: `movement: { axis: "horizontal" }` steering,
|
|
|
351
351
|
**`presentation: "hud"` games get 3D parity.** A pure-HUD game (no camera rig) now reaches the same input/audio seams as a 3D game:
|
|
352
352
|
- **Touch gestures** — the shell mounts a headless `TouchPlaySurface` in the hud branch too, so `touch.gestures` (swipe/tap) reach actions without the game hand-wiring pointer events on its own canvas. The visible dock stays game-authored per the rule above.
|
|
353
353
|
- **No phantom reservations** — camera action names (`turnLeft`/`turnRight`/`interact`/…) are reserved *only* when a camera rig is active, so a hud game may bind them directly instead of renaming to `steer*`.
|
|
354
|
-
- **Audio actually plays**
|
|
354
|
+
- **Audio actually plays** - audio resumes on the first pointer gesture in hud games (not just 3D), and `playOneShot` self-resumes the suspended context. Cues played before any gesture wait in a bounded queue and play on the first real input instead of vanishing. Trigger sound from anywhere holding `ctx` via `ctx.game.audio.play(soundId, at?)` / `ctx.game.audio.resume()` - the reachable seam over the shell's audio engine. Bus gain and mute compose (`engine.setBusMute`), so a muted bus keeps the player's chosen volume for unmute, and Settings carries per-bus and master mute. `ctx.game.feedback.cue("wave", "WAVE 3")` raises the engine's own reaction for a moment no event covers.
|
|
355
355
|
|
|
356
356
|
## 10. Progressive instruction
|
|
357
357
|
|
|
@@ -455,11 +455,11 @@
|
|
|
455
455
|
|
|
456
456
|
## @jgengine/core/audio/audioFalloff
|
|
457
457
|
|
|
458
|
-
- `AudioBusDef` (interface): interface AudioBusDef { id: AudioBusId; gain?: number } — ⚠ undocumented · used by `
|
|
458
|
+
- `AudioBusDef` (interface): interface AudioBusDef { id: AudioBusId; gain?: number } — ⚠ undocumented · used by `withFeedbackCueSounds` (@jgengine/core/audio/feedbackCues): Merge the default feedback reactions into a game's sound catalog.
|
|
459
459
|
- `AudioBusId` (type): type AudioBusId = string — ⚠ undocumented
|
|
460
460
|
- `AudioFalloffConfig` (interface): interface AudioFalloffConfig { minDistance?: number; maxDistance?: number; curve?: FalloffCurve } — ⚠ undocumented
|
|
461
461
|
- `FalloffCurve` (type): type FalloffCurve = "linear" | "inverse" | "none" — ⚠ undocumented
|
|
462
|
-
- `SoundDef` (interface): interface SoundDef { id: string; url?: string; synth?: SynthPatch; bus: AudioBusId; gain?: number; loop?: boolean; maxVoices?: number; priority?: number; positional?: boolean; falloff?: AudioFalloffConfig; doppler?: number; spatial?: {panning: "hrtf" | "equal… — ⚠ undocumented · used by `
|
|
462
|
+
- `SoundDef` (interface): interface SoundDef { id: string; url?: string; synth?: SynthPatch; bus: AudioBusId; gain?: number; loop?: boolean; maxVoices?: number; priority?: number; positional?: boolean; falloff?: AudioFalloffConfig; doppler?: number; spatial?: {panning: "hrtf" | "equal… — ⚠ undocumented · used by `DEFAULT_FEEDBACK_CUE_SOUNDS` (@jgengine/core/audio/feedbackCues): Short procedural reactions - no samples to load, so every game has impact feedback without authoring audio.
|
|
463
463
|
- `computeFalloffGain` (function): function computeFalloffGain(distance: number, config: AudioFalloffConfig = {}): number — ⚠ undocumented
|
|
464
464
|
- `distance3` (function): function distance3(a: { x: number; y: number; z: number }, b: { x: number; y: number; z: number }): number — ⚠ undocumented
|
|
465
465
|
- `resolveEmitterGain` (function): function resolveEmitterGain(distance: number, sound: Pick<SoundDef, "gain" | "positional" | "falloff">, busGain: number): number — ⚠ undocumented
|
|
@@ -481,6 +481,16 @@
|
|
|
481
481
|
- `EngineLayersState` (interface): interface EngineLayersState — Serializable {@link EngineLayers} state.
|
|
482
482
|
- `createEngineLayers` (function): function createEngineLayers(initial: EngineLayersConfig): EngineLayers — Layered engine sound: each set of rpm-keyed samples is equal-power crossfaded between the two samples bracketing the current rpm and pitched by `rpm / layer.rpm`; the on- and off-load sets are equal-power crossfaded by smoothed `engineLoad`. A config with only one load set plays it at every load. `play` drives `ctx.game.audio` directly, so a game needs no per-layer glue.
|
|
483
483
|
|
|
484
|
+
## @jgengine/core/audio/feedbackCues
|
|
485
|
+
|
|
486
|
+
- `DEFAULT_FEEDBACK_CUE_SOUNDS` (const): const DEFAULT_FEEDBACK_CUE_SOUNDS: Readonly<Record<FeedbackCue, SoundDef>> — Short procedural reactions - no samples to load, so every game has impact feedback without authoring audio. Loud enough to read, quiet enough to sit under a weapon's own sound.
|
|
487
|
+
- `FEEDBACK_CUES` (const): const FEEDBACK_CUES: readonly FeedbackCue[] — Every {@link FeedbackCue}, in a stable order.
|
|
488
|
+
- `FEEDBACK_CUE_BUS` (const): const FEEDBACK_CUE_BUS: "sfx" — Bus the default feedback cues mix through; the settings menu shows its volume and mute.
|
|
489
|
+
- `FeedbackCue` (type): type FeedbackCue = "hit" | "hurt" | "kill" | "pickup" | "objective" | "wave" | "deny" — A gameplay moment the engine reacts to: taking or dealing a hit, a kill, a pickup, an objective, a wave starting, or a refused action. The game names the moment; the engine owns the reaction.
|
|
490
|
+
- `FeedbackCueOverrides` (type): type FeedbackCueOverrides = false | Partial<Record<FeedbackCue, SoundDef | false>> — Per-cue override: a replacement sound, or `false` to silence that cue. `false` for the whole map silences all.
|
|
491
|
+
- `feedbackCueSoundId` (function): function feedbackCueSoundId(cue: FeedbackCue): string — Catalog id a cue plays under: `feel.hit`, `feel.kill`, ... A game sound with that id replaces the default.
|
|
492
|
+
- `withFeedbackCueSounds` (function): function withFeedbackCueSounds(sounds: Readonly<Record<string, SoundDef>> | undefined, buses: Readonly<Record<string, AudioBusDef>> | undefined, overrides?: FeedbackCueOverrides): { sounds: Record<string, SoundDef>; buses: Record<string, AudioBusDef> | undefined } — Merge the default feedback reactions into a game's sound catalog. A game sound already named `feel.<cue>` wins, then `overrides`, then the default. Adds the `sfx` bus (gain 0.9) when the game did not declare one, so the impact layer has its own volume and mute row.
|
|
493
|
+
|
|
484
494
|
## @jgengine/core/audio/music
|
|
485
495
|
|
|
486
496
|
- `MusicInstrument` (type): type MusicInstrument = | "strings" | "flute" | "harp" | "horn" | "choir" | "bell" | "timpani" | "bass" | "stacc" | "pad" | "lute" | "dulcimer" | "frameDrum" | "warDrum" | "reed" | "pipe" | "squareLead" | "woodBlock" | "tinyBell" | "piano" | "shaker" | "brassStab" | "cymSwell" | "oboe" — Named synthesised instrument. Each maps to a voice in the shell's instrument library (`@jgengine/shell/audio/musicVoices`); an unknown name falls back to a plain sine voice so a theme is never silent.
|
|
@@ -2358,7 +2368,7 @@
|
|
|
2358
2368
|
- `AssetSpace` (interface): interface AssetSpace — Catalog-level asset-space metadata: how a model is authored relative to the engine, owned by the catalog entry rather than re-derived per game. Every field is optional so an unmeasured asset stays valid; {@link resolveFacingRotationY}/{@link assetUnitScale}/{@link resolveAnchorOffset} supply the documented defaults.
|
|
2359
2369
|
- `AssetSpaceIssue` (interface): interface AssetSpaceIssue — One problem found by {@link validateAssetSpace}: which metadata field and why it is invalid.
|
|
2360
2370
|
- `AttackMoveOrderPayload` (interface): interface AttackMoveOrderPayload — Payload for an attack-move: advance toward `point`, engaging hostiles encountered en route.
|
|
2361
|
-
- `AudioBusDef` (interface): interface AudioBusDef { id: AudioBusId; gain?: number } — ⚠ undocumented · used by `
|
|
2371
|
+
- `AudioBusDef` (interface): interface AudioBusDef { id: AudioBusId; gain?: number } — ⚠ undocumented · used by `withFeedbackCueSounds` (@jgengine/core/audio/feedbackCues): Merge the default feedback reactions into a game's sound catalog.
|
|
2362
2372
|
- `AudioFalloffConfig` (interface): interface AudioFalloffConfig { minDistance?: number; maxDistance?: number; curve?: FalloffCurve } — ⚠ undocumented
|
|
2363
2373
|
- `AuthoredNavLink` (interface): interface AuthoredNavLink — A connection the scene author places between two spots — a door through a wall, a ladder to a deck, a jump across a gap. Authored as world points, not polygon ids, so it survives a re-bake: {@link NavRuntime.applyMesh} resolves each end onto the nearest walkable polygon.
|
|
2364
2374
|
- `AuthoredTrigger` (interface): interface AuthoredTrigger — One resolved trigger binding from a document object.
|
|
@@ -2847,7 +2857,7 @@
|
|
|
2847
2857
|
- `SnapMode` (type): type SnapMode = "grid" | "free" | "surface" — ⚠ undocumented
|
|
2848
2858
|
- `SnowEnvironmentDescriptor` (type): type SnowEnvironmentDescriptor = { kind: "snow" } & Required< Pick<SnowEnvironmentConfig, "area" | "density" | "speed" | "flakeSize" | "drift" | "wind" | "color" | "opacity"> > — ⚠ undocumented · used by `snow`: Declares a snowfall weather effect for `environment()` — area, density, drift, wind, and flake opacity.
|
|
2849
2859
|
- `SoilRules` (interface): interface SoilRules — Fully-defaulted soil params parsed from a volume's `meta`.
|
|
2850
|
-
- `SoundDef` (interface): interface SoundDef { id: string; url?: string; synth?: SynthPatch; bus: AudioBusId; gain?: number; loop?: boolean; maxVoices?: number; priority?: number; positional?: boolean; falloff?: AudioFalloffConfig; doppler?: number; spatial?: {panning: "hrtf" | "equal… — ⚠ undocumented · used by `
|
|
2860
|
+
- `SoundDef` (interface): interface SoundDef { id: string; url?: string; synth?: SynthPatch; bus: AudioBusId; gain?: number; loop?: boolean; maxVoices?: number; priority?: number; positional?: boolean; falloff?: AudioFalloffConfig; doppler?: number; spatial?: {panning: "hrtf" | "equal… — ⚠ undocumented · used by `DEFAULT_FEEDBACK_CUE_SOUNDS` (@jgengine/core/audio/feedbackCues): Short procedural reactions - no samples to load, so every game has impact feedback without authoring audio.
|
|
2851
2861
|
- `SpatialGrid` (class): class SpatialGrid — A uniform-grid broad-phase over the x/z plane, separate from the rigid-body sim, for cheap same-tick proximity across hundreds–thousands of simple movers (swarm enemies). Rebuild each tick from the caller's own position arrays, then `queryCircle` (enemies hitting the player / an AoE) or `forEachPair` (mutual separation). Both are precise: no false negatives, no false positives beyond the exact distance test.
|
|
2852
2862
|
- `SpawnDirectorConfig` (interface): interface SpawnDirectorConfig { waves: readonly WaveManifest[]; maxAlive?: number; escalationPerSecond?: number; alertBudgetPerSecond?: number; alertDecayPerSecond?: number; playerBudgetPerSecond?: number; maxSpawnsPerTick?: number; loop?: boolean; seed?: number; spawnP… — ⚠ undocumented
|
|
2853
2863
|
- `SpawnDirectorState` (interface): interface SpawnDirectorState { wave: number; elapsed: number; waveElapsed: number; budget: number; alert: number; spawnedThisWave: number; spawnedTotal: number; rng: RandomSeed; done: boolean } — ⚠ undocumented
|
|
@@ -370,6 +370,10 @@ Reach for these before hand-rolling. Each row is *the thing you need* → *the p
|
|
|
370
370
|
|
|
371
371
|
- `createFastTravelNetwork` (function) · `import { createFastTravelNetwork } from "@jgengine/core/world"`
|
|
372
372
|
|
|
373
|
+
## feedback-cue-sounds — default procedural hit/hurt/kill/pickup/objective/wave/deny reactions on an "sfx" bus, overridable per game
|
|
374
|
+
|
|
375
|
+
- `withFeedbackCueSounds` (function) · `import { withFeedbackCueSounds } from "@jgengine/core/audio/feedbackCues"`
|
|
376
|
+
|
|
373
377
|
## feedback-mixer — map sim telemetry to camera, audio and haptic parameters through curves, smoothing and threshold events
|
|
374
378
|
|
|
375
379
|
- `createFeedbackMixer` (function) · `import { createFeedbackMixer } from "@jgengine/core/vfx/feedbackMixer"`
|