The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


createNoiseBuffer(ctx, color = 'white', duration = DEFAULTDURATION, options = {})

createNoiseSource(ctx, color = 'white', options = {})

createStereoNoiseSource(ctx, color = 'white', options = {})

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: No file level description found in source. Add one as a leading JSDoc comment, or document it below. Functions Create a noise AudioBuffer of the specified color. Parameters: (AudioContext) — No description in source JSDoc. (string) — Noise color (white pink brown blue violet grey velvet crackle) (number) — Buffer duration in seconds (Object) — No description in source JSDoc. (number) — Impulses/sec for velvet/crackle (default 100) (boolean) — Generate stereo buffer (default false) Create a looping noise source node. Parameters: (AudioContext) — No description in source JSDoc. (string) — Noise color (Object) — No description in source JSDoc. (number) — Buffer duration (default 2s) (number) — For velvet/crackle (number) — LP filter cutoff (null = no filter) (boolean) — Stereo decorrelation Returns: } Create stereo noise with decorrelated channels. Parameters: (AudioContext) — No description in source JSDoc. (string) — No description in source JSDoc. (Object) — No description in source JSDoc. Returns: } Constants <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread


to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/OscillatorNode.js
Functions
createOscillator(ctx, config = {})
isValidShape(shape)
Constants
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: OscillatorNode.js — Advanced Oscillator Synthesis Supports multiple waveform types beyond Web Audio defaults: sine, square, sawtooth, triangle (native) pulse (variable duty cycle via PeriodicWave) supersaw (multiple detuned sawtooths) custom (user defined wavetable) Additional features: Sub oscillator ( 1 or 2 octaves) Unison/supersaw with configurable voice count and spread Pulse width modulation Usage: import { createOscillator, createSupersawOscillator } from './OscillatorNode.js'; const osc = createOscillator(audioCtx, { shape: 'pulse', frequency: 440, pulseWidth: 0.3 }); osc.output.connect(destination); osc.start(); Functions Create an advanced oscillator node. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. (number) — Base frequency in Hz (number) — Detune in cents (string) — Waveform shape (number) — Duty cycle for pulse wave (0 1) (number) — Number of unison voices for supersaw (number) — Detune spread in cents for supersaw (number) — Sub oscillator: 0=off, 1= 1oct, 2= 2oct (number) — Sub oscillator mix level (0 1) (Float32Array) — Custom wavetable harmonics Returns: Oscillator instance Constants <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form


sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


createSamplePlayer(ctx, buffer, config = {})

createCrossfadeLoopBuffer(ctx, buffer, loopStart, loopEnd, crossfadeDuration)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: SamplePlayerNode.js — Advanced Sample Playback Enhanced sample player with: Loop modes: forward, pingpong, reverse Start/end points and loop regions Crossfade looping for seamless loops Built in ADSR envelope Pitch tracking from MIDI note Usage: import { createSamplePlayer } from './SamplePlayerNode.js'; const player = createSamplePlayer(audioCtx, buffer, { loop: true, loopMode: 'pingpong' }); player.trigger(); Functions Create an advanced sample player. Parameters: (AudioContext) — No description in source JSDoc. (AudioBuffer) — Source audio buffer (Object) — No description in source JSDoc. Returns: Sample player instance Create a crossfade loop buffer. Blends the end of the loop region back into the start for seamless looping. Parameters: (AudioContext) — No description in source JSDoc. (AudioBuffer) — No description in source JSDoc. (number) — Loop start in seconds (number) — Loop end in seconds (number) — Crossfade length in seconds Constants <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion.


(filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/SequencerNode.js
Functions
createClock(ctx, config = {})
createStepSequencer(ctx, config = {})
createArpeggiator(ctx, config = {})
Constants
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: No file level description found in source. Add one as a leading JSDoc comment, or document it below. Functions Create a master clock with BPM and time signature. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Create a step sequencer. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Create an arpeggiator. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Constants <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


createPhaseDistortionSynth(ctx, config = {})

createSubtractiveSynth(ctx, config = {})

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: SynthesisTypes.js — Additional Synthesis Methods Extended synthesis techniques: Additive: Harmonic/partial based synthesis Wavetable: Morphing wavetable oscillator PhaseDistortion: CZ style phase distortion Subtractive: Classic subtractive synth voice Usage: import { createAdditiveSynth, createWavetableSynth } from './SynthesisTypes.js'; const add = createAdditiveSynth(audioCtx, { partialCount: 32 }); Functions Create an additive synthesizer. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Create a wavetable synthesizer. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Create a phase distortion synthesizer (CZ style). Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Create a classic subtractive synthesizer voice. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Constants <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API


sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/WaveguideNode.js
Functions
renderWaveguide(ctx, config = {})
createWaveguide(ctx, config = {})
isValidTermination(term)
isValidWaveguideMode(mode)
Constants
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: No file level description found in source. Add one as a leading JSDoc comment, or document it below. Functions Render a waveguide to an AudioBuffer (offline). Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Create a real time waveguide engine using Web Audio nodes. This is a simplified version using delay + filter + feedback. Parameters: (AudioContext) — No description in source JSDoc. (Object) — No description in source JSDoc. Returns: Waveguide instance Constants <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/atoms/CrackleAtom.js
Functions
createCrackleAtomPatch(config = {})
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CrackleAtom.js Crackle Sound Atom (Verron 2012) Pre wired patch: Impulse → ModalBank (2 3 modes) → Envelope (AD) → Gain Driven by: emitRate → density, temperature → brightness Use case: fire crackle, ice crack, sparks Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/atoms/DropAtom.js
Functions
createDropAtomPatch(config = {})
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: DropAtom.js Drop Sound Atom (Verron 2012) Pre wired patch: Impulse → Resonator (single mode) → Envelope (AD) Driven by: mass → pitch, velocity → amplitude Use case: rain drops, drips, liquid impacts Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/atoms/HissAtom.js
Functions
createHissAtomPatch(config = {})
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: HissAtom.js Hiss Sound Atom (Verron 2012) Pre wired patch: Noise(white) → HighPass → Gain Driven by: temperature → cutoff, emitRate → volume Use case: steam, gas escape, sizzle, continuous background Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/atoms/RumbleAtom.js
Functions
createRumbleAtomPatch(config = {})
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: RumbleAtom.js Rumble Sound Atom (Verron 2012) Pre wired patch: BrownNoise → LowPass → Gain Driven by: size → cutoff, velocity → volume Use case: thunder, ground shake, lava, explosions Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/atoms/WhooshAtom.js
Functions
createWhooshAtomPatch(config = {})
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: WhooshAtom.js Whoosh Sound Atom (Verron 2012) Pre wired patch: Noise → BandPass → Envelope → Gain Driven by: velocity → centerFreq, size → bandwidth Use case: wind, projectile flyby, movement Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


createStringsInstrument(ctx, config = {})

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: No file level description found in source. Add one as a leading JSDoc comment, or document it below. Functions Convert MIDI note number to frequency. Parameters: (number) — MIDI note (0 127) Returns: Frequency in Hz Convert frequency to MIDI note number. Parameters: (number) — Frequency in Hz Returns: MIDI note (fractional) Create a piano instrument using Karplus Strong + FM. Create a string ensemble instrument. Create a brass instrument with growl and brightness. Create a lush pad synthesizer. Create a mono lead synthesizer with glide. Create a bass synthesizer. Create an analog style drum synthesizer. Constants <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See


until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CombustionModel.js Fire/Combustion Synthesis Model Combines Crackle + Hiss + Rumble atoms mixed by intensity. Low intensity = gentle crackle. High intensity = roaring fire with rumble. Driven by: emitRate, temperature Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/physics/FluidModel.js
Functions
createFluidPatch(config = {})
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: FluidModel.js Fluid/Water Synthesis Model Combines Drop atoms (splashes) + Hiss (flow) for liquid sounds. Driven by: emitRate, velocity, splash rate Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: ModalImpactModel.js Material Aware Impact Synthesis Excites a bank of resonators on collision. Material properties determine mode frequencies, Q factors, and decay times. Uses MATERIAL enum from SubstanceSchema for lookup. Based on Cook/Smith modal synthesis (Stanford CCRMA). Functions Get modal preset for a material. Parameters: (string) — No description in source JSDoc. Get all available material names. Generate a ModalImpact patch descriptor for a given material. Parameters: (Object) — No description in source JSDoc. (string) — 'metal' 'glass' 'wood' 'stone' 'ice' 'ceramic' (number) — Scale all mode frequencies (default 1.0) (number) — Output volume (default 0.8) Returns: Patch JSON <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large


Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: WeatherModel.js Weather Synthesis Model Rain (grain cloud of drops), hail, thunder (rumble). Driven by: weather type, intensity Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


audio/synth/nodes/physics/WindModel.js
Functions
createWindPatch(config = {})
Notes & Examples
Audio Graph Architecture
Audio Graph Architecture

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: WindModel.js Wind Synthesis Model Combines Whoosh + Rumble, with gust modulation from WindSystem. Driven by: windSpeed, gustiness Functions <! HUMAN NOTES Notes & Examples Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain See also: Audio · Engine Overview Audio Graph Architecture The audio system uses a node based graph architecture. AudioNodes connect to form processing chains: sources (oscillator, buffer) → effects (filter, delay, reverb) → destination (speakers). All processing happens on the audio thread via the Web Audio API with automatic sample rate conversion. Example: Creating a sound effect chain Advanced: Loading and playing audio assets Advanced: 3D spatial audio Advanced: Mixing and buses Gotchas: AudioContext state : Browsers block audio until user interaction. Call after a click. Memory : holds raw PCM — unload large files when not needed. Scheduling : Use for precise rhythm; drifts vs . See also: Audio · Engine Overview


collab/CollabAnonymousRelay.js

collabAnonTimestampReport(timestamp, nowMs = Date.now()

collabAnonScoreReport(scoreData, nowMs = Date.now()

async wrapGarlic(relay, op, recipientAnonId, ownEcdhPrivateKey)

async unwrapGarlic(relay, garlicOp, ownEcdhPrivateKey)

async verifyAnonCredential(persistentPubKeyRaw, sessionSeed, credential)

async verifyAnonScoreReceipt(certifiedSessionKeys, scoreData, signature, signerPublicKey = null, nowMs = Date.now()

async signAnonCriticalOp(sessionKeyPair, sessionPubKeyRaw, op, anonId)

async verifyAnonCriticalOp(op, senderAnonId, certifiedSessionKeys, relay = null, nowMs = Date.now()

async buildAnonScoreReportOp(relay, targetAnonId, score)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabAnonymousRelay.js Anonymous peer mapping and routing for P2P collab channels. Inspired by Tor onion routing, I2P garlic routing, and AP3 pseudonymous overlays — adapted for real time game networking where latency matters. Three layers of anonymity: 1. Pseudonymous IDs — each peer gets a random session token (anonId). All ops use anonIds instead of real selfIds. Peers never see each other's real identity. Different anonId each session prevents cross session correlation. 2. TURN only relay — forces iceTransportPolicy:'relay' so WebRTC ICE candidates never leak real IP addresses between peers. 3. Garlic encryption — each message payload is encrypted with the recipient's ECDH public key before being sent through the relay. The relay host can route messages (via anonId headers) but cannot read the encrypted payload. Only the intended recipient can decrypt. Architecture: The host acts as an anonymizing relay (already in relay mode) Peers send messages to the host with a destination anonId The host maps anonId → realPeerId, forwards the message The forwarded message has the sender's anonId (not real ID) Result: no peer knows any other peer's real identity or IP Flow: 1. createAnonymousRelay() → relay state with self anonId 2. Host: registerPeer(realPeerId) → assigns anonId, stores mapping 3. Outgoing: sanitizeOp(op) → replaces peerId with anonId 4. Host routing: resolveAnonToReal(anonId) → realPeerId for delivery 5. Incoming: the op already has sender's anonId (safe to process) 6. Garlic: wrapGarlic(op, recipientEcdhPub) → encrypted payload 7. Garlic: unwrapGarlic(op, ownEcdhPrivate) → decrypted payload Functions Generate an anonymous username from an anonId. Format: "Anon XXXX"


collab/CollabAnonymousRelay.js

encrypted payload 7. Garlic: unwrapGarlic(op, ownEcdhPrivate) → decrypted payload Functions Generate an anonymous username from an anonId. Format: "Anon XXXX" where XXXX is first 4 chars of the anonId. Parameters: (string) — No description in source JSDoc. Create an anonymous relay state. Parameters: (Object) — No description in source JSDoc. (string) — our real peer ID (boolean) — =false] host maintains full mapping (boolean) — =false] enable garlic encryption Returns: relay state Register a peer and assign them an anonymous ID. On the host: stores both directions of the mapping. On non host: only stores our own mapping (we know our own anonId). Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. (Uint8Array number[]) — peer's ECDH key for garlic Returns: the assigned anonId Remove a peer from the anonymous mapping. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. Resolve a real peer ID to its anonymous ID. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. Returns: anonId or null if not registered Resolve an anonymous ID back to the real peer ID. HOST ONLY — non host peers cannot resolve other peers' anonIds. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. Returns: realPeerId or null Get the anonymous username for a peer. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. Sanitize an outgoing op: replace all real peer IDs with anonymous IDs. This is called before broadcasting — peers only see anonIds. Parameters: (Object) — No description in source JSDoc. (Object) — the op to sanitize (will be shallow cloned) Returns: sanitized op


collab/CollabAnonymousRelay.js

— peers only see anonIds. Parameters: (Object) — No description in source JSDoc. (Object) — the op to sanitize (will be shallow cloned) Returns: sanitized op with anonIds De anonymize an incoming op: resolve anonIds back to real peer IDs. HOST ONLY — used for internal routing decisions. The forwarded copy to other peers keeps the anonIds intact. Parameters: (Object) — No description in source JSDoc. (Object) — No description in source JSDoc. Returns: op with real peer IDs restored (or anonIds if non host) Re anonymize an op for forwarding to another peer. The host de anonymizes for routing, then this re anonymizes for delivery. This ensures the recipient only sees the sender's anonId. Parameters: (Object) — No


collab/CollabCameraInterp.js

pushCameraSnapshot(state, peerId, pos, target, vel, targetVel, remoteTs)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabCameraInterp.js Hermite spline camera interpolation for smooth remote peer camera rendering. Based on Glenn Fiedler's "Snapshot Interpolation" (Gaffer on Games, GDC 2015): Buffer camera snapshots and render slightly behind real time Use cubic Hermite splines (position + velocity at each sample) for C1 continuity Adaptive jitter compensation adjusts the playback delay automatically Hermite basis: H(t) = (2t³ 3t² + 1)·p0 + (t³ 2t² + t)·v0·Δt + ( 2t³ + 3t²)·p1 + (t³ t²)·v1·Δt This guarantees the curve passes through p0 and p1 with matching velocities, eliminating the 1st order discontinuity artifacts that linear interpolation causes. Functions Create the global camera interpolation state. Attach to editor.collab or pass around explicitly. Push a camera sync snapshot into the interpolation buffer. Call this from the camera sync op handler instead of snapping peer.camera directly. Parameters: (Object) — from createCameraInterpState() (string) — No description in source JSDoc. (number[]) — [x,y,z] camera position (full precision) (number[]) — [x,y,z] camera look at target (number[]) — [vx,vy,vz] camera velocity (units/sec) (number[]) — [vx,vy,vz] target velocity (number) — performance.now() timestamp from sender Get the smoothly interpolated camera position for a remote peer. Call this every render frame from CollabOverlayRenderer. Parameters: (Object) — from createCameraInterpState() (string) — No description in source JSDoc. Returns: null} Remove stale peer buffers. Call periodically ( 1Hz). Remove a specific peer's buffer (on disconnect). Get interpolation stats for UI display. Destroy all state. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or


collab/CollabCameraInterp.js

(on disconnect). Get interpolation stats for UI display. Destroy all state. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabCodec.js

collab/CollabCodec.js
Functions
encode(value, options = {})
codecEncodeReport(value, options = {})
decode(data, options = {})
codecDecodeReport(data, options = {})
Constants
Notes & Examples

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabCodec.js Inline MessagePack encoder/decoder for binary collab messages. Zero dependencies — implements msgpack spec directly. Supports: null, bool, int (safe integer range), float64, string, bin (Uint8Array), array, map (plain objects). Special extension type 0x01: Float32Array with canonical little endian bytes. Usage: import { encode, decode } from './CollabCodec.js'; const bytes = encode({ ch: 'ops', data: { type: 'transform', pos: new Float32Array([1,2,3]) } }); const obj = decode(bytes); Functions Encode a JS value into a msgpack Uint8Array. Parameters: ( ) — No description in source JSDoc. Decode a msgpack Uint8Array (or ArrayBuffer) back into a JS value. Parameters: (Uint8Array ArrayBuffer) — No description in source JSDoc. Constants <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabCore.js

getPeerConnectionTier(core, peerId, peerScore, fastChannel)

connectCollabPeer(core, peerId, username = 'Remote')

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabCore.js WebRTC peer connection management. Manages RTCPeerConnection instances, data channels, and reconnection. Two data channels per peer: 'ops' — reliable, ordered (scene operations) 'presence' — unreliable, unordered (camera/selection at 10Hz) Functions Create a collab core instance. config: { projectId, selfId, username, onOp, onPresence, onPeerDiscovered, shouldConnectPeer, onPeerJoin, onPeerLeave } Start signaling and begin peer discovery. Force an immediate discovery pass: re announce on all signaling tiers right now. Lets an app layer "Connect now" find a known contact without waiting for the periodic announce cycle. Does not tear down existing peers. Broadcast an op to all connected peers. Transport priority: 1. FastChannel (same origin BroadcastChannel) — <1ms 2. Gossip mesh (partial mesh / supernode mode) — K neighbors, O(log N) delivery 3. Full mesh WebRTC — direct to all (≤6 peers) Broadcast presence data to all connected peers (unreliable channel). Prefers fast channel for same origin peers. Send data to a specific peer only. Prefers fast channel for same origin peers. Auto chunks large messages to avoid SCTP size limits. Relay an op from one peer to all other peers (host only, relay mode). Optionally filters by spatial interest set. Parameters: (Object) — No description in source JSDoc. (string) — peer who sent the op (Object) — the op to relay Compute the dynamic peer capacity based on connection quality. Fast channel peers are free. Trusted peers expand the mesh limit. Parameters: (Object) — No description in source JSDoc. (Object) — reputation state for score lookups Returns: } Check peer count and toggle relay mode if threshold is crossed. Now uses


collab/CollabCore.js

description in source JSDoc. (Object) — reputation state for score lookups Returns: } Check peer count and toggle relay mode if threshold is crossed. Now uses dynamic capacity — fast peers don't count, trusted peers expand the limit. Parameters: (Object) — No description in source JSDoc. (Object) — optional reputation state Returns: true if relay mode changed Set the spatial authority reference for interest filtered relay. Set the fast channel reference on the core. Called by EditorCollab after creating the fast channel. Set the mesh topology reference on the core. Called by EditorCollab after creating the topology manager. Check if a peer is trusted (high reputation) and should get a direct connection even in relay mode. Trusted peers bypass the relay host for lower latency. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. (number) — reputation score 0 1000 Returns: true if peer is trusted Get the connection tier label for a peer. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. (number) — No description in source JSDoc. (Object) — No description in source JSDoc. Returns: } Get the maximum bufferedAmount across all peer ops channels. Used by CollabMessageRouter for backpressure detection. Get the local peer ID. Get all connected peers. Begin a targeted WebRTC connection to an already discovered peer. Close one direct peer connection without tearing down discovery. Collect locally observed transport quality. Remote peers cannot supply or inflate these values, which makes them suitable input for topology roles. Destroy all connections and signaling. Derive a shared AES 256 GCM key from ECDH key exchange. Called after hello handshake when both peers have ECDH public keys.


collab/CollabCore.js

all connections and signaling. Derive a shared AES 256 GCM key from ECDH key exchange. Called after hello handshake when both peers have ECDH public keys. Broadcast a graceful goodbye to all peers before leaving. This lets other peers immediately remove us instead of waiting for heartbeat timeout or WebRTC state change. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabCrypto.js

async deriveSharedKey(privateKey, remotePublicKey, salt)

async deriveHmacKey(privateKey, remotePublicKey, salt)

cryptoNonceReport(counter, channelId = null)

encryptedMessageReport(message, channelId = null)

async encrypt(key, plaintext, counter, channelId)

async decrypt(key, message, channelId, replayState = null)

async verifyChallenge(hmacKey, challenge, signature)

async completePeerCrypto(state, remotePublicKeyRaw, roomPassword)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabCrypto.js ECDH P 256 key exchange + AES 256 GCM encryption for P2P collab channels. Uses the SubtleCrypto API with shared finite number admission. Flow: 1. Each peer calls generateKeyPair() on connect 2. Peers exchange public keys during hello handshake 3. deriveSharedKey() produces an AES 256 GCM key via ECDH + HKDF 4. All subsequent messages: encrypt() before send, decrypt() on receive 5. HMAC for challenge response authentication during handshake Nonce scheme: 12 bytes = [8 byte channelId 4 byte monotonic counter] Counter MUST never repeat for a given key. Functions Generate an ECDH P 256 key pair for key exchange. Returns: } Import a raw public key (65 bytes) received from a remote peer. Parameters: (ArrayBuffer Uint8Array) — No description in source JSDoc. Derive a shared AES 256 GCM key from our private key + remote public key. Optionally mixes in a room password for authentication. Parameters: (CryptoKey) — Our ECDH private key (CryptoKey) — Remote peer's imported public key (string) — Optional room password / salt for HKDF Returns: AES 256 GCM key Derive an HMAC SHA256 key from ECDH shared bits for challenge response auth. Parameters: (CryptoKey) — No description in source JSDoc. (CryptoKey) — No description in source JSDoc. (string) — No description in source JSDoc. Encrypt a msgpack payload with AES 256 GCM. Parameters: (CryptoKey) — AES 256 GCM key from deriveSharedKey (Uint8Array) — Raw msgpack bytes (number) — Monotonic nonce counter (must never repeat) (Uint8Array) — 8 byte channel identifier (default: zeros) Returns: Encrypted message: [4 byte counter][N byte ciphertext+tag] Decrypt an AES 256 GCM encrypted message. Parameters: (CryptoKey) — AES 256 GCM key


