NET FORGE DOCS

@netforge/engine/game API reference

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

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

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.

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.

KindCount
Functions43
Classes7
Constants15
Types41

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.

function arenaBotInput(v: ArenaBotView, mem: ArenaBotMemory, tick: number, tickRate?: number): InputCommand;

Source: packages/engine/src/game/arena-bot.ts

arenaBotMemory

function arenaBotMemory(): ArenaBotMemory;

Source: 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).

function botDelaySeconds(id: number, skill: number): number;

Source: packages/engine/src/game/platformer.ts

botInput

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

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

Source: 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.

function collectManifest(): GameManifest;

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

compileGame

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

Source: packages/engine/src/game/compile.ts

compilePlatformer

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

function compilePlatformer(m: GameManifest, tickRate: number, issues: string[]): CompiledPlatformer;

Source: packages/engine/src/game/platformer.ts

compileRacer

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

function compileRacer(m: GameManifest, issues: string[]): CompiledRacer;

Source: packages/engine/src/game/racer.ts

curveAt

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

function curveAt(c: Curve, t: number): number;

Source: packages/engine/src/game/director.ts

disposeEngineWorld

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

function disposeEngineWorld(w: EngineRoomWorld): void;

Source: 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.

function engineSimAdapter(opts: EngineAdapterOptions): SimAdapter<EngineRoomWorld, InputCommand>;

Source: 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].

function footprint(v: CameraView): [number, number][];

Source: packages/engine/src/game/view.ts

insideView

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

function insideView(radii: readonly number[], dx: number, dz: number): boolean;

Source: 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).

function kartAdapter(o: KartAdapterOptions): SimAdapter<KartRoomWorld, InputCommand>;

Source: packages/engine/src/game/racer.ts

kartAutopilot

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

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

Source: 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.

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

Source: packages/engine/src/game/racer.ts

kartFromValues

function kartFromValues(e: EntityState): Wire;

Source: packages/engine/src/game/racer.ts

laneLength

Lane length for an enemy type's telegraphed lane.

function laneLength(def: EnemyTypeDef | undefined): number;

Source: 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.

function levelTable(w: ApiWeaponDef, tickRate: number): WeaponLevelStats[];

Source: 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.

function metaBonus(spec: ProfileSpec, levels: Readonly<Record<string, number>>): Partial<Record<MetaStat, number>>;

Source: 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.

function metaPrice(def: MetaUpgradeDef, level: number): number | null;

Source: 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).

function openKeepers(spec: ProfileSpec, state: ProfileUnlockState): number[];

Source: packages/engine/src/game/profile.ts

ownedCosmetics

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

function ownedCosmetics(spec: ProfileSpec, owned: Iterable<string>): number[];

Source: packages/engine/src/game/profile.ts

ownedGear

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

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

Source: 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.

function packMeta(spec: ProfileSpec, levels: Readonly<Record<string, number>>): number;

Source: 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.

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

platformAdapter

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

function platformAdapter(o: PlatformAdapterOptions): SimAdapter<PlatformRoomWorld, InputCommand>;

Source: 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.

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

Source: 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.

function platformBotInput(w: PlatformWorld, p: PlatformPlayer, mem: PlatformBotMemory, clock: number, skill: number): InputCommand;

Source: packages/engine/src/game/platformer.ts

prefabKind

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

function prefabKind(m: GameManifest, id: string, p: PrefabDef): "enemy" | "pickup";

Source: packages/engine/src/game/compile.ts

profileSpec

The profile view of a manifest.

function profileSpec(m: GameManifest): ProfileSpec;

Source: packages/engine/src/game/profile.ts

radiusAt

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

function radiusAt(radii: readonly number[], a: number): number;

Source: packages/engine/src/game/view.ts

resetRegistry

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

function resetRegistry(): void;

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

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.

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

sightBlocked

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

function sightBlocked(x0: number, z0: number, x1: number, z1: number, pillars: ArenaBotView["pillars"]): boolean;

