NET FORGE DOCS

@netforge/engine/runtime API reference

Last updated Checked against @netforge/engine 0.2.0View as Markdown

Net Forge, the open-source multiplayer browser game engine built for AI coding agents, is published on npm under @netforge with source at github.com/netnetdev/net-forge.

The three.js runtime templates draw with: the WebGPU renderer with a WebGL2 fallback, createRenderStack, the game feel kit, CameraRig, InputController, AssetLoader, instanced and animated crowds, and the arena client.

import { createRenderStack, FeelKit } from "@netforge/engine/runtime";

Generated from packages/engine/src/runtime/index.ts by apps/forge-docs/scripts/api.mjs. Signatures are what the TypeScript compiler reports for the current source; long types are cut and say so.

KindCount
Functions40
Classes36
Constants13
Types109
Other1

Functions

applyCrowdMotion

Vertex animation for crowds without skeletons: bob, waddle, forward lean and step cadence from each instance's speed, a squash-and-stretch on hit, a hit flash, idle breathing. Applied to an existing node material (positionNode, emissiveNode); geometry stands on y = 0 and faces -z.

function applyCrowdMotion(material: MotionMaterial, attrs: CrowdAttributes, time: Node<"float">, opts?: CrowdMotionOptions): MotionMaterial;

Source: packages/engine/src/runtime/render/crowd-motion.ts

bakeVertexAnimation

Bake one or more clips of a skinned mesh into a vertex animation texture (CPU, at load). Frames are laid out clip after clip; a crowd then plays any clip on thousands of instances in one draw (VatCrowd).

function bakeVertexAnimation(mesh: SkinnedMesh, clips: AnimationClip | readonly AnimationClip[], opts?: BakeOptions): VertexAnimation;

Source: packages/engine/src/runtime/render/vat.ts

billboardWorld