collab/CollabCrypto.js

zeros) Returns: Encrypted message: [4 byte counter][N byte ciphertext+tag] Decrypt an AES 256 GCM encrypted message. Parameters: (CryptoKey) — AES 256 GCM key (Uint8Array) — Wire format from encrypt() (Uint8Array) — Same channelId used during encrypt (Object) — Optional peer state from createPeerCryptoState() Returns: Decrypted msgpack bytes Generate a random 32 byte challenge. Sign a challenge with HMAC SHA256. Parameters: (CryptoKey) — No description in source JSDoc. (Uint8Array) — No description in source JSDoc. Verify a challenge signature. Parameters: (CryptoKey) — No description in source JSDoc. (Uint8Array) — No description in source JSDoc. (Uint8Array) — No description in source JSDoc. Create crypto state for a single peer connection. Initialize crypto state with a fresh key pair. Parameters: (Object) — From createPeerCryptoState() Complete the handshake: import remote public key, derive shared keys. Parameters: (Object) — No description in source JSDoc. (Uint8Array ArrayBuffer) — 65 byte raw public key (string) — No description in source JSDoc. Check if crypto is available in this environment. Constants <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabDivergenceTracker.js

receiveRemoteHash(tracker, peerId, simTime, frameHash)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabDivergenceTracker.js Records per frame position hashes during play mode and compares them across peers to detect simulation divergence. Hash algorithm: FNV 1a 32 bit over quantized entity positions. Functions Record a local frame hash. Call every simHistoryInterval during play. Receive a remote heartbeat hash from a peer. Remove a peer's data on disconnect. Get all recorded divergence events. Clear all tracking data (call on exitPlayMode). Export a JSON report of all divergences + local timeline. Compute a fast FNV 1a hash of all entity positions in the scene. Quantizes positions to 3 decimal places for float stability. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabEntityAuthority.js

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabEntityAuthority.js Per entity ownership model for collaborative multiplayer. Every entity has at most one "owner" peer. The owner is the sole source of truth for that entity's transform, physics, and interactive state. Ownership transfers via explicit claim/release ops — no server needed. Priority levels (higher number wins): 0 DEFAULT — physics authority (host) owns unclaimed entities 1 PROXIMITY — auto assigned to nearest peer's camera (future) 2 SELECTED — peer clicked/selected the entity in the inspector 3 GRABBED — peer is actively dragging/manipulating the entity Conflict resolution: Higher priority always wins (grab beats select beats proximity) Equal priority: earlier timestamp wins (first come first served) Owner can always release voluntarily Stale claims (no refresh for STALE TIMEOUT MS) are auto released Inspired by: Photon Takeover policy, Gaffer on Games authority scheme, Roblox Network Ownership, Source Engine shadow controllers. Functions Create an entity authority state object. Parameters: (string) — This peer's unique ID Returns: authority state Get the current owner of an entity. Returns: null} Check if the local peer owns an entity. Check if an entity is owned by anyone (not default authority). Get all entities owned by a specific peer. Returns: array of entity IDs Get all locally owned entity IDs as a Set (for fast lookup in sync loops). Check if the local peer should broadcast transforms for an entity. Returns true if: (a) we own it, or (b) nobody owns it and we're play authority. Check if the local peer should accept remote transforms for an entity. Returns true if we do NOT own it. Claim ownership of an entity at a given priority. Returns the op to


