# @netforge/engine/game API reference

> Every export of @netforge/engine/game, generated from its TypeScript source: 106 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-game  
Last updated: 2026-10-23. Checked against @netforge/engine 0.2.0.

Runs a declared game on the shared simulation: `compileGame` (manifest to sim content), `GameRunner`, `EarnTracker`, the engine-sim adapter and the playtest bots. Template code uses it; game code does not.

```ts
import { compileGame } from "@netforge/engine/game";
```

Generated from `packages/engine/src/game/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 | 43 |
| Classes | 7 |
| Constants | 15 |
| Types | 41 |

## Functions

### arenaBotInput

One tick of an arena bot: pick the nearest opponent it can see (sticky
for a while), keep a weapon-appropriate distance while strafing, go for a
heal cell when hurt, switch to the right weapon for the range, and fire
when the shot is clear. Aim carries a per-bot error, so bots are beatable.
`tickRate` scales its timers.

```ts check=skip
function arenaBotInput(v: ArenaBotView, mem: ArenaBotMemory, tick: number, tickRate?: number): InputCommand;
```

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

### arenaBotMemory

```ts check=skip
function arenaBotMemory(): ArenaBotMemory;
```

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

### botDelaySeconds

Seconds a bot of this skill waits after the start signal before running its route (quarter seconds).

```ts check=skip
function botDelaySeconds(id: number, skill: number): number;
```

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

### botInput

One tick of input. `enemies` are nearby enemy positions [x, z]; `id` varies the bot's path.

```ts check=skip
function botInput(me: BotView, enemies: Iterable<readonly [number, number]>, tick: number, id: number): InputCommand;
```

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

### collectManifest

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

```ts check=skip
function collectManifest(): GameManifest;
```

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

### compileGame

```ts check=skip
function compileGame(m: GameManifest, opts?: { maxEntities?: number; views?: readonly CameraView[]; }): CompiledGame;
```

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

### compilePlatformer

Compile the platformer parts of a manifest. Issues are agent-readable.

```ts check=skip
function compilePlatformer(m: GameManifest, tickRate: number, issues: string[]): CompiledPlatformer;
```

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

### compileRacer

Compile the racer parts of a manifest. Issues are agent-readable.

```ts check=skip
function compileRacer(m: GameManifest, issues: string[]): CompiledRacer;
```

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

### curveAt

Value of a curve at `t` seconds: linear between keyframes, held outside them.

```ts check=skip
function curveAt(c: Curve, t: number): number;
```

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

### disposeEngineWorld

Free a world's physics memory (rooms call this on dispose).

```ts check=skip
function disposeEngineWorld(w: EngineRoomWorld): void;
```

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

### engineSimAdapter

Build the SimAdapter. One instance serves every room of a template; each
room gets its own world from `createWorld`. `maxInputsPerTick: 1`:
engine-sim steps exactly one command per player per tick.

```ts check=skip
function engineSimAdapter(opts: EngineAdapterOptions): SimAdapter<EngineRoomWorld, InputCommand>;
```

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

### footprint

The four ground corners of the camera's view, relative to the focus point's ground position [x, z].

```ts check=skip
function footprint(v: CameraView): [number, number][];
```

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

### insideView

True when (dx, dz) from a player is inside a radii table.

```ts check=skip
function insideView(radii: readonly number[], dx: number, dz: number): boolean;
```

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

### kartAdapter

The racer's SimAdapter: the room runs the race; a client predicts only its own kart (no bumps).

```ts check=skip
function kartAdapter(o: KartAdapterOptions): SimAdapter<KartRoomWorld, InputCommand>;
```

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

### kartAutopilot

A client autopilot: the seat bot's driving on our newest predicted kart.

```ts check=skip
function kartAutopilot(compiled: CompiledRacer, tickRate: number): (self: EntityState | undefined, tick: number, skill?: number, others?: readonly EntityState[]) => InputCommand;
```

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

### kartBotInput

What a kart bot does: steer at a point on the racing line ahead (further
at speed), lift off for tight bends, and drift through long ones at
higher skill. `skill` 0..1 shades its top speed and its line.

```ts check=skip
function kartBotInput(w: KartWorld, k: Kart, clock: number, skill: number, lane?: number, mem?: { driftUntil: number; }): InputCommand;
```

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

### kartFromValues

```ts check=skip
function kartFromValues(e: EntityState): Wire;
```

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

### laneLength

Lane length for an enemy type's telegraphed lane.

```ts check=skip
function laneLength(def: EnemyTypeDef | undefined): number;
```

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

### levelTable

Every level's numbers: level 1 is the weapon's own, each declared level applies its changes to the one before.

```ts check=skip
function levelTable(w: ApiWeaponDef, tickRate: number): WeaponLevelStats[];
```

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

### metaBonus

The stat bonus a profile's meta levels give, with the engine's caps
applied again (+15% per stat, +30% in total, scaled down evenly past
it), whatever the declarations or the stored levels say.

```ts check=skip
function metaBonus(spec: ProfileSpec, levels: Readonly<Record<string, number>>): Partial<Record<MetaStat, number>>;
```

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

### metaPrice

Coins for the next level of a meta upgrade from `level` (0 = none owned), or null at the top. Geometric: cost x growth^level.

```ts check=skip
function metaPrice(def: MetaUpgradeDef, level: number): number | null;
```

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

### openKeepers

Keeper indices a profile may play: free keepers, keepers whose achievement
it reached, keepers it bought. A sold keeper opens only by purchase: an
imported achievement never opens it (defense in depth; the build already
refuses a keeper that is both earned and sold).

```ts check=skip
function openKeepers(spec: ProfileSpec, state: ProfileUnlockState): number[];
```

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

### ownedCosmetics

Cosmetic ids a profile owns (0, the default look, always).

```ts check=skip
function ownedCosmetics(spec: ProfileSpec, owned: Iterable<string>): number[];
```

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

### ownedGear

Owned gear (losable, staked runs only): the SKU, the run upgrade it brings, and its loss line.

```ts check=skip
function ownedGear(spec: ProfileSpec, owned: Iterable<string>): Array<{ sku: string; upgrade: string; loseBelow: number; coins: number; }>;
```

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

### packMeta

Meta levels as one integer (3 bits per upgrade, declaration order), the payload of the room's "meta" sim command.

```ts check=skip
function packMeta(spec: ProfileSpec, levels: Readonly<Record<string, number>>): number;
```

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

### planCourse

Search for a run from the start to the flag (the gate's softlock check:
every level must be finishable). Best-first over short macro moves (run,
jump of three heights, dash, wait) on a one-player copy of the sim, keyed
by position cells so it never re-explores. Moving platforms run on the
real clock from `startTick`.

```ts check=skip
function planCourse(level: PlatformLevel, opts: { tickRate: number; tuning?: Partial<PlatformTuning>; statSteps?: readonly number[]; startTick?: number; budget?: number; from?: ReturnType<typeof capturePlatformPlayer>; }): PlanResult;
```

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

### platformAdapter

The platformer's SimAdapter: the room runs the race; a client predicts only its own runner.

```ts check=skip
function platformAdapter(o: PlatformAdapterOptions): SimAdapter<PlatformRoomWorld, InputCommand>;
```

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

### platformAutopilot

A playing autopilot for a client (measurement, previews, load tests): from
the newest predicted state of our own climber it plans a route to the flag
(cached by state), plays it back tick for tick on the course clock, and
replans after a fall, a new course or the end of the tape. Falls back to
the course bot's reflexes while no route is known.

```ts check=skip
function platformAutopilot(compiled: CompiledPlatformer, tickRate: number): (self: EntityState | undefined, course: number, tick: number) => InputCommand;
```

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

### platformBotInput

What a course-running bot does this tick: run toward the flag, jump at
walls, gaps and hazards, wait for a moving platform, hold Jump for a full
jump, dash across a gap it is falling into. Deterministic.

```ts check=skip
function platformBotInput(w: PlatformWorld, p: PlatformPlayer, mem: PlatformBotMemory, clock: number, skill: number): InputCommand;
```

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

### prefabKind

"enemy" or "pickup": explicit, else a prefab something drops is a pickup.

```ts check=skip
function prefabKind(m: GameManifest, id: string, p: PrefabDef): "enemy" | "pickup";
```

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

### profileSpec

The profile view of a manifest.

```ts check=skip
function profileSpec(m: GameManifest): ProfileSpec;
```

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

### radiusAt

Radius at a heading of a radii table (linear between samples).

```ts check=skip
function radiusAt(radii: readonly number[], a: number): number;
```

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

### resetRegistry

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

```ts check=skip
function resetRegistry(): void;
```

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

### routeFor

A planned run from a climber's exact state (cached), or null when the
planner found none. Without `from`, from the start at `startTick`.

```ts check=skip
function routeFor(level: PlatformLevel, tickRate: number, tuning: Partial<PlatformTuning>, startTick: number, from?: ReturnType<typeof capturePlatformPlayer>): readonly InputCommand[] | null;
```

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

### sightBlocked

Does the segment from (x0, z0) to (x1, z1) pass through a pillar?

```ts check=skip
function sightBlocked(x0: number, z0: number, x1: number, z1: number, pillars: ArenaBotView["pillars"]): boolean;
```

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

### skuKind

```ts check=skip
function skuKind(grants: SkuGrant | undefined | null): SkuKind;
```

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

### threatOf

The warning an entity shows now, or null. `kind`, `flags`, `type` and
`level` are its snapshot fields; (x, z) its position, (vx, vz) its
velocity (shots).

```ts check=skip
function threatOf(enemyTypes: readonly EnemyTypeDef[], kind: number, flags: number, type: number, level: number, x: number, z: number, vx?: number, vz?: number): ThreatShape | null;
```

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

### todaysGoals

Today's goals: `n` of the declared missions, the same for everyone on a UTC day.

```ts check=skip
function todaysGoals(ids: readonly string[], day: number, n?: number): string[];
```

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

### unpackMeta

```ts check=skip
function unpackMeta(spec: ProfileSpec, value: number): Record<string, number>;
```

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

### unroutable

True when routeFor found no way from this course's start to its flag.

```ts check=skip
function unroutable(level: PlatformLevel): boolean;
```

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

### utcDay

UTC day number (days since 1970-01-01): daily goals roll over at 00:00 UTC.

```ts check=skip
function utcDay(ms: number): number;
```

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

### viewRadii

View radii (engine-sim ViewRules) for the union of several camera views, at `n` evenly spaced headings.

```ts check=skip
function viewRadii(views: readonly CameraView[], n?: number): number[];
```

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

### viewsFor

The camera views a template's client draws with (the spawn director and the playtest's "on screen" use them).

```ts check=skip
function viewsFor(template: string): readonly CameraView[];
```

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

## Classes

### Director

```ts check=skip
class Director {
  constructor(def: DirectorDef, world: SimWorld, hooks: DirectorHooks);
  pause(now: number, ticks: number): void;
  surge(now: number, k: number, ticks: number): void;
  aliveTarget(tick: number): number;
  tick(tick: number): void;
}
```

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

### EarnTracker

```ts check=skip
class EarnTracker {
  constructor(rules: ReadonlyMap<string, EarnRuleDef>);
  record(e: GameEvent): EarnAward[];
  resetRun(): void;
  forget(player: number): void;
  count(player: number, event: string): number;
}
```

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

### GameRunner

```ts check=skip
class GameRunner {
  constructor(compiled: CompiledGame, world: SimWorld, opts?: RunnerOptions);
  takeProgress(): RunProgress[];
  get phaseNow(): RunPhase;
  get runNumber(): number;
  beforeStep(inputs?: Map<number, InputCommand>): void;
  autopilot(id: number): InputCommand;
  afterStep(simEvents: readonly SimEvent[]): RunnerStep;
  summary(): RunSummary;
  info(): RunInfo;
  bossIds(): number[];
  startRun(player: number): void;
  count(player: number, event: string): number;
  emittedCount(event: string): number;
  killsOf(player: number): number;
}
```

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

### HumanBot

A playtest bot that plays like a person, for fun metrics
(GAME-DESIGN.md "measure fun with bots"): it reacts about 200 ms late,
kites in wide arcs instead of circling the centre, walks over gems when
it is safe, dashes when something is about to touch it or a telegraph is
about to land under it, and takes a second or so to read each card.
Template-agnostic: it needs positions only. Deterministic for a given
input sequence (its own xorshift, never the sim's PRNG).

```ts check=skip
class HumanBot {
  constructor(opts?: HumanBotOptions);
  input(now: HumanBotView, tick: number): InputCommand;
}
```

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

### KartCore

```ts check=skip
class KartCore {
  constructor(compiled: CompiledRacer, tickRate: number, authority?: boolean);
  readonly tickRate: number;
  readonly world: KartWorld;
  ids(): number[];
  add(id: number, bot: boolean, frozen: boolean): void;
  remove(id: number): void;
  reset(course: number, frozen: boolean): void;
  setFrozen(frozen: boolean): void;
  finished(id: number): boolean;
  progress(id: number): number;
  position(id: number): readonly [number, number, number];
  step(inputs: ReadonlyMap<number, InputCommand>): RaceSimEvent[];
  botInput(id: number, clock: number, skill: number): InputCommand;
  grant(id: number, upgrade: number): boolean;
  setCosmetic(id: number, cosmetic: number): void;
}
```

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

### PlatformCore

The platform sim as the race runner drives it.

```ts check=skip
class PlatformCore {
  constructor(compiled: CompiledPlatformer, tickRate: number);
  readonly tickRate: number;
  readonly world: PlatformWorld;
  ids(): number[];
  add(id: number, bot: boolean, frozen: boolean): void;
  remove(id: number): void;
  reset(course: number, frozen: boolean): void;
  setFrozen(frozen: boolean): void;
  finished(id: number): boolean;
  progress(id: number): number;
  position(id: number): readonly [number, number, number];
  step(inputs: ReadonlyMap<number, InputCommand>): RaceSimEvent[];
  botInput(id: number, clock: number, skill: number): InputCommand;
  grant(id: number, upgrade: number): boolean;
  setCosmetic(id: number, cosmetic: number): void;
}
```

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

### RaceRunner

```ts check=skip
class RaceRunner {
  constructor(manifest: GameManifest, core: RaceCore, opts: { readonly bots: number; readonly roundSeconds: number | null; readonly courses: number; readonly seed: number; } & RaceRunnerOptions);
  get phaseNow(): RacePhase;
  get runNumber(): number;
  get courseNow(): number;
  placeOf(id: number): number | null;
  joined(id: number): void;
  left(id: number): void;
  beforeStep(inputs: Map<number, InputCommand>): void;
  afterStep(sim: readonly RaceSimEvent[]): RaceStep;
  takeProgress(): RunProgress[];
  startRun(player: number): void;
  count(player: number, event: string): number;
  standings(): number[];
  info(): RaceInfo;
}
```

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

## Constants

### ARENA_DEFAULTS

Arena defaults: a 3 minute round, a 3 s respawn, 2 s spawn protection, heal cells last 20 s.

```ts check=skip
const ARENA_DEFAULTS: { readonly roundSeconds: 180; readonly respawnSeconds: 3; readonly spawnProtectSeconds: 2; readonly pickupSeconds: 20; readonly pillarHeight: 2.4; };
```

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

### CROWD_UNITS

Units per metre of the crowd position fields (ex, ez): 1/16 m (6 cm) is below what a crowd shows on screen.

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

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

### DUNGEON_VIEWS

The dungeon crawl's camera (template-dungeon client/scene.ts: distance 13
landscape, 18 portrait, fov 50, pitch 1.02): closer than the field's, so
a room fills the screen and the next one is out of sight.

```ts check=skip
const DUNGEON_VIEWS: readonly CameraView[];
```

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

### engineSchema

```ts check=skip
const engineSchema: EntitySchema;
```

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

### F

Field indices of the engine wire schema.

```ts check=skip
const F: { readonly px: 0; readonly py: 1; readonly pz: 2; readonly vx: 3; readonly vy: 4; readonly vz: 5; readonly yaw: 6; readonly health: 7; readonly flags: 8; readonly cooldown: 9; readonly buttons: 10; readonly timers: 11; readonly type: 12; readonly level: 13; readonly xp: 14; readonly weapons: 15; readonly wcd: 16; readonly stats: 17; readonly choices: 18; readonly bleed: 19; readonly revive: 20; readonly iframes: 21; readonly dash: 22; readonly ex: 23; readonly ez: 24; readonly value: 25; };
```

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

### kartSchema

```ts check=skip
const kartSchema: EntitySchema;
```

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

### KF

Field indices of the racer wire schema.

```ts check=skip
const KF: { readonly x: 0; readonly z: 1; readonly yaw: 2; readonly vx: 3; readonly vz: 4; readonly flags: 5; readonly timers: 6; readonly track: 7; readonly coinsLo: 8; readonly coinsHi: 9; readonly finishTick: 10; readonly stats: 11; readonly cosmetic: 12; readonly clock: 13; };
```

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

### PF

Field indices of the platformer wire schema.

```ts check=skip
const PF: { readonly x: 0; readonly y: 1; readonly vx: 2; readonly vy: 3; readonly flags: 4; readonly timers: 5; readonly timers2: 6; readonly cp: 7; readonly coinsLo: 8; readonly coinsHi: 9; readonly finishTick: 10; readonly stats: 11; readonly cosmetic: 12; readonly clock: 13; };
```

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

### PLATFORMER_DEFAULTS

Platformer defaults: a 3 minute limit, 60 Hz, three seat bots.

```ts check=skip
const PLATFORMER_DEFAULTS: { readonly roundSeconds: 180; readonly tickRate: 60; readonly bots: 3; };
```

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

### platformSchema

```ts check=skip
const platformSchema: EntitySchema;
```

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

### PLAYER_UNITS

Units per metre of player positions (px, py, pz): engine-sim's own fixed point.

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

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

### raceInputCodec

The engine InputCommand on the wire (moves int8, yaw u16, buttons u16), shared by the race templates.

```ts check=skip
const raceInputCodec: { idle: InputCommand; write(w: BitWriter, i: InputCommand): void; read(r: BitReader): InputCommand; };
```

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

### RACER_DEFAULTS

Racer defaults: a 4 minute limit, 60 Hz, five seat bots.

```ts check=skip
const RACER_DEFAULTS: { readonly roundSeconds: 240; readonly tickRate: 60; readonly bots: 5; };
```

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

### RESERVED_COMMANDS

Room command names a client may never send: the room issues them from the profile.

```ts check=skip
const RESERVED_COMMANDS: ReadonlySet<string>;
```

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

### SURVIVOR_VIEWS

EMBERWATCH's camera (client/scene.ts: distance 17 landscape, 24 portrait,
fov 50, pitch 0.98, focus 0.5 m up) on a 16:9 and a 21:9 monitor and a
9:19.5 phone. Change these with the scene's rig. (Round 1 playtest: 20%
closer than the first cut's 21 and 30, so the hero reads.)

```ts check=skip
const SURVIVOR_VIEWS: readonly CameraView[];
```

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

## Types

### ArenaBotMemory

A bot's memory between ticks (the caller keeps one per bot).

```ts check=skip
interface ArenaBotMemory {
  target: number;
  since: number;
  aimError: number;
  lastHealth: number;
  sightSince?: number;
}
```

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

### ArenaBotOpponent

One opponent as an arena bot sees it.

```ts check=skip
interface ArenaBotOpponent {
  readonly id: number;
  readonly x: number;
  readonly z: number;
  readonly skill?: number;
  readonly crowded?: boolean;
}
```

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

### ArenaBotView

What an arena bot knows this tick (server side: the present).

```ts check=skip
interface ArenaBotView {
  readonly id: number;
  readonly x: number;
  readonly z: number;
  readonly health: number;
  readonly maxHealth: number;
  readonly up: boolean;
  readonly slot: number;
  readonly loadout: readonly ArenaBotWeapon[];
  readonly opponents: readonly ArenaBotOpponent[];
  readonly pickups: readonly { readonly x: number; readonly z: number }[];
  readonly pillars: readonly { readonly x: number; readonly z: number; readonly radius: number }[];
  readonly half: number;
  readonly seed?: number;
  readonly skill?: number;
}
```

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

### ArenaBotWeapon

```ts check=skip
interface ArenaBotWeapon {
  readonly kind: string;
  readonly range: number;
  readonly count: number;
}
```

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

### BotDanger

A danger the bot can see coming: a telegraphed area that lands soon (circle, or a lane from (x, z) along (dx, dz)).

```ts check=skip
interface BotDanger {
  readonly x: number;
  readonly z: number;
  readonly r: number;
  readonly dx?: number;
  readonly dz?: number;
  readonly len?: number;
}
```

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

### BotView

```ts check=skip
interface BotView {
  readonly x: number;
  readonly z: number;
  readonly choices: number;
  readonly half: number;
}
```

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

### CameraView

A fixed top-down follow camera (yaw 0: it sits on +z and looks toward -z).

```ts check=skip
interface CameraView {
  readonly distance: number;
  readonly pitch: number;
  readonly fov: number;
  readonly aspect: number;
  readonly focusHeight?: number;
}
```

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

### CompiledGame

```ts check=skip
interface CompiledGame {
  readonly manifest: GameManifest;
  readonly sim: SimConfig;
  readonly enemyPrefabs: readonly string[];
  readonly enemyType: ReadonlyMap<string, number>;
  readonly pickupPrefabs: readonly string[];
  readonly specialPickups: readonly string[];
  readonly weaponIds: readonly string[];
  readonly upgradeIds: readonly string[];
  readonly tickRate: number;
  readonly mode: "survivor" | "arena" | "platformer" | "racer";
  readonly platformer?: CompiledPlatformer;
  readonly racer?: CompiledRacer;
  readonly loadout: readonly number[];
  readonly bots: number;
  readonly round: { readonly seconds: number; readonly frags: number | null } | null;
  readonly view: readonly number[];
}
```

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

### CompiledPlatformer

```ts check=skip
interface CompiledPlatformer {
  readonly levels: readonly PlatformLevel[];
  readonly names: readonly string[];
  readonly tuning: Partial<PlatformTuning>;
  readonly statSteps: readonly number[];
  readonly upgradeStat: readonly PlatStat[];
}
```

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

### CompiledRacer

```ts check=skip
interface CompiledRacer {
  readonly tracks: readonly KartTrackDef[];
  readonly names: readonly string[];
  readonly tuning: Partial<KartTuning>;
  readonly statSteps: readonly number[];
  readonly upgradeStat: readonly KartStat[];
}
```

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

### EarnAward

```ts check=skip
interface EarnAward {
  readonly player: number;
  readonly rule: string;
  readonly units: number;
}
```

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

### EngineAdapterOptions

```ts check=skip
interface EngineAdapterOptions {
  readonly name: string;
  readonly version: string;
  readonly game?: CompiledGame;
  readonly arena?: SimConfig;
  readonly runner?: RunnerOptions;
}
```

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

### EngineRoomWorld

The world each side of the netcode holds.

```ts check=skip
interface EngineRoomWorld {
  readonly sim: SimWorld;
  readonly role: 'server' | 'client';
  readonly runner: GameRunner | null;
  readonly shots: Map<PlayerId, BeamShot>;
}
```

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

### GameEvent

Something that happened in a run, and the players it credits.

```ts check=skip
interface GameEvent {
  readonly name: string;
  readonly players: readonly number[];
  readonly unpaid?: true;
  readonly own?: true;
}
```

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

### HumanBotOptions

```ts check=skip
interface HumanBotOptions {
  readonly reactionTicks?: number;
  readonly picks?: "random" | "greedy";
  readonly weaponCount?: number;
  readonly evolved?: readonly number[];
  readonly pairs?: readonly (readonly [number, number])[];
  readonly seed?: number;
}
```

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

### HumanBotView

What a human-like bot sees this tick (the caller passes the present; the bot reacts to it late).

```ts check=skip
interface HumanBotView {
  readonly x: number;
  readonly z: number;
  readonly up: boolean;
  readonly choices: number;
  readonly weapons: number;
  readonly half: number;
  readonly enemies: readonly (readonly [number, number])[];
  readonly gems: readonly (readonly [number, number])[];
  readonly pillars: readonly { readonly x: number; readonly z: number; readonly radius: number }[];
  readonly dangers?: readonly BotDanger[];
  readonly reach?: number;
  readonly bosses?: readonly (readonly [number, number])[];
  readonly downed?: readonly (readonly [number, number])[];
}
```

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

### KartAdapterOptions

```ts check=skip
interface KartAdapterOptions {
  readonly name: string;
  readonly version: string;
  readonly manifest: GameManifest;
  readonly compiled: CompiledRacer;
  readonly tickRate: number;
  readonly bots: number;
  readonly roundSeconds: number | null;
  readonly runner?: RaceRunnerOptions;
}
```

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

### KartRoomWorld

```ts check=skip
interface KartRoomWorld {
  readonly role: "server" | "client";
  readonly core: KartCore;
  readonly runner: RaceRunner | null;
}
```

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

### KillFeedEntry

Arena: one kill, newest last. `ago` is seconds since it happened.

```ts check=skip
interface KillFeedEntry {
  readonly by: number;
  readonly victim: number;
  readonly ago: number;
}
```

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

### PlanResult

```ts check=skip
interface PlanResult {
  readonly found: boolean;
  readonly seconds: number;
  readonly bestX: number;
  readonly expanded: number;
  readonly tape: readonly InputCommand[];
}
```

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

### PlatformAdapterOptions

```ts check=skip
interface PlatformAdapterOptions {
  readonly name: string;
  readonly version: string;
  readonly manifest: GameManifest;
  readonly compiled: CompiledPlatformer;
  readonly tickRate: number;
  readonly bots: number;
  readonly roundSeconds: number | null;
  readonly runner?: RaceRunnerOptions;
}
```

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

### PlatformBotMemory

Per-bot memory for the course runner.

```ts check=skip
interface PlatformBotMemory {
  bestX: number;
  since: number;
  holdJump: number;
  tape?: readonly InputCommand[] | null;
  tapeAt?: number;
}
```

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

### PlatformRoomWorld

```ts check=skip
interface PlatformRoomWorld {
  readonly role: "server" | "client";
  readonly core: PlatformCore;
  readonly runner: RaceRunner | null;
}
```

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

### ProfileSku

```ts check=skip
interface ProfileSku {
  readonly id: string;
  readonly kind: SkuKind;
  readonly coins: number | null;
  readonly grants: SkuGrant | null;
}
```

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

### ProfileSpec

What one game lets a profile hold, from its manifest.

```ts check=skip
interface ProfileSpec {
  readonly keepers: readonly { readonly id: string; readonly unlock: string | null; readonly sold: boolean }[];
  readonly achievements: readonly string[];
  readonly missions: ReadonlyMap<string, { readonly when: string; readonly n: number }>;
  readonly titles: readonly string[];
  readonly skus: ReadonlyMap<string, ProfileSku>;
  readonly meta: ReadonlyMap<string, MetaUpgradeDef>;
  readonly economy: EconomyDef;
}
```

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

### ProfileUnlockState

Which keepers a profile may play (by index), from its achievements and owned unlocks.

```ts check=skip
interface ProfileUnlockState {
  readonly achievements: Iterable<string>;
  readonly imported?: Iterable<string>;
  readonly owned: Iterable<string>;
}
```

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

### RaceCore

A template's sim as the race runner drives it.

```ts check=skip
interface RaceCore {
  readonly tickRate: number;
  ids(): number[];
  add(id: number, bot: boolean, frozen: boolean): void;
  remove(id: number): void;
  reset(course: number, frozen: boolean): void;
  setFrozen(frozen: boolean): void;
  finished(id: number): boolean;
  progress(id: number): number;
  position(id: number): readonly [number, number, number];
  step(inputs: ReadonlyMap<number, InputCommand>): RaceSimEvent[];
  botInput(id: number, clock: number, skill: number): InputCommand;
  grant(id: number, upgrade: number): boolean;
  setCosmetic(id: number, cosmetic: number): void;
}
```

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

### RaceInfo

```ts check=skip
interface RaceInfo {
  readonly run: number;
  readonly phase: RacePhase;
  readonly course: number;
  readonly countdown: number;
  readonly seconds: number;
  readonly left: number | null;
  readonly players: readonly RacePlayerInfo[];
  readonly announce: { readonly id: number; readonly text: string; readonly tone: "info" | "danger" | "reward" } | null;
  readonly next: { readonly label: string; readonly in: number } | null;
  readonly nextRunIn: number | null;
  readonly coins: readonly { readonly id: number; readonly rules: readonly { readonly rule: string; readonly units: number }[] }[];
}
```

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

### RacePhase

```ts check=skip
type RacePhase = "countdown" | "racing" | "results";
```

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

### RacePlayerInfo

```ts check=skip
interface RacePlayerInfo {
  readonly id: number;
  readonly bot: boolean;
  readonly place: number | null;
  readonly time: number | null;
  readonly progress: number;
  readonly rank: number;
  readonly counts: Readonly<Record<string, number>>;
  readonly ready: boolean;
}
```

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

### RaceRunnerOptions

```ts check=skip
interface RaceRunnerOptions {
  readonly countdownSeconds?: number;
  readonly endSeconds?: number;
  readonly graceSeconds?: number;
  readonly finishWindowSeconds?: number;
}
```

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

### RaceSimEvent

What the sim says happened this tick, as named game events for one player.

```ts check=skip
interface RaceSimEvent {
  readonly name: string;
  readonly player: number;
}
```

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

### RaceStep

```ts check=skip
interface RaceStep {
  readonly events: readonly GameEvent[];
  readonly awards: readonly EarnAward[];
  readonly reset: boolean;
}
```

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

### RunInfo

What the room broadcasts about the run (a few times a second, a few hundred bytes).

```ts check=skip
interface RunInfo {
  readonly run: number;
  readonly phase: RunPhase;
  readonly seconds: number;
  readonly wave: number;
  readonly kills: number;
  readonly enemies: number;
  readonly boss: { readonly prefab: string; readonly health: number; readonly max: number } | null;
  readonly bosses: readonly { readonly prefab: string; readonly health: number; readonly max: number; readonly x: number; readonly z: number }[];
  readonly paused: boolean;
  readonly announce: { readonly id: number; readonly text: string; readonly tone: "info" | "danger" | "reward" } | null;
  readonly players: readonly RunPlayerInfo[];
  readonly nextRunIn: number | null;
  readonly round: { readonly seconds: number; readonly left: number; readonly frags: number | null } | null;
  readonly feed: readonly KillFeedEntry[];
  readonly next: { readonly label: string; readonly in: number } | null;
  readonly summary: RunSummary | null;
}
```

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

### RunnerOptions

```ts check=skip
interface RunnerOptions {
  readonly holdEnemies?: number;
  readonly godMode?: boolean;
  readonly holdMix?: boolean;
  readonly loseGraceSeconds?: number;
  readonly endSeconds?: number;
}
```

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

### RunnerStep

```ts check=skip
interface RunnerStep {
  readonly events: readonly GameEvent[];
  readonly awards: readonly EarnAward[];
  readonly reset: boolean;
}
```

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

### RunPhase

```ts check=skip
type RunPhase = "playing" | "won" | "lost";
```

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

### RunPlayerInfo

```ts check=skip
interface RunPlayerInfo {
  readonly id: number;
  readonly level: number;
  readonly kills: number;
  readonly downed: boolean;
  readonly dead: boolean;
  readonly deaths: number;
  readonly bot: boolean;
  readonly keeper: string | null;
  readonly buffed: boolean;
  readonly counts: Readonly<Record<string, number>>;
  readonly achievements: readonly string[];
  readonly ready: boolean;
}
```

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

### RunProgress

Event a run reports for a player's profile (the room writes it; the browser never does).

```ts check=skip
interface RunProgress {
  readonly player: number;
  readonly kind: "achievement" | "goal" | "title";
  readonly id: string;
}
```

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

### SkuKind

What a SKU is in the coin model: an in-run consumable, a look owned for good, or an unlock owned for good.

```ts check=skip
type SkuKind = "consumable" | "cosmetic" | "unlock" | "gear";
```

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

### ThreatShape

One warning on the ground. Lanes run from (x, z) along (dx, dz) for `len` m with half width `r`.

```ts check=skip
interface ThreatShape {
  readonly kind: "circle" | "lane" | "aura";
  readonly x: number;
  readonly z: number;
  readonly r: number;
  readonly dx?: number;
  readonly dz?: number;
  readonly len?: number;
  readonly progress: number;
  readonly shot?: boolean;
}
```

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