# @netforge/engine-sim API reference

> Every export of @netforge/engine-sim, generated from its TypeScript source: 259 functions, classes, constants and types with their signatures and doc comments.

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

Source: https://forge.netnet.capital/docs/reference/engine-sim  
Last updated: 2026-10-23. Checked against @netforge/engine 0.2.0.

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.

```ts
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

```ts check=skip
function addKart(w: KartWorld, id: number, opts?: { bot?: boolean; frozen?: boolean; slot?: number; }): Kart;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### addPlatformPlayer

```ts check=skip
function addPlatformPlayer(w: PlatformWorld, id: number, opts?: { bot?: boolean; frozen?: boolean; }): PlatformPlayer;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### addPlayer

Spawn a player's character. Throws if the id is already present.

```ts check=skip
function addPlayer(world: SimWorld, playerId: PlayerId, spawn?: Vec3): NetId;
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/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`.

```ts check=skip
function applyBeamHit(world: SimWorld, shot: BeamShot, target: NetId): void;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### applyKart

```ts check=skip
function applyKart(w: KartWorld, s: KartWire): Kart;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### applyPlatformPlayer

Overwrite (or create) a player from wire state, and take the world tick from it.

```ts check=skip
function applyPlatformPlayer(w: PlatformWorld, s: PlatformPlayerWire): PlatformPlayer;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
function applyState(world: SimWorld, state: SimState): void;
```

Source: [packages/engine-sim/src/snapshot.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/snapshot.ts)

### arenaHitboxes

Living players' and enemies' hitboxes this tick (the room's rewind buffer records them).

```ts check=skip
function arenaHitboxes(world: SimWorld): ArenaHitbox[];
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### arenaSpawn

Where a player joining or respawning now would stand: the spawn point farthest from opponents.

```ts check=skip
function arenaSpawn(world: SimWorld, playerId: PlayerId): [number, number];
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function beamRange(config: ResolvedSimConfig, x: number, z: number, dx: number, dz: number, range: number): number;
```

Source: [packages/engine-sim/src/arena.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function beamShot(world: SimWorld, playerId: PlayerId, cmd: InputCommand): BeamShot | null;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### buildKartTrack

Sample a closed Catmull-Rom centreline every ~2 m. Pure arithmetic, identical on every side.

```ts check=skip
function buildKartTrack(def: KartTrackDef): KartTrack;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### captureKart

```ts check=skip
function captureKart(w: KartWorld, k: Kart): KartWire;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### capturePlatformPlayer

```ts check=skip
function capturePlatformPlayer(w: PlatformWorld, p: PlatformPlayer): PlatformPlayerWire;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### captureState

Read the world's networked state. `include` filters entities (interest management).

```ts check=skip
function captureState(world: SimWorld, include?: (e: EntityState) => boolean): SimState;
```

Source: [packages/engine-sim/src/snapshot.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/snapshot.ts)

### collisionGroups

Rapier interaction groups: membership in the high 16 bits, filter in the low 16.

```ts check=skip
function collisionGroups(layer: number, mask: number): number;
```

Source: [packages/engine-sim/src/physics/layers.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/layers.ts)

### createKartWorld

```ts check=skip
function createKartWorld(cfg: KartConfig): KartWorld;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### createPhysics

Build a physics world. Requires `await initSim()` first (it loads the Rapier WebAssembly).

```ts check=skip
function createPhysics(opts?: PhysicsOptions): PhysicsWorld;
```

Source: [packages/engine-sim/src/physics/world.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/world.ts)

### createPlatformWorld

```ts check=skip
function createPlatformWorld(cfg: PlatformConfig): PlatformWorld;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### createWorld

Create a world: static arena colliders, empty of entities, tick 0. Requires `initSim()`.

```ts check=skip
function createWorld(config?: SimConfig): SimWorld;
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function critRoll(tick: number, netId: number): number;
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/content.ts)

### decodeChoices

The three offered upgrade indices (-1 for none) and the pending level-ups.