collab/CollabEntityAuthority.js

local peer should accept remote transforms for an entity. Returns true if we do NOT own it. Claim ownership of an entity at a given priority. Returns the op to broadcast, or null if claim was rejected locally. Release ownership of an entity. Reverts to default authority. Returns the op to broadcast, or null if we didn't own it. Release ALL claims owned by the local peer (e.g. on disconnect or exit play mode). Returns array of ops to broadcast. Handle an incoming entity authority op from a remote peer. Applies the claim/release to local state after conflict resolution. Returns true if the claim was accepted. Build refresh ops for all local claims (call at 2Hz from the collab loop). Also prunes stale remote claims. Returns: array of ops to broadcast Handle a peer disconnecting — release all their claims. Get handoff blend factor for an entity (0 = fully old owner, 1 = fully new owner). Used by interpolation to smoothly blend during ownership transfer. Set callback for ownership changes. Destroy / reset authority state. Constants <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabFastChannel.js

createFastChannel(projectId, selfId, callbacks = {})

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabFastChannel.js Low overhead data transport for same origin peers via BroadcastChannel. Problem: WebRTC DataChannels add 50 100ms RTT even on localhost due to DTLS encryption, SCTP transport, and msgpack encode/decode overhead. Solution: For peers sharing the same browser origin (same machine testing, same domain deployment), use the BroadcastChannel API which provides: Structured clone transfer (no msgpack encode/decode) No encryption overhead (same origin security model) Browser scheduled local delivery without ICE/STUN/DTLS setup Zero setup — no ICE/STUN/DTLS negotiation This module creates a dedicated data BroadcastChannel (separate from the signaling channel in CollabSignal.js) that carries ops and presence. CollabCore detects same origin peers and prefers this transport. For cross origin / cross machine peers, WebRTC is still used. Inspired by: Meshtastic's tiered transport (LoRa → BLE → WiFi), choosing the fastest available link per peer. Functions Create a fast channel instance. Parameters: (string) — room/project identifier (string) — this peer's unique ID (Object) — { onOp, onPresence, onFastPeerDetected, onFastPeerLost } Returns: fast channel state, or null if BroadcastChannel unavailable Send an op via fast channel to all same origin peers. Uses structured clone (no msgpack encode/decode). Parameters: (Object) — fast channel state (Object) — the operation to send Returns: true if sent (false if no fast channel or no fast peers) Send presence data via fast channel. Send an op to a specific peer via fast channel. Returns: true if the peer is a fast peer and message was sent Check if a specific peer is reachable via fast channel. Get the set of all fast peer IDs.


collab/CollabFastChannel.js

Returns: true if the peer is a fast peer and message was sent Check if a specific peer is reachable via fast channel. Get the set of all fast peer IDs. Get fast channel stats. Destroy the fast channel. Sends a bye message to peers first. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabHostMigration.js

createHostMigration(selfId, config = {})

