@netforge/engine-sim API reference
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 shared simulation: ECS, deterministic Rapier physics, the fixed tick and bit-exact snapshots. It runs the same in the browser and on the server and has no rendering dependency.
import { initSim, createPhysics } from "@netforge/engine-sim";Generated from packages/engine-sim/src/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.
| Kind | Count |
|---|---|
| Functions | 117 |
| Classes | 2 |
| Constants | 47 |
| Types | 93 |
Functions
addKart
function addKart(w: KartWorld, id: number, opts?: { bot?: boolean; frozen?: boolean; slot?: number; }): Kart;Source: packages/engine-sim/src/kart.ts
addPlatformPlayer
function addPlatformPlayer(w: PlatformWorld, id: number, opts?: { bot?: boolean; frozen?: boolean; }): PlatformPlayer;Source: packages/engine-sim/src/platform.ts
addPlayer
Spawn a player's character. Throws if the id is already present.
function addPlayer(world: SimWorld, playerId: PlayerId, spawn?: Vec3): NetId;Source: packages/engine-sim/src/world.ts
applyBeamHit
Apply a lag-compensated beam hit (the rewind found target, a NetId). Its events come out of the next step.
function applyBeamHit(world: SimWorld, shot: BeamShot, target: NetId): void;Source: packages/engine-sim/src/control.ts
applyKart
function applyKart(w: KartWorld, s: KartWire): Kart;Source: packages/engine-sim/src/kart.ts
applyPlatformPlayer
Overwrite (or create) a player from wire state, and take the world tick from it.
function applyPlatformPlayer(w: PlatformWorld, s: PlatformPlayerWire): PlatformPlayer;Source: packages/engine-sim/src/platform.ts
applyState
Make the world match state: update entities present in both, spawn
missing ones with their netIds, remove the rest. Lossless for captured
states. Interpolation history is reset (prev = current).
function applyState(world: SimWorld, state: SimState): void;Source: packages/engine-sim/src/snapshot.ts
arenaHitboxes
Living players' and enemies' hitboxes this tick (the room's rewind buffer records them).
function arenaHitboxes(world: SimWorld): ArenaHitbox[];Source: packages/engine-sim/src/control.ts
arenaSpawn
Where a player joining or respawning now would stand: the spawn point farthest from opponents.
function arenaSpawn(world: SimWorld, playerId: PlayerId): [number, number];Source: packages/engine-sim/src/control.ts
beamRange
How far a beam from (x, z) along the unit (dx, dz) reaches before a
pillar or the arena wall stops it, capped at range. Clients draw beams
with it; the server clamps hitscans with it.
function beamRange(config: ResolvedSimConfig, x: number, z: number, dx: number, dz: number, range: number): number;Source: packages/engine-sim/src/arena.ts
beamShot
A human player's beam this tick, for a room's lag compensation. Call before step with the command it will consume.
function beamShot(world: SimWorld, playerId: PlayerId, cmd: InputCommand): BeamShot | null;Source: packages/engine-sim/src/control.ts
buildKartTrack
Sample a closed Catmull-Rom centreline every ~2 m. Pure arithmetic, identical on every side.
function buildKartTrack(def: KartTrackDef): KartTrack;Source: packages/engine-sim/src/kart.ts
captureKart
function captureKart(w: KartWorld, k: Kart): KartWire;Source: packages/engine-sim/src/kart.ts
capturePlatformPlayer
function capturePlatformPlayer(w: PlatformWorld, p: PlatformPlayer): PlatformPlayerWire;Source: packages/engine-sim/src/platform.ts
captureState
Read the world's networked state. include filters entities (interest management).
function captureState(world: SimWorld, include?: (e: EntityState) => boolean): SimState;Source: packages/engine-sim/src/snapshot.ts
collisionGroups
Rapier interaction groups: membership in the high 16 bits, filter in the low 16.
function collisionGroups(layer: number, mask: number): number;Source: packages/engine-sim/src/physics/layers.ts
createKartWorld
function createKartWorld(cfg: KartConfig): KartWorld;Source: packages/engine-sim/src/kart.ts
createPhysics
Build a physics world. Requires await initSim() first (it loads the Rapier WebAssembly).
function createPhysics(opts?: PhysicsOptions): PhysicsWorld;Source: packages/engine-sim/src/physics/world.ts
createPlatformWorld
function createPlatformWorld(cfg: PlatformConfig): PlatformWorld;Source: packages/engine-sim/src/platform.ts
createWorld
Create a world: static arena colliders, empty of entities, tick 0. Requires initSim().
function createWorld(config?: SimConfig): SimWorld;Source: packages/engine-sim/src/world.ts
critRoll
The crit roll for hits on enemy netId at tick, in [0, 1): a fixed hash, so clients can mark crit numbers.
function critRoll(tick: number, netId: number): number;Source: packages/engine-sim/src/content.ts
decodeChoices
The three offered upgrade indices (-1 for none) and the pending level-ups.
function decodeChoices(choices: number): { offers: [number, number, number]; pending: number; };Source: packages/engine-sim/src/content.ts
decodeInput
function decodeInput(bytes: Uint8Array, offset?: number): InputCommand;Source: packages/engine-sim/src/input.ts
decodeInputs
function decodeInputs(bytes: Uint8Array): InputCommand[];Source: packages/engine-sim/src/input.ts
decodeSnapshot
function decodeSnapshot(bytes: Uint8Array, baseline?: SimState): SimState;Source: packages/engine-sim/src/snapshot.ts
decodeTelegraph
Decode a telegraph word (clients and bots).
function decodeTelegraph(word: number): { kind: number; progress: number; angle: number; radius: number; };Source: packages/engine-sim/src/roles.ts
destroyWorld
Free the world's physics memory. The world is unusable afterwards.
function destroyWorld(world: SimWorld): void;Source: packages/engine-sim/src/world.ts
edgeSpawnPoint
A point just off the screen of playerId (or of a random living player),
inside the arena, clear of pillars and off every other player's screen.
Null when there is none: skip the spawn, never clamp it on screen.
function edgeSpawnPoint(world: SimWorld, playerId: PlayerId | undefined, opts?: EdgeSpawnOptions): [number, number] | null;Source: packages/engine-sim/src/control.ts
encodeInput
15 bytes, little endian: seq u32, tick u32, moveX i8, moveZ i8, yaw u16, buttons u16, reserved u8 (0).
function encodeInput(cmd: InputCommand, out?: Uint8Array, offset?: number): Uint8Array;Source: packages/engine-sim/src/input.ts
encodeInputs
Count byte (u8, max 255) followed by that many 15-byte commands.
function encodeInputs(cmds: readonly InputCommand[]): Uint8Array;Source: packages/engine-sim/src/input.ts
encodeSnapshot
Binary snapshot. With baseline, a delta against it (the receiver must hold the same baseline).
function encodeSnapshot(state: SimState, baseline?: SimState): Uint8Array;Source: packages/engine-sim/src/snapshot.ts
enemyCount
Living (non-corpse) enemies, of one type or all.
function enemyCount(world: SimWorld, type?: number): number;Source: packages/engine-sim/src/control.ts
enemyMaxHealth
An enemy's max health as spawned (scaled), by NetId; undefined when gone or not an enemy.
function enemyMaxHealth(world: SimWorld, netId: NetId): number | undefined;Source: packages/engine-sim/src/control.ts
enemyTypeOf
An enemy's type index by NetId, or -1 when it is gone or not an enemy.
function enemyTypeOf(world: SimWorld, netId: NetId): number;Source: packages/engine-sim/src/control.ts
entityHeadroom
Room left under maxEntities (spawners should stop before 0).
function entityHeadroom(world: SimWorld): number;Source: packages/engine-sim/src/control.ts
entityHealth
An entity's health by NetId, or undefined when it is gone.
function entityHealth(world: SimWorld, netId: NetId): number | undefined;Source: packages/engine-sim/src/control.ts
entityPosition
An entity's ground position by NetId, or undefined when it is gone.
function entityPosition(world: SimWorld, netId: NetId): [number, number] | undefined;Source: packages/engine-sim/src/control.ts
grantKartStat
function grantKartStat(w: KartWorld, id: number, stat: KartStat): boolean;Source: packages/engine-sim/src/kart.ts
grantLevels
Raise a player by levels levels now (a late joiner catching up): each
level arrives as if from gems, with its card pending. Returns the levels granted.
function grantLevels(world: SimWorld, playerId: PlayerId, levels: number): number;Source: packages/engine-sim/src/control.ts
grantPlatformStat
Add one level of a stat (store upgrades and gear). Returns false at the 4-bit cap.
function grantPlatformStat(w: PlatformWorld, id: number, stat: PlatStat): boolean;Source: packages/engine-sim/src/platform.ts
grantUpgrade
Give a player one level of passive index (content.stats) for the rest of the run: a store upgrade.
function grantUpgrade(world: SimWorld, playerId: PlayerId, index: number): boolean;Source: packages/engine-sim/src/control.ts
grantXp
Give a player XP now (levels and cards follow as from gems). Returns false when the player is absent.
function grantXp(world: SimWorld, playerId: PlayerId, amount: number): boolean;Source: packages/engine-sim/src/control.ts
initSim
Load the Rapier WebAssembly. Call once per process before createWorld. Idempotent.
function initSim(): Promise<void>;Source: packages/engine-sim/src/world.ts
inWall
True when a circle at (x, z) of radius r overlaps any wall.
function inWall(walls: readonly WallBox[], x: number, z: number, r: number): boolean;Source: packages/engine-sim/src/walls.ts
isOnScreen
True when (x, z) is on the screen of any player who is up.
function isOnScreen(world: SimWorld, x: number, z: number): boolean;Source: packages/engine-sim/src/control.ts
kartCoinCount
function kartCoinCount(k: { coinsLo: number; coinsHi: number; }): number;Source: packages/engine-sim/src/kart.ts
kartCoinTaken
function kartCoinTaken(k: { coinsLo: number; coinsHi: number; }, i: number): boolean;Source: packages/engine-sim/src/kart.ts
kartProgress
Race progress in laps (lap + this lap's fraction), for standings.
function kartProgress(w: KartWorld, k: Kart): number;Source: packages/engine-sim/src/kart.ts
kartStatLevel
function kartStatLevel(k: { stats: number; }, stat: KartStat): number;Source: packages/engine-sim/src/kart.ts
kartStep
One fixed tick.
function kartStep(w: KartWorld, inputs: ReadonlyMap<number, InputCommand>): KartEvent[];Source: packages/engine-sim/src/kart.ts
keeperButtons
Input bits that choose keeper index (0..14).
function keeperButtons(index: number): number;Source: packages/engine-sim/src/api.ts
lastProcessedSeq
The last input seq the sim consumed for this player (the reconciliation ack). 0 if none or absent.
function lastProcessedSeq(world: SimWorld, playerId: PlayerId): number;Source: packages/engine-sim/src/world.ts
lateralOffset
Signed sideways offset from the centreline at sample seg (positive to the right of travel).
function lateralOffset(t: KartTrack, seg: number, x: number, z: number): number;Source: packages/engine-sim/src/kart.ts
layerMask
A mask from layer names or bits: layerMask("Level", "Enemy").
function layerMask(...layers: readonly (LayerName | number)[]): number;Source: packages/engine-sim/src/physics/layers.ts
layersCollide
True when two bodies with these layers and masks collide (Rapier's pairwise rule).
function layersCollide(layerA: number, maskA: number, layerB: number, maskB: number): boolean;Source: packages/engine-sim/src/physics/layers.ts
listPickups
Pickups on the floor: position (m) and value (XP, or heal in the arena).
function listPickups(world: SimWorld): { x: number; z: number; value: number; }[];Source: packages/engine-sim/src/control.ts
listPlayers
Every player, in playerId order.
function listPlayers(world: SimWorld): PlayerSummary[];Source: packages/engine-sim/src/control.ts
maxHealthFor
Max health for a packed stats field (clients draw health bars with it).
function maxHealthFor(config: ResolvedSimConfig, stats: number): number;Source: packages/engine-sim/src/control.ts
metaBonusOf
A player's meta bonus as the sim applies it (zeros when none).
function metaBonusOf(world: SimWorld, playerId: PlayerId): MetaBonus;Source: packages/engine-sim/src/control.ts
moverBox
A moving platform's box at a tick: a smooth there-and-back swing.
function moverBox(m: PlatformMover, tick: number): PlatBox;Source: packages/engine-sim/src/platform.ts
nearestSample
Nearest centreline sample to (x, z), searching around from (or everywhere).
function nearestSample(t: KartTrack, x: number, z: number, from?: number, reach?: number): number;Source: packages/engine-sim/src/kart.ts
onFloor
True when the circle at (x, z) of radius r lies on some floor rectangle (its centre inside it, with r of margin where it can).
function onFloor(floors: readonly WallBox[], x: number, z: number, r: number): boolean;Source: packages/engine-sim/src/walls.ts
orbitAngle
Orbit blade angle for blade i of n at a tick (radians). Exported so renderers draw blades where the sim hits.
function orbitAngle(tick: number, tickRate: number, speed: number, i: number, n: number): number;Source: packages/engine-sim/src/content.ts
pendingCards
Cards a player has waiting (level-ups not yet picked).
function pendingCards(world: SimWorld, playerId: PlayerId): number;Source: packages/engine-sim/src/control.ts
platBox
Normalize a box so x0 < x1 and y0 < y1.
function platBox(x0: number, y0: number, x1: number, y1: number): PlatBox;Source: packages/engine-sim/src/platform.ts
platformCoinCount
function platformCoinCount(p: { coinsLo: number; coinsHi: number; }): number;Source: packages/engine-sim/src/platform.ts
platformCoinTaken
function platformCoinTaken(p: { coinsLo: number; coinsHi: number; }, i: number): boolean;Source: packages/engine-sim/src/platform.ts
platformProgress
How far along the course a player is, 0..1 (by x from start to flag).
function platformProgress(w: PlatformWorld, p: { x: number; flags: number; }): number;Source: packages/engine-sim/src/platform.ts
platformRespawnPoint
Where a fall puts you back: the furthest checkpoint touched, or the start.
function platformRespawnPoint(w: PlatformWorld, cp: number): readonly [number, number];Source: packages/engine-sim/src/platform.ts
platformStep
One fixed tick. Inputs by player id; a player with none gets a neutral input.
function platformStep(w: PlatformWorld, inputs: ReadonlyMap<number, InputCommand>): PlatformEvent[];Source: packages/engine-sim/src/platform.ts
platStatLevel
A stat's level (0..15) from the packed word.
function platStatLevel(p: { stats: number; }, stat: PlatStat): number;Source: packages/engine-sim/src/platform.ts
playerBuild
function playerBuild(world: SimWorld, playerId: PlayerId): PlayerBuild | null;Source: packages/engine-sim/src/control.ts
playerNetId
The NetId of a player's character, if present.
function playerNetId(world: SimWorld, playerId: PlayerId): NetId | undefined;Source: packages/engine-sim/src/world.ts
pushOutOfWalls
Push a circle out of every wall it overlaps. Returns the new centre and the push normal of the last wall met (0, 0 when nothing was in the way).
function pushOutOfWalls(walls: readonly WallBox[], x: number, z: number, r: number): [x: number, z: number, nx: number, nz: number];Source: packages/engine-sim/src/walls.ts
quantizeInput
Snap a command onto the wire grid. The sim applies this to every input it consumes.
function quantizeInput(cmd: InputCommand): InputCommand;Source: packages/engine-sim/src/input.ts
recycleEnemies
Move far-off-screen non-boss enemies back to the spawn edge (see content.ts). Call every periodTicks.
function recycleEnemies(world: SimWorld, periodTicks: number, afterTicks: number, margin: number): { moved: number; removed: number; };Source: packages/engine-sim/src/control.ts
removeEnemies
Remove every living enemy of a type at once, with no kills or drops. Returns how many.
function removeEnemies(world: SimWorld, type: number): number;Source: packages/engine-sim/src/control.ts
removeKart
function removeKart(w: KartWorld, id: number): boolean;Source: packages/engine-sim/src/kart.ts
removePlatformPlayer
function removePlatformPlayer(w: PlatformWorld, id: number): boolean;Source: packages/engine-sim/src/platform.ts
removePlayer
Remove a player's character. No-op if absent.
function removePlayer(world: SimWorld, playerId: PlayerId): void;Source: packages/engine-sim/src/world.ts
renderView
Dense arrays for rendering this tick, in netId order, with last tick's
transforms for interpolation. The buffers are reused: copy anything you
need to keep past the next step or applyState.
function renderView(world: SimWorld): RenderView;Source: packages/engine-sim/src/render.ts
resetKart
Back to the grid for a fresh race (stats kept; the runner clears them).
function resetKart(w: KartWorld, k: Kart, frozen: boolean): void;Source: packages/engine-sim/src/kart.ts
resetPlatformPlayer
Put a player back at the start of a fresh round (stats are kept; the runner clears them per run).
function resetPlatformPlayer(w: PlatformWorld, p: PlatformPlayer, frozen: boolean): void;Source: packages/engine-sim/src/platform.ts
resetRun
A fresh run in place: enemies, gems and projectiles cleared; players reset at the spawn. NetIds of players are kept.
function resetRun(world: SimWorld): void;Source: packages/engine-sim/src/control.ts
resolveCharacter
Fill a character description with defaults and validate it.
function resolveCharacter(d: CharacterDesc): ResolvedCharacterDesc;Source: packages/engine-sim/src/physics/character.ts
resolveConfig
function resolveConfig(config?: SimConfig): ResolvedSimConfig;Source: packages/engine-sim/src/config.ts
respawnDead
Bring dead (out) players back beside a living teammate. Returns who came back.
function respawnDead(world: SimWorld): PlayerId[];Source: packages/engine-sim/src/control.ts
restorePhysics
Rebuild a world from snapshot() bytes. Stepping it gives exactly what the original would have.
function restorePhysics(bytes: Uint8Array): PhysicsWorld;Source: packages/engine-sim/src/physics/world.ts
revivePlayer
Revive one downed or dead player now (a paid revive). Returns false if they were up or absent.
function revivePlayer(world: SimWorld, playerId: PlayerId): boolean;Source: packages/engine-sim/src/control.ts
ringSpawnPoint
A ring point around (cx, cz) inside the arena and clear of pillars (headings retried, never clamped). Null if none.
function ringSpawnPoint(world: SimWorld, cx: number, cz: number, radius: number, enemyRadius?: number): [number, number] | null;Source: packages/engine-sim/src/control.ts
scaledWeapon
A weapon at a level with a player's passives applied.
function scaledWeapon(def: WeaponDef, level: number, mods: WeaponMods): Scaled;Source: packages/engine-sim/src/weapons.ts
scatterEnemies
Scatter count enemies of a type (props) over the field, off every screen. Returns how many.
function scatterEnemies(world: SimWorld, type: number, count: number): number;Source: packages/engine-sim/src/control.ts
segmentWalls
The first hit of a moving circle of radius r on a wall: the segment from (x0, z0) along (dx, dz), as a fraction 0..1, or -1 when it meets none. A box grown by r, slab method.
function segmentWalls(walls: readonly WallBox[], x0: number, z0: number, dx: number, dz: number, r: number): number;Source: packages/engine-sim/src/walls.ts
selectedSlot
The selected weapon slot (0..3) in a player's packed choices field (arena mode).
function selectedSlot(choices: number): number;Source: packages/engine-sim/src/arena.ts
setCosmetic
Set a player's cosmetic id (drawn by clients; no gameplay effect).
function setCosmetic(world: SimWorld, playerId: PlayerId, cosmetic: number): void;Source: packages/engine-sim/src/control.ts
setEnemySpeed
Authority: multiply every non-boss enemy's steering speed by k (0.25..3) from now on.
function setEnemySpeed(world: SimWorld, k: number): void;Source: packages/engine-sim/src/control.ts
setKartsFrozen
function setKartsFrozen(w: KartWorld, frozen: boolean): void;Source: packages/engine-sim/src/kart.ts
setKartTrack
function setKartTrack(w: KartWorld, index: number): void;Source: packages/engine-sim/src/kart.ts
setMetaBonus
Set a player's permanent (meta) stat bonus for this world: fractions, 0.05 = +5%. Each stat is clamped to META_MAX_PER_STAT and the sum to META_MAX_TOTAL (scaled down evenly past it). A player at full health stays at full health. Pass an empty object to clear it.
function setMetaBonus(world: SimWorld, playerId: PlayerId, bonus: Partial<MetaBonus>): void;Source: packages/engine-sim/src/control.ts
setPlatformFrozen
The countdown: hold (or release) every player.
function setPlatformFrozen(w: PlatformWorld, frozen: boolean): void;Source: packages/engine-sim/src/platform.ts
setPlatformLevel
Switch the course (a new round). Players keep their state; reset them after.
function setPlatformLevel(w: PlatformWorld, index: number): void;Source: packages/engine-sim/src/platform.ts
setXpBoost
Multiply the XP of gems dropped from now on (1 turns it off). Server-side, for timed events.
function setXpBoost(world: SimWorld, multiplier: number): void;Source: packages/engine-sim/src/control.ts
simPaused
True while the sim is paused for a solo player's upgrade cards.
function simPaused(world: SimWorld): boolean;Source: packages/engine-sim/src/control.ts
simRandom
The world's seeded PRNG, 0..1 (server-side game logic).
function simRandom(world: SimWorld): number;Source: packages/engine-sim/src/control.ts
slotLevel
function slotLevel(weapons: number, slot: number): number;Source: packages/engine-sim/src/content.ts
slotWeapon
Weapon index in a slot, or -1 when empty.
function slotWeapon(weapons: number, slot: number): number;Source: packages/engine-sim/src/content.ts
snapshotBaseTick
The baseline tick a delta snapshot needs, or null for a full snapshot.
function snapshotBaseTick(bytes: Uint8Array): number | null;Source: packages/engine-sim/src/snapshot.ts
spawnEnemy
Spawn an enemy of type (index into content.enemyTypes) at (x, z). Returns its NetId.
function spawnEnemy(world: SimWorld, type: number, x: number, z: number): NetId;Source: packages/engine-sim/src/control.ts
spawnEnemyScaled
function spawnEnemyScaled(world: SimWorld, type: number, x: number, z: number, scale: SpawnScale): NetId;Source: packages/engine-sim/src/control.ts
spawnPickupAt
Spawn special pickup index (content.pickups) at (x, z). Returns its NetId, or 0 when the world is full.
function spawnPickupAt(world: SimWorld, index: number, x: number, z: number): NetId;Source: packages/engine-sim/src/control.ts
spawnRingPoint
A point on a ring of radius m around a random living player (the arena spawn if none). Consumes the world PRNG.
function spawnRingPoint(world: SimWorld, radius: number): [number, number];Source: packages/engine-sim/src/control.ts
statLevel
function statLevel(stats: number, i: number): number;Source: packages/engine-sim/src/content.ts
step
THE API: advance the world exactly one fixed tick.
Systems run in a fixed order: input, AI, physics, combat, pickups, spawners, game rules, lifetime. Every loop that touches floats walks entities in netId order, so a world restored from a snapshot steps exactly like the one it was captured from.
function step(world: SimWorld, inputs: TickInputs): StepResult;Source: packages/engine-sim/src/step.ts
teleWord
Telegraph word: kind, progress 0..1, and an angle (lanes) or a radius in metres (circles).
function teleWord(kind: number, progress: number, angleOrRadius: number, isRadius?: boolean): number;Source: packages/engine-sim/src/roles.ts
viewEdge
Distance from a player to the edge of the screen at a heading (radians from +x toward +z), m.
function viewEdge(world: SimWorld, heading: number): number;Source: packages/engine-sim/src/control.ts
weaponModsFor
A player's weapon multipliers from a packed stats field (clients draw weapons the size the sim uses).
function weaponModsFor(config: ResolvedSimConfig, stats: number): { might: number; haste: number; area: number; amount: number; };Source: packages/engine-sim/src/control.ts
xpForLevel
XP needed to go from level to level + 1.
function xpForLevel(config: ResolvedSimConfig, level: number): number;Source: packages/engine-sim/src/control.ts
Classes
FixedStepper
Fixed-timestep accumulator (Glenn Fiedler, "Fix Your Timestep!").
Pure: no timers, no clock. The client feeds it frame deltas from
requestAnimationFrame, the room server feeds it from its own loop, and
both run step exactly ticks times per advance.
class FixedStepper {
constructor(tickRate: number, maxTicksPerAdvance?: number);
readonly tickRate: number;
readonly tickMs: number;
readonly maxTicksPerAdvance: number;
advance(elapsedMs: number): StepperAdvance;
reset(): void;
}Source: packages/engine-sim/src/stepper.ts
PhysicsWorld
class PhysicsWorld {
constructor(raw: RapierWorld, tickRate: number, gravity: Vec3);
readonly dt: number;
get tick(): number;
get bodyCount(): number;
addBody(desc: BodyDesc): BodyId;
addStaticBox(halfExtents: Vec3, position: Vec3, opts?: Omit<BodyDesc, "type" | "shape" | "position">): BodyId;
addTrigger(shape: ShapeDesc, position: Vec3, opts?: Omit<BodyDesc, "type" | "shape" | "position" | "sensor">): BodyId;
removeBody(id: BodyId): void;
has(id: BodyId): boolean;
userData(id: BodyId): number;
bodyType(id: BodyId): BodyType;
bodyIds(): BodyId[];
position(id: BodyId): Vec3;
rotation(id: BodyId): Quat;
velocity(id: BodyId): Vec3;
angularVelocity(id: BodyId): Vec3;
mass(id: BodyId): number;
setPosition(id: BodyId, p: Vec3): void;
setRotation(id: BodyId, q: Quat): void;
setLinearVelocity(id: BodyId, v: Vec3): void;
setAngularVelocity(id: BodyId, v: Vec3): void;
applyImpulse(id: BodyId, impulse: Vec3): void;
applyForce(id: BodyId, force: Vec3): void;
applyKnockback(id: BodyId, from: Vec3, strength: number, opts?: KnockbackOptions): void;
setKinematicTarget(id: BodyId, p: Vec3, q?: Quat): void;
wake(id: BodyId): void;
sleep(id: BodyId): void;
isSleeping(id: BodyId): boolean;
addJoint(desc: JointDesc): JointId;
removeJoint(id: JointId): void;
addCharacter(desc: CharacterDesc): BodyId;
characterState(id: BodyId): CharacterState;
setCharacterState(id: BodyId, s: CharacterState): void;
isCharacter(id: BodyId): boolean;
step(inputs?: ReadonlyMap<BodyId, CharacterInput>): PhysicsStepResult;
raycast(origin: Vec3, dir: Vec3, maxDist: number, opts?: QueryOptions): RayHit | null;
raycastAll(origin: Vec3, dir: Vec3, maxDist: number, opts?: QueryOptions): RayHit[];
shapeCast(shape: ShapeDesc, from: Vec3, dir: Vec3, maxDist: number, opts?: QueryOptions & { rotation?: Quat; }): ShapeHit | null;
overlap(shape: ShapeDesc, position: Vec3, opts?: QueryOptions & { rotation?: Quat; }): BodyId[];
// ... 5 more lines in the sourceSource: packages/engine-sim/src/physics/world.ts
Constants
ALL_LAYERS
Every layer (the default mask).
const ALL_LAYERS: 65535;Source: packages/engine-sim/src/physics/layers.ts
ARENA_BOLT_RADIUS
Projectile hit radius, m, and the height projectiles fly at.
const ARENA_BOLT_RADIUS: 0.2;Source: packages/engine-sim/src/arena.ts
ARENA_HITBOX_PAD
Extra reach of a player's hitbox over their capsule radius, m (beams and the rewind buffer).
const ARENA_HITBOX_PAD: 0.2;Source: packages/engine-sim/src/arena.ts
ARENA_SPAWN_CLEAR
A spawn never lands within this many metres of a living opponent when anywhere else is free, m.
const ARENA_SPAWN_CLEAR: 12;Source: packages/engine-sim/src/arena.ts
BOT_PLAYER_BASE
Player ids from here up are server-side bots (seat fillers). They play through the same sim; their arena beams resolve in the sim, never through the room's lag compensation (a bot sees the present).
const BOT_PLAYER_BASE: 65280;Source: packages/engine-sim/src/api.ts
Button
Input button bits. Games may use bits 8..15 for their own actions.
const Button: { readonly Jump: number; readonly Fire: number; readonly Alt: number; readonly Use: number; readonly Sprint: number; readonly Choice1: number; readonly Choice2: number; readonly Choice3: number; readonly Reroll: number; readonly Skip: number; readonly Ready: number; };Source: packages/engine-sim/src/api.ts
DEFAULT_ARENA
const DEFAULT_ARENA: ArenaConfig;Source: packages/engine-sim/src/config.ts
DEFAULT_ARENA_RULES
const DEFAULT_ARENA_RULES: ArenaRules;Source: packages/engine-sim/src/config.ts
DEFAULT_COOP
const DEFAULT_COOP: CoopRules;Source: packages/engine-sim/src/config.ts
DEFAULT_ENEMIES
const DEFAULT_ENEMIES: EnemyRules;Source: packages/engine-sim/src/config.ts
DEFAULT_KART_TUNING
const DEFAULT_KART_TUNING: KartTuning;Source: packages/engine-sim/src/kart.ts
DEFAULT_PLATFORM_TUNING
const DEFAULT_PLATFORM_TUNING: PlatformTuning;Source: packages/engine-sim/src/platform.ts
DEFAULT_PLAYER
const DEFAULT_PLAYER: PlayerRules;Source: packages/engine-sim/src/config.ts
DEFAULT_PROGRESSION
const DEFAULT_PROGRESSION: ProgressionRules;Source: packages/engine-sim/src/config.ts
DEFAULT_TICK_RATE
Default fixed tick rate in Hz (spec: 30 Hz default, 60 for shooters).
const DEFAULT_TICK_RATE: 30;Source: packages/engine-sim/src/api.ts
DEFAULT_VIEW
Default view: a 22 m circle (games compile their camera's real footprint into this).
const DEFAULT_VIEW: ViewRules;Source: packages/engine-sim/src/config.ts
EntityFlag
Per-entity state flag bits (EntityState.flags).
const EntityFlag: { readonly Grounded: number; readonly Dead: number; readonly Downed: number; readonly Dashing: number; readonly Solo: number; readonly Shielded: number; readonly Elite: number; readonly Hostile: number; };Source: packages/engine-sim/src/api.ts
EntityKind
Entity kinds carried in snapshots.
const EntityKind: { readonly Player: 1; readonly Enemy: 2; readonly Projectile: 3; readonly Pickup: 4; };Source: packages/engine-sim/src/api.ts
INPUT_BYTES
Bytes per encoded InputCommand.
const INPUT_BYTES: 15;Source: packages/engine-sim/src/api.ts
KART_COIN_CAP
Coins held that raise top speed, and how much each adds.
const KART_COIN_CAP: 10;Source: packages/engine-sim/src/kart.ts
KART_COIN_SPEED
const KART_COIN_SPEED: 0.01;Source: packages/engine-sim/src/kart.ts
KART_MAX_COINS
const KART_MAX_COINS: 62;Source: packages/engine-sim/src/kart.ts
KART_RADIUS
Kart body radius for bumps, m.
const KART_RADIUS: 0.9;Source: packages/engine-sim/src/kart.ts
KART_STAT_DOC
const KART_STAT_DOC: Readonly<Record<"magnet" | "speed" | "armor" | "might" | "haste", string>>;Source: packages/engine-sim/src/kart.ts
KART_STATS
Upgrade stats a kart can carry (4 bits each in stats).
const KART_STATS: readonly ["speed", "haste", "might", "armor", "magnet"];Source: packages/engine-sim/src/kart.ts
KartFlag
const KartFlag: { readonly Drifting: number; readonly DriftRight: number; readonly OnGrass: number; readonly Finished: number; readonly Frozen: number; readonly Bot: number; readonly Bumped: number; readonly Boosting: number; };Source: packages/engine-sim/src/kart.ts
KEEPER_MASK
const KEEPER_MASK: number;Source: packages/engine-sim/src/api.ts
KEEPER_SHIFT
Keeper (character) choice rides input bits 11..14 as index + 1 (0: no choice). It is held, not pressed: the sim takes it while the keeper is still level 1 with nothing pending (the start of a run), so a client keeps sending its pick and it lands on the first tick of every run.
const KEEPER_SHIFT: 11;Source: packages/engine-sim/src/api.ts
Layer
Collision layers. Every body is on exactly one layer and carries a mask of the layers it collides with. Rapier's rule is pairwise: two bodies touch only when EACH one's mask contains the other's layer, so both sides of a pair must agree (a projectile that wants to hit enemies needs Enemy in its mask, and enemies need Projectile in theirs). Queries (raycasts, shape casts, overlaps) only look at the layers in the query's mask.
const Layer: { readonly Level: number; readonly Player: number; readonly Enemy: number; readonly Projectile: number; readonly Pickup: number; readonly Prop: number; readonly Trigger: number; readonly Debris: number; readonly User1: number; readonly User2: number; readonly User3: number; readonly User4: number; readonly User5: number; readonly User6: number; readonly User7: number; readonly User8: number; };Source: packages/engine-sim/src/physics/layers.ts
META_MAX_PER_STAT
Hard ceilings on a meta bonus, whatever a caller passes: +15% per stat, +30% across stats.
const META_MAX_PER_STAT: 0.15;Source: packages/engine-sim/src/control.ts
META_MAX_TOTAL
const META_MAX_TOTAL: 0.3;Source: packages/engine-sim/src/control.ts
METEOR_FALL_SECONDS
Seconds a meteor's circle shows before it lands.
const METEOR_FALL_SECONDS: 0.6;Source: packages/engine-sim/src/weapons.ts
ORBIT_BLADE_RADIUS
Orbit blade hit radius, m.
const ORBIT_BLADE_RADIUS: 0.45;Source: packages/engine-sim/src/content.ts
ORBIT_HIT_EVERY
Ticks between hits from one orbit blade on one enemy.
const ORBIT_HIT_EVERY: 8;Source: packages/engine-sim/src/content.ts
PICKUP_SPECIAL
Pickup entity types from here up are special pickups (index = type - PICKUP_SPECIAL).
const PICKUP_SPECIAL: 16;Source: packages/engine-sim/src/api.ts
PLAT_HALF_W
Half width and height of the body box (feet at y).
const PLAT_HALF_W: 0.34;Source: packages/engine-sim/src/platform.ts
PLAT_HEIGHT
const PLAT_HEIGHT: 1.4;Source: packages/engine-sim/src/platform.ts
PLAT_MAX_COINS
Most coins a level holds (two u31 masks).
const PLAT_MAX_COINS: 62;Source: packages/engine-sim/src/platform.ts
PLAT_STAT_DOC
What one level of each stat does (the declared upgrade's step scales it).
const PLAT_STAT_DOC: Readonly<Record<"magnet" | "speed" | "amount" | "maxHealth" | "haste", string>>;Source: packages/engine-sim/src/platform.ts
PLAT_STATS
Upgrade stats a platformer player can carry (4 bits each in stats).
const PLAT_STATS: readonly ["speed", "amount", "magnet", "maxHealth", "haste"];Source: packages/engine-sim/src/platform.ts
PlatFlag
Player flags (u16 on the wire).
const PlatFlag: { readonly Grounded: number; readonly FacingLeft: number; readonly Rising: number; readonly Dead: number; readonly Finished: number; readonly Frozen: number; readonly DashReady: number; readonly Bot: number; readonly OnMover: number; };Source: packages/engine-sim/src/platform.ts
POSITION_SCALE
Fixed-point units per metre for positions in state and snapshots.
const POSITION_SCALE: 1024;Source: packages/engine-sim/src/api.ts
ROLE_DEFAULTS
Defaults per role (seconds and metres are converted at use).
const ROLE_DEFAULTS: { readonly runner: { readonly lead: 0.5; }; readonly charger: { readonly range: 6; readonly windup: 0.55; readonly act: 0.6; readonly recover: 1; readonly cooldown: 2.5; readonly speed: 3.4; }; readonly ranged: { readonly range: 10; readonly windup: 0.3; readonly cooldown: 2.6; readonly speed: 7; }; readonly bomber: { readonly range: 1.8; readonly windup: 1; readonly radius: 2.5; readonly damage: 1.4; }; readonly shielder: { readonly cooldown: 6; readonly windup: 0.8; readonly radius: 8; readonly count: 6; readonly share: 0.35; readonly seconds: 8; }; readonly healer: { readonly cooldown: 3.5; /* ... */;Source: packages/engine-sim/src/roles.ts
SNAPSHOT_VERSION
Snapshot wire format version (first byte after the magic).
const SNAPSHOT_VERSION: 2;Source: packages/engine-sim/src/api.ts
Telegraph
Enemy telegraph word (EntityState.level on enemies and hostile projectiles; it rides snapshots): kind in bits 0-2, fill progress 0..31 in bits 3-7, and an angle (lanes, 256 steps of a turn) or a radius (circles, in 0.1 m) in bits 8-15.
const Telegraph: { readonly None: 0; readonly Circle: 1; readonly Lane: 2; readonly Aura: 3; };Source: packages/engine-sim/src/api.ts
VELOCITY_SCALE
Fixed-point units per metre/second for velocities.
const VELOCITY_SCALE: 1024;Source: packages/engine-sim/src/api.ts
YAW_UNITS
Yaw is a u16 turn: 65536 units per full revolution.
const YAW_UNITS: 65536;Source: packages/engine-sim/src/api.ts
Types
ArenaConfig
The static level. Part of the world's config, never of a snapshot.
interface ArenaConfig {
readonly halfExtent: number;
readonly wallHeight: number;
readonly pillars: readonly Pillar[];
readonly walls?: readonly WallBox[];
readonly floors?: readonly WallBox[];
readonly spawn: Vec3;
}Source: packages/engine-sim/src/api.ts
ArenaHitbox
What the rewind buffer records each tick: living players and enemies.
interface ArenaHitbox {
readonly netId: NetId;
readonly owner: PlayerId;
readonly x: number;
readonly z: number;
readonly r: number;
}Source: packages/engine-sim/src/arena.ts
ArenaRules
Arena (shooter) mode: players aim with yaw and move in the world frame,
fire their selected loadout weapon on Button.Fire, hurt each other, die
and respawn at the spawn point farthest from their opponents.
interface ArenaRules {
readonly enabled: boolean;
readonly authority: boolean;
readonly externalHitscan: boolean;
readonly respawnTicks: number;
readonly spawnIframeTicks: number;
readonly spawns: readonly (readonly [number, number])[];
readonly dropHeal: number;
readonly pickupTicks: number;
}Source: packages/engine-sim/src/api.ts
BeamShot
A human's beam this tick, for the room's rewind.
interface BeamShot {
readonly shooter: PlayerId;
readonly x: number;
readonly z: number;
readonly dx: number;
readonly dz: number;
readonly range: number;
readonly damage: number;
readonly knockback: number;
}Source: packages/engine-sim/src/arena.ts
BodyDesc
interface BodyDesc {
readonly type: BodyType;
readonly shape: ShapeDesc;
readonly position?: Vec3;
readonly rotation?: Quat;
readonly mass?: number;
readonly density?: number;
readonly friction?: number;
readonly restitution?: number;
readonly linearDamping?: number;
readonly angularDamping?: number;
readonly gravityScale?: number;
readonly layer?: number;
readonly mask?: number;
readonly sensor?: boolean;
readonly ccd?: boolean;
readonly lockRotations?: boolean;
readonly linearVelocity?: Vec3;
readonly angularVelocity?: Vec3;
readonly userData?: number;
}Source: packages/engine-sim/src/physics/types.ts
BodyId
A stable id for one body in a PhysicsWorld (u32, assigned in creation order, never reused).
type BodyId = number;Source: packages/engine-sim/src/physics/types.ts
BodyType
type BodyType = "dynamic" | "kinematic" | "static";Source: packages/engine-sim/src/physics/types.ts
BossAttack
What a boss can do. Each is telegraphed before it lands.
type BossAttack = "slam" | "dash" | "leap" | "rain" | "ring" | "fan" | "summon";Source: packages/engine-sim/src/api.ts
BossPattern
interface BossPattern {
readonly attacks: readonly BossAttack[];
readonly enrageAt: number;
readonly summon?: number;
readonly mini?: boolean;
}Source: packages/engine-sim/src/api.ts
ButtonBit
type ButtonBit = (typeof Button)[keyof typeof Button];Source: packages/engine-sim/src/api.ts
CharacterDef
A playable character: its start weapon and a signature passive at level 1.
Clients draw it from its index (Player value bits 12..15).
interface CharacterDef {
readonly weapon: number;
readonly stat: number;
}Source: packages/engine-sim/src/api.ts
CharacterDesc
A kinematic character (capsule on Rapier's character controller). All fields optional except where noted.
interface CharacterDesc {
readonly position: Vec3;
readonly radius?: number;
readonly halfHeight?: number;
readonly layer?: number;
readonly mask?: number;
readonly offset?: number;
readonly maxSlopeClimb?: number;
readonly minSlopeSlide?: number;
readonly stepHeight?: number;
readonly stepWidth?: number;
readonly stepOverDynamic?: boolean;
readonly snapToGround?: number;
readonly maxSpeed?: number;
readonly groundAccel?: number;
readonly groundDecel?: number;
readonly airAccel?: number;
readonly airDecel?: number;
readonly jumpVelocity?: number;
readonly jumpCut?: number;
readonly gravityScale?: number;
readonly terminalVelocity?: number;
readonly coyoteTicks?: number;
readonly jumpBufferTicks?: number;
readonly dashTicks?: number;
readonly dashSpeed?: number;
readonly dashCooldownTicks?: number;
readonly dashBufferTicks?: number;
readonly dashInvulnerable?: boolean;
readonly pushBodies?: boolean;
readonly mass?: number;
readonly userData?: number;
}Source: packages/engine-sim/src/physics/types.ts
CharacterInput
One tick of character input. Move is in world space (x right, z toward the camera), -1..1.
interface CharacterInput {
readonly moveX: number;
readonly moveZ: number;
readonly jump?: boolean;
readonly dash?: boolean;
}Source: packages/engine-sim/src/physics/types.ts
CharacterReport
interface CharacterReport {
readonly id: BodyId;
readonly grounded: boolean;
readonly landed: boolean;
readonly jumped: boolean;
readonly dashed: boolean;
readonly hitCeiling: boolean;
readonly groundNormal: Vec3;
}Source: packages/engine-sim/src/physics/types.ts
CharacterState
A character's whole motor state: plain numbers, serialized in snapshots.
interface CharacterState {
x: number;
y: number;
z: number;
vx: number;
vy: number;
vz: number;
grounded: boolean;
coyote: number;
jumpBuffer: number;
jumping: boolean;
dashTicks: number;
dashCooldown: number;
dashBuffer: number;
dashX: number;
dashZ: number;
facingX: number;
facingZ: number;
invulnerable: boolean;
buttons: number;
groundNormalX: number;
groundNormalY: number;
groundNormalZ: number;
}Source: packages/engine-sim/src/physics/types.ts
ContentConfig
Game content: when weapons is non-empty the world runs in content mode
(auto-firing weapons, XP gems, level-ups, co-op downed and revive, dash)
instead of the week-2 arena rules (Fire = pulse, respawn on death).
interface ContentConfig {
readonly enemyTypes?: readonly EnemyTypeDef[];
readonly weapons?: readonly WeaponDef[];
readonly stats?: readonly StatDef[];
readonly progression?: Partial<ProgressionRules>;
readonly coop?: Partial<CoopRules>;
readonly arena?: Partial<ArenaRules>;
readonly view?: ViewRules;
readonly pickups?: readonly PickupTypeDef[];
readonly loot?: { readonly chest: number; readonly heal: number; readonly vacuum: number; readonly bossChest?: number };
readonly mergeGemsAbove?: number;
readonly characters?: readonly CharacterDef[];
}Source: packages/engine-sim/src/api.ts
CoopRules
interface CoopRules {
readonly downedTicks: number;
readonly reviveTicks: number;
readonly reviveRadius: number;
readonly reviveHealth: number;
readonly iframeTicks: number;
readonly corpseTicks: number;
readonly dashTicks: number;
readonly dashSpeed: number;
readonly dashCooldownTicks: number;
readonly dashBufferTicks: number;
readonly hitIframeTicks: number;
readonly pauseSolo: boolean;
readonly soloFromFlag: boolean;
readonly choicePulseRadius: number;
readonly choicePulseIframeTicks: number;
readonly reviveBuffTicks: number;
readonly reviveBuffMight: number;
readonly reviveBuffSpeed: number;
readonly crawlSpeed: number;
readonly selfRevives: number;
readonly selfReviveDelayTicks: number;
readonly respawnTicks: number;
readonly risePulseRadius: number;
}Source: packages/engine-sim/src/api.ts
EdgeSpawnOptions
interface EdgeSpawnOptions {
readonly heading?: number;
readonly spread?: number;
readonly margin?: number;
readonly radius?: number;
readonly relative?: "ahead" | "behind";
}Source: packages/engine-sim/src/control.ts
EnemyAi
Enemy behaviours the sim runs (content mode).
type EnemyAi =
| "chase"
| "idle"
| "runner"
| "charger"
| "ranged"
| "bomber"
| "shielder"
| "healer"
| "summoner"
| "flee"
| "wander";Source: packages/engine-sim/src/api.ts
EnemyAttack
Attack numbers for an enemy role. Every field is optional; the role's defaults (roles.ts ROLE_DEFAULTS) fill the rest. Seconds and metres.
interface EnemyAttack {
readonly damage?: number;
readonly range?: number;
readonly windupTicks?: number;
readonly cooldownTicks?: number;
readonly speed?: number;
readonly radius?: number;
readonly summon?: number;
readonly count?: number;
}Source: packages/engine-sim/src/api.ts
EnemyRules
interface EnemyRules {
readonly target: number;
readonly spawnPerTick: number;
readonly spawnRadius: number;
readonly speed: number;
readonly radius: number;
readonly maxHealth: number;
readonly contactDamage: number;
readonly contactCooldownTicks: number;
}Source: packages/engine-sim/src/api.ts
EnemyTypeDef
One enemy prefab, compiled from the game API (prefab(...)). Enemy type
0 is always the arena's EnemyRules (the built-in target spawner uses it).
interface EnemyTypeDef {
readonly health: number;
readonly speed: number;
readonly radius: number;
readonly damage: number;
readonly xp: number;
readonly boss?: boolean;
readonly mass?: number;
readonly ai?: EnemyAi;
readonly attack?: EnemyAttack;
readonly split?: { readonly type: number; readonly count: number };
readonly pattern?: BossPattern;
readonly drops?: readonly { readonly pickup: number; readonly chance: number }[];
readonly prop?: boolean;
}Source: packages/engine-sim/src/api.ts
EntityKindId
type EntityKindId = (typeof EntityKind)[keyof typeof EntityKind];Source: packages/engine-sim/src/api.ts
EntityState
One entity's networked state. Every field is an integer: positions and
velocities in fixed point (POSITION_SCALE, VELOCITY_SCALE), yaw as a
u16 turn. The sim keeps its own state on this grid at every tick
boundary, so capture → apply is lossless.
interface EntityState {
netId: NetId;
kind: EntityKindId;
owner: PlayerId;
px: number;
py: number;
pz: number;
vx: number;
vy: number;
vz: number;
yaw: number;
health: number;
flags: number;
ack: number;
cooldown: number;
buttons: number;
timers: number;
type: number;
value: number;
level: number;
xp: number;
weapons: number;
wcd: number;
stats: number;
choices: number;
bleed: number;
revive: number;
iframes: number;
dash: number;
}Source: packages/engine-sim/src/api.ts
HitSource
What dealt a hit to a player. Everything but "contact" was telegraphed first.
type HitSource = "contact" | "charge" | "blast" | "projectile" | "slam" | "hazard";Source: packages/engine-sim/src/api.ts
InputCommand
One player's input for one tick. Serializable and sequence-numbered.
The sim quantizes every command on entry (quantizeInput), so a client's
prediction and the server's authority consume bit-identical inputs.
Wire size: 15 bytes (INPUT_BYTES).
interface InputCommand {
seq: number;
tick: number;
moveX: number;
moveZ: number;
yaw: number;
buttons: number;
}Source: packages/engine-sim/src/api.ts
JointDesc
interface JointDesc {
readonly kind: JointKind;
readonly a: BodyId;
readonly b: BodyId;
readonly anchorA?: Vec3;
readonly anchorB?: Vec3;
readonly axis?: Vec3;
}Source: packages/engine-sim/src/physics/types.ts
JointId
A stable id for one joint.
type JointId = number;Source: packages/engine-sim/src/physics/types.ts
JointKind
type JointKind = "fixed" | "ball" | "hinge" | "slider";Source: packages/engine-sim/src/physics/types.ts
Kart
interface Kart {
readonly id: number;
x: number;
z: number;
yaw: number;
vx: number;
vz: number;
flags: number;
charge: number;
boost: number;
seg: number;
lap: number;
cps: number;
coinsLo: number;
coinsHi: number;
finishTick: number;
stats: number;
cosmetic: number;
slot: number;
ack: number;
held: number;
}Source: packages/engine-sim/src/kart.ts
KartConfig
interface KartConfig {
readonly tickRate: number;
readonly tracks: readonly KartTrackDef[];
readonly tuning?: Partial<KartTuning>;
readonly statSteps?: readonly number[];
readonly authority?: boolean;
}Source: packages/engine-sim/src/kart.ts
KartEvent
type KartEvent =
| { readonly type: "coin"; readonly kart: number; readonly index: number }
| { readonly type: "lap"; readonly kart: number; readonly lap: number }
| { readonly type: "finish"; readonly kart: number; readonly tick: number }
| { readonly type: "turbo"; readonly kart: number; readonly tier: number }
| { readonly type: "pad"; readonly kart: number }
| { readonly type: "wall"; readonly kart: number; readonly speed: number }
| { readonly type: "bump"; readonly kart: number; readonly other: number };Source: packages/engine-sim/src/kart.ts
KartStat
type KartStat = (typeof KART_STATS)[number];Source: packages/engine-sim/src/kart.ts
KartTrack
A track, sampled.
interface KartTrack {
readonly def: KartTrackDef;
readonly x: Float64Array;
readonly z: Float64Array;
readonly tx: Float64Array;
readonly tz: Float64Array;
readonly dist: Float64Array;
readonly length: number;
readonly count: number;
readonly half: number;
readonly wall: number;
readonly pads: readonly { readonly x: number; readonly z: number; readonly tx: number; readonly tz: number }[];
readonly coinAt: readonly (readonly [number, number])[];
readonly grid: readonly (readonly [number, number, number])[];
}Source: packages/engine-sim/src/kart.ts
KartTrackDef
interface KartTrackDef {
readonly points: readonly (readonly [number, number])[];
readonly width: number;
readonly laps: number;
readonly boosts: readonly (readonly [number, number])[];
readonly coins: readonly (readonly [number, number])[];
readonly verge?: number;
}Source: packages/engine-sim/src/kart.ts
KartTuning
interface KartTuning {
readonly topSpeed: number;
readonly accel: number;
readonly brake: number;
readonly drag: number;
readonly turn: number;
readonly grip: number;
readonly driftGrip: number;
readonly grass: number;
readonly boostSpeed: number;
readonly turbo: readonly [number, number, number];
readonly turboAt: readonly [number, number, number];
readonly padSeconds: number;
readonly coinRadius: number;
}Source: packages/engine-sim/src/kart.ts
KartWire
Integer wire state of one kart.
interface KartWire {
readonly id: number;
readonly x: number;
readonly z: number;
readonly yaw: number;
readonly vx: number;
readonly vz: number;
readonly flags: number;
readonly timers: number;
readonly track: number;
readonly coinsLo: number;
readonly coinsHi: number;
readonly finishTick: number;
readonly stats: number;
readonly cosmetic: number;
readonly clock: number;
}Source: packages/engine-sim/src/kart.ts
KartWorld
interface KartWorld {
readonly tickRate: number;
readonly dt: number;
readonly tracks: readonly KartTrack[];
track: KartTrack;
trackIndex: number;
readonly tuning: KartTuning;
readonly statSteps: readonly number[];
readonly authority: boolean;
tick: number;
readonly karts: Map<number, Kart>;
}Source: packages/engine-sim/src/kart.ts
KnockbackOptions
interface KnockbackOptions {
readonly lift?: number;
readonly byMass?: boolean;
}Source: packages/engine-sim/src/physics/types.ts
LayerBit
One bit of Layer.
type LayerBit = (typeof Layer)[LayerName];Source: packages/engine-sim/src/physics/layers.ts
LayerName
type LayerName = keyof typeof Layer;Source: packages/engine-sim/src/physics/layers.ts
MetaBonus
A player's permanent stat bonus from meta upgrades bought with coins (opt-in per game). Fractions: 0.05 is +5%. speed, might and area multiply; haste cuts cooldowns; maxHealth and magnet add that fraction of the base value.
interface MetaBonus {
speed: number;
maxHealth: number;
magnet: number;
might: number;
haste: number;
area: number;
}Source: packages/engine-sim/src/world.ts
NetId
A stable network id for one entity (u32, never reused within a world). 0 means "none". Snapshots are keyed by NetId, never by ECS entity id.
type NetId = number;Source: packages/engine-sim/src/api.ts
PhysicsEvent
A contact or trigger change during one step. a < b; for triggers one of them is the sensor.
interface PhysicsEvent {
readonly type: PhysicsEventType;
readonly a: BodyId;
readonly b: BodyId;
}Source: packages/engine-sim/src/physics/types.ts
PhysicsEventType
type PhysicsEventType = "contact.start" | "contact.end" | "trigger.enter" | "trigger.exit";Source: packages/engine-sim/src/physics/types.ts
PhysicsOptions
interface PhysicsOptions {
readonly gravity?: Vec3;
readonly tickRate?: number;
}Source: packages/engine-sim/src/physics/world.ts
PhysicsStepResult
interface PhysicsStepResult {
readonly tick: number;
readonly events: readonly PhysicsEvent[];
readonly characters: readonly CharacterReport[];
}Source: packages/engine-sim/src/physics/types.ts
PickupEffect
What a special pickup does when a player collects it.
type PickupEffect = "heal" | "vacuum" | "bomb" | "chest";Source: packages/engine-sim/src/api.ts
PickupTypeDef
A special pickup (content.pickups). Entities carry PICKUP_SPECIAL + index as their type; gem tiers stay 0..2.
- heal:
amountof max health (0..1) or hit points (above 1); - vacuum: every gem on the floor flies to the collector;
- bomb: kills every non-boss enemy on the collector's screen;
- chest:
amountcard picks (1-3; a ready evolution shows first).
interface PickupTypeDef {
readonly effect: PickupEffect;
readonly amount: number;
readonly evolve?: boolean;
}Source: packages/engine-sim/src/api.ts
Pillar
A cylindrical pillar in the arena (static collider).
interface Pillar {
readonly x: number;
readonly z: number;
readonly radius: number;
readonly height: number;
}Source: packages/engine-sim/src/api.ts
PlatBox
An axis-aligned box: [x0, y0, x1, y1] in metres, x0 < x1, y0 < y1.
type PlatBox = readonly [number, number, number, number];Source: packages/engine-sim/src/platform.ts
PlatformConfig
interface PlatformConfig {
readonly tickRate: number;
readonly levels: readonly PlatformLevel[];
readonly tuning?: Partial<PlatformTuning>;
readonly statSteps?: readonly number[];
}Source: packages/engine-sim/src/platform.ts
PlatformEvent
type PlatformEvent =
| { readonly type: "coin"; readonly player: number; readonly index: number }
| { readonly type: "checkpoint"; readonly player: number; readonly index: number }
| { readonly type: "finish"; readonly player: number; readonly tick: number }
| { readonly type: "fell"; readonly player: number; readonly hazard: boolean }
| { readonly type: "shield"; readonly player: number }
| { readonly type: "jump"; readonly player: number; readonly air: boolean }
| { readonly type: "land"; readonly player: number; readonly speed: number }
| { readonly type: "spring"; readonly player: number }
| { readonly type: "dash"; readonly player: number }
| { readonly type: "respawn"; readonly player: number };Source: packages/engine-sim/src/platform.ts
PlatformLevel
interface PlatformLevel {
readonly start: readonly [number, number];
readonly flag: readonly [number, number];
readonly killY: number;
readonly solids: readonly PlatBox[];
readonly ledges: readonly PlatBox[];
readonly hazards: readonly PlatBox[];
readonly springs: readonly PlatformSpring[];
readonly movers: readonly PlatformMover[];
readonly coins: readonly (readonly [number, number])[];
readonly checkpoints: readonly (readonly [number, number])[];
}Source: packages/engine-sim/src/platform.ts
PlatformMover
interface PlatformMover {
readonly box: PlatBox;
readonly dx: number;
readonly dy: number;
readonly periodTicks: number;
readonly phaseTicks: number;
}Source: packages/engine-sim/src/platform.ts
PlatformPlayer
interface PlatformPlayer {
readonly id: number;
x: number;
y: number;
vx: number;
vy: number;
flags: number;
coyote: number;
buffer: number;
airLeft: number;
dashT: number;
dashCd: number;
drop: number;
cp: number;
coinsLo: number;
coinsHi: number;
finishTick: number;
respawn: number;
iframes: number;
shield: number;
stats: number;
cosmetic: number;
ack: number;
held: number;
}Source: packages/engine-sim/src/platform.ts
PlatformPlayerWire
Integer wire state of one player (positions and speeds in 1/1024).
interface PlatformPlayerWire {
readonly id: number;
readonly x: number;
readonly y: number;
readonly vx: number;
readonly vy: number;
readonly flags: number;
readonly timers: number;
readonly timers2: number;
readonly cp: number;
readonly coinsLo: number;
readonly coinsHi: number;
readonly finishTick: number;
readonly stats: number;
readonly cosmetic: number;
readonly clock: number;
}Source: packages/engine-sim/src/platform.ts
PlatformSpring
interface PlatformSpring {
readonly x: number;
readonly y: number;
readonly power: number;
}Source: packages/engine-sim/src/platform.ts
PlatformTuning
Motor numbers. Seconds become ticks at world creation.
interface PlatformTuning {
readonly runSpeed: number;
readonly groundAccel: number;
readonly airAccel: number;
readonly friction: number;
readonly jumpHeight: number;
readonly timeToApex: number;
readonly fallGravity: number;
readonly jumpCut: number;
readonly apexHang: number;
readonly apexWindow: number;
readonly coyoteSeconds: number;
readonly bufferSeconds: number;
readonly terminal: number;
readonly airJumps: number;
readonly airJumpScale: number;
readonly dashSpeed: number;
readonly dashSeconds: number;
readonly dashCooldown: number;
readonly coinRadius: number;
readonly respawnSeconds: number;
readonly iframeSeconds: number;
}Source: packages/engine-sim/src/platform.ts
PlatformWorld
interface PlatformWorld {
readonly tickRate: number;
readonly levels: readonly PlatformLevel[];
level: PlatformLevel;
levelIndex: number;
readonly tuning: PlatformTuning;
readonly motor: Motor;
readonly statSteps: readonly number[];
tick: number;
readonly players: Map<number, PlatformPlayer>;
}Source: packages/engine-sim/src/platform.ts
PlatStat
type PlatStat = (typeof PLAT_STATS)[number];Source: packages/engine-sim/src/platform.ts
PlayerBuild
One player's build this run: weapons (with levels), passives, keeper, and damage per weapon index.
interface PlayerBuild {
readonly keeper: number;
readonly weapons: readonly { readonly index: number; readonly level: number }[];
readonly stats: readonly { readonly index: number; readonly level: number }[];
readonly damage: readonly number[];
}Source: packages/engine-sim/src/control.ts
PlayerId
A player slot in a room, 1..65535. 0 means "no player".
type PlayerId = number;Source: packages/engine-sim/src/api.ts
PlayerRules
interface PlayerRules {
readonly speed: number;
readonly sprintMultiplier: number;
readonly jumpVelocity: number;
readonly gravity: number;
readonly radius: number;
readonly halfHeight: number;
readonly maxHealth: number;
readonly pulseRadius: number;
readonly pulseCooldownTicks: number;
readonly jumpBufferTicks: number;
readonly coyoteTicks: number;
}Source: packages/engine-sim/src/api.ts
PlayerSummary
One player as game logic sees it (listPlayers).
interface PlayerSummary {
readonly playerId: PlayerId;
readonly netId: NetId;
readonly x: number;
readonly y: number;
readonly z: number;
readonly health: number;
readonly maxHealth: number;
readonly level: number;
readonly up: boolean;
readonly downed: boolean;
readonly dead: boolean;
readonly slot: number;
readonly keeper: number;
readonly buffed: boolean;
readonly selfRevives: number;
}Source: packages/engine-sim/src/api.ts
ProgressionRules
interface ProgressionRules {
readonly xpBase: number;
readonly xpGrowth: number;
readonly magnet: number;
readonly maxWeapons: number;
readonly startWeapon: number;
readonly maxPickups: number;
readonly rerolls: number;
readonly xpExponent: number;
readonly loadout: readonly number[];
readonly xpShare: XpShare;
readonly critChance: number;
readonly critMultiplier: number;
}Source: packages/engine-sim/src/api.ts
Quat
Quaternion [x, y, z, w].
type Quat = readonly [x: number, y: number, z: number, w: number];Source: packages/engine-sim/src/physics/types.ts
QueryOptions
interface QueryOptions {
readonly mask?: number;
readonly exclude?: readonly BodyId[];
readonly includeSensors?: boolean;
}Source: packages/engine-sim/src/physics/types.ts
RayHit
interface RayHit {
readonly body: BodyId;
readonly point: Vec3;
readonly normal: Vec3;
readonly distance: number;
}Source: packages/engine-sim/src/physics/types.ts
RenderView
Dense, renderer-friendly arrays for the current tick, plus the previous
tick's transform for interpolation (alpha from FixedStepper). Valid
until the next step or applyState on the same world.
interface RenderView {
readonly tick: number;
readonly count: number;
readonly netId: Uint32Array;
readonly kind: Uint8Array;
readonly owner: Uint16Array;
readonly health: Uint16Array;
readonly flags: Uint8Array;
readonly x: Float32Array;
readonly y: Float32Array;
readonly z: Float32Array;
readonly yaw: Float32Array;
readonly prevX: Float32Array;
readonly prevY: Float32Array;
readonly prevZ: Float32Array;
readonly prevYaw: Float32Array;
}Source: packages/engine-sim/src/api.ts
ResolvedCharacterDesc
type ResolvedCharacterDesc = Required<Omit<CharacterDesc, "position">> & { readonly position: Vec3 };Source: packages/engine-sim/src/physics/types.ts
ResolvedContent
interface ResolvedContent {
readonly enabled: boolean;
readonly enemyTypes: readonly EnemyTypeDef[];
readonly weapons: readonly WeaponDef[];
readonly stats: readonly StatDef[];
readonly progression: ProgressionRules;
readonly coop: CoopRules;
readonly arena: ArenaRules;
readonly view: ViewRules;
readonly pickups: readonly PickupTypeDef[];
readonly loot: { readonly chest: number; readonly heal: number; readonly vacuum: number; readonly bossChest?: number };
readonly mergeGemsAbove: number;
readonly characters: readonly CharacterDef[];
}Source: packages/engine-sim/src/api.ts
ResolvedSimConfig
interface ResolvedSimConfig {
readonly tickRate: number;
readonly seed: number;
readonly maxEntities: number;
readonly arena: ArenaConfig;
readonly player: PlayerRules;
readonly enemies: EnemyRules;
readonly content: ResolvedContent;
}Source: packages/engine-sim/src/api.ts
Scaled
A weapon's numbers at a player's level, after passives.
interface Scaled {
damage: number;
cooldown: number;
count: number;
range: number;
speed: number;
pierce: number;
knockback: number;
spread: number;
}Source: packages/engine-sim/src/weapons.ts
ShapeDesc
Collision shapes. Capsules and cylinders stand along +y.
type ShapeDesc =
| { readonly box: Vec3 }
| { readonly sphere: number }
| { readonly capsule: readonly [halfHeight: number, radius: number] }
| { readonly cylinder: readonly [halfHeight: number, radius: number] };Source: packages/engine-sim/src/physics/types.ts
ShapeHit
interface ShapeHit {
readonly body: BodyId;
readonly distance: number;
readonly point: Vec3;
readonly normal: Vec3;
}Source: packages/engine-sim/src/physics/types.ts
SimConfig
interface SimConfig {
readonly tickRate?: number;
readonly seed?: number;
readonly maxEntities?: number;
readonly arena?: Partial<ArenaConfig>;
readonly player?: Partial<PlayerRules>;
readonly enemies?: Partial<EnemyRules>;
readonly content?: ContentConfig;
}Source: packages/engine-sim/src/api.ts
SimEvent
Things that happened during one step, in the order they happened.
type SimEvent =
| { readonly type: "player.joined"; readonly playerId: PlayerId; readonly netId: NetId }
| { readonly type: "player.left"; readonly playerId: PlayerId; readonly netId: NetId }
| {
readonly type: "player.hit";
readonly playerId: PlayerId;
readonly netId: NetId;
readonly by: NetId;
readonly damage: number;
readonly health: number;
readonly source?: HitSource;
readonly enemyType?: number;
}
| { readonly type: "player.died"; readonly playerId: PlayerId; readonly netId: NetId }
| { readonly type: "player.killed"; readonly playerId: PlayerId; readonly netId: NetId; readonly by: PlayerId }
| { readonly type: "player.shot"; readonly playerId: PlayerId; readonly netId: NetId; readonly slot: number }
| { readonly type: "player.respawned"; readonly playerId: PlayerId; readonly netId: NetId }
| { readonly type: "player.pulse"; readonly playerId: PlayerId; readonly netId: NetId }
| {
readonly type: "enemy.killed";
readonly netId: NetId;
readonly by: PlayerId;
readonly enemyType: number;
readonly boss: boolean;
readonly elite?: boolean;
}
| { readonly type: "player.downed"; readonly playerId: PlayerId; readonly netId: NetId }
| { readonly type: "player.revived"; readonly playerId: PlayerId; readonly netId: NetId; readonly by: PlayerId }
| { readonly type: "player.levelup"; readonly playerId: PlayerId; readonly netId: NetId; readonly level: number }
| { readonly type: "player.upgraded"; readonly playerId: PlayerId; readonly netId: NetId; readonly upgrade: number; readonly evolved?: boolean }
| { readonly type: "player.collected"; readonly playerId: PlayerId; readonly netId: NetId; readonly effect: PickupEffect }
| {
readonly type: "entity.spawned";
readonly netId: NetId;
readonly kind: EntityKindId;
readonly from?: NetId;
}
| { readonly type: "entity.removed"; readonly netId: NetId; readonly kind: EntityKindId };Source: packages/engine-sim/src/api.ts
SimState
A whole world's networked state at one tick. Entities sorted by netId.
interface SimState {
tick: number;
rng: number;
nextNetId: number;
kills: number;
entities: EntityState[];
}Source: packages/engine-sim/src/api.ts
SimWorld
A simulation world. Opaque on purpose: callers read it through the functions in this package, never through ECS or Rapier handles.
interface SimWorld {
readonly tick: number;
readonly tickRate: number;
readonly dt: number;
readonly config: ResolvedSimConfig;
}Source: packages/engine-sim/src/api.ts
SpawnScale
Per-spawn multipliers (the spawn director's difficulty curve and density compensation). Health and damage are rounded to integers on the entity.
interface SpawnScale {
readonly health?: number;
readonly damage?: number;
readonly xp?: number;
readonly elite?: boolean;
readonly from?: number;
}Source: packages/engine-sim/src/api.ts
StatDef
A passive upgrade. Per level: speed and might multiply by (1 + step x level), haste multiplies cooldowns by (1 - step x level) (floor 0.3), maxHealth and magnet add step x level, regen heals step x level per second, armor removes step x level from each contact hit (floor 1).
interface StatDef {
readonly stat: StatKind;
readonly step: number;
readonly maxLevel: number;
}Source: packages/engine-sim/src/api.ts
StatKind
type StatKind = "speed" | "maxHealth" | "magnet" | "might" | "haste" | "regen" | "armor" | "area" | "amount";Source: packages/engine-sim/src/api.ts
StepperAdvance
Result of advancing a FixedStepper by wall-clock time.
interface StepperAdvance {
readonly ticks: number;
readonly alpha: number;
readonly dropped: number;
}Source: packages/engine-sim/src/api.ts
StepResult
interface StepResult {
readonly tick: number;
readonly events: readonly SimEvent[];
}Source: packages/engine-sim/src/api.ts
TickInputs
The inputs for one tick, by player. A player with no entry this tick gets a neutral input (no move, no buttons, facing kept). A room server that wants "repeat last input on packet loss" passes the repeat explicitly.
type TickInputs = ReadonlyMap<PlayerId, InputCommand>;Source: packages/engine-sim/src/api.ts
Vec3
A 3-vector in metres, y up.
type Vec3 = readonly [x: number, y: number, z: number];Source: packages/engine-sim/src/api.ts
ViewRules
The visible ground around a player, as distances from the player to the edge of the screen at evenly spaced headings (index i is the heading 2pii/n, measured from +x toward +z). The spawn director spawns just outside it, and the playtest counts what is inside it as "on screen".
interface ViewRules {
readonly radii: readonly number[];
}Source: packages/engine-sim/src/api.ts
WallBox
An axis-aligned box standing on the floor, wallHeight tall: a dungeon's
walls. Centre (x, z) and half sizes hx, hz in metres.
interface WallBox {
readonly x: number;
readonly z: number;
readonly hx: number;
readonly hz: number;
}Source: packages/engine-sim/src/api.ts
WeaponDef
interface WeaponDef {
readonly kind: WeaponKind;
readonly damage: number;
readonly cooldownTicks: number;
readonly range: number;
readonly count: number;
readonly speed: number;
readonly pierce: number;
readonly knockback: number;
readonly maxLevel: number;
readonly spread?: number;
readonly levels?: readonly WeaponLevelStats[];
readonly blast?: number;
readonly evolved?: boolean;
readonly evolve?: { readonly into: number; readonly requires: number };
}Source: packages/engine-sim/src/api.ts
WeaponKind
Weapon behaviours (content mode). Survivor weapons fire by themselves:
nova: a burst that hits every enemy withinrange, when one is in range.bolt:countprojectiles at the nearest enemy withinrange, moving atspeedm/s, passing throughpierceenemies.orbit:countblades circling atrangem andspeedrad/s; each blade hits an enemy at most every 8 ticks. Arena weapons fire on Button.Fire along the player's aim (yaw):blaster:countprojectiles fanned overspreadradians atspeedm/s forrangem.beam: an instant hitscan torangem (stopped by pillars and walls); a room server resolves it with lag compensation.nova(arena): a blast hitting every opponent withinrangem.
type WeaponKind = "nova" | "bolt" | "orbit" | "blaster" | "beam" | "cone" | "chain" | "aura" | "meteor" | "boomerang";Source: packages/engine-sim/src/api.ts
WeaponLevelStats
A weapon's numbers at one level (absolute, before passives).
interface WeaponLevelStats {
readonly damage: number;
readonly cooldownTicks: number;
readonly range: number;
readonly count: number;
readonly speed: number;
readonly pierce: number;
readonly knockback: number;
readonly spread: number;
}Source: packages/engine-sim/src/api.ts
XpShare
How a gem's XP is shared in co-op.
interface XpShare {
readonly mode: "collector" | "nearby" | "all";
readonly fraction: number;
readonly radius: number;
}Source: packages/engine-sim/src/api.ts