Source: packages/engine/src/game/arena-bot.ts

skuKind

function skuKind(grants: SkuGrant | undefined | null): SkuKind;

Source: 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).

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

todaysGoals

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

function todaysGoals(ids: readonly string[], day: number, n?: number): string[];

Source: packages/engine/src/game/profile.ts

unpackMeta

function unpackMeta(spec: ProfileSpec, value: number): Record<string, number>;

Source: packages/engine/src/game/profile.ts

unroutable

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

function unroutable(level: PlatformLevel): boolean;

Source: packages/engine/src/game/platformer.ts

utcDay

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

function utcDay(ms: number): number;

Source: packages/engine/src/game/profile.ts

viewRadii

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

function viewRadii(views: readonly CameraView[], n?: number): number[];

Source: 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).

function viewsFor(template: string): readonly CameraView[];

Source: packages/engine/src/game/view.ts

Classes

Director

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

EarnTracker

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

GameRunner

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

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).

class HumanBot {
  constructor(opts?: HumanBotOptions);
  input(now: HumanBotView, tick: number): InputCommand;
}

Source: packages/engine/src/game/bot.ts

KartCore

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

PlatformCore

The platform sim as the race runner drives it.

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

RaceRunner

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

Constants

ARENA_DEFAULTS

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

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

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.

const CROWD_UNITS: 16;

Source: 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.

const DUNGEON_VIEWS: readonly CameraView[];

Source: packages/engine/src/game/view.ts

engineSchema

const engineSchema: EntitySchema;

Source: packages/engine/src/game/adapter.ts

F

Field indices of the engine wire schema.

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

kartSchema

const kartSchema: EntitySchema;

Source: packages/engine/src/game/racer.ts

KF

Field indices of the racer wire schema.

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

PF

Field indices of the platformer wire schema.

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

PLATFORMER_DEFAULTS

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

const PLATFORMER_DEFAULTS: { readonly roundSeconds: 180; readonly tickRate: 60; readonly bots: 3; };

Source: packages/engine/src/game/platformer.ts

platformSchema

const platformSchema: EntitySchema;

Source: packages/engine/src/game/platformer.ts

PLAYER_UNITS

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

const PLAYER_UNITS: 1024;

Source: packages/engine/src/game/adapter.ts

raceInputCodec

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

const raceInputCodec: { idle: InputCommand; write(w: BitWriter, i: InputCommand): void; read(r: BitReader): InputCommand; };

Source: packages/engine/src/game/platformer.ts

RACER_DEFAULTS

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

const RACER_DEFAULTS: { readonly roundSeconds: 240; readonly tickRate: 60; readonly bots: 5; };

Source: packages/engine/src/game/racer.ts

RESERVED_COMMANDS

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

const RESERVED_COMMANDS: ReadonlySet<string>;

Source: 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.)

const SURVIVOR_VIEWS: readonly CameraView[];

Source: packages/engine/src/game/view.ts

Types

ArenaBotMemory

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

interface ArenaBotMemory {
  target: number;
  since: number;
  aimError: number;
  lastHealth: number;
  sightSince?: number;
}

Source: packages/engine/src/game/arena-bot.ts

ArenaBotOpponent

One opponent as an arena bot sees it.

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

ArenaBotView

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

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

ArenaBotWeapon

interface ArenaBotWeapon {
  readonly kind: string;
  readonly range: number;
  readonly count: number;
}

Source: 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)).

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

BotView

interface BotView {
  readonly x: number;
  readonly z: number;
  readonly choices: number;
  readonly half: number;
}

Source: packages/engine/src/game/bot.ts

CameraView

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

interface CameraView {
  readonly distance: number;
  readonly pitch: number;
  readonly fov: number;
  readonly aspect: number;
  readonly focusHeight?: number;
}

Source: packages/engine/src/game/view.ts

CompiledGame

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

CompiledPlatformer

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

CompiledRacer

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

EarnAward

interface EarnAward {
  readonly player: number;
  readonly rule: string;
  readonly units: number;
}