hostMigrationCandidacyScoreReport(metrics = {}, timestampMs = Date.now()

onPeerGoodbye(hm, payload, fromPeerId = payload?.peerId)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabHostMigration.js Automatic host migration for P2P collaboration sessions. Problem: When the host peer drops (closes tab, network outage, crash), relay mode breaks — all non host peers lose the ability to communicate through the relay hub. The session effectively dies. Solution: Bully style host election with reputation weighted scoring. When the host is detected as dead: 1. All peers start a migration election 2. The peer with the highest "candidacy score" wins 3. New host assumes relay duties and notifies all peers 4. If the original host returns, it can reclaim the role Election Algorithm (modified Bully): Each peer computes a candidacy score based on: • Reputation score (40%) — trustworthy peers preferred • Uptime in session (30%) — stable peers preferred • Connection count (20%) — well connected peers preferred • Deterministic tiebreaker (10%) — lexicographic selfId for consistency All peers broadcast their candidacy After a short election timeout, the highest scoring peer wins If two peers tie, the one with the lexicographically higher selfId wins Inspired by: Xbox Live host migration (Halo 2/3) Photon PUN MasterClient migration Raft leader election (simplified — no log replication needed) Bully algorithm (Garcia Molina, 1982) Current scope: this module elects a relay host and reconfigures routing. Authority map handoff, replicated log consensus, election terms/quorums, and signature gated dispatch are not implemented here and remain audit gaps. Candidate reputation/connection metrics remain locally self reported, and captured multi peer host failure/rejoin traces remain absent. Functions Create a host migration manager. Parameters: (string) — No description in source


collab/CollabHostMigration.js

and captured multi peer host failure/rejoin traces remain absent. Functions Create a host migration manager. Parameters: (string) — No description in source JSDoc. (Object) — No description in source JSDoc. Start host migration monitoring. Parameters: (Object) — No description in source JSDoc. (boolean) — are we the initial host? (string) — peerId of the initial host (null if we are host) Set the host peer ID (for joiners who didn't know at startup). Starts the host liveness monitor if not already running. Stop host migration monitoring. Record that we received a heartbeat (or any message) from the host. Call this from the heartbeat handler. Record that we received ANY op from a peer (used for liveness). Even non heartbeat ops prove the host is alive. Handle a received election candidacy from another peer. Handle a received election result from another peer. Handle the original host returning to the session. The original host broadcasts a reclaim request. The current acting host defers after a grace period, handing duties back. Called by the original host when it returns to reclaim. Only call if we ARE the original host and someone else took over. Register a known peer. Remove a known peer. Update our own metrics (call from collab loop). Handle an incoming host election op. Routes to the appropriate handler based on phase. Build a goodbye op to broadcast before leaving. Other peers use this to immediately detect departure instead of waiting for heartbeat timeout. Handle a received goodbye from a departing peer. If the host sent the goodbye, immediately start election (no timeout wait). <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabIdentity.js

collabIdentityTimestampReport(timestamp, nowMs = Date.now()

async createIdentity(keyId = COLLABIDENTITYKEYID)

async verifyIdentityProof(publicKeyRaw, selfId, signature)

collabIdentityScoreReceiptReport(scoreData, nowMs = Date.now()

async verifyScoreReceipt(publicKeyRaw, scoreData, signature, nowMs = Date.now()

async verifyRawBytes(publicKeyRaw, bytes, signature)

async verifyData(publicKeyRaw, data, signature)

async registerPeerIdentity(registry, peerId, publicKeyRaw, identityProof, isHost = false)

resetIdentityRegistry(registry, options = {})

async recordScoreReceipt(registry, reporterPeerId, targetPeerId, score, timestamp, signature)

async buildScoreReportOp(identity, selfId, targetPeerId, score)

collabIdentityCriticalOpReport(op, senderPeerId, nowMs = Date.now()

async signCriticalOp(identity, op, selfId)

async verifyCriticalOp(op, senderPeerId, registry)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabIdentity.js Cryptographic peer identity using ECDSA P 256 (Web Crypto API). Each peer generates an ECDSA key pair on init. The public key's SHA 256 fingerprint becomes the peer's verified identity — unforgeable without the private key. During the hello handshake, peers exchange public keys and a signed proof (signature of their selfId). The remote side verifies the signature, confirming the peer truly owns the claimed public key. Host verification: the host's fingerprint is embedded in the invite code. Joiners verify the host's fingerprint matches the one in the invite code, preventing host impersonation. Reputation receipts: peers sign their score reports. Others verify the signature before trusting the score, preventing score tampering. Flow: 1. createIdentity() → ECDSA P 256 key pair + fingerprint 2. buildIdentityProof(identity, selfId) → signed selfId (for hello) 3. Remote receives proof → verifyIdentityProof(publicKey, selfId, proof) 4. If host: fingerprint embedded in invite code → joiner checks match 5. signScoreReceipt(identity, scoreData) → signed score for reputation 6. verifyScoreReceipt(publicKey, scoreData, signature) → boolean Functions Validate one bounded v1/v2 identity record without guessing future shapes. Generate or load an ECDSA P 256 key pair. Tries IndexedDB first for persistent identity across sessions. If not found, generates a new key pair and stores it. The fingerprint (SHA 256 of public key) stays the same across sessions, enabling long term reputation tracking. Returns: identity state Compute fingerprint from a raw public key (public API for verification). Parameters: (Uint8Array number[]) — No description in source JSDoc. Returns: 16 hex chars


collab/CollabIdentity.js

fingerprint from a raw public key (public API for verification). Parameters: (Uint8Array number[]) — No description in source JSDoc. Returns: 16 hex chars Build an identity proof: sign our selfId with our private key. The remote peer verifies this signature to confirm we own the public key. Parameters: (Object) — from createIdentity() (string) — our peer UUID Returns: signature bytes (DER encoded, 70 bytes) Verify an identity proof from a remote peer. Parameters: (Uint8Array number[]) — remote peer's raw public key (65 bytes) (string) — the selfId the remote peer claims (Uint8Array number[]) — the identity proof bytes Returns: true if the signature is valid Sign a reputation score receipt. The receipt proves that this peer calculated and reported a specific score for a target peer at a specific time. Other peers verify the signature to prevent score tampering. Parameters: (Object) — from createIdentity() (Object) — { targetPeerId, score, timestamp, selfId } Returns: signature bytes Verify a reputation score receipt from a remote peer. Parameters: (Uint8Array number[]) — the reporter's raw public key (Object) — { targetPeerId, score, timestamp, selfId } (Uint8Array number[]) — No description in source JSDoc. Sign arbitrary string data with our identity. Parameters: (Object) — No description in source JSDoc. (string) — string to sign Sign raw bytes with our identity (no TextEncoder step) — needed when the verifier expects a signature over an exact byte string it issued (e.g. a random challenge), not over the UTF 8 encoding of some stringified form of it. See signData() for the string based counterpart. Parameters: (Object) — No description in source JSDoc. (Uint8Array) — No description in source JSDoc. Verify a signature on raw bytes. Counterpart to signRawBytes().


collab/CollabIdentity.js

(Object) — No description in source JSDoc. (Uint8Array) — No description in source JSDoc. Verify a signature on raw bytes. Counterpart to signRawBytes(). Parameters: (Uint8Array number[]) — No description in source JSDoc. (Uint8Array) — No description in source JSDoc. (Uint8Array number[]) — No description in source JSDoc. Verify a signature on arbitrary string data. Parameters: (Uint8Array number[]) — No description in source JSDoc. (string) — No description in source JSDoc. (Uint8Array number[]) — No description in source JSDoc. Create a registry that tracks verified identities for all connected peers. Each peer's identity is verified once during the hello handshake and then cached. The registry also tra


collab/CollabIntegrityVerifier.js

createIntegrityVerifier(selfId, config = {})

computeZoneDigest(verifier, sceneEntities, ecsWorld, getEntityComponent, authoritySet)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabIntegrityVerifier.js Integrity validation and anomaly tracking for P2P collab. Inspired by: Hash chain receipts: valid ops contribute to a local rolling chain. Server side validation rules adapted to pairwise peer validation. Lockstep P2P: periodic state hashing — all peers hash their zone state and exchange hashes for pairwise divergence detection. FairPlay: operation whitelist — only registered op types are accepted. Unknown op types are rejected and penalized. Components: 1. Op Receipt Chain — local rolling hash chain per peer 2. Zone State Digest — periodic position hash for pairwise comparison 3. Anomaly Detector — physics/spatial rule violations 4. Operation Whitelist — only valid op types accepted 5. Violation Tracker — accumulates strikes, triggers auto kick 6. Reputation Integration — violations lower peer score Hashes preserve the existing non cryptographic legacy FNV like wire format. Functions Preserve the existing integrity chain FNV like string hash. This intentionally keeps the old JavaScript number multiply path instead of switching to canonical Math.imul FNV 1a, which would change peer digests. Parameters: (string) — No description in source JSDoc. Returns: 8 character hex hash Create an integrity verifier. Parameters: (string) — No description in source JSDoc. (Object) — No description in source JSDoc. Returns: verifier state Validate an incoming op from a peer. Checks: 1. Op type is in the whitelist 2. Op has valid structure 3. Entity position changes are within physics limits Returns: } Record an op in the peer's hash chain for tamper evidence. Call after validateIncomingOp succeeds. Parameters: (Object) — No description in source JSDoc. (string) — No


collab/CollabIntegrityVerifier.js

op in the peer's hash chain for tamper evidence. Call after validateIncomingOp succeeds. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. (Object) — No description in source JSDoc. Get the current chain head hash for a peer (for verification exchange). Compute a hash digest of all entity positions in the caller's zone. This is exchanged with peers for consensus based state verification. Parameters: (Object) — No description in source JSDoc. (Map) — editor.scene.entities (Object) — No description in source JSDoc. (Function) — No description in source JSDoc. (Set) — only include entities in our authority zone Returns: null} Build an integrity digest op to broadcast. Handle an incoming integrity digest from a remote peer. Compares against our own digest — mismatch indicates desync or tampering. Returns: } Tick the verifier: decay violations, build trust, compute social influence. Call at 1Hz. Parameters: (Object) — No description in source JSDoc. (Object) — optional CollabPeerReputation state for social influence Get the violation count for a peer. Get recent violations for a peer. Get all peer violation summaries. Get the current tier for a peer. Returns: 'clean' 'warning' 'throttled' 'muted' 'kicked' Get trust level for a peer (0.0 1.0). Set play mode flag — violations during play mode are weighted less. Check if a peer's ops should be throttled (tier = THROTTLED). Check if a peer's scene edit ops should be blocked (tier = MUTED). Get verifier stats. Build a capabilities op to send to a peer on connect. Contains our supported op types and version string so the remote peer can be lenient about ops we don't recognize (version mismatch, not cheating). Register a remote peer's declared capabilities. Called when we receive a


collab/CollabIntegrityVerifier.js

peer can be lenient about ops we don't recognize (version mismatch, not cheating). Register a remote peer's declared capabilities. Called when we receive a capabilities op from them. Unknown ops from peers with declared capabilities that include the op are treated as version mismatches (INFO), not cheating (HIGH). Set the local version string for capability comparison. Remove a peer's tracking state. Destroy verifier state. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabMeshTopology.js

topologyAddPeer(topo, peerId, info = {})

evaluateSupernodeStatus(topo, selfScore, selfLatencyAvg, integrityInfo)

topologyRegisterSupernode(topo, peerId, announcement = null)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabMeshTopology.js Adaptive mesh topology for scalable P2P collaboration. Problem: Full mesh is O(N²) connections. At 8+ WebRTC peers, browsers struggle with connection management, DTLS overhead, and bandwidth. The old system had a hard limit of 4 8 peers before switching to star relay (single point of failure, bottleneck on host). Solution: Hybrid topology combining proven P2P techniques: 1. PARTIAL MESH — Each peer maintains K direct WebRTC connections to its "best" neighbors (lowest latency, highest reputation). K = 3 6 instead of N 1. Scales linearly, not quadratically. 2. GOSSIP PROPAGATION — Ops ripple through the partial mesh. Each peer forwards received ops to its neighbors (minus sender). With K=4, messages reach all 50 peers in 3 hops (log K(N)). Deduplication via op fingerprint prevents infinite loops. 3. SUPERNODE ELECTION — High reputation peers (score ≥ 700) with good uptime and low latency are elected as supernodes. They maintain more connections (up to 2K) and serve as relay hubs between clusters. Inspired by Skype's original P2P architecture. 4. FAST CHANNEL BRIDGING — Same origin peers use BroadcastChannel (zero cost). They don't count toward K and act as free bridges. Topology modes (auto selected based on peer count): FULL MESH: ≤6 WebRTC peers → everyone connects to everyone PARTIAL MESH: 7 50 peers → K neighbor gossip mesh SUPERNODE: 20+ peers → supernodes bridge clusters Inspired by: libp2p (IPFS), Kademlia, Bitcoin gossip, Meshtastic, Skype supernode architecture, and epidemic broadcast protocols. Current policy boundaries: topology callbacks recommend connection changes but EditorCollab does not execute them; topology reports are advisory rather than


collab/CollabMeshTopology.js

Current policy boundaries: topology callbacks recommend connection changes but EditorCollab does not execute them; topology reports are advisory rather than consensus; gossip envelopes are forwarded before application level integrity validation; and captured large room WebRTC traces remain absent. Functions Create a topology manager. Parameters: (string) — No description in source JSDoc. (Object) — No description in source JSDoc. Resolve the current topology mode based on peer count and quality. Called after peer join/leave and during periodic rebalance. Parameters: (Object) — No description in source JSDoc. Returns: the new topology mode Register a discovered peer (from signaling). Remove a peer (disconnected / left). Mark a peer as connected (WebRTC DataChannel open). Mark a peer as disconnected. Update a peer's metrics (called from reputation system). Compute the ideal neighbor set based on current metrics. Returns { connect: string[], disconnect: string[] } — peers to add/remove. Parameters: (Object) — No description in source JSDoc. Returns: } Evaluate whether this peer should be a supernode. Criteria: high reputation, low latency, good uptime, clean integrity, trusted. Peers with violations (throttled/muted/kicked) are immediately disqualified. Trust and social standing boost candidacy score. Parameters: (Object) — No description in source JSDoc. (number) — our own reputation score (number) — our average latency to neighbors (Object) — { tier, trust, socialModifier } from integrity verifier Returns: true if we became/remained a supernode Update a peer's integrity data (called from integrity verifier tick). Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. Evaluate all remote supernodes and demote any that have


collab/CollabMeshTopology.js

Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. Evaluate all remote supernodes and demote any that have degraded. Called during rebalance tick. Demoted supernodes are unregistered and a topology change is triggered so the mesh re routes around them. Parameters: (Object) — No description in source JSDoc. Returns: peerIds of demoted supernodes Register a remote peer as a supernode. Unregister a remote peer as a supernode. Validate and apply one advisory topology info payload atomically. The report may expand discovery knowledge but never mutates live routes. Generate a gossip fingerprint for deduplication. Uses a compact hash of the op to avoid forwarding the sa


collab/CollabMessageRouter.js

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabMessageRouter.js Priority based message orchestration for collab sync. Sits between EditorCollab and CollabCore, providing: 4 priority lanes (critical → ephemeral) Bandwidth monitoring via channel.bufferedAmount Transform coalescing (latest position wins per entity) Adaptive rate control under backpressure Priority lanes: 0 — Critical: play sync, kick , snapshot → immediate, never throttled 1 — Realtime: play transforms/PBD/grab force → coalesced or rate budgeted 2 — Scene: create, delete, transform, property… → ordered, rate budgeted 3 — Ephemeral: sim heartbeat → latest only, droppable Functions Create a message router instance. Parameters: (Function) — (op) = void — raw send to CollabCore.broadcastOp (Function) — () = number — returns max bufferedAmount across peers Enqueue an op for prioritized delivery. Flush all queued ops respecting priority and backpressure. Call once per render frame from the render loop. Start automatic flush timer (call once on init). Stop the automatic flush timer. Get router statistics. Reset router state (on disconnect/reconnect). Destroy router. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabOpQueue.js

collab/CollabOpQueue.js
Functions
collabOpAdmissionReport(op)
createOpQueue()
enqueueOp(queue, op)
flushPeer(queue, peerId)
removePeer(queue, peerId)
tickOpQueue(queue)
getOpQueueStats(queue)
clearOpQueue(queue)
Notes & Examples

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabOpQueue.js Op ordering, deduplication, and per peer sequence gap handling. Each op: { id, peerId, seq, type, payload, ts } Current scope: bounded local ordering for admitted logical peer IDs. Sequence epochs/wrap, retransmission/NACK, cryptographic sender binding, and captured loss/reordering transport traces remain audit gaps. Functions Enqueue an incoming op. Returns array of ops ready to apply. Flush all held ops for a peer (called on timeout or peer leave). Remove all state for a peer (on disconnect). Tick — flush any peers with stale gaps. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabPeerReputation.js

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabPeerReputation.js Peer quality scoring system — rates each peer 0 1000 based on real time connection metrics. Inspired by Meshtastic SNR based prioritization and multi layer throttling. Score breakdown (1000 total): 250 — Latency (RTT from heartbeat pings) 200 — Packet delivery (sent vs received ratio) 200 — Connection stability (reconnection count) 150 — Session duration (longer = more trusted) 100 — Jitter (variance in latency — lower = better) 100 — Throughput quality (buffered amount / backpressure) Each sub score is 0.0–1.0, multiplied by its weight. The total is rounded to an integer 0–1000. Scores update every 2 seconds; observed peer scores are shared through signed reports, while the local self score rides pongs. Inspired by: Meshtastic SNR based node prioritization, role based priority, and automatic traffic scaling for large meshes. Functions Create a reputation tracker for all peers. Parameters: (string) — this peer's unique ID Returns: reputation state Register a new peer. Remove a peer. Build ping ops to send to all peers. Call at PING INTERVAL MS. Returns: } per peer ping ops Build a pong response to an incoming ping. Returns: op to send back Handle an incoming pong from a peer. Records RTT and jitter. Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. (Object) — No description in source JSDoc. Record the current bufferedAmount for a peer's data channel. Call this periodically (e.g., every presence tick). Recompute scores for all peers. Call at 0.5Hz. Returns: true if scores were updated this tick Get the reputation score for a specific peer (0 1000). Get full metrics for a specific peer (for debug / stats


collab/CollabPeerReputation.js

Returns: true if scores were updated this tick Get the reputation score for a specific peer (0 1000). Get full metrics for a specific peer (for debug / stats display). Get the local peer's self score. This remains the bootstrap score until a self observation consensus path exists. Get all peer scores as an array of { peerId, score, subScores, avgRtt, avgJitter }. Get the score color for rendering (green → yellow → red gradient). Parameters: (number) — 0 1000 Returns: CSS color string Get a human readable label for a score range. Parameters: (number) — No description in source JSDoc. Destroy reputation state. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabPlaySync.js

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabPlaySync.js Synchronizes play/pause/stop across all connected peers. Broadcasts a shared determinism seed so all simulations run identically. Sends heartbeat hashes every 1s for divergence detection. Functions Broadcast a play command to all peers. Called when local user hits Play. seed: optional 32 bit int. Generated here if not provided. Broadcast a pause command to all peers. Broadcast a stop command to all peers. Handle an incoming play sync op from a remote peer. Returns the action taken: 'play' 'pause' 'stop' null Handle an incoming sim heartbeat op from a remote peer. Export local simHistory as a downloadable JSON file. Check if the current play command was triggered remotely. Get the current determinism seed. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabPresence.js

buildLocalPresencePacket(username, cameraPos, cameraTarget, selectionIds, simTime, mode, userColor)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabPresence.js Tracks all peers' camera positions, usernames, selections, and colors. Presence packet: { v:1, u:username, c:[x,y,z], t:[tx,ty,tz], s:[entityIds] } Current scope: lossy latest state presence. Authenticated presence identity, sequence/freshness fields, cross system stale peer cleanup, interpolation ownership, and captured churn traces remain audit gaps. Functions Build a presence packet from local state to broadcast. Apply a remote presence packet for a peer. Register a peer joining (before first presence packet). Remove a peer (on disconnect). Get list of all known peers with their presence data. Get color for a specific peer. Prune peers not seen for 30s. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabSceneSync.js

collabSceneValueReport(value, options = {})

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: No file level description found in source. Add one as a leading JSDoc comment, or document it below. Functions Convert an EditorHistory action into a collab op payload. Convert a collab op back into an EditorHistory compatible action. Serialize the full scene state into a compact snapshot for new joiners. Apply a full scene snapshot to the editor (for new joiners). Clears existing scene and rebuilds from snapshot. Constants — CollabSceneSync.js Serializes EditorHistory actions < collab ops. Handles full scene snapshots for new joiners. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabSignal.js

collabSignalTextReport(value, maxBytes, options = {})

sendOffer(channel, peerId, sdpOffer, offerId)

broadcastOffer(channel, peerId, sdpOffer, offerId)

sendAnswer(channel, peerId, sdpAnswer, offerId)

sendCandidate(channel, peerId, candidate, offerId)

collabSignalOfferPlanReport(pendingCount, inFlightCount = 0)

collabSignalHelloReport(message, selfId = '')

collabSignalPeerHelloReport(message, selfId = '')

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabSignal.js 4 tier signaling abstraction for WebRTC peer discovery. Tier 1: BroadcastChannel — same machine, instant, offline Tier 2: SharedWorker — same machine multi tab relay Tier 4: Particle Masterserver — PRIMARY cross internet signaling relay. Pinned V2 endpoints use the shared ParticleNetworkDaemon; legacy V1 is accepted only when that endpoint explicitly opts in. Uses the same room/route scoped HELLO/OFFER/ANSWER/CANDIDATE dispatch as Tiers 1/2 (see handleSignalMessage) rather than a binary swarm protocol — the Masterserver just fans opaque JSON out to every other session attached to the same locally derived opaque route. This is server mediated, so it works across NATs/networks without any third party dependency. Server configured via localStorage 'os.network.masterServers' (same list the Particle Network control panel app manages); falls back to the pinned production bootstrap if unset. Tier 3: BitTorrent WSS — EXPLICIT FALLBACK ONLY. It remains off by default and can run only after the user opts in. A V2 integrity failure always fails closed and suppresses legacy/BitTorrent downgrade. Tiers 1/2/4 start immediately; Tier 3 is deferred/conditional (see above). First tier to form a WebRTC connection to a given peer wins — after that, signaling is no longer needed for that peer. Functions Create a signal channel. config: { projectId, selfId, username, onOffer, onAnswer, onCandidate, onPeerJoin, onPeerLeave } Negotiation callbacks receive (peerId, payload, offerId). Generic signaling is deliberately strict: every OFFER/ANSWER/CANDIDATE is addressed to one peer and correlated to one offer generation. The WebTorrent tier retains its independent tracker offer id lifecycle


collab/CollabSignal.js

OFFER/ANSWER/CANDIDATE is addressed to one peer and correlated to one offer generation. The WebTorrent tier retains its independent tracker offer id lifecycle and does not use these envelopes. Fetch TURN relay credentials from Cloudflare Pages Function. ONLY called as a fallback when STUN only P2P connection fails. TURN relays ALL traffic through Cloudflare = expensive. Avoid unless necessary. Parameters: (Object) — No description in source JSDoc. Returns: true if TURN credentials were obtained Start all 3 signaling tiers simultaneously. Uses FREE STUN servers only — no Cloudflare data cost. TURN relay is only fetched on demand when a direct P2P connection fails. Force an immediate discovery re announce across all active tiers, bypassing the periodic announce timers. Used by app layer "Connect now" so a known contact is found without waiting for the next BC hello / tracker announce cycle. Send one SDP offer to one discovered peer on the generic signaling tiers. Retained as a strict compatibility symbol. Untargeted offers are unsafe in a multi peer room, so callers must now supply the target and offer generation. Send an SDP answer to a specific peer. Send an ICE candidate to a specific peer. Destroy all signaling resources. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabSpatialAuthority.js

updateEntityPosition(auth, entityId, x, z)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabSpatialAuthority.js Distributed spatial authority for collaborative multiplayer. Each peer owns a circular "zone" centered on their camera position. Entities within a peer's zone are simulated locally by that peer. Entities outside all zones are dormant (no physics, no sync). Authority resolution (Roblox + Gaffer hybrid): Nearest peer within zone radius wins (automatic proximity) 20% hysteresis prevents ping pong at boundaries Higher priority claims (SELECTED, GRABBED) override proximity Sequence numbers resolve conflicts (Gaffer style) Interest management (Photon style): Interest area = zoneRadius × interestMultiplier (default 1.3×) Only send state for entities you're authoritative over Only receive state for entities in your interest area Inspired by: Star Citizen dynamic server meshing, Roblox Network Ownership, Photon Fusion Shared Authority + AoI grid, Gaffer on Games authority scheme. Functions Create a spatial authority state. Parameters: (string) — This peer's unique ID (Object) — Optional overrides Returns: spatial authority state Auto compute zone radius from scene bounds. Parameters: (Object) — { min: [x,y,z], max: [x,y,z] } or { diagonal: number } Returns: zone radius in world units Update the zone radius (e.g., after scene bounds change or manual override). Rebuilds the spatial grid with the new cell size. Update a peer's camera position (called from presence packets). Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. (number[]) — [x, y, z] Remove a peer (on disconnect). Update an entity's position in the spatial grid. Call this when entity transforms change (from physics step or remote sync). Parameters: (Object)


collab/CollabSpatialAuthority.js

disconnect). Update an entity's position in the spatial grid. Call this when entity transforms change (from physics step or remote sync). Parameters: (Object) — No description in source JSDoc. (number string) — No description in source JSDoc. (number) — World X (number) — World Z Remove an entity from the spatial grid (on entity delete). Resolve authority for a single entity based on proximity. Applies hysteresis: current owner keeps it unless new peer is 20% closer. Parameters: (Object) — No description in source JSDoc. (number string) — No description in source JSDoc. (number) — Entity world X (number) — Entity world Z Returns: } Get all entity IDs that the local peer is authoritative over. Uses the auto authority map (resolved at RESOLVE INTERVAL MS). Parameters: (Object) — No description in source JSDoc. Get all entity IDs within the local peer's interest area (zone × interestMultiplier). Parameters: (Object) — No description in source JSDoc. Get the interest set for a specific peer (used by relay host for filtering). Parameters: (Object) — No description in source JSDoc. (string) — No description in source JSDoc. Check if an entity position is within the local peer's authority zone. Parameters: (Object) — No description in source JSDoc. (number) — No description in source JSDoc. (number) — No description in source JSDoc. Check if an entity position is within the buffer zone (boundary ring). Parameters: (Object) — No description in source JSDoc. (number) — No description in source JSDoc. (number) — No description in source JSDoc. Check if an entity is dormant (outside all peer zones). Parameters: (Object) — No description in source JSDoc. (number string) — No description in source JSDoc. Periodic tick: re resolve auto authority for all tracked entities. Call this at


collab/CollabSpatialAuthority.js

description in source JSDoc. (number string) — No description in source JSDoc. Periodic tick: re resolve auto authority for all tracked entities. Call this at 2Hz from the collab loop (or faster if needed). Parameters: (Object) — No description in source JSDoc. Returns: }} detected authority changes Clear all state (on leave room / exit play mode). <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabTransformSync.js

buildFullPlayTransformOp(syncState, ecsWorld, getEntityComponent, sceneEntities, entityAuthority, spatialAuthoritySet)

applyRemotePlayTransforms(op, peerId, ecsWorld, getEntityComponent, setEntityComponent, syncState)

interpolateRemoteEntities(syncState, ecsWorld, getEntityComponent, localDragEntityId, entityAuthority)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabTransformSync.js Broadcasts entity transform updates during play mode so grabbed/moved objects are visible on all peer screens in real time. Authority model: The peer who presses Play becomes the physics authority. Authority broadcasts ALL entity transforms at 10Hz. Non authority peers receive and apply transforms, skipping local physics. Grabbed entity transforms are always sent at 15Hz by anyone. Functions Create a transform sync state object. Mark an entity as being actively grabbed/dragged by the local user. Unmark an entity when released. Build a play transforms op for grabbed entities only. Returns null if nothing to broadcast or if throttled. Build a play transforms op for ALL scene entities. Only called by the physics authority at 10Hz. Parameters: (Object) — No description in source JSDoc. (Object) — No description in source JSDoc. (Function) — No description in source JSDoc. (Map) — editor.scene.entities map (Object) — CollabEntityAuthority state for per entity ownership (Set) — If provided, only broadcast entities in this set (spatial zone filter) Returns: null} Build a play pbd state op that snapshots PBD particle positions. Any peer running physics simulations broadcasts at 30Hz for real time rope sync. Only includes sims with 0 particles. Full float precision for smooth visual sync. Parameters: (Object) — No description in source JSDoc. (Map) — editor.physicsSimulations (Set) — If provided, only broadcast sims for entities in this set (spatial zone filter) Returns: null} Apply incoming PBD particle state from the authority (host). Non authority clients do NOT run their own PBD solver for these sims — they just apply the received positions directly. Tags each


