@netforge/engine/game API reference
Net Forge, the open-source multiplayer browser game engine built for AI coding agents, is published on npm under @netforge with source at github.com/netnetdev/net-forge.
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.
| 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.
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;
}