Source: packages/engine/src/game/earn.ts

EngineAdapterOptions

interface EngineAdapterOptions {
  readonly name: string;
  readonly version: string;
  readonly game?: CompiledGame;
  readonly arena?: SimConfig;
  readonly runner?: RunnerOptions;
}

Source: packages/engine/src/game/adapter.ts

EngineRoomWorld

The world each side of the netcode holds.

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

GameEvent

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

interface GameEvent {
  readonly name: string;
  readonly players: readonly number[];
  readonly unpaid?: true;
  readonly own?: true;
}

Source: packages/engine/src/game/earn.ts

HumanBotOptions

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

HumanBotView

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

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

KartAdapterOptions

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

KartRoomWorld

interface KartRoomWorld {
  readonly role: "server" | "client";
  readonly core: KartCore;
  readonly runner: RaceRunner | null;
}

Source: packages/engine/src/game/racer.ts

KillFeedEntry

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

interface KillFeedEntry {
  readonly by: number;
  readonly victim: number;
  readonly ago: number;
}

Source: packages/engine/src/game/runner.ts

PlanResult

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

PlatformAdapterOptions

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

PlatformBotMemory

Per-bot memory for the course runner.

interface PlatformBotMemory {
  bestX: number;
  since: number;
  holdJump: number;
  tape?: readonly InputCommand[] | null;
  tapeAt?: number;
}

Source: packages/engine/src/game/platformer.ts

PlatformRoomWorld

interface PlatformRoomWorld {
  readonly role: "server" | "client";
  readonly core: PlatformCore;
  readonly runner: RaceRunner | null;
}

Source: packages/engine/src/game/platformer.ts

ProfileSku

interface ProfileSku {
  readonly id: string;
  readonly kind: SkuKind;
  readonly coins: number | null;
  readonly grants: SkuGrant | null;
}

Source: packages/engine/src/game/profile.ts

ProfileSpec

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

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

ProfileUnlockState

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

interface ProfileUnlockState {
  readonly achievements: Iterable<string>;
  readonly imported?: Iterable<string>;
  readonly owned: Iterable<string>;
}

Source: packages/engine/src/game/profile.ts

RaceCore

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

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

RaceInfo

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

RacePhase

type RacePhase = "countdown" | "racing" | "results";

Source: packages/engine/src/game/race.ts

RacePlayerInfo

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

RaceRunnerOptions

interface RaceRunnerOptions {
  readonly countdownSeconds?: number;
  readonly endSeconds?: number;
  readonly graceSeconds?: number;
  readonly finishWindowSeconds?: number;
}

Source: packages/engine/src/game/race.ts

RaceSimEvent

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

interface RaceSimEvent {
  readonly name: string;
  readonly player: number;
}

Source: packages/engine/src/game/race.ts

RaceStep

interface RaceStep {
  readonly events: readonly GameEvent[];
  readonly awards: readonly EarnAward[];
  readonly reset: boolean;
}

Source: packages/engine/src/game/race.ts

RunInfo

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

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

RunnerOptions

interface RunnerOptions {
  readonly holdEnemies?: number;
  readonly godMode?: boolean;
  readonly holdMix?: boolean;
  readonly loseGraceSeconds?: number;
  readonly endSeconds?: number;
}

Source: packages/engine/src/game/runner.ts

RunnerStep

interface RunnerStep {
  readonly events: readonly GameEvent[];
  readonly awards: readonly EarnAward[];
  readonly reset: boolean;
}

Source: packages/engine/src/game/runner.ts

RunPhase

type RunPhase = "playing" | "won" | "lost";

Source: packages/engine/src/game/runner.ts

RunPlayerInfo

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

RunProgress

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

interface RunProgress {
  readonly player: number;
  readonly kind: "achievement" | "goal" | "title";
  readonly id: string;
}

Source: 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.

type SkuKind = "consumable" | "cosmetic" | "unlock" | "gear";

Source: 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.

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