collab/CollabTransformSync.js

from the authority (host). Non authority clients do NOT run their own PBD solver for these sims — they just apply the received positions directly. Tags each sim with so stepPhysicsSimulations skips the local solver for it (prevents local physics from fighting the authoritative positions). Parameters: (Object) — No description in source JSDoc. (Map) — editor.physicsSimulations Apply incoming play transforms from a remote peer. Pushes transforms into the interpolation buffer, measures jitter for adaptive delay, and detects "nuke" events (massive state changes) for instant snap. Interpolate buffered remote transforms and write to ECS + physics. Called every render frame by non authority peers. Uses adaptive render delay that auto adjusts based on measured packet jitter. On LAN/good connections: as low as 20ms. On jittery links: up to 150ms. Slowly tightens delay when stable; instantly widens on late arrivals. Get the current adaptive interpolation delay (ms) for diagnostics. Get set of entity IDs currently being grabbed by remote peers. Returns Map<entityId, peerColor for glow rendering. Parameters: (Object) — No description in source JSDoc. (Object) — CollabPresence state for peer colors Destroy / reset transform sync state. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/CollabZoneHandoff.js

initiateHandoff(handoff, entityId, fromPeer, toPeer)

buildHandoffOp(entityId, fromPeer, toPeer, seq, entityState)