```ts check=skip
function decodeChoices(choices: number): { offers: [number, number, number]; pending: number; };
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/content.ts)

### decodeInput

```ts check=skip
function decodeInput(bytes: Uint8Array, offset?: number): InputCommand;
```

Source: [packages/engine-sim/src/input.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/input.ts)

### decodeInputs

```ts check=skip
function decodeInputs(bytes: Uint8Array): InputCommand[];
```

Source: [packages/engine-sim/src/input.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/input.ts)

### decodeSnapshot

```ts check=skip
function decodeSnapshot(bytes: Uint8Array, baseline?: SimState): SimState;
```

Source: [packages/engine-sim/src/snapshot.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/snapshot.ts)

### decodeTelegraph

Decode a telegraph word (clients and bots).

```ts check=skip
function decodeTelegraph(word: number): { kind: number; progress: number; angle: number; radius: number; };
```

Source: [packages/engine-sim/src/roles.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/roles.ts)

### destroyWorld

Free the world's physics memory. The world is unusable afterwards.

```ts check=skip
function destroyWorld(world: SimWorld): void;
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function edgeSpawnPoint(world: SimWorld, playerId: PlayerId | undefined, opts?: EdgeSpawnOptions): [number, number] | null;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
function encodeInput(cmd: InputCommand, out?: Uint8Array, offset?: number): Uint8Array;
```

Source: [packages/engine-sim/src/input.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/input.ts)

### encodeInputs

Count byte (u8, max 255) followed by that many 15-byte commands.

```ts check=skip
function encodeInputs(cmds: readonly InputCommand[]): Uint8Array;
```

Source: [packages/engine-sim/src/input.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/input.ts)

### encodeSnapshot

Binary snapshot. With `baseline`, a delta against it (the receiver must hold the same baseline).

```ts check=skip
function encodeSnapshot(state: SimState, baseline?: SimState): Uint8Array;
```

Source: [packages/engine-sim/src/snapshot.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/snapshot.ts)

### enemyCount

Living (non-corpse) enemies, of one type or all.

```ts check=skip
function enemyCount(world: SimWorld, type?: number): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### enemyMaxHealth

An enemy's max health as spawned (scaled), by NetId; undefined when gone or not an enemy.

```ts check=skip
function enemyMaxHealth(world: SimWorld, netId: NetId): number | undefined;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### enemyTypeOf

An enemy's type index by NetId, or -1 when it is gone or not an enemy.

```ts check=skip
function enemyTypeOf(world: SimWorld, netId: NetId): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### entityHeadroom

Room left under `maxEntities` (spawners should stop before 0).

```ts check=skip
function entityHeadroom(world: SimWorld): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### entityHealth

An entity's health by NetId, or undefined when it is gone.

```ts check=skip
function entityHealth(world: SimWorld, netId: NetId): number | undefined;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### entityPosition

An entity's ground position by NetId, or undefined when it is gone.

```ts check=skip
function entityPosition(world: SimWorld, netId: NetId): [number, number] | undefined;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### grantKartStat

```ts check=skip
function grantKartStat(w: KartWorld, id: number, stat: KartStat): boolean;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function grantLevels(world: SimWorld, playerId: PlayerId, levels: number): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### grantPlatformStat

Add one level of a stat (store upgrades and gear). Returns false at the 4-bit cap.

```ts check=skip
function grantPlatformStat(w: PlatformWorld, id: number, stat: PlatStat): boolean;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function grantUpgrade(world: SimWorld, playerId: PlayerId, index: number): boolean;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function grantXp(world: SimWorld, playerId: PlayerId, amount: number): boolean;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### initSim

Load the Rapier WebAssembly. Call once per process before `createWorld`. Idempotent.

```ts check=skip
function initSim(): Promise<void>;
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/world.ts)

### inWall

True when a circle at (x, z) of radius r overlaps any wall.

```ts check=skip
function inWall(walls: readonly WallBox[], x: number, z: number, r: number): boolean;
```

Source: [packages/engine-sim/src/walls.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/walls.ts)

### isOnScreen

True when (x, z) is on the screen of any player who is up.

```ts check=skip
function isOnScreen(world: SimWorld, x: number, z: number): boolean;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### kartCoinCount

```ts check=skip
function kartCoinCount(k: { coinsLo: number; coinsHi: number; }): number;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### kartCoinTaken

```ts check=skip
function kartCoinTaken(k: { coinsLo: number; coinsHi: number; }, i: number): boolean;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### kartProgress

Race progress in laps (lap + this lap's fraction), for standings.

```ts check=skip
function kartProgress(w: KartWorld, k: Kart): number;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### kartStatLevel

```ts check=skip
function kartStatLevel(k: { stats: number; }, stat: KartStat): number;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### kartStep

One fixed tick.

```ts check=skip
function kartStep(w: KartWorld, inputs: ReadonlyMap<number, InputCommand>): KartEvent[];
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### keeperButtons

Input bits that choose keeper `index` (0..14).

```ts check=skip
function keeperButtons(index: number): number;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function lastProcessedSeq(world: SimWorld, playerId: PlayerId): number;
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/world.ts)

### lateralOffset

Signed sideways offset from the centreline at sample `seg` (positive to the right of travel).

```ts check=skip
function lateralOffset(t: KartTrack, seg: number, x: number, z: number): number;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### layerMask