World position of a sprite vertex: center is the feet in world space, x/y the vertex in metres on the plane (x across, y up from the feet), flip -1 to mirror. The plane turns to the camera (its up is the camera's up, so a sprite under a high camera shows its full height).

function billboardWorld(center: Node<"vec3">, x: Node<"float">, y: Node<"float">, flip: Node<"float">): Node<"vec3">;

Source: packages/engine/src/runtime/render/sprite.ts

boundsShift

How far to move a view so seen stays inside bounds, per axis: zero when it already fits, the overshoot when it pokes out of one side, and centring when it is wider than the bounds.

function boundsShift(seen: GroundBounds, bounds: GroundBounds): { x: number; z: number; };

Source: packages/engine/src/runtime/camera.ts

browserHints

Read the hints from the running browser (safe in node: returns {}).

function browserHints(backend?: "webgpu" | "webgl2"): DeviceHints;

Source: packages/engine/src/runtime/render/quality.ts

buildSegmentRig

A three-bone procedural character (hip, spine, head) skinned to a cylinder or any upright geometry, with a full animation set built in code: rest, idle, walk, run, hit, attack, die. Templates with procedural art get real skinned animation (and VAT crowds via bakeVertexAnimation) without any asset files.

function buildSegmentRig(material: Material, opts?: SegmentRigOptions): SegmentRig;

Source: packages/engine/src/runtime/render/rig.ts

collectManifest

Collect and cross-check what the game module declared. Called by the build and the runtime after importing the module, not by game code.

function collectManifest(): GameManifest;

Source: packages/engine/src/api/registry.ts

countUp

Count a number up in an element's text (scores, balances).

function countUp(el: FeelElement, from: number, to: number, ms?: number, format?: (n: number) => string, tweens?: Tweens): void;

Source: packages/engine/src/runtime/feel/tween.ts

createPixelStyle

The pixel style with its options.

function createPixelStyle(o?: PixelStyleOptions): StyleKit;

Source: packages/engine/src/runtime/styles/pixel/index.ts

createRenderer

three.js WebGPURenderer. It targets WebGPU where navigator.gpu yields an adapter and falls back to its WebGL2 backend otherwise, so one code path (node materials, instancing) covers every browser (spec).

function createRenderer(canvas: HTMLCanvasElement, opts?: RendererOptions): Promise<RendererHandle>;

Source: packages/engine/src/runtime/renderer.ts

createRenderStack

Everything a template needs for a good-looking frame, in one call: lighting with a following shadow, fog and sky, bloom and grade, GPU particles, decals and shockwave rings, quality tiers and dynamic resolution. Replace renderer.render(scene, camera) with stack.frame(...).

function createRenderStack(handle: RendererHandle, scene: Scene, camera: Camera, opts?: RenderStackOptions): RenderStack;

Source: packages/engine/src/runtime/render/stack.ts

createStyledView

The style's view of a scene, or null when the style has no session (lowpoly, unknown, or a kit with world builders only).

function createStyledView(handle: RendererHandle, scene: Scene, camera: Camera, style: string | StyleKit | null | undefined, opts?: StyledViewOptions): StyledView | null;

Source: packages/engine/src/runtime/styles/view.ts

damp

Frame-rate independent exponential smoothing factor for a rate in 1/s.

function damp(rate: number, dt: number): number;

Source: packages/engine/src/runtime/interpolate.ts

detectTier

Pick a tier from device hints. Phones and tablets start at medium (low on weak or WebGL-only ones); desktops start at high unless the CPU is small. Dynamic resolution then holds the frame rate within the tier.

function detectTier(h: DeviceHints): QualityTier;

Source: packages/engine/src/runtime/render/quality.ts

distanceGain

Gain for a source distance m away (inverse falloff, 0 past maxDistance).

function distanceGain(distance: number, refDistance?: number, maxDistance?: number, rolloff?: number): number;

Source: packages/engine/src/runtime/feel/audio.ts

fieldBounds

Square bounds around the origin: a field of half size half plus margin of outside ground.

function fieldBounds(half: number, margin?: number): GroundBounds;

Source: packages/engine/src/runtime/camera.ts

flashColor

Write a flashed instance colour into out at offset (rgb floats): base colour mixed toward tint and boosted by the flash.

function flashColor(out: Float32Array | number[], offset: number, flash: number, base?: readonly [number, number, number], tint?: readonly [number, number, number], boost?: number): void;

Source: packages/engine/src/runtime/feel/flash.ts

flashMultiplier

Colour multiplier for a flash: 1 at rest, 1 + boost at full flash (instance colours above 1 read as glowing white).

function flashMultiplier(flash: number, boost?: number): number;

Source: packages/engine/src/runtime/feel/flash.ts

groundFootprint

The ground a camera sees: the box around where its four corner rays meet the plane y = groundY. A ray at or above the horizon counts as reaching reach m out along the ground. The camera's matrices must be current.

function groundFootprint(camera: Camera, groundY?: number, reach?: number): GroundBounds;

Source: packages/engine/src/runtime/camera.ts

hashSigned

Seeded integer hash to -1..1 (deterministic, no Math.random).

function hashSigned(i: number, seed: number): number;

Source: packages/engine/src/runtime/feel/noise.ts

isSprite

Whether a geometry is a sprite plane (markSprite).

function isSprite(geometry: { userData: Record<string, unknown>; }): boolean;

Source: packages/engine/src/runtime/render/sprite.ts

lerp

Linear interpolation.

function lerp(a: number, b: number, t: number): number;

Source: packages/engine/src/runtime/interpolate.ts

lerpAngle

Interpolate angles along the shortest arc (radians).

function lerpAngle(a: number, b: number, t: number): number;

Source: packages/engine/src/runtime/interpolate.ts

locomotionState

The locomotion state for a speed, with hysteresis around the current state. Pure.

function locomotionState(speed: number, current: LocomotionState, t?: LocomotionThresholds): LocomotionState;

Source: packages/engine/src/runtime/render/animation.ts

markSprite

Flag a sprite plane so AnimatedCrowd draws it as billboards (geometry.userData).

function markSprite(geometry: { userData: Record<string, unknown>; }): void;

Source: packages/engine/src/runtime/render/sprite.ts

markSpriteMaterial

A sprite material's extra output: the pixel style keeps sprites in their own palette colours and steps only the 3D world into light bands. Safe everywhere: a target without a "sprite" texture just takes the colour.

function markSpriteMaterial(material: { mrtNode: unknown; }): void;

Source: packages/engine/src/runtime/render/sprite.ts

pickStyle

The art style a template draws in: a known ?style= on the URL wins over the game's declared style.

function pickStyle(declared: string, requested: string | null | undefined): string;

Source: packages/engine/src/runtime/styles/index.ts

pixelBlock

The integer block size (screen pixels per low-res pixel) that puts texelsPerMetre low-res rows on each metre of a view viewMetres tall.

function pixelBlock(bufferHeight: number, viewMetres: number, texelsPerMetre: number, minRows?: number): number;

Source: packages/engine/src/runtime/styles/pixel/index.ts

pop

Punch an element's scale up to scale and spring it back (level-up, coin gain).

function pop(el: FeelElement, scale?: number, ms?: number, tweens?: Tweens): void;

Source: packages/engine/src/runtime/feel/tween.ts

qualitySettings

function qualitySettings(tier: QualityTier): QualitySettings;

Source: packages/engine/src/runtime/render/quality.ts

resetRegistry

Forget all declarations (the build and tests load several game modules in one process).

function resetRegistry(): void;

Source: packages/engine/src/api/registry.ts

resolveLook

A preset by name; unknown names fall back to "studio" (never throws at runtime).

function resolveLook(name: string | undefined): Look;

Source: packages/engine/src/runtime/render/presets.ts

seededRandom

A small seeded PRNG (mulberry32), 0..1, for cosmetic variation that should not use Math.random.

function seededRandom(seed: number): () => number;

Source: packages/engine/src/runtime/feel/noise.ts

shakeEl

Shake an element sideways by up to px, decaying over ms (denied action, damage taken).

function shakeEl(el: FeelElement, px?: number, ms?: number, tweens?: Tweens): void;

Source: packages/engine/src/runtime/feel/tween.ts

snapToTexel

Snap a world point to the shadow map's texel grid in light space, so a shadow camera that follows the player moves in whole texels and the shadow edges never shimmer. dir is the light's travel-from direction (unit), texel the world size of one shadow texel.

function snapToTexel(p: readonly [number, number, number], dir: readonly [number, number, number], texel: number): Vec3Tuple;

Source: packages/engine/src/runtime/render/lighting.ts

spriteBillboardNode

positionNode for a single sprite mesh (a player, a boss): the plane faces the camera whatever the mesh's rotation, and mirrors when the mesh's forward (-z) points to screen left.

function spriteBillboardNode(): Node<"vec3">;

Source: packages/engine/src/runtime/render/sprite.ts

stepSpring

Advance one spring axis toward target by dt seconds with the exact solution of the damped oscillator, so it is stable at any stiffness and frame rate. omega is the natural frequency in rad/s, zeta the damping ratio. Returns [value, velocity].

function stepSpring(value: number, velocity: number, target: number, omega: number, zeta: number, dt: number): [number, number];

Source: packages/engine/src/runtime/feel/spring.ts

styleKit

The kit for a style, or null (low-poly, or a style with no kit yet).

function styleKit(style: string | null | undefined): StyleKit | null;

Source: packages/engine/src/runtime/styles/index.ts

toNodeMaterial

Copy a classic MeshStandardMaterial into a node material (so positionNode can be set).

function toNodeMaterial(m: MeshStandardMaterial): MeshStandardNodeMaterial;

Source: packages/engine/src/runtime/render/crowd-motion.ts

valueNoise1

Smooth 1D value noise in -1..1, continuous in t, fixed for a seed.

function valueNoise1(t: number, seed: number): number;

Source: packages/engine/src/runtime/feel/noise.ts

Classes

AnimatedCharacter

A skinned character (glTF or procedural) with an AnimationMixer: setSpeed(mps) drives idle/walk/run with crossfades and playback rate matched to ground speed; oneShot("attack") plays once and blends back to locomotion; play(name) for anything else. Call update(dt) per frame.

class AnimatedCharacter {
  constructor(root: Object3D, clips: readonly AnimationClip[], opts?: AnimatedCharacterOptions);
  readonly mixer: AnimationMixer<AnimationMixerEventMap>;
  has(name: string): boolean;
  get state(): LocomotionState;
  get playing(): string | null;
  play(name: string, opts?: PlayOptions): boolean;
  oneShot(name: string, opts?: Omit<PlayOptions, "loop">): boolean;
  setSpeed(mps: number): void;
  update(dt: number): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/animation.ts

AnimatedCrowd

An instanced crowd with procedural animation: one draw, per-instance position, yaw, scale, phase, speed, hit squash and flash. Write instances between begin() and end(time) each frame; only the written range uploads.

class AnimatedCrowd {
  constructor(geometry: BufferGeometry, material: MeshStandardMaterial | MeshStandardNodeMaterial, capacity: number, opts?: CrowdMotionOptions);
  readonly mesh: Mesh<BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>, Material<MaterialEventMap> | Material<MaterialEventMap>[], Object3DEventMap>;
  readonly time: UniformNode<"float", number>;
  readonly attrs: CrowdAttributes;
  count: number;
  begin(): void;
  push(x: number, y: number, z: number, yaw: number, phase: number, speed: number, hit?: number, flash?: number, scale?: number): void;
  end(timeSeconds: number): void;
  addTo(parent: Object3D): this;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/crowd-motion.ts

ArenaClient

The week-2 single-player arena: engine-sim on a fixed tick, rendered by three.js with interpolation, one instanced draw for every enemy, a follow camera, keyboard/mouse/touch input. Placeholder primitives only.

class ArenaClient {
  constructor(host: HTMLElement, handle: RendererHandle, world: SimWorld, opts: ArenaOptions);
  static create(host: HTMLElement, opts?: ArenaOptions): Promise<ArenaClient>;
  start(): void;
  stats(): ArenaStats | null;
  dispose(): void;
}

Source: packages/engine/src/runtime/arena.ts

AssetLoader

glTF loading with the runtime's compression stack: meshopt geometry (EXT_meshopt_compression) and KTX2/Basis textures (KHR_texture_basisu). Loads are cached by id, so a prefab used 2,000 times is fetched once.

class AssetLoader {
  constructor(renderer: WebGPURenderer, opts: AssetLoaderOptions);
  load(id: string): Promise<GLTF>;
  dispose(): void;
}

Source: packages/engine/src/runtime/assets.ts

Atmosphere

Fog matched to a sky gradient, so the far ground melts into the background instead of meeting a hard color. Linear or exp2 distance fog, plus an optional low height fog (ground mist). Values live in uniforms: changing them never recompiles a shader.

class Atmosphere {
  constructor(scene: Scene, opts?: AtmosphereOptions);
  readonly fogColor: UniformNode<"color", Color>;
  readonly skyTop: UniformNode<"color", Color>;
  readonly near: UniformNode<"float", number>;
  readonly far: UniformNode<"float", number>;
  readonly density: UniformNode<"float", number>;
  readonly heightDensity: UniformNode<"float", number>;
  readonly heightTop: UniformNode<"float", number>;
  setPreset(preset: LookPreset, overrides?: Partial<AtmospherePreset>): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/atmosphere.ts

CameraRig

Third-person orbit-follow camera with the camera parts of the feel kit: critically damped follow, smoothed and clamped lead, a dead zone, trauma shake and FOV punches. yaw matches the sim's convention (0 looks down -z), so the input layer can send the camera's yaw as the character's facing. Shake is applied as a per-frame offset and roll on top of the computed pose, so it never accumulates drift.

class CameraRig {
  constructor(aspect: number, opts?: CameraRigOptions);
  readonly camera: PerspectiveCamera;
  yaw: number;
  pitch: number;
  readonly trauma: Trauma;
  readonly offset: Vector3;
  roll: number;
  readonly clampShift: { x: number; z: number; };
  setDistance(metres: number): void;
  setBounds(bounds: GroundBounds | null): void;
  get target(): Readonly<Vector3>;
  look(dYaw: number, dPitch: number): void;
  addTrauma(amount: number): void;
  shake(amplitude: number, seconds: number): void;
  punch(degrees: number): void;
  get fovKick(): number;
  update(target: Vector3, dt: number, realDt?: number): void;
  resize(aspect: number): void;
}

Source: packages/engine/src/runtime/camera.ts

CueGate

The DOM-free decision core: may a cue start now? Per-cue gap and voice cap, and a global voice cap.

class CueGate {
  constructor(maxVoices?: number);
  allow(name: string, nowMs: number, durationMs: number, minGapMs: number, cueVoices: number): boolean;
  get voices(): number;
}

Source: packages/engine/src/runtime/feel/audio.ts

DamageNumbers

The DOM pool. Construct only in a browser (it creates nodes under host).

class DamageNumbers {
  constructor(host: HTMLElement, opts?: DamageNumbersOptions | number);
  readonly stack: NumberStack;
  get shown(): number;
  show(x: number, y: number, amount: number, big?: boolean): void;
  add(n: NumberInput, nowMs?: number): void;
  update(dt: number): void;
}

Source: packages/engine/src/runtime/feel/numbers.ts

DynamicResolution

Pixel-ratio controller: trades pixels for frame time. Push every frame's interval; update(now) returns the new ratio when it changes, else null. After a change the window restarts so the next decision sees the new cost.

class DynamicResolution {
  constructor(initial: number, opts?: DynamicResolutionOptions);
  ratio: number;
  readonly o: Required<DynamicResolutionOptions>;
  push(frameMs: number): void;
  p95(): number;
  setRange(min: number, max: number): number | null;
  update(now: number): number | null;
}

Source: packages/engine/src/runtime/render/quality.ts

FeelAudio

class FeelAudio {
  constructor(opts?: FeelAudioOptions);
  muted: boolean;
  played: number;
  readonly gate: CueGate;
  unlock(): void;
  whenUnlocked(fn: (ctx: AudioContext) => void): void;
  get context(): AudioContext | null;
  unlockOnGesture(target?: EventTarget): void;
  get ready(): boolean;
  get master(): number;
  define(name: string, recipe: SynthRecipe, opts?: CueOptions): void;
  addBuffer(name: string, source: AudioBuffer | string, opts?: CueOptions & { readonly gain?: number; }): Promise<void>;
  has(name: string): boolean;
  play(name: string, opts?: PlayOptions): boolean;
  impact(damage: number, opts?: PlayOptions): boolean;
}

Source: packages/engine/src/runtime/feel/audio.ts

FeelClock

class FeelClock {
  constructor(opts?: FeelClockOptions);
  stops: number;
  slows: number;
  hitStop(ms: number, realNow?: number): void;
  slowMo(scale: number, ms: number, easeMs?: number, realNow?: number): void;
  tick(realNow?: number): ClockTick;
  get stopped(): boolean;
  get lagMs(): number;
}

Source: packages/engine/src/runtime/feel/clock.ts

FeelKit

class FeelKit {
  constructor(opts?: FeelKitOptions);
  readonly preset: FeelPreset;
  readonly clock: FeelClock;
  readonly flash: HitFlash;
  readonly knock: KnockbackOffsets;
  readonly trauma: Trauma;
  readonly tweens: Tweens;
  readonly numbers: DamageNumbers | null;
  readonly audio: FeelAudio | null;
  readonly rumble: Rumble | null;
  readonly footsteps: Footsteps | null;
  particles: ParticleSink | null;
  hurtPulse: number;
  readonly counts: { hits: number; kills: number; bigKills: number; hurts: number; levelUps: number; lands: number; dashes: number; };
  camera: TraumaTarget;
  project: Projector | undefined;
  tick(realNow?: number): ClockTick;
  hit(e: HitEvent): void;
  kill(e: KillEvent): void;
  hurt(amount: number, maxHealth?: number): void;
  levelUp(): void;
  land(intensity?: number): void;
  dash(): void;
  footstep(speed: number, grounded?: boolean, surface?: Surface): void;
  update(dt: number, realDt?: number): void;
}

Source: packages/engine/src/runtime/feel/kit.ts

Footsteps

Footstep cadence from speed: steps per second = speed / stride, with an alternating left/right pitch. Calls play(pitch, gain) on each step.

class Footsteps {
  constructor(play: (pitch: number, gain: number) => void, opts?: FootstepOptions);
  surface: "grass" | "stone" | "dirt" | "wood" | "metal";
  steps: number;
  update(dt: number, speed: number, grounded?: boolean): number;
}

Source: packages/engine/src/runtime/feel/audio.ts

FrameStats

Rolling frame-time statistics (ms) over the last size frames.

class FrameStats {
  constructor(size?: number);
  push(ms: number): void;
  get count(): number;
  mean(): number;
  percentile(q: number): number;
}

Source: packages/engine/src/runtime/stats.ts

GpuParticles

Pooled GPU particles: one draw for every additive particle on screen (and one for alpha-blended smoke and dust). The CPU writes only the spawn slots of a burst; the vertex stage computes motion (velocity, drag, gravity, a floor clamp), billboarding, velocity stretch, size and fade.

class GpuParticles {
  constructor(parent: Object3D, opts?: GpuParticlesOptions);
  readonly time: UniformNode<"float", number>;
  bursts: number;
  get meshes(): Mesh<BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>, Material<MaterialEventMap> | Material<MaterialEventMap>[], Object3DEventMap>[];
  burst(preset: string, x: number, y: number, z: number, opts?: ParticleBurstOptions): void;
  emit(preset: string, x: number, y: number, z: number, rate: number, dt: number, opts?: ParticleBurstOptions): void;
  update(timeSeconds: number): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/particles.ts

GroundDecals

Ground decals (scorch marks, splats, rings) in one draw: flat quads on the floor, shapes drawn procedurally in the fragment stage (no textures), faded over their life. A ring buffer: the oldest decal is reused.

class GroundDecals {
  constructor(parent: Object3D, capacity?: number, random?: () => number, look?: DecalLook);
  readonly time: UniformNode<"float", number>;
  readonly ring: ParticleRing;
  readonly mesh: Mesh<BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>, Material<MaterialEventMap> | Material<MaterialEventMap>[], Object3DEventMap>;
  floorY: number;
  add(kind: DecalKind, x: number, z: number, opts?: DecalOptions): void;
  update(timeSeconds: number): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/decals.ts

GroundRings

Expanding shockwave rings on the floor (nova blasts, landings, dash starts): one additive draw, pooled. Generalized from EMBERWATCH's rings.

class GroundRings {
  constructor(parent: Object3D, capacity?: number, look?: RingLook);
  readonly time: UniformNode<"float", number>;
  readonly ring: ParticleRing;
  readonly mesh: Mesh<BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>, Material<MaterialEventMap> | Material<MaterialEventMap>[], Object3DEventMap>;
  fired: number;
  fire(x: number, z: number, radius: number, opts?: RingOptions): void;
  update(timeSeconds: number): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/decals.ts

HeroHighlight

class HeroHighlight {
  constructor(root: Object3D, opts?: HeroHighlightOptions);
  readonly parts: Mesh<BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>, Material<MaterialEventMap> | Material<MaterialEventMap>[], Object3DEventMap>[];
  dispose(): void;
}

Source: packages/engine/src/runtime/render/highlight.ts

HitFlash

Hit flash: per-entity timers that read as 0..1 intensity, for instanced crowds that tint an instance toward white (or any colour) on a hit.

class HitFlash {
  constructor(seconds?: number);
  count: number;
  trigger(id: number, strength?: number): void;
  value(id: number): number;
  update(dt: number): void;
  get size(): number;
  clear(): void;
}

Source: packages/engine/src/runtime/feel/flash.ts

InputController

Keyboard + mouse (pointer lock) and touch (nipplejs virtual stick on the left half, drag-to-look and action buttons on the right). sample() produces one sequence-numbered InputCommand per fixed tick.

class InputController {
  constructor(element: HTMLElement, look: LookTarget, opts?: InputOptions);
  readonly touch: boolean;
  sample(tick: number): InputCommand;
  dispose(): void;
}

Source: packages/engine/src/runtime/input.ts

InstancedCrowd

One InstancedMesh per entity kind: 2,000 enemies are one draw call (spec). Each frame writes interpolated matrices straight into the instance buffer (rotation about y only; no per-instance Object3D).

class InstancedCrowd {
  constructor(geometry: BufferGeometry, material: Material, capacity: number, kind: number, scale?: number);
  readonly mesh: InstancedMesh<BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>, Material<MaterialEventMap> | Material<MaterialEventMap>[], Object3DEventMap>;
  update(view: RenderView, alpha: number): number;
  dispose(): void;
}

Source: packages/engine/src/runtime/crowd.ts

KnockbackOffsets

class KnockbackOffsets {
  constructor(opts?: KnockbackOptions);
  kicks: number;
  kick(id: number, dirX: number, dirZ: number, strength?: number): void;
  get(id: number): Readonly<KnockbackSample>;
  update(dt: number): void;
  get size(): number;
  clear(): void;
}

Source: packages/engine/src/runtime/feel/knockback.ts

LightingRig

Hemisphere + one directional light whose single shadow map follows a focus point (the player), snapped to texels. Sized for a top-down or third-person view: one tuned map beats cascades at this camera distance.

class LightingRig {
  constructor(renderer: WebGPURenderer, scene: Scene, opts?: LightingOptions);
  readonly root: Object3D<Object3DEventMap>;
  readonly hemi: HemisphereLight;
  readonly sun: DirectionalLight;
  readonly ambient: AmbientLight;
  get texel(): number;
  get shadowsOn(): boolean;
  setShadowMapSize(size: number): void;
  setShadowExtent(extent: number): void;
  follow(x: number, y: number, z: number): void;
  setPreset(preset: LookPreset, overrides?: Partial<LightingPreset>): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/lighting.ts

NumberStack

class NumberStack {
  constructor(capacity?: number, opts?: NumberStackOptions);
  readonly slots: NumberSlot[];
  shown: number;
  merged: number;
  add(nowMs: number, n: NumberInput): { index: number; merged: boolean; };
  update(dt: number): void;
  draw(s: NumberSlot): NumberDraw;
  get active(): number;
}

Source: packages/engine/src/runtime/feel/numbers.ts

ParticleRing

A ring of capacity particle slots. Allocation never iterates live particles: the oldest slot is simply overwritten. Records which slot ranges changed since the last flush so only those bytes are uploaded.

class ParticleRing {
  constructor(capacity: number);
  head: number;
  written: number;
  alloc(n: number): number[];
  flush(): [number, number][];
}

Source: packages/engine/src/runtime/render/particles.ts

PostFX

The post stack: scene pass (HDR) -> bloom -> optional depth outline -> color grade (exposure, contrast, saturation, split tone, vignette, hurt pulse) -> tone mapping and sRGB (once, via renderOutput) -> FXAA.

Tone mapping is the renderer's (renderer.toneMapping), so the same curve applies whether post is on (here, in renderOutput) or off (renderer.render to the canvas). Every knob is a uniform.

class PostFX {
  constructor(renderer: WebGPURenderer, scene: Scene, camera: Camera, opts?: PostFXOptions);
  readonly pipeline: RenderPipeline;
  readonly exposure: UniformNode<"float", number>;
  readonly contrast: UniformNode<"float", number>;
  readonly saturation: UniformNode<"float", number>;
  readonly shadowTint: UniformNode<"vec3", Vector3>;
  readonly highlightTint: UniformNode<"vec3", Vector3>;
  readonly vignette: UniformNode<"float", number>;
  readonly hurt: UniformNode<"float", number>;
  readonly outlineColor: UniformNode<"color", Color>;
  readonly outlineThickness: UniformNode<"float", number>;
  readonly outlineThreshold: UniformNode<"float", number>;
  readonly outlineStrength: UniformNode<"float", number>;
  enabled: boolean;
  get bloom(): BloomNode | null;
  setPreset(preset: LookPreset, overrides?: Partial<GradePreset>): void;
  configure(o: { bloom?: boolean; outline?: boolean; fxaa?: boolean; bloomScale?: number; enabled?: boolean; }): void;
  setQuality(tier: QualityTier, outlineWanted?: boolean): void;
  get stages(): { enabled: boolean; bloom: boolean; outline: boolean; fxaa: boolean; };
  setStyle(style: StylePost | null): void;
  setSize(width: number, height: number): void;
  render(): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/post.ts

QualityManager

Holds the tier and the dynamic resolution for one renderer. Listeners (lighting, post, particles) re-read settings on onChange.

class QualityManager {
  constructor(target: QualityTarget, tier: QualityTier, opts?: { devicePixelRatio?: number; dynamic?: boolean; budgetMs?: number; });
  settings: QualitySettings;
  readonly dynamic: DynamicResolution;
  enabled: boolean;
  get tier(): QualityTier;
  get pixelRatio(): number;
  onChange(fn: (s: QualitySettings) => void): void;
  setTier(tier: QualityTier): void;
  frame(now: number): boolean;
}

Source: packages/engine/src/runtime/render/quality.ts

RenderClock

class RenderClock {
  constructor(opts?: FeelClockOptions);
  stops: number;
  slows: number;
  hitStop(ms: number, realNow?: number): void;
  slowMo(scale: number, ms: number, easeMs?: number, realNow?: number): void;
  tick(realNow?: number): ClockTick;
  get stopped(): boolean;
  get lagMs(): number;
}

Source: packages/engine/src/runtime/feel/clock.ts

Rumble

class Rumble {
  constructor(opts?: RumbleOptions);
  enabled: boolean;
  pulses: number;
  pulse(strong: number, weak?: number, ms?: number): boolean;
}

Source: packages/engine/src/runtime/feel/rumble.ts

SoundPlayer

class SoundPlayer {
  constructor(audio: FeelAudio, opts?: SoundPlayerOptions);
  readonly loaded: { cues: number; failed: number; music: boolean; };
  load(bank: SoundBank): void;
  unlockOnGesture(target?: EventTarget): void;
  get muted(): boolean;
  toggle(): boolean;
  get musicEnabled(): boolean;
  get musicPlaying(): boolean;
  get current(): SoundBank | null;
  dispose(): void;
}

Source: packages/engine/src/runtime/feel/sound.ts

Spring

class Spring {
  constructor(value?: number, opts?: SpringOptions);
  value: number;
  velocity: number;
  target: number;
  frequency: number;
  damping: number;
  kick(velocity: number): void;
  snap(value: number): void;
  step(dt: number): number;
  settled(eps?: number): boolean;
}

Source: packages/engine/src/runtime/feel/spring.ts

Spring3

Three springs sharing settings (a position or offset).

class Spring3 {
  constructor(x?: number, y?: number, z?: number, opts?: SpringOptions);
  readonly x: Spring;
  readonly y: Spring;
  readonly z: Spring;
  setTarget(x: number, y: number, z: number): void;
  snap(x: number, y: number, z: number): void;
  step(dt: number): void;
}

Source: packages/engine/src/runtime/feel/spring.ts

SystemScheduler

Runs the declared systems' schedules against a host, one fixed tick at a time. Timers are tick-based (seconds are rounded to whole ticks at declaration), so the schedule is identical on the server and in client prediction. Timers fire in declaration order within a tick.

class SystemScheduler {
  constructor(manifest: GameManifest, host: SystemHost);
  start(): void;
  dispatch(event: string, players: readonly number[]): void;
  tick(): void;
}

Source: packages/engine/src/api/scheduler.ts

Trauma

Trauma screen shake: hits add trauma 0..1, it decays linearly, and the shake is trauma squared, so small hits barely move the camera and big ones kick hard. Offsets come from smooth seeded noise, so the shake is fluid rather than jittery and never uses Math.random.

class Trauma {
  constructor(opts?: TraumaOptions);
  value: number;
  x: number;
  y: number;
  roll: number;
  adds: number;
  get options(): Readonly<Required<TraumaOptions>>;
  add(amount: number): void;
  addTrauma(amount: number): void;
  sustain(seconds: number): void;
  get shake(): number;
  update(dt: number): void;
  reset(): void;
  traumaFor(amplitude: number): number;
}

Source: packages/engine/src/runtime/feel/trauma.ts

Tweens

class Tweens {
  constructor();
  to<T extends object>(target: T, props: TweenProps<T>, opts: TweenOptions): number;
  cancel(handleOrTarget: number | object): void;
  get active(): number;
  tick(dt: number): void;
}

Source: packages/engine/src/runtime/feel/tween.ts

VatCrowd

Thousands of animated characters in one draw: every instance samples the VAT at its own clip, phase and rate, then is rotated, scaled and placed from per-instance attributes. CPU work per instance is one 12-float write.

class VatCrowd {
  constructor(vat: VertexAnimation, material: Material & { positionNode: Node | null; normalNode: Node | null; emissiveNode?: Node | null; flatShading?: boolean; }, capacity: number, opts?: VatCrowdOptions);
  readonly mesh: Mesh<BufferGeometry<NormalBufferAttributes, BufferGeometryEventMap>, Material<MaterialEventMap> | Material<MaterialEventMap>[], Object3DEventMap>;
  readonly time: UniformNode<"float", number>;
  count: number;
  clipNamed(name: string): VatClip | undefined;
  begin(): void;
  push(x: number, y: number, z: number, yaw: number, opts?: { clip?: string; phase?: number; rate?: number; scale?: number; flash?: number; }): void;
  end(timeSeconds: number): void;
  addTo(parent: Object3D): this;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/vat.ts

Constants

DEFAULT_CUES

The built-in cues every template can use by name.

const DEFAULT_CUES: Readonly<Record<string, SynthRecipe & CueOptions>>;

Source: packages/engine/src/runtime/feel/audio.ts

DEFAULT_LOCOMOTION

const DEFAULT_LOCOMOTION: LocomotionThresholds;

Source: packages/engine/src/runtime/render/animation.ts

Ease

const Ease: { readonly linear: (t: number) => number; readonly quadIn: (t: number) => number; readonly quadOut: (t: number) => number; readonly quadInOut: (t: number) => number; readonly cubicOut: (t: number) => number; readonly cubicInOut: (t: number) => number; readonly sineInOut: (t: number) => number; readonly expoOut: (t: number) => number; readonly backOut: (t: number) => number; readonly elasticOut: (t: number) => number; readonly bounceOut: (t: number) => number; };

Source: packages/engine/src/runtime/feel/tween.ts

FEEL_PRESETS

const FEEL_PRESETS: Readonly<Record<FeelPresetName, FeelPreset>>;

Source: packages/engine/src/runtime/feel/kit.ts

LOOK_PRESETS

const LOOK_PRESETS: readonly LookPreset[];

Source: packages/engine/src/runtime/render/presets.ts

PARTICLE_PRESETS

const PARTICLE_PRESETS: Readonly<Record<ParticlePresetName, ParticlePreset>>;

Source: packages/engine/src/runtime/render/particles.ts

PIXEL_PALETTE

The pixel style's palette (DawnBringer 16). The asset library's manifest/pixel.json carries the same list; its test keeps them equal.

const PIXEL_PALETTE: readonly string[];

Source: packages/engine/src/runtime/styles/pixel/index.ts

QUALITY_TIERS

const QUALITY_TIERS: readonly QualityTier[];

Source: packages/engine/src/runtime/render/quality.ts

SPRITE_TEXEL

Metres one source pixel covers at spriteScale 1.

const SPRITE_TEXEL: number;

Source: packages/engine/src/runtime/render/sprite.ts

spriteScale

The pixel style's resize for every billboard sprite (1 elsewhere).

const spriteScale: UniformNode<"float", number>;

Source: packages/engine/src/runtime/render/sprite.ts

STYLE_KITS

One entry per art style. Keep it a plain map.

const STYLE_KITS: Readonly<Record<string, StyleKit>>;

Source: packages/engine/src/runtime/styles/index.ts

SURFACES

Surfaces change a footstep's pitch and weight.

const SURFACES: { readonly grass: { readonly pitch: 0.85; readonly gain: 0.8; }; readonly dirt: { readonly pitch: 0.9; readonly gain: 0.9; }; readonly stone: { readonly pitch: 1.25; readonly gain: 1; }; readonly wood: { readonly pitch: 1.05; readonly gain: 1; }; readonly metal: { readonly pitch: 1.6; readonly gain: 1.1; }; };

Source: packages/engine/src/runtime/feel/audio.ts

uiTweens

The shared UI tween manager. It drives itself on requestAnimationFrame in a browser; call uiTweens.tick(dt) elsewhere.

const uiTweens: Tweens;

Source: packages/engine/src/runtime/feel/tween.ts

Types

AnimatedCharacterOptions

interface AnimatedCharacterOptions {
  readonly clips?: Partial<Record<LocomotionState, string>>;
  readonly thresholds?: Partial<LocomotionThresholds>;
  readonly walkSpeed?: number;
  readonly runSpeed?: number;
  readonly fade?: number;
}

Source: packages/engine/src/runtime/render/animation.ts

AnimationPlayOptions

interface PlayOptions {
  readonly fade?: number;
  readonly loop?: "repeat" | "once";
  readonly timeScale?: number;
}

Source: packages/engine/src/runtime/render/animation.ts

ArenaOptions

interface ArenaOptions {
  readonly sim?: SimConfig;
  readonly forceWebGL?: boolean;
  readonly onStats?: (s: ArenaStats) => void;
  readonly frameBudgetMs?: number;
  readonly autopilot?: boolean;
}

Source: packages/engine/src/runtime/arena.ts

ArenaStats

interface ArenaStats {
  readonly backend: Backend;
  readonly fps: number;
  readonly frameMs: { readonly mean: number; readonly p50: number; readonly p95: number; readonly p99: number };
  readonly cpuMs: { readonly mean: number; readonly p95: number };
  readonly simMsPerTick: number;
  readonly drawCalls: number;
  readonly triangles: number;
  readonly entities: number;
  readonly enemies: number;
  readonly frames: number;
  readonly pixelRatio: number;
  readonly tick: number;
  readonly health: number;
  readonly kills: number;
}

Source: packages/engine/src/runtime/arena.ts

AssetLoaderOptions

interface AssetLoaderOptions {
  readonly resolve: (id: string) => string;
  readonly transcoderPath: string;
}

Source: packages/engine/src/runtime/assets.ts

AtmosphereOptions

interface AtmosphereOptions {
  readonly preset?: LookPreset;
  readonly overrides?: Partial<AtmospherePreset>;
  readonly sky?: boolean;
}

Source: packages/engine/src/runtime/render/atmosphere.ts

AtmospherePreset

interface AtmospherePreset {
  readonly fog: number;
  readonly skyTop: number;
  readonly mode: "linear" | "exp2";
  readonly near: number;
  readonly far: number;
  readonly density: number;
  readonly heightFog: number;
  readonly heightFogTop: number;
}

Source: packages/engine/src/runtime/render/presets.ts

Backend

type Backend = "webgpu" | "webgl2";

Source: packages/engine/src/runtime/renderer.ts

BakeOptions

interface BakeOptions {
  readonly fps?: number;
  readonly frames?: number;
  readonly normals?: boolean;
  readonly maxWidth?: number;
}

Source: packages/engine/src/runtime/render/vat.ts

CameraRigOptions

interface CameraRigOptions {
  readonly distance?: number;
  readonly height?: number;
  readonly minPitch?: number;
  readonly maxPitch?: number;
  readonly follow?: number;
  readonly lead?: number;
  readonly leadMax?: number;
  readonly leadSmoothing?: number;
  readonly deadZone?: number;
  readonly fov?: number;
  readonly shake?: TraumaOptions;
  readonly punchFrequency?: number;
  readonly punchDamping?: number;
  readonly bounds?: GroundBounds | null;
  readonly groundY?: number;
}

Source: packages/engine/src/runtime/camera.ts

ClockTick

interface ClockTick {
  readonly now: number;
  readonly dt: number;
  readonly realDt: number;
  readonly timeScale: number;
}

Source: packages/engine/src/runtime/feel/clock.ts

CrowdAttributes

The per-instance attributes a crowd-motion material reads.

interface CrowdAttributes {
  readonly xform: InstancedBufferAttribute;
  readonly anim: InstancedBufferAttribute;
  readonly extra: InstancedBufferAttribute;
}

Source: packages/engine/src/runtime/render/crowd-motion.ts

CrowdMotionOptions

interface CrowdMotionOptions {
  readonly bob?: number;
  readonly waddle?: number;
  readonly lean?: number;
  readonly squash?: number;
  readonly cadence?: readonly [number, number];
  readonly fullSpeed?: number;
  readonly breathe?: number;
  readonly flash?: number;
  readonly billboard?: boolean;
}

Source: packages/engine/src/runtime/render/crowd-motion.ts

CueOptions

interface CueOptions {
  readonly minGapMs?: number;
  readonly pitchVar?: number;
  readonly gainVar?: number;
  readonly voices?: number;
}

Source: packages/engine/src/runtime/feel/audio.ts

DamageNumbersOptions

interface DamageNumbersOptions extends NumberStackOptions {
  readonly capacity?: number;
  readonly className?: string;
  readonly colors?: Readonly<Record<string, string>>;
  readonly format?: (amount: number) => string;
}

Source: packages/engine/src/runtime/feel/numbers.ts

DecalKind

type DecalKind = "scorch" | "splat" | "ring";

Source: packages/engine/src/runtime/render/decals.ts

DecalLook

type DecalLook = (n: DecalLookInput) => LookOutput;

Source: packages/engine/src/runtime/styles/kit.ts

DecalLookInput

What a ground decal's look can read (GroundDecals).

interface DecalLookInput {
  readonly uv: Node<"vec2">;
  readonly r: Node<"float">;
  readonly angle: Node<"float">;
  readonly kind: Node<"float">;
  readonly t: Node<"float">;
  readonly color: Node<"vec3">;
  readonly shape: Node<"float">;
  readonly opacity: Node<"float">;
}

Source: packages/engine/src/runtime/styles/kit.ts

DecalOptions

interface DecalOptions {
  size?: number;
  color?: number;
  life?: number;
  opacity?: number;
  rotation?: number;
  glow?: number;
}

Source: packages/engine/src/runtime/render/decals.ts

DeviceHints

What the browser tells us about the device. Every field optional: missing reads as "unknown".

interface DeviceHints {
  readonly userAgent?: string;
  readonly coarsePointer?: boolean;
  readonly hardwareConcurrency?: number;
  readonly deviceMemory?: number;
  readonly devicePixelRatio?: number;
  readonly backend?: "webgpu" | "webgl2";
  readonly screenWidth?: number;
}

Source: packages/engine/src/runtime/render/quality.ts

DynamicResolutionOptions

interface DynamicResolutionOptions {
  readonly budgetMs?: number;
  readonly overFactor?: number;
  readonly underFactor?: number;
  readonly step?: number;
  readonly min?: number;
  readonly max?: number;
  readonly hysteresisMs?: number;
  readonly minSamples?: number;
  readonly window?: number;
}

Source: packages/engine/src/runtime/render/quality.ts

EaseFn

Juicy UI tweens: a tiny tween manager with an easing table, and DOM helpers (pop, shake, count up) built on it. The helpers use the CSS scale and translate properties, so they never fight a transform the page already sets.

type EaseFn = (t: number) => number;

Source: packages/engine/src/runtime/feel/tween.ts

EaseName

type EaseName = keyof typeof Ease;

Source: packages/engine/src/runtime/feel/tween.ts

FeelAudioOptions

interface FeelAudioOptions {
  readonly master?: number;
  readonly voices?: number;
  readonly refDistance?: number;
  readonly maxDistance?: number;
  readonly context?: () => AudioContext;
  readonly now?: () => number;
  readonly seed?: number;
}

Source: packages/engine/src/runtime/feel/audio.ts

FeelClockOptions

The render clock: hit-stop and slow motion for the DRAWN world only. The netcode never pauses; the clock returns a render time now that runs behind real time while frozen or slowed, then catches up smoothly so the world never jumps. now never runs ahead of real time.

interface FeelClockOptions {
  readonly catchUpMs?: number;
  readonly maxLagMs?: number;
  readonly maxFrameMs?: number;
}

Source: packages/engine/src/runtime/feel/clock.ts

FeelElement

A minimal element: anything with a style and text (real elements, or fakes in tests).

interface FeelElement {
  readonly style: { scale: string; translate: string };
  textContent: string | null;
}

Source: packages/engine/src/runtime/feel/tween.ts

FeelKitOptions

interface FeelKitOptions {
  readonly preset?: FeelPresetName | (Partial<FeelPreset> & { readonly base?: FeelPresetName });
  readonly camera?: TraumaTarget;
  readonly particles?: ParticleSink | null;
  readonly project?: Projector;
  readonly screenWidth?: () => number;
  readonly numbers?: DamageNumbers | HTMLElement | null;
  readonly audio?: FeelAudio | null;
  readonly rumble?: Rumble | null;
  readonly clock?: FeelClock;
}

Source: packages/engine/src/runtime/feel/kit.ts

FeelPreset

Tunables for every one-liner. Pick a named preset or override fields.

interface FeelPreset {
  readonly hitTrauma: number;
  readonly hitTraumaPerFrame: number;
  readonly killTrauma: number;
  readonly bigKillTrauma: number;
  readonly hurtTrauma: number;
  readonly bigKillStopMs: number;
  readonly hurtStopMs: number;
  readonly levelUpStopMs: number;
  readonly knockback: number;
  readonly bigKnockback: number;
  readonly flashSeconds: number;
  readonly bigKillPunch: number;
  readonly hurtPunch: number;
  readonly levelUpPunch: number;
  readonly dashPunch: number;
  readonly landTrauma: number;
  readonly hurtRumble: readonly [number, number, number];
  readonly bigKillRumble: readonly [number, number, number];
  readonly landRumble: readonly [number, number, number];
  readonly killParticles: number;
  readonly bigKillParticles: number;
  readonly numbersPerFrame: number;
}

Source: packages/engine/src/runtime/feel/kit.ts

FeelPresetName

type FeelPresetName = "subtle" | "default" | "heavy";

Source: packages/engine/src/runtime/feel/kit.ts

FieldSpec

The play field: a square of half size half m with a wall wallHeight tall, and outside m of dressed ground past it.

interface FieldSpec {
  readonly half: number;
  readonly wallHeight: number;
  readonly outside: number;
  readonly theme: WorldTheme;
  readonly wall?: boolean;
  readonly pillars?: readonly PillarSpec[];
}

Source: packages/engine/src/runtime/styles/kit.ts

FootstepOptions

interface FootstepOptions {
  readonly stride?: number;
  readonly maxRate?: number;
  readonly minSpeed?: number;
}

Source: packages/engine/src/runtime/feel/audio.ts

GamepadLike

interface GamepadLike {
  readonly connected?: boolean;
  readonly vibrationActuator?: RumbleActuator | null;
}

Source: packages/engine/src/runtime/feel/rumble.ts

GpuBurstOptions

The feel kit's burst options plus the renderer's extras (all optional).

interface ParticleBurstOptions extends FeelBurstOptions {
  readonly dirY?: number;
  readonly speed?: number;
  readonly spread?: number;
  readonly size?: number;
}

Source: packages/engine/src/runtime/render/particles.ts

GpuParticlesOptions

interface GpuParticlesOptions {
  readonly capacity?: number;
  readonly random?: () => number;
  readonly look?: ParticleShade;
}

Source: packages/engine/src/runtime/render/particles.ts

GradePreset

interface GradePreset {
  readonly exposure: number;
  readonly contrast: number;
  readonly saturation: number;
  readonly shadowTint: readonly [number, number, number];
  readonly highlightTint: readonly [number, number, number];
  readonly vignette: number;
  readonly bloomStrength: number;
  readonly bloomRadius: number;
  readonly bloomThreshold: number;
  readonly toneMapping: "aces" | "agx" | "neutral";
}

Source: packages/engine/src/runtime/render/presets.ts

GroundBounds

A rectangle on the ground plane.

interface GroundBounds {
  readonly minX: number;
  readonly maxX: number;
  readonly minZ: number;
  readonly maxZ: number;
}

Source: packages/engine/src/runtime/camera.ts

HeroHighlightOptions

interface HeroHighlightOptions {
  readonly rim?: ColorRepresentation | null;
  readonly rimStrength?: number;
  readonly rimPower?: number;
  readonly outline?: ColorRepresentation | null;
  readonly outlineWidth?: number;
}

Source: packages/engine/src/runtime/render/highlight.ts

HitEvent

interface HitEvent {
  readonly x: number;
  readonly y: number;
  readonly z: number;
  readonly amount: number;
  readonly id?: number;
  readonly big?: boolean;
  readonly dirX?: number;
  readonly dirZ?: number;
  readonly kind?: string;
}

Source: packages/engine/src/runtime/feel/kit.ts

InputOptions

interface InputOptions {
  readonly mouseSensitivity?: number;
  readonly touchSensitivity?: number;
  readonly touch?: boolean;
}

Source: packages/engine/src/runtime/input.ts

KillEvent

interface KillEvent {
  readonly x: number;
  readonly y: number;
  readonly z: number;
  readonly big?: boolean;
  readonly id?: number;
  readonly color?: number;
  readonly particles?: string;
  readonly dirX?: number;
  readonly dirZ?: number;
}

Source: packages/engine/src/runtime/feel/kit.ts

KnockbackOptions

Client-side visual knockback and squash per entity. The authoritative sim moves the entity; this adds a springy offset and a squash-stretch on top of the interpolated position, so a hit reads instantly even ~100 ms in the past. Read get(id) each frame and add it when drawing.

interface KnockbackOptions {
  readonly frequency?: number;
  readonly damping?: number;
  readonly maxOffset?: number;
  readonly squash?: number;
}

Source: packages/engine/src/runtime/feel/knockback.ts

KnockbackSample

interface KnockbackSample {
  x: number;
  z: number;
  sx: number;
  sy: number;
  sz: number;
}

Source: packages/engine/src/runtime/feel/knockback.ts

LightingOptions

interface LightingOptions {
  readonly preset?: LookPreset;
  readonly overrides?: Partial<LightingPreset>;
  readonly shadowMapSize?: number;
  readonly shadowExtent?: number;
}

Source: packages/engine/src/runtime/render/lighting.ts

LightingPreset

interface LightingPreset {
  readonly sky: number;
  readonly ground: number;
  readonly hemi: number;
  readonly sun: number;
  readonly sunIntensity: number;
  readonly sunDir: readonly [number, number, number];
  readonly ambient: number;
  readonly ambientColor: number;
  readonly shadowStrength: number;
}

Source: packages/engine/src/runtime/render/presets.ts

LocomotionState

type LocomotionState = "idle" | "walk" | "run";

Source: packages/engine/src/runtime/render/animation.ts

LocomotionThresholds

interface LocomotionThresholds {
  readonly walk: number;
  readonly run: number;
  readonly band: number;
}

Source: packages/engine/src/runtime/render/animation.ts

Look

interface Look {
  readonly lighting: LightingPreset;
  readonly atmosphere: AtmospherePreset;
  readonly grade: GradePreset;
}

Source: packages/engine/src/runtime/render/presets.ts

LookOutput

A decal or ring look's answer: colour and opacity nodes, and the blend to draw with.

interface LookOutput {
  readonly color: Node<"vec3">;
  readonly opacity: Node<"float">;
  readonly blending?: "add" | "normal";
}

Source: packages/engine/src/runtime/styles/kit.ts

LookPreset

Look presets: one name picks the lighting, the atmosphere and the color grade together, so a template (or a generated game) says preset: "dusk" and gets a coherent picture. Plain data, node-testable.

type LookPreset = "night" | "dusk" | "day" | "studio";

Source: packages/engine/src/runtime/render/presets.ts

LookTarget

interface LookTarget {
  look(dYaw: number, dPitch: number): void;
  readonly yaw: number;
}

Source: packages/engine/src/runtime/input.ts

MusicElement

The slice of HTMLAudioElement the music uses.

interface MusicElement {
  src: string;
  loop: boolean;
  volume: number;
  muted: boolean;
  preload: string;
  readonly paused: boolean;
  play(): Promise<void> | void;
  pause(): void;
}

Source: packages/engine/src/runtime/feel/sound.ts

interface NavigatorLike {
  getGamepads?(): readonly (GamepadLike | null)[];
  vibrate?(pattern: number | number[]): boolean;
}

Source: packages/engine/src/runtime/feel/rumble.ts

NumberDraw

interface NumberDraw {
  readonly x: number;
  readonly y: number;
  readonly scale: number;
  readonly opacity: number;
}

Source: packages/engine/src/runtime/feel/numbers.ts

NumberInput

Floating damage numbers. NumberStack is the DOM-free core (slots, merging, motion); DamageNumbers draws it with a fixed pool of DOM nodes moved by transforms only (no layout per frame).

interface NumberInput {
  readonly x: number;
  readonly y: number;
  readonly amount: number;
  readonly id?: number;
  readonly big?: boolean;
  readonly kind?: string;
}

Source: packages/engine/src/runtime/feel/numbers.ts

NumberSlot

interface NumberSlot {
  active: boolean;
  id: number;
  amount: number;
  t: number;
  x: number;
  y: number;
  drift: number;
  big: boolean;
  kind: string;
  at: number;
  gen: number;
}

Source: packages/engine/src/runtime/feel/numbers.ts

NumberStackOptions

interface NumberStackOptions {
  readonly mergeMs?: number;
  readonly lifeSeconds?: number;
  readonly rise?: number;
}

Source: packages/engine/src/runtime/feel/numbers.ts

ParticleBurstOptions

interface ParticleBurstOptions {
  readonly count?: number;
  readonly color?: number;
  readonly scale?: number;
  readonly dirX?: number;
  readonly dirZ?: number;
}

Source: packages/engine/src/runtime/feel/types.ts

ParticlePreset

interface ParticlePreset {
  readonly blend: "add" | "alpha";
  readonly count: number;
  readonly speed: readonly [number, number];
  readonly spread: number;
  readonly dir: readonly [number, number, number];
  readonly life: readonly [number, number];
  readonly size: readonly [number, number];
  readonly gravity: number;
  readonly drag: number;
  readonly color: number;
  readonly stretch: number;
  readonly jitter: number;
}

Source: packages/engine/src/runtime/render/particles.ts

ParticlePresetName

type ParticlePresetName = "sparks" | "burst" | "embers" | "smoke" | "hitSpark" | "dust" | "magic" | "kill" | "bigKill";

Source: packages/engine/src/runtime/render/particles.ts

ParticleShade

A particle look: every particle's shape and colour, plus an optional size curve over its life (a pop, a shrink). The default is soft round glows; an art style brings its own (the toon style draws stars, streaks and puffs).

interface ParticleShade {
  shade(p: ParticleShadeInput): ParticleShadeOutput;
  size?(t: Node<"float">, seed: Node<"float">, blend: "add" | "alpha"): Node<"float">;
}

Source: packages/engine/src/runtime/render/particles.ts

ParticleShadeInput

What a particle look (an art style's) reads, per fragment.

interface ParticleShadeInput {
  readonly t: Node<"float">;
  readonly uv: Node<"vec2">;
  readonly color: Node<"vec3">;
  readonly seed: Node<"float">;
  readonly blend: "add" | "alpha";
}

Source: packages/engine/src/runtime/render/particles.ts

ParticleShadeOutput

interface ParticleShadeOutput {
  readonly color: Node<"vec3">;
  readonly opacity: Node<"float">;
  readonly blend?: "add" | "alpha";
}

Source: packages/engine/src/runtime/render/particles.ts

ParticleSink

Something that can play a pooled particle effect (the GPU particle system implements it).

interface ParticleSink {
  burst(preset: string, x: number, y: number, z: number, opts?: ParticleBurstOptions): void;
}

Source: packages/engine/src/runtime/feel/types.ts

PillarSpec

One pillar or post (sim metres).

interface PillarSpec {
  readonly x: number;
  readonly z: number;
  readonly radius: number;
  readonly height: number;
}

Source: packages/engine/src/runtime/styles/kit.ts

PixelStyleOptions

interface PixelStyleOptions {
  readonly texelsPerMetre?: number;
  readonly dither?: number;
  readonly saturation?: number;
  readonly bands?: readonly number[];
  readonly minRows?: number;
}

Source: packages/engine/src/runtime/styles/pixel/index.ts

PlayOptions

interface PlayOptions {
  readonly pitch?: number;
  readonly gain?: number;
  readonly pan?: number;
  readonly screenX?: number;
  readonly width?: number;
  readonly distance?: number;
}

Source: packages/engine/src/runtime/feel/audio.ts

PostFXOptions

interface PostFXOptions {
  readonly preset?: LookPreset;
  readonly overrides?: Partial<GradePreset>;
  readonly bloom?: boolean;
  readonly outline?: boolean;
  readonly fxaa?: boolean;
  readonly enabled?: boolean;
  readonly bloomScale?: number;
  readonly style?: StylePost;
}

Source: packages/engine/src/runtime/render/post.ts

Projector

World position to CSS pixels on the canvas.

type Projector = (x: number, y: number, z: number) => { x: number; y: number; onScreen: boolean };

Source: packages/engine/src/runtime/feel/types.ts

QualitySettings

What a tier turns on.

interface QualitySettings {
  readonly tier: QualityTier;
  readonly shadowMapSize: number;
  readonly post: boolean;
  readonly bloomScale: number;
  readonly outline: boolean;
  readonly maxPixelRatio: number;
  readonly minPixelRatio: number;
  readonly particles: number;
}

Source: packages/engine/src/runtime/render/quality.ts

QualityTier

Quality tiers and dynamic resolution ("auto-detected low, medium or high (shadows, post-processing, resolution scale) with dynamic resolution to hold the frame rate"). The decision logic is pure so it is tested in node; QualityManager applies it to a renderer.

type QualityTier = "low" | "medium" | "high";

Source: packages/engine/src/runtime/render/quality.ts

RendererHandle

interface RendererHandle {
  readonly renderer: WebGPURenderer;
  readonly backend: Backend;
}

Source: packages/engine/src/runtime/renderer.ts

RendererOptions

interface RendererOptions {
  readonly forceWebGL?: boolean;
  readonly antialias?: boolean;
  readonly maxPixelRatio?: number;
}

Source: packages/engine/src/runtime/renderer.ts

RenderStack

interface RenderStack {
  readonly lighting: LightingRig;
  readonly atmosphere: Atmosphere;
  readonly post: PostFX;
  readonly particles: GpuParticles;
  readonly decals: GroundDecals;
  readonly rings: GroundRings;
  readonly quality: QualityManager;
  readonly style: string | null;
  readonly kit: StyleKit | null;
  readonly session: StyleSession | null;
  readonly time: number;
  frame(dt: number, focus: { x: number; y: number; z: number }, realNowMs?: number): boolean;
  resize(width: number, height: number): void;
  setPreset(preset: LookPreset): void;
  setQuality(tier: QualityTier): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/render/stack.ts

RenderStackOptions

interface RenderStackOptions {
  readonly preset?: LookPreset;
  readonly style?: string;
  readonly quality?: QualityTier | "auto";
  readonly bloom?: boolean;
  readonly outline?: boolean;
  readonly dynamicResolution?: boolean;
  readonly shadowExtent?: number;
  readonly lighting?: Partial<LightingPreset>;
  readonly atmosphere?: Partial<AtmospherePreset>;
  readonly grade?: Partial<GradePreset>;
  readonly particles?: number;
  readonly makeParticles?: (scene: Scene, capacity: number) => GpuParticles;
  readonly decals?: number;
  readonly resolve?: (id: string) => string | null;
}

Source: packages/engine/src/runtime/render/stack.ts

RingLook

type RingLook = (n: RingLookInput) => LookOutput;

Source: packages/engine/src/runtime/styles/kit.ts

RingLookInput

What a shockwave ring's look can read (GroundRings).

interface RingLookInput {
  readonly uv: Node<"vec2">;
  readonly r: Node<"float">;
  readonly t: Node<"float">;
  readonly alive: Node<"float">;
  readonly color: Node<"vec3">;
}

Source: packages/engine/src/runtime/styles/kit.ts

RingOptions

interface RingOptions {
  color?: number;
  duration?: number;
  glow?: number;
}

Source: packages/engine/src/runtime/render/decals.ts

RumbleActuator

Controller rumble (Gamepad API dual-rumble) with a phone vibration fallback, rate-limited so a swarm of hits is one buzz, not fifty.

interface RumbleActuator {
  playEffect?(type: string, params: { duration: number; strongMagnitude: number; weakMagnitude: number; startDelay?: number }): Promise<unknown>;
}

Source: packages/engine/src/runtime/feel/rumble.ts

RumbleOptions

interface RumbleOptions {
  readonly minGapMs?: number;
  readonly vibrateFallback?: boolean;
  readonly navigator?: NavigatorLike;
  readonly now?: () => number;
}

Source: packages/engine/src/runtime/feel/rumble.ts

SegmentRig

interface SegmentRig {
  readonly mesh: SkinnedMesh;
  readonly bones: readonly [Bone, Bone, Bone];
  readonly clips: readonly AnimationClip[];
}

Source: packages/engine/src/runtime/render/rig.ts

SegmentRigOptions

interface SegmentRigOptions {
  readonly height?: number;
  readonly radius?: number;
  readonly topRadius?: number;
  readonly radialSegments?: number;
  readonly heightSegments?: number;
  readonly geometry?: BufferGeometry;
}

Source: packages/engine/src/runtime/render/rig.ts

SoundBank

Cue name -> sample, and an optional music loop (the asset library's soundBank() builds one).

interface SoundBank {
  readonly cues: Readonly<Record<string, SoundBankEntry>>;
  readonly music?: SoundBankEntry | null;
}

Source: packages/engine/src/runtime/feel/sound.ts

SoundBankEntry

interface SoundBankEntry {
  readonly url: string;
  readonly gain?: number;
}

Source: packages/engine/src/runtime/feel/sound.ts

SoundPlayerOptions

interface SoundPlayerOptions {
  readonly musicVolume?: number;
  readonly sfxVolume?: number;
  readonly music?: boolean;
  readonly key?: string | null;
  readonly fadeIn?: number;
  readonly createMusic?: () => MusicElement | null;
  readonly fetchBytes?: (url: string) => Promise<ArrayBuffer>;
  readonly pauseWhenHidden?: boolean;
}

Source: packages/engine/src/runtime/feel/sound.ts

SpringOptions

Damped springs for game feel: camera follow, FOV punch, knockback offsets, UI pops. frequency is the natural frequency in Hz and damping the damping ratio (1 = critically damped, no overshoot; below 1 it wobbles). Integrated with fixed sub-steps, so any frame rate is stable.

interface SpringOptions {
  readonly frequency?: number;
  readonly damping?: number;
}

Source: packages/engine/src/runtime/feel/spring.ts

StyleContext

What a style's session is attached to (one renderer, one scene).

interface StyleContext {
  readonly handle: RendererHandle;
  readonly renderer: WebGPURenderer;
  readonly scene: Scene;
  readonly camera: Camera;
  readonly tier: QualityTier;
  readonly preset: LookPreset;
  readonly post?: PostFX;
  readonly atmosphere?: Atmosphere;
  readonly resolve?: (id: string) => string | null;
}

Source: packages/engine/src/runtime/styles/kit.ts

StyledPillar

A pillar as drawn: its body (own material, so the template can fade it), the pieces on top, and where its flame burns (null: none).

interface StyledPillar {
  readonly body: Object3D;
  readonly fade: readonly Material[];
  readonly top: readonly Object3D[];
  readonly flame: readonly [number, number, number] | null;
}

Source: packages/engine/src/runtime/styles/kit.ts

StyledView

interface StyledView {
  readonly session: StyleSession;
  readonly post: PostFX;
  render(nowMs?: number): void;
  setSize(width: number, height: number): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/styles/view.ts

StyledViewOptions

interface StyledViewOptions {
  readonly preset?: LookPreset;
  readonly bloom?: boolean;
  readonly tier?: QualityTier;
}

Source: packages/engine/src/runtime/styles/view.ts

StyleKit

interface StyleKit {
  readonly id: string;
  stack?(preset: LookPreset): StyleStack;
  look?(preset: LookPreset): Look;
  readonly needsPost?: boolean;
  readonly bloom?: boolean;
  readonly outline?: boolean;
  attach?(ctx: StyleContext): StyleSession;
  field?(spec: FieldSpec): Object3D[];
  groundHeight?(spec: FieldSpec, x: number, z: number): number;
  pillar?(spec: PillarSpec, theme: WorldTheme, index: number): StyledPillar;
  shape?(name: StyleShapeName): StyleShape | null;
}

Source: packages/engine/src/runtime/styles/kit.ts

StylePost

Post-graph hooks, in graph order: called whenever the post stack rebuilds its node graph.

interface StylePost {
  scenePass?(pass: PassNode): void;
  scene?(input: StylePostInput): Node<"vec4">;
  color?(rgb: Node<"vec3">, pass: PassNode): Node<"vec3">;
  display?(color: Node<"vec4">, input: StylePostInput): Node<"vec4">;
}

Source: packages/engine/src/runtime/styles/kit.ts

StylePostInput

What the post stages can read: the scene pass, sampleable at any uv.

interface StylePostInput {
  readonly color: Node<"vec4"> & { sample(uv: Node<"vec2">): Node<"vec4"> };
  readonly depth: Node<"vec4"> & { sample(uv: Node<"vec2">): Node<"vec4"> };
  readonly texel: UniformNode<"vec2", Vector2>;
  readonly near: UniformNode<"float", number>;
  readonly far: UniformNode<"float", number>;
}

Source: packages/engine/src/runtime/styles/kit.ts

StyleSession

One style attached to one renderer and scene (StyleKit.attach).

interface StyleSession {
  render?(draw: () => void): void;
  readonly post?: StylePost;
  readonly particles?: ParticleShade;
  readonly decals?: DecalLook;
  readonly rings?: RingLook;
  frame?(seconds: number): void;
  setPreset?(preset: LookPreset): void;
  surface?(kind: SurfaceKind, opts?: SurfaceOptions): Texture | null;
  setSize?(width: number, height: number): void;
  setQuality?(tier: QualityTier): void;
  dispose(): void;
}

Source: packages/engine/src/runtime/styles/kit.ts

StyleShape

A shape a template draws instanced (bolts, blades, chunks, props).

interface StyleShape {
  readonly geometry: BufferGeometry;
  readonly material: Material;
}

Source: packages/engine/src/runtime/styles/kit.ts

StyleShapeName

Template machinery shapes a style may redraw.

type StyleShapeName = "bolt" | "lance" | "blade" | "pellet" | "shard" | "chunk" | "rock" | "stump" | "barrel" | "crate" | "lantern" | "flame";

Source: packages/engine/src/runtime/styles/kit.ts

StyleStack

Overrides for the render stack under one look preset, plus the style's opinion on sun shadows.

interface StyleStack extends Partial<Pick<RenderStackOptions, "lighting" | "atmosphere" | "grade" | "makeParticles">> {
  readonly shadows?: boolean;
}

Source: packages/engine/src/runtime/styles/kit.ts

Surface

type Surface = keyof typeof SURFACES;

Source: packages/engine/src/runtime/feel/audio.ts

SurfaceKind

Surfaces templates build themselves and may ask the style for: ground (a natural field), floor (paving), wall, stone, and glow (a pool of light on the ground, white with alpha, which the template tints).

type SurfaceKind = "ground" | "floor" | "wall" | "stone" | "glow";

Source: packages/engine/src/runtime/styles/kit.ts

SurfaceOptions

interface SurfaceOptions {
  readonly tile?: number;
  readonly mood?: string;
}

Source: packages/engine/src/runtime/styles/kit.ts

SynthRecipe

interface SynthRecipe {
  readonly wave: OscillatorType | "noise";
  readonly f0: number;
  readonly f1: number;
  readonly ms: number;
  readonly gain: number;
}

Source: packages/engine/src/runtime/feel/audio.ts

SystemHost

What the scheduler needs from the simulation it drives.

interface SystemHost {
  readonly tickRate: number;
  tick(): number;
  players(): readonly PlayerView[];
  spawn(prefab: string, at: readonly [number, number, number], opts?: { readonly elite?: boolean }): void;
  random(): number;
  emit(event: string, players?: readonly number[]): void;
  alive?(prefab?: string): number;
  respawnDead?(): void;
  end?(outcome: "won" | "lost"): void;
  ringPoint?(cx: number, cz: number, radius: number, prefab: string): readonly [number, number] | null;
  spawnEdge?(prefab: string, opts: SpawnEdgeOptions): number;
  spawnPickup?(prefab: string, at: readonly [number, number, number]): void;
  announce?(text: string, tone: "info" | "danger" | "reward"): void;
  upcoming?(label: string, seconds: number): void;
  bossAlive?(): boolean;
  pauseDirector?(seconds: number): void;
  surge?(multiplier: number, seconds: number): void;
  xpBoost?(multiplier: number, seconds: number): void;
  scatter?(prefab: string, count: number): number;
  clear?(prefab: string): number;
  onScreen?(x: number, z: number): boolean;
}

Source: packages/engine/src/api/scheduler.ts

TraumaOptions

interface TraumaOptions {
  readonly decay?: number;
  readonly exponent?: number;
  readonly maxOffset?: number;
  readonly maxRoll?: number;
  readonly frequency?: number;
  readonly seed?: number;
}

Source: packages/engine/src/runtime/feel/trauma.ts

TraumaTarget

Anything that takes trauma and an optional FOV punch: a CameraRig, or a bare Trauma.

interface TraumaTarget {
  addTrauma(amount: number): void;
  punch?(fovKickDegrees: number): void;
}

Source: packages/engine/src/runtime/feel/types.ts

TweenOptions

interface TweenOptions {
  readonly duration: number;
  readonly ease?: EaseName | EaseFn;
  readonly delay?: number;
  readonly yoyo?: boolean;
  readonly repeat?: number;
  readonly onUpdate?: () => void;
  readonly onDone?: () => void;
}

Source: packages/engine/src/runtime/feel/tween.ts

TweenProps

type TweenProps<T> = Partial<Record<NumericKeys<T>, number>>;

Source: packages/engine/src/runtime/feel/tween.ts

VatClip

interface VatClip {
  readonly name: string;
  readonly start: number;
  readonly frames: number;
}

Source: packages/engine/src/runtime/render/vat.ts

VatCrowdOptions

interface VatCrowdOptions {
  readonly bakedNormals?: boolean;
}

Source: packages/engine/src/runtime/render/vat.ts

VertexAnimation

A vertex animation texture: every vertex's skinned position (and normal) per frame.

interface VertexAnimation {
  readonly positions: DataTexture;
  readonly normals: DataTexture | null;
  readonly vertexCount: number;
  readonly width: number;
  readonly rowsPerFrame: number;
  readonly totalFrames: number;
  readonly fps: number;
  readonly clips: readonly VatClip[];
  readonly geometry: BufferGeometry;
}

Source: packages/engine/src/runtime/render/vat.ts

WorldTheme

Words a template passes so one kit can dress different places: "meadow" (EMBERWATCH's night field), "yard" (VOLTYARD's lot).

type WorldTheme = string;

Source: packages/engine/src/runtime/styles/kit.ts

Other

voxel

voxel

Source: packages/engine/src/runtime/styles/voxel/index.ts