captureEntityState(ecsWorld, getEntityComponent, entityId, physicsSimulations)

onRemoteHandoffOp(handoff, op, selfId, ecsWorld, setEntityComponent, getEntityComponent, physicsSimulations)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: CollabZoneHandoff.js Smooth authority transfer protocol when entities cross spatial zone boundaries. Buffer zone (15% of zone radius): Entity enters buffer → both peers simulate, current owner broadcasts state Entity crosses buffer center → handoff op with full state snapshot 500ms hysteresis prevents rapid back and forth Handoff op: { type: 'zone handoff', payload: { entityId, fromPeer, toPeer, seq, state } } state: { pos, rot, vel, angVel, pbdParticles? } seq: authority sequence number (higher always wins, Gaffer style) Assembly awareness: if entity A is constrained to entity B, both get handed off together to the same peer. Fallback: if fromPeer disconnects mid handoff, nearest remaining peer takes ownership immediately. Inspired by: Roblox "buffer zone" (red outline), Star Citizen entity graph authority transfers, Gaffer on Games ownership sequence numbers. Functions Create a zone handoff manager. Returns: handoff state Start a pending handoff for an entity (called when spatial authority detects a zone change). Does NOT commit yet — waits for hysteresis period. Parameters: (Object) — handoff state (string number) — No description in source JSDoc. (string) — No description in source JSDoc. (string) — No description in source JSDoc. Returns: true if handoff was initiated (false if already pending for same pair) Cancel a pending handoff (entity moved back to original zone). Parameters: (Object) — No description in source JSDoc. (string number) — No description in source JSDoc. Build a zone handoff op with full entity state for network transmission. Called by the outgoing peer when handoff commits. Parameters: (string number) — No description in source JSDoc. (string) — No