A mask from layer names or bits: `layerMask("Level", "Enemy")`.

```ts check=skip
function layerMask(...layers: readonly (LayerName | number)[]): number;
```

Source: [packages/engine-sim/src/physics/layers.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/layers.ts)

### layersCollide

True when two bodies with these layers and masks collide (Rapier's pairwise rule).

```ts check=skip
function layersCollide(layerA: number, maskA: number, layerB: number, maskB: number): boolean;
```

Source: [packages/engine-sim/src/physics/layers.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/layers.ts)

### listPickups

Pickups on the floor: position (m) and value (XP, or heal in the arena).

```ts check=skip
function listPickups(world: SimWorld): { x: number; z: number; value: number; }[];
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### listPlayers

Every player, in playerId order.

```ts check=skip
function listPlayers(world: SimWorld): PlayerSummary[];
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### maxHealthFor

Max health for a packed `stats` field (clients draw health bars with it).

```ts check=skip
function maxHealthFor(config: ResolvedSimConfig, stats: number): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### metaBonusOf

A player's meta bonus as the sim applies it (zeros when none).

```ts check=skip
function metaBonusOf(world: SimWorld, playerId: PlayerId): MetaBonus;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### moverBox

A moving platform's box at a tick: a smooth there-and-back swing.

```ts check=skip
function moverBox(m: PlatformMover, tick: number): PlatBox;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### nearestSample

Nearest centreline sample to (x, z), searching around `from` (or everywhere).

```ts check=skip
function nearestSample(t: KartTrack, x: number, z: number, from?: number, reach?: number): number;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
function onFloor(floors: readonly WallBox[], x: number, z: number, r: number): boolean;
```

Source: [packages/engine-sim/src/walls.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function orbitAngle(tick: number, tickRate: number, speed: number, i: number, n: number): number;
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/content.ts)

### pendingCards

Cards a player has waiting (level-ups not yet picked).

```ts check=skip
function pendingCards(world: SimWorld, playerId: PlayerId): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### platBox

Normalize a box so x0 < x1 and y0 < y1.

```ts check=skip
function platBox(x0: number, y0: number, x1: number, y1: number): PlatBox;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### platformCoinCount

```ts check=skip
function platformCoinCount(p: { coinsLo: number; coinsHi: number; }): number;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### platformCoinTaken

```ts check=skip
function platformCoinTaken(p: { coinsLo: number; coinsHi: number; }, i: number): boolean;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### platformProgress

How far along the course a player is, 0..1 (by x from start to flag).

```ts check=skip
function platformProgress(w: PlatformWorld, p: { x: number; flags: number; }): number;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### platformRespawnPoint

Where a fall puts you back: the furthest checkpoint touched, or the start.

```ts check=skip
function platformRespawnPoint(w: PlatformWorld, cp: number): readonly [number, number];
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### platformStep

One fixed tick. Inputs by player id; a player with none gets a neutral input.

```ts check=skip
function platformStep(w: PlatformWorld, inputs: ReadonlyMap<number, InputCommand>): PlatformEvent[];
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### platStatLevel

A stat's level (0..15) from the packed word.

```ts check=skip
function platStatLevel(p: { stats: number; }, stat: PlatStat): number;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### playerBuild

```ts check=skip
function playerBuild(world: SimWorld, playerId: PlayerId): PlayerBuild | null;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### playerNetId

The NetId of a player's character, if present.

```ts check=skip
function playerNetId(world: SimWorld, playerId: PlayerId): NetId | undefined;
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/walls.ts)

### quantizeInput

Snap a command onto the wire grid. The sim applies this to every input it consumes.

```ts check=skip
function quantizeInput(cmd: InputCommand): InputCommand;
```

Source: [packages/engine-sim/src/input.ts](https://github.com/netnetdev/net-forge/blob/main/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`.

```ts check=skip
function recycleEnemies(world: SimWorld, periodTicks: number, afterTicks: number, margin: number): { moved: number; removed: number; };
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### removeEnemies

Remove every living enemy of a type at once, with no kills or drops. Returns how many.

```ts check=skip
function removeEnemies(world: SimWorld, type: number): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### removeKart

```ts check=skip
function removeKart(w: KartWorld, id: number): boolean;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### removePlatformPlayer

```ts check=skip
function removePlatformPlayer(w: PlatformWorld, id: number): boolean;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### removePlayer

Remove a player's character. No-op if absent.

```ts check=skip
function removePlayer(world: SimWorld, playerId: PlayerId): void;
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/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`.

```ts check=skip
function renderView(world: SimWorld): RenderView;
```

Source: [packages/engine-sim/src/render.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/render.ts)

### resetKart

Back to the grid for a fresh race (stats kept; the runner clears them).

```ts check=skip
function resetKart(w: KartWorld, k: Kart, frozen: boolean): void;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
function resetPlatformPlayer(w: PlatformWorld, p: PlatformPlayer, frozen: boolean): void;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function resetRun(world: SimWorld): void;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### resolveCharacter

Fill a character description with defaults and validate it.

```ts check=skip
function resolveCharacter(d: CharacterDesc): ResolvedCharacterDesc;
```

Source: [packages/engine-sim/src/physics/character.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/character.ts)

### resolveConfig

```ts check=skip
function resolveConfig(config?: SimConfig): ResolvedSimConfig;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### respawnDead

Bring dead (out) players back beside a living teammate. Returns who came back.

```ts check=skip
function respawnDead(world: SimWorld): PlayerId[];
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### restorePhysics

Rebuild a world from `snapshot()` bytes. Stepping it gives exactly what the original would have.

```ts check=skip
function restorePhysics(bytes: Uint8Array): PhysicsWorld;
```

Source: [packages/engine-sim/src/physics/world.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function revivePlayer(world: SimWorld, playerId: PlayerId): boolean;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function ringSpawnPoint(world: SimWorld, cx: number, cz: number, radius: number, enemyRadius?: number): [number, number] | null;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### scaledWeapon

A weapon at a level with a player's passives applied.

```ts check=skip
function scaledWeapon(def: WeaponDef, level: number, mods: WeaponMods): Scaled;
```

Source: [packages/engine-sim/src/weapons.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/weapons.ts)

### scatterEnemies

Scatter `count` enemies of a type (props) over the field, off every screen. Returns how many.

```ts check=skip
function scatterEnemies(world: SimWorld, type: number, count: number): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function segmentWalls(walls: readonly WallBox[], x0: number, z0: number, dx: number, dz: number, r: number): number;
```

Source: [packages/engine-sim/src/walls.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/walls.ts)

### selectedSlot

The selected weapon slot (0..3) in a player's packed `choices` field (arena mode).

```ts check=skip
function selectedSlot(choices: number): number;
```

Source: [packages/engine-sim/src/arena.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/arena.ts)

### setCosmetic

Set a player's cosmetic id (drawn by clients; no gameplay effect).

```ts check=skip
function setCosmetic(world: SimWorld, playerId: PlayerId, cosmetic: number): void;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### setEnemySpeed

Authority: multiply every non-boss enemy's steering speed by `k` (0.25..3) from now on.

```ts check=skip
function setEnemySpeed(world: SimWorld, k: number): void;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### setKartsFrozen

```ts check=skip
function setKartsFrozen(w: KartWorld, frozen: boolean): void;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### setKartTrack

```ts check=skip
function setKartTrack(w: KartWorld, index: number): void;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function setMetaBonus(world: SimWorld, playerId: PlayerId, bonus: Partial<MetaBonus>): void;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### setPlatformFrozen

The countdown: hold (or release) every player.

```ts check=skip
function setPlatformFrozen(w: PlatformWorld, frozen: boolean): void;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### setPlatformLevel

Switch the course (a new round). Players keep their state; reset them after.

```ts check=skip
function setPlatformLevel(w: PlatformWorld, index: number): void;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function setXpBoost(world: SimWorld, multiplier: number): void;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### simPaused

True while the sim is paused for a solo player's upgrade cards.

```ts check=skip
function simPaused(world: SimWorld): boolean;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### simRandom

The world's seeded PRNG, 0..1 (server-side game logic).

```ts check=skip
function simRandom(world: SimWorld): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### slotLevel

```ts check=skip
function slotLevel(weapons: number, slot: number): number;
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/content.ts)

### slotWeapon

Weapon index in a slot, or -1 when empty.

```ts check=skip
function slotWeapon(weapons: number, slot: number): number;
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/content.ts)

### snapshotBaseTick

The baseline tick a delta snapshot needs, or null for a full snapshot.

```ts check=skip
function snapshotBaseTick(bytes: Uint8Array): number | null;
```

Source: [packages/engine-sim/src/snapshot.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/snapshot.ts)

### spawnEnemy

Spawn an enemy of `type` (index into `content.enemyTypes`) at (x, z). Returns its NetId.

```ts check=skip
function spawnEnemy(world: SimWorld, type: number, x: number, z: number): NetId;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### spawnEnemyScaled

```ts check=skip
function spawnEnemyScaled(world: SimWorld, type: number, x: number, z: number, scale: SpawnScale): NetId;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function spawnPickupAt(world: SimWorld, index: number, x: number, z: number): NetId;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function spawnRingPoint(world: SimWorld, radius: number): [number, number];
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### statLevel

```ts check=skip
function statLevel(stats: number, i: number): number;
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function step(world: SimWorld, inputs: TickInputs): StepResult;
```

Source: [packages/engine-sim/src/step.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/step.ts)

### teleWord

Telegraph word: kind, progress 0..1, and an angle (lanes) or a radius in metres (circles).

```ts check=skip
function teleWord(kind: number, progress: number, angleOrRadius: number, isRadius?: boolean): number;
```

Source: [packages/engine-sim/src/roles.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
function viewEdge(world: SimWorld, heading: number): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
function weaponModsFor(config: ResolvedSimConfig, stats: number): { might: number; haste: number; area: number; amount: number; };
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### xpForLevel

XP needed to go from `level` to `level + 1`.

```ts check=skip
function xpForLevel(config: ResolvedSimConfig, level: number): number;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/stepper.ts)