collab/CollabZoneHandoff.js

state for network transmission. Called by the outgoing peer when handoff commits. Parameters: (string number) — No description in source JSDoc. (string) — No description in source JSDoc. (string) — No description in source JSDoc. (number) — No description in source JSDoc. (Object) — { pos:[x,y,z], rot:[x,y,z,w], vel:[x,y,z], angVel:[x,y,z], pbdParticles?:Float32Array } Returns: op to broadcast Capture entity state for the handoff snapshot. Parameters: (Object) — No description in source JSDoc. (Function) — No description in source JSDoc. (string number) — No description in source JSDoc. (Map) — for PBD particle state Returns: entityState Handle an incoming zone handoff op from a remote peer. Applies the state snapshot if the sequence number is higher than our last. Parameters: (Object) — No description in source JSDoc. (Object) — { type: 'zone handoff', payload: { entityId, fromPeer, toPeer, seq, state } } (string) — this peer's ID (Object) — No description in source JSDoc. (Function) — No description in source JSDoc. (Function) — No description in source JSDoc. (Map) — No description in source JSDoc. Returns: true if handoff was accepted Tick pending handoffs. Commits any that have passed the hysteresis period. Prunes stale pending handoffs. Parameters: (Object) — No description in source JSDoc. (string) — this peer's ID Returns: } handoffs ready to commit Handle peer disconnect: cancel pending handoffs involving this peer and reassign any entities that were mid handoff. Parameters: (Object) — No description in source JSDoc. (string) — disconnected peer Returns: entity IDs that need re assignment Set callback for handoff completion. Destroy handoff state. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API


collab/CollabZoneHandoff.js

for handoff completion. Destroy handoff state. <! HUMAN NOTES Notes & Examples No hand authored notes yet. Add page notes in or a reusable block in — see API Reference Standard.


collab/PhysicsGrab.js

physicsGrabVectorReport(value, kind = 'position')

physicsGrabForceReport(objPos, objVel, targetPos, strength, mass)

grabForceOperationReport(op, transportPeerId = null)

admitRemoteGrabForce(remoteGrabs, op, transportPeerId, receivedAtMs = Date.now()

pruneRemoteGrabForces(remoteGrabs, nowMs = Date.now()

computeGrabForce(objPos, objVel, targetPos, strength, mass)

buildGrabForceOp(peerId, entityId, targetPos, strength, fatigue)

applyGrabForcesToActor(actor, PhysX, objPos, objVel, grabs, mass)

<! AUTOGENERATED by tools/extract api.py — content above HUMAN NOTES is overwritten Source: PhysicsGrab.js Mass proportional spring damper (PD controller) physics grab system. How other games do it: Garry's Mod Physgun: pure spring damper, body stays dynamic Half Life 2 gravity gun: spring + angular correction torque Boneworks/BONELAB VR: PD controller with grip strength cap UE4 Physics Handle: D6 joint linear drive to target pos This implementation uses a frequency / damping ratio parameterization (ref: Orange Duck "Spring It On", Gaffer on Games "Spring Physics"): omega = 2π × frequency (natural frequency, rad/s) kp = omega² × mass (spring stiffness, N/m) ← mass proportional kd = 2 × ζ × omega × mass (damping, N·s/m) ← mass proportional With ζ = 1.0 (critical damping), the object reaches the target as fast as possible with zero overshoot regardless of mass. A 0.5 kg ball and a 200 kg crate both converge at the same rate. Multiple players grabbing the same object creates competing spring forces that resolve naturally through physics — tug of war emerges with no special case code needed. Fatigue model (Boneworks inspired): Holding heavy objects drains fatigue over time Effective strength = baseStrength (0.2 + 0.8 fatigue) Minimum 20% strength even when exhausted Fatigue recovers quickly when not holding Grip break: Progressive grip weakening beyond GRIP WEAKEN DIST Full slip at GRIP BREAK DIST Scope: point target PD forces for dynamic rigid bodies. Constraint/joint drives, rotational grabs, continuous collision detection, solver substep tuning, and captured multi peer PhysX traces remain outside this module. Functions Compute mass proportional spring damper grab force. Uses frequency/damping ratio parameterization so the convergence rate is identical regardless of