### PhysicsWorld

```ts check=skip
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 source
```

Source: [packages/engine-sim/src/physics/world.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/world.ts)

## Constants

### ALL_LAYERS

Every layer (the default mask).

```ts check=skip
const ALL_LAYERS: 65535;
```

Source: [packages/engine-sim/src/physics/layers.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/layers.ts)

### ARENA_BOLT_RADIUS

Projectile hit radius, m, and the height projectiles fly at.

```ts check=skip
const ARENA_BOLT_RADIUS: 0.2;
```

Source: [packages/engine-sim/src/arena.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
const ARENA_HITBOX_PAD: 0.2;
```

Source: [packages/engine-sim/src/arena.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
const ARENA_SPAWN_CLEAR: 12;
```

Source: [packages/engine-sim/src/arena.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
const BOT_PLAYER_BASE: 65280;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### Button

Input button bits. Games may use bits 8..15 for their own actions.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### DEFAULT_ARENA

```ts check=skip
const DEFAULT_ARENA: ArenaConfig;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### DEFAULT_ARENA_RULES

```ts check=skip
const DEFAULT_ARENA_RULES: ArenaRules;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### DEFAULT_COOP

```ts check=skip
const DEFAULT_COOP: CoopRules;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### DEFAULT_ENEMIES

```ts check=skip
const DEFAULT_ENEMIES: EnemyRules;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### DEFAULT_KART_TUNING

```ts check=skip
const DEFAULT_KART_TUNING: KartTuning;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### DEFAULT_PLATFORM_TUNING

```ts check=skip
const DEFAULT_PLATFORM_TUNING: PlatformTuning;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### DEFAULT_PLAYER

```ts check=skip
const DEFAULT_PLAYER: PlayerRules;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### DEFAULT_PROGRESSION

```ts check=skip
const DEFAULT_PROGRESSION: ProgressionRules;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### DEFAULT_TICK_RATE

Default fixed tick rate in Hz (spec: 30 Hz default, 60 for shooters).

```ts check=skip
const DEFAULT_TICK_RATE: 30;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### DEFAULT_VIEW

Default view: a 22 m circle (games compile their camera's real footprint into this).

```ts check=skip
const DEFAULT_VIEW: ViewRules;
```

Source: [packages/engine-sim/src/config.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/config.ts)

### EntityFlag

Per-entity state flag bits (EntityState.flags).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### EntityKind

Entity kinds carried in snapshots.

```ts check=skip
const EntityKind: { readonly Player: 1; readonly Enemy: 2; readonly Projectile: 3; readonly Pickup: 4; };
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### INPUT_BYTES

Bytes per encoded InputCommand.

```ts check=skip
const INPUT_BYTES: 15;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### KART_COIN_CAP

Coins held that raise top speed, and how much each adds.

```ts check=skip
const KART_COIN_CAP: 10;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KART_COIN_SPEED

```ts check=skip
const KART_COIN_SPEED: 0.01;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KART_MAX_COINS

```ts check=skip
const KART_MAX_COINS: 62;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KART_RADIUS

Kart body radius for bumps, m.

```ts check=skip
const KART_RADIUS: 0.9;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KART_STAT_DOC

```ts check=skip
const KART_STAT_DOC: Readonly<Record<"magnet" | "speed" | "armor" | "might" | "haste", string>>;
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KART_STATS

Upgrade stats a kart can carry (4 bits each in `stats`).

```ts check=skip
const KART_STATS: readonly ["speed", "haste", "might", "armor", "magnet"];
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartFlag

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KEEPER_MASK

```ts check=skip
const KEEPER_MASK: number;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
const KEEPER_SHIFT: 11;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
const META_MAX_PER_STAT: 0.15;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### META_MAX_TOTAL

```ts check=skip
const META_MAX_TOTAL: 0.3;
```

Source: [packages/engine-sim/src/control.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### METEOR_FALL_SECONDS

Seconds a meteor's circle shows before it lands.

```ts check=skip
const METEOR_FALL_SECONDS: 0.6;
```

Source: [packages/engine-sim/src/weapons.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/weapons.ts)

### ORBIT_BLADE_RADIUS

Orbit blade hit radius, m.

```ts check=skip
const ORBIT_BLADE_RADIUS: 0.45;
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/content.ts)

### ORBIT_HIT_EVERY

Ticks between hits from one orbit blade on one enemy.

```ts check=skip
const ORBIT_HIT_EVERY: 8;
```

Source: [packages/engine-sim/src/content.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/content.ts)

### PICKUP_SPECIAL

Pickup entity types from here up are special pickups (index = type - PICKUP_SPECIAL).

```ts check=skip
const PICKUP_SPECIAL: 16;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### PLAT_HALF_W

Half width and height of the body box (feet at y).

```ts check=skip
const PLAT_HALF_W: 0.34;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PLAT_HEIGHT

```ts check=skip
const PLAT_HEIGHT: 1.4;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PLAT_MAX_COINS

Most coins a level holds (two u31 masks).

```ts check=skip
const PLAT_MAX_COINS: 62;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PLAT_STAT_DOC

What one level of each stat does (the declared upgrade's step scales it).

```ts check=skip
const PLAT_STAT_DOC: Readonly<Record<"magnet" | "speed" | "amount" | "maxHealth" | "haste", string>>;
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PLAT_STATS

Upgrade stats a platformer player can carry (4 bits each in `stats`).

```ts check=skip
const PLAT_STATS: readonly ["speed", "amount", "magnet", "maxHealth", "haste"];
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatFlag

Player flags (u16 on the wire).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### POSITION_SCALE

Fixed-point units per metre for positions in state and snapshots.

```ts check=skip
const POSITION_SCALE: 1024;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### ROLE_DEFAULTS

Defaults per role (seconds and metres are converted at use).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/roles.ts)

### SNAPSHOT_VERSION

Snapshot wire format version (first byte after the magic).

```ts check=skip
const SNAPSHOT_VERSION: 2;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
const Telegraph: { readonly None: 0; readonly Circle: 1; readonly Lane: 2; readonly Aura: 3; };
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### VELOCITY_SCALE

Fixed-point units per metre/second for velocities.

```ts check=skip
const VELOCITY_SCALE: 1024;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### YAW_UNITS

Yaw is a u16 turn: 65536 units per full revolution.

```ts check=skip
const YAW_UNITS: 65536;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

## Types

### ArenaConfig

The static level. Part of the world's config, never of a snapshot.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### ArenaHitbox

What the rewind buffer records each tick: living players and enemies.

```ts check=skip
interface ArenaHitbox {
  readonly netId: NetId;
  readonly owner: PlayerId;
  readonly x: number;
  readonly z: number;
  readonly r: number;
}
```

Source: [packages/engine-sim/src/arena.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### BeamShot

A human's beam this tick, for the room's rewind.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/arena.ts)

### BodyDesc

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### BodyId

A stable id for one body in a PhysicsWorld (u32, assigned in creation order, never reused).

```ts check=skip
type BodyId = number;
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### BodyType

```ts check=skip
type BodyType = "dynamic" | "kinematic" | "static";
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### BossAttack

What a boss can do. Each is telegraphed before it lands.

```ts check=skip
type BossAttack = "slam" | "dash" | "leap" | "rain" | "ring" | "fan" | "summon";
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### BossPattern

```ts check=skip
interface BossPattern {
  readonly attacks: readonly BossAttack[];
  readonly enrageAt: number;
  readonly summon?: number;
  readonly mini?: boolean;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### ButtonBit

```ts check=skip
type ButtonBit = (typeof Button)[keyof typeof Button];
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
interface CharacterDef {
  readonly weapon: number;
  readonly stat: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### CharacterDesc

A kinematic character (capsule on Rapier's character controller). All fields optional except where noted.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
interface CharacterInput {
  readonly moveX: number;
  readonly moveZ: number;
  readonly jump?: boolean;
  readonly dash?: boolean;
}
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### CharacterReport

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### CharacterState

A character's whole motor state: plain numbers, serialized in snapshots.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### CoopRules

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### EdgeSpawnOptions

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### EnemyAi

Enemy behaviours the sim runs (content mode).

```ts check=skip
type EnemyAi =
  | "chase"
  | "idle"
  | "runner"
  | "charger"
  | "ranged"
  | "bomber"
  | "shielder"
  | "healer"
  | "summoner"
  | "flee"
  | "wander";
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### EnemyRules

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### EntityKindId

```ts check=skip
type EntityKindId = (typeof EntityKind)[keyof typeof EntityKind];
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### HitSource

What dealt a hit to a player. Everything but "contact" was telegraphed first.

```ts check=skip
type HitSource = "contact" | "charge" | "blast" | "projectile" | "slam" | "hazard";
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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`).

```ts check=skip
interface InputCommand {
  seq: number;
  tick: number;
  moveX: number;
  moveZ: number;
  yaw: number;
  buttons: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### JointDesc

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### JointId

A stable id for one joint.

```ts check=skip
type JointId = number;
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### JointKind

```ts check=skip
type JointKind = "fixed" | "ball" | "hinge" | "slider";
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### Kart

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartConfig

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartEvent

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartStat

```ts check=skip
type KartStat = (typeof KART_STATS)[number];
```

Source: [packages/engine-sim/src/kart.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartTrack

A track, sampled.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartTrackDef

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartTuning

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartWire

Integer wire state of one kart.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KartWorld

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/kart.ts)

### KnockbackOptions

```ts check=skip
interface KnockbackOptions {
  readonly lift?: number;
  readonly byMass?: boolean;
}
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### LayerBit

One bit of `Layer`.

```ts check=skip
type LayerBit = (typeof Layer)[LayerName];
```

Source: [packages/engine-sim/src/physics/layers.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/layers.ts)

### LayerName

```ts check=skip
type LayerName = keyof typeof Layer;
```

Source: [packages/engine-sim/src/physics/layers.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
interface MetaBonus {
  speed: number;
  maxHealth: number;
  magnet: number;
  might: number;
  haste: number;
  area: number;
}
```

Source: [packages/engine-sim/src/world.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
type NetId = number;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
interface PhysicsEvent {
  readonly type: PhysicsEventType;
  readonly a: BodyId;
  readonly b: BodyId;
}
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### PhysicsEventType

```ts check=skip
type PhysicsEventType = "contact.start" | "contact.end" | "trigger.enter" | "trigger.exit";
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### PhysicsOptions

```ts check=skip
interface PhysicsOptions {
  readonly gravity?: Vec3;
  readonly tickRate?: number;
}
```

Source: [packages/engine-sim/src/physics/world.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/world.ts)

### PhysicsStepResult

```ts check=skip
interface PhysicsStepResult {
  readonly tick: number;
  readonly events: readonly PhysicsEvent[];
  readonly characters: readonly CharacterReport[];
}
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### PickupEffect

What a special pickup does when a player collects it.

```ts check=skip
type PickupEffect = "heal" | "vacuum" | "bomb" | "chest";
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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: `amount` of 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: `amount` card picks (1-3; a ready evolution shows first).

```ts check=skip
interface PickupTypeDef {
  readonly effect: PickupEffect;
  readonly amount: number;
  readonly evolve?: boolean;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### Pillar

A cylindrical pillar in the arena (static collider).

```ts check=skip
interface Pillar {
  readonly x: number;
  readonly z: number;
  readonly radius: number;
  readonly height: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### PlatBox

An axis-aligned box: [x0, y0, x1, y1] in metres, x0 < x1, y0 < y1.

```ts check=skip
type PlatBox = readonly [number, number, number, number];
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformConfig

```ts check=skip
interface PlatformConfig {
  readonly tickRate: number;
  readonly levels: readonly PlatformLevel[];
  readonly tuning?: Partial<PlatformTuning>;
  readonly statSteps?: readonly number[];
}
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformEvent

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformLevel

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformMover

```ts check=skip
interface PlatformMover {
  readonly box: PlatBox;
  readonly dx: number;
  readonly dy: number;
  readonly periodTicks: number;
  readonly phaseTicks: number;
}
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformPlayer

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformPlayerWire

Integer wire state of one player (positions and speeds in 1/1024).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformSpring

```ts check=skip
interface PlatformSpring {
  readonly x: number;
  readonly y: number;
  readonly power: number;
}
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformTuning

Motor numbers. Seconds become ticks at world creation.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatformWorld

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlatStat

```ts check=skip
type PlatStat = (typeof PLAT_STATS)[number];
```

Source: [packages/engine-sim/src/platform.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/platform.ts)

### PlayerBuild

One player's build this run: weapons (with levels), passives, keeper, and damage per weapon index.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/control.ts)

### PlayerId

A player slot in a room, 1..65535. 0 means "no player".

```ts check=skip
type PlayerId = number;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### PlayerRules

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### PlayerSummary

One player as game logic sees it (`listPlayers`).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### ProgressionRules

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### Quat

Quaternion [x, y, z, w].

```ts check=skip
type Quat = readonly [x: number, y: number, z: number, w: number];
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### QueryOptions

```ts check=skip
interface QueryOptions {
  readonly mask?: number;
  readonly exclude?: readonly BodyId[];
  readonly includeSensors?: boolean;
}
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### RayHit

```ts check=skip
interface RayHit {
  readonly body: BodyId;
  readonly point: Vec3;
  readonly normal: Vec3;
  readonly distance: number;
}
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### ResolvedCharacterDesc

```ts check=skip
type ResolvedCharacterDesc = Required<Omit<CharacterDesc, "position">> & { readonly position: Vec3 };
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### ResolvedContent

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### ResolvedSimConfig

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### Scaled

A weapon's numbers at a player's level, after passives.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/weapons.ts)

### ShapeDesc

Collision shapes. Capsules and cylinders stand along +y.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### ShapeHit

```ts check=skip
interface ShapeHit {
  readonly body: BodyId;
  readonly distance: number;
  readonly point: Vec3;
  readonly normal: Vec3;
}
```

Source: [packages/engine-sim/src/physics/types.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/physics/types.ts)

### SimConfig

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### SimEvent

Things that happened during one step, in the order they happened.

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### SimState

A whole world's networked state at one tick. Entities sorted by netId.

```ts check=skip
interface SimState {
  tick: number;
  rng: number;
  nextNetId: number;
  kills: number;
  entities: EntityState[];
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
interface SimWorld {
  readonly tick: number;
  readonly tickRate: number;
  readonly dt: number;
  readonly config: ResolvedSimConfig;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
interface SpawnScale {
  readonly health?: number;
  readonly damage?: number;
  readonly xp?: number;
  readonly elite?: boolean;
  readonly from?: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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).

```ts check=skip
interface StatDef {
  readonly stat: StatKind;
  readonly step: number;
  readonly maxLevel: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### StatKind

```ts check=skip
type StatKind = "speed" | "maxHealth" | "magnet" | "might" | "haste" | "regen" | "armor" | "area" | "amount";
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### StepperAdvance

Result of advancing a `FixedStepper` by wall-clock time.

```ts check=skip
interface StepperAdvance {
  readonly ticks: number;
  readonly alpha: number;
  readonly dropped: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### StepResult

```ts check=skip
interface StepResult {
  readonly tick: number;
  readonly events: readonly SimEvent[];
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
type TickInputs = ReadonlyMap<PlayerId, InputCommand>;
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### Vec3

A 3-vector in metres, y up.

```ts check=skip
type Vec3 = readonly [x: number, y: number, z: number];
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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
2*pi*i/n, measured from +x toward +z). The spawn director spawns just
outside it, and the playtest counts what is inside it as "on screen".

```ts check=skip
interface ViewRules {
  readonly radii: readonly number[];
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/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.

```ts check=skip
interface WallBox {
  readonly x: number;
  readonly z: number;
  readonly hx: number;
  readonly hz: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### WeaponDef

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### WeaponKind

Weapon behaviours (content mode). Survivor weapons fire by themselves:
 - `nova`: a burst that hits every enemy within `range`, when one is in range.
 - `bolt`: `count` projectiles at the nearest enemy within `range`, moving at `speed` m/s, passing through `pierce` enemies.
 - `orbit`: `count` blades circling at `range` m and `speed` rad/s; each blade hits an enemy at most every 8 ticks.
Arena weapons fire on Button.Fire along the player's aim (yaw):
 - `blaster`: `count` projectiles fanned over `spread` radians at `speed` m/s for `range` m.
 - `beam`: an instant hitscan to `range` m (stopped by pillars and walls); a room server resolves it with lag compensation.
 - `nova` (arena): a blast hitting every opponent within `range` m.

```ts check=skip
type WeaponKind = "nova" | "bolt" | "orbit" | "blaster" | "beam" | "cone" | "chain" | "aura" | "meteor" | "boomerang";
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### WeaponLevelStats

A weapon's numbers at one level (absolute, before passives).

```ts check=skip
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](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)

### XpShare

How a gem's XP is shared in co-op.

```ts check=skip
interface XpShare {
  readonly mode: "collector" | "nearby" | "all";
  readonly fraction: number;
  readonly radius: number;
}
```

Source: [packages/engine-sim/src/api.ts](https://github.com/netnetdev/net-forge/blob/main/packages/engine-sim/src/api.ts)
