# @netforge/engine/net API reference

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

The client half of the netcode and the wire protocol: prediction and reconciliation, interpolation, delta snapshots, input packets, the client clock and the `SimAdapter` seam a room host drives.

```ts
import { InputQueue, encodeSnapshot } from "@netforge/engine/net";
```

Generated from `packages/engine/src/net/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 | 23 |
| Classes | 11 |
| Constants | 9 |
| Types | 47 |

## Functions

### bitsForSigned

Bits needed for a zigzagged signed value of magnitude up to `maxAbs`.

```ts check=skip
function bitsForSigned(maxAbs: number): number;
```

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

### connectReservation

```ts check=skip
function connectReservation<W, I>(sim: SimAdapter<W, I>, endpoint: string, reservation: Parameters<Client["consumeSeatReservation"]>[0]): Promise<RoomConnection<W, I>>;
```

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

### decodeInputPacket

```ts check=skip
function decodeInputPacket<I>(codec: InputCodec<I>, bytes: Uint8Array): InputPacket<I>;
```

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

### decodeSnapshot

Decodes a snapshot. `baselineFor` returns the client's stored entity set
for a tick it previously decoded.

```ts check=skip
function decodeSnapshot(schema: EntitySchema, bytes: Uint8Array, baselineFor: (tick: number) => ReadonlyMap<number, QEntity> | undefined): DecodedSnapshot;
```

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

### dequantize

Wire integer back to the real value.

```ts check=skip
function dequantize(f: FieldSpec, q: number): number;
```

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

### dequantizeValues

```ts check=skip
function dequantizeValues(schema: EntitySchema, q: readonly number[]): number[];
```

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

### encodeInputPacket

```ts check=skip
function encodeInputPacket<I>(codec: InputCodec<I>, p: InputPacket<I>): Uint8Array;
```

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

### encodeSnapshot

Encodes `current` (any order) against `baseline` (null for a full snapshot).

```ts check=skip
function encodeSnapshot(schema: EntitySchema, header: SnapshotHeader, current: readonly QEntity[], baseline: ReadonlyMap<number, QEntity> | null): Uint8Array;
```

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

### fieldBits

```ts check=skip
function fieldBits(f: FieldSpec): number;
```

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

### fieldDeltaBits

Default bit width for a "small change" delta of a field, or 0 for none.

```ts check=skip
function fieldDeltaBits(f: FieldSpec): number;
```

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

### guestId

This browser's guest id (made on first use). Storage blocked: one per page load.

```ts check=skip
function guestId(): string;
```

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

### interpolateField

Interpolate one field between a and b (real values).

```ts check=skip
function interpolateField(f: FieldSpec, a: number, b: number, t: number): number;
```

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

### joinRoom

```ts check=skip
function joinRoom<W, I>(sim: SimAdapter<W, I>, p: JoinParams): Promise<RoomConnection<W, I>>;
```

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

### kindFieldIndices

Field indices carried on the wire for an entity kind (all fields unless the schema narrows that kind).

```ts check=skip
function kindFieldIndices(schema: EntitySchema, kind: number): readonly number[];
```

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

### pageGame

The page's ?game= slug (set by Net Forge on a launched game's frame), or null outside a browser or without one.

```ts check=skip
function pageGame(): string | null;
```

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

### quantize

Real value to the integer the wire carries.

```ts check=skip
function quantize(f: FieldSpec, v: number): number;
```

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

### quantizeEntity

Quantize an entity's values. With `only` (the kind's wire fields), the
other fields are left 0: they never go on the wire for that kind.

```ts check=skip
function quantizeEntity(schema: EntitySchema, e: EntityState, only?: readonly number[]): number[];
```

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

### rotateGuestId

A fresh guest id: after a guest profile merges into a wallet, the old id is spent.

```ts check=skip
function rotateGuestId(): string;
```

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

### savedSession

The saved session token for a rooms server, if it has not expired.

```ts check=skip
function savedSession(endpoint: string): { token: string; address: string; } | null;
```

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

### saveSession

```ts check=skip
function saveSession(endpoint: string, s: { token: string; address: string; expiresAt: number; } | null): void;
```

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

### signInWithWallet

Sign in to a rooms server with a wallet: its nonce, an EIP-4361 message
for its domain, one personal_sign (no gas), a session token. Saved for
this endpoint until it expires.

```ts check=skip
function signInWithWallet(endpoint: string, provider: Eip1193, statement?: string): Promise<{ token: string; address: string; expiresAt: number; }>;
```

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

### unzigzag

```ts check=skip
function unzigzag(z: number): number;
```

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

### zigzag

```ts check=skip
function zigzag(n: number): number;
```

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

## Classes

### BaselineMissingError

```ts check=skip
class BaselineMissingError {
  constructor(baselineTick: number);
}
```

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

### BitReader

```ts check=skip
class BitReader {
  constructor(buf: Uint8Array);
  readBits(bits: number): number;
  readBool(): boolean;
  readSigned(bits: number): number;
  readVarUint(): number;
  get remainingBits(): number;
}
```

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

### BitWriter

```ts check=skip
class BitWriter {
  constructor(initialBytes?: number);
  writeBits(value: number, bits: number): void;
  writeBool(b: boolean): void;
  writeSigned(value: number, bits: number): void;
  writeVarUint(value: number): void;
  get bitLength(): number;
  finish(): Uint8Array;
}
```

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

### InputQueue

Server-side per-player input queue with speed-hack protection.

```ts check=skip
class InputQueue {
  constructor<I>(opts?: InputQueueOptions);
  lastAppliedSeq: number;
  dropped: number;
  starved: number;
  receive(commands: readonly InputCommand<I>[]): void;
  consume(): InputCommand<I>[];
  get pending(): number;
}
```

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

### InterpolationBuffer

```ts check=skip
class InterpolationBuffer {
  constructor(schema: EntitySchema, capacity?: number);
  push(tick: number, entities: ReadonlyMap<number, QEntity>): void;
  sample(renderTick: number, exclude?: number): InterpolatedEntity[];
  get newestTick(): number;
}
```

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

### NetClient

```ts check=skip
class NetClient {
  constructor<W, I>(sim: SimAdapter<W, I>, player: PlayerId, selfEntity: number, send: (bytes: Uint8Array) => void, opts?: NetClientOptions);
  readonly stats: ClientStats;
  get nextSeq(): number;
  receiveSnapshot(bytes: Uint8Array, nowMs: number): void;
  tick(input: I, nowMs: number): void;
  tickIntervalMs(): number;
  get serverInputBuffer(): number | null;
  renderTick(nowMs: number): number;
  render(nowMs: number): { self: EntityState | undefined; others: InterpolatedEntity[]; };
  authoritativeSelf(): EntityState | undefined;
  interpolatedSelf(nowMs: number): InterpolatedEntity | undefined;
  predicted(): EntityState | undefined;
  get ready(): boolean;
  get corrections(): number;
  get lastCorrection(): number;
  get pendingInputs(): number;
}
```

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

### Predictor

```ts check=skip
class Predictor {
  constructor<W, I>(sim: SimAdapter<W, I>, player: PlayerId, selfEntity: number, seed?: number, firstSeq?: number);
  lastCorrection: number;
  corrections: number;
  get upcomingSeq(): number;
  get isReady(): boolean;
  predict(input: I, viewTick16: number): InputCommand<I> | null;
  unacked(): readonly InputCommand<I>[];
  reconcile(ackSeq: number, serverSelf: EntityState): void;
  state(): EntityState | undefined;
  renderState(dtMs: number): EntityState | undefined;
}
```

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

### ProfileApi

The room server's profile routes for one game.

```ts check=skip
class ProfileApi {
  constructor(endpoint: string, game: string);
  get(auth: ProfileAuth): Promise<GameProfile>;
  importLocal(guest: string, local: LocalProgress): Promise<GameProfile>;
  claim(session: string, guest: string): Promise<GameProfile>;
  setSettings(auth: ProfileAuth, settings: Readonly<Record<string, unknown>>): Promise<GameProfile>;
  setName(auth: ProfileAuth, displayName: string): Promise<GameProfile>;
  redeem(session: string, item: string, key: string): Promise<GameProfile>;
}
```

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

### ServerClock

Tracks server time from snapshot arrivals. The offset (server ms minus
local ms) is taken from the freshest-looking arrival, eased toward later
samples so jitter does not make the render time jump.

```ts check=skip
class ServerClock {
  constructor(tickMs: number);
  observe(tick: number, localMs: number): void;
  serverTick(localMs: number): number;
  get ready(): boolean;
}
```

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

### SnapshotHistory

Per-client history of what was sent, keyed by tick, so the next snapshot
can be encoded against whatever the client last acked.

```ts check=skip
class SnapshotHistory {
  constructor(capacity?: number);
  put(tick: number, entities: readonly QEntity[] | ReadonlyMap<number, QEntity>): void;
  get(tick: number): ReadonlyMap<number, QEntity> | undefined;
  pruneBefore(tick: number): void;
  get size(): number;
}
```

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

### VirtualNet

```ts check=skip
class VirtualNet {
  constructor(seed?: number);
  now: number;
  sent: number;
  dropped: number;
  random(): number;
  send(link: LinkOptions, deliver: () => void): void;
  advanceTo(t: number): void;
}
```

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

## Constants

### DEFAULT_CLIENT

```ts check=skip
const DEFAULT_CLIENT: NetClientOptions;
```

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

### DEFAULT_INPUT_QUEUE

```ts check=skip
const DEFAULT_INPUT_QUEUE: InputQueueOptions;
```

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

### GAME_SLUG_RE

A game slug as the GameFactory and the room server take it.

```ts check=skip
const GAME_SLUG_RE: RegExp;
```

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

### GUEST_ID_RE

Guest profile ids: 16-80 characters of A-Z, a-z, 0-9, _ or - (the same rule as Launcher guest drafts).

```ts check=skip
const GUEST_ID_RE: RegExp;
```

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

### GUEST_KEY

Storage key for the guest id: shared by every game on one origin, like a Launcher guest.

```ts check=skip
const GUEST_KEY: "netnet:guest:v1";
```

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

### MSG_INPUT

```ts check=skip
const MSG_INPUT: 1;
```

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

### MSG_SNAPSHOT

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

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

### REDUNDANCY

How many unacked commands each packet repeats.

```ts check=skip
const REDUNDANCY: 4;
```

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

### ROOM_NAME

```ts check=skip
const ROOM_NAME: "instance";
```

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

## Types

### ClientStats

```ts check=skip
interface ClientStats {
  snapshots: number;
  snapshotBytes: number;
  inputPackets: number;
  inputBytes: number;
  baselineMisses: number;
  staleSnapshots: number;
}
```

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

### CommandMessage

Client -> server: a store hook (paid revive, cosmetic). The room verifies before the sim applies it.

```ts check=skip
interface CommandMessage {
  readonly name: string;
  readonly value?: number;
  readonly proof?: string;
}
```

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

### CommandResult

Server -> client: the outcome of a command.

```ts check=skip
interface CommandResult {
  readonly name: string;
  readonly ok: boolean;
  readonly reason?: string;
}
```

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

### CreateOptions

```ts check=skip
interface CreateOptions {
  readonly place: string;
  readonly template: string;
  readonly game?: string;
}
```

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

### DecodedSnapshot

```ts check=skip
interface DecodedSnapshot {
  readonly header: SnapshotHeader;
  readonly entities: ReadonlyMap<number, QEntity>;
  readonly removed: readonly number[];
}
```

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

### EarnEvent

Something the authoritative sim says a player earned.

```ts check=skip
interface EarnEvent {
  readonly type: 'earn';
  readonly player: PlayerId;
  readonly rule: string;
  readonly units: number;
}
```

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

### EarnMessage

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

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

### EarnRefusal

```ts check=skip
type EarnRefusal = 'guest' | 'wallet-busy' | 'session';
```

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

### Eip1193

The slice of an EIP-1193 provider sign-in needs.

```ts check=skip
interface Eip1193 {
  request(args: { method: string; params?: unknown[] }): Promise<unknown>;
}
```

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

### EntitySchema

```ts check=skip
interface EntitySchema {
  readonly fields: readonly FieldSpec[];
  readonly xField: number;
  readonly yField: number;
  readonly unitsPerWorld: number;
  readonly kindFields?: Readonly<Record<number, readonly number[]>>;
}
```

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

### EntityState

One entity as the sim reports it: values are real (dequantized) numbers.

```ts check=skip
interface EntityState {
  readonly id: number;
  readonly kind: number;
  readonly owner: number;
  readonly values: readonly number[];
}
```

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

### FieldSpec

```ts check=skip
type FieldSpec =
  | { readonly name: string; readonly kind: 'uint'; readonly bits: number; readonly interp?: Interp; readonly deltaBits?: number }
  | { readonly name: string; readonly kind: 'int'; readonly bits: number; readonly interp?: Interp; readonly deltaBits?: number }
  | {
      readonly name: string;
      readonly kind: 'quant';
      readonly min: number;
      readonly max: number;
      readonly bits: number;
      readonly interp?: Interp;
      readonly deltaBits?: number;
    }
  | { readonly name: string; readonly kind: 'angle16'; readonly deltaBits?: number }
  | { readonly name: string; readonly kind: 'bool' };
```

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

### GameProfile

A player's saved progress in one game, kept by the room server: the same on every device the player signs in on.
Achievements, goals and titles come from the authoritative sim only.

```ts check=skip
interface GameProfile {
  readonly game: string;
  readonly kind: 'wallet' | 'guest' | null;
  readonly wallet: string | null;
  readonly displayName: string | null;
  readonly achievements: readonly { readonly id: string; readonly at: number; readonly source: 'sim' | 'import' }[];
  readonly keepers: readonly string[];
  readonly owned: readonly string[];
  readonly cosmetics: readonly number[];
  readonly meta: Readonly<Record<string, number>>;
  readonly goals: { readonly day: number; readonly today: readonly string[]; readonly done: readonly string[] };
  readonly titles: Readonly<Record<string, number>>;
  readonly settings: Readonly<Record<string, unknown>>;
  readonly store: readonly ProfileStoreItem[];
  readonly imported: boolean;
  readonly credit: number;
  readonly totals: { readonly achievements: number; readonly titles: number; readonly games: number };
}
```

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

### Hitbox

```ts check=skip
interface Hitbox {
  readonly entity: number;
  readonly owner: PlayerId;
  readonly x: number;
  readonly y: number;
  readonly r: number;
}
```

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

### HitscanRequest

A hitscan the sim wants resolved against lag-compensated hitboxes.

```ts check=skip
interface HitscanRequest {
  readonly shooter: PlayerId;
  readonly ox: number;
  readonly oy: number;
  readonly dx: number;
  readonly dy: number;
  readonly range: number;
}
```

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

### InputCodec

```ts check=skip
interface InputCodec<I> {
  write(w: BitWriter, input: I): void;
  read(r: BitReader): I;
  readonly idle: I;
}
```

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

### InputCommand

```ts check=skip
interface InputCommand<I> {
  readonly seq: number;
  readonly viewTick16: number;
  readonly input: I;
}
```

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

### InputPacket

```ts check=skip
interface InputPacket<I> {
  readonly ackTick: number;
  readonly commands: readonly InputCommand<I>[];
}
```

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

### InputQueueOptions

```ts check=skip
interface InputQueueOptions {
  readonly maxQueue: number;
  readonly maxCredits: number;
  readonly targetDepth?: number;
}
```

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

### Interp

```ts check=skip
type Interp = 'lerp' | 'step';
```

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

### InterpolatedEntity

```ts check=skip
interface InterpolatedEntity {
  readonly id: number;
  readonly kind: number;
  readonly owner: number;
  readonly values: readonly number[];
}
```

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

### JoinOptions

```ts check=skip
interface JoinOptions {
  readonly wallet?: string;
  readonly session?: string;
  readonly guest?: string;
}
```

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

### JoinParams

```ts check=skip
interface JoinParams {
  readonly endpoint: string; // http(s)://host:port
  readonly place: string;
  readonly template: string;
  readonly game?: string;
  readonly wallet?: string;
  readonly session?: string;
  readonly guest?: string;
  readonly friendRoomId?: string;
}
```

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

### LinkOptions

```ts check=skip
interface LinkOptions {
  readonly latencyMs: number;
  readonly jitterMs: number;
  readonly loss: number;
}
```

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

### LocalProgress

```ts check=skip
interface LocalProgress {
  readonly achievements?: readonly string[];
  readonly goals?: { readonly day: number; readonly done: readonly string[] };
  readonly settings?: Readonly<Record<string, unknown>>;
}
```

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

### NetClientOptions

```ts check=skip
interface NetClientOptions {
  readonly interpDelayMs: number;
  readonly inputBufferTarget?: number;
  readonly firstSeq?: number;
}
```

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

### PlayerId

Small integer assigned by the room to each connected player (1..65535).

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

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

### PlayerRights

What a player's profile lets them choose (the room checks it on every input).

```ts check=skip
interface PlayerRights {
  readonly keepers: readonly number[] | null;
}
```

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

### PotMessage

Server -> client ('pot'): 'in' this round's pot holds the player's entry
(`pot` is the whole pot so far); 'waiting' the entry is placed for the
next round; 'closed' the round split the pot (`paid` is this player's
part); 'refused' (`reason`). Whole coins.

```ts check=skip
interface PotMessage {
  readonly state: 'in' | 'waiting' | 'closed' | 'refused';
  readonly entry: number;
  readonly pot?: number;
  readonly paid?: number;
  readonly reason?: string;
}
```

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

### ProfileAuth

Who is asking: a signed-in session (bearer) or a guest id.

```ts check=skip
type ProfileAuth = { readonly session: string } | { readonly guest: string };
```

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

### ProfileStoreItem

One item of a game's permanent store as a profile sees it (cosmetics, unlocks, meta levels).

```ts check=skip
interface ProfileStoreItem {
  readonly id: string;
  readonly kind: 'cosmetic' | 'unlock' | 'meta' | 'gear';
  readonly coins: number | null;
  readonly owned: boolean;
  readonly cosmetic?: number;
  readonly keeper?: string;
  readonly gear?: string;
  readonly loseBelow?: number;
  readonly stat?: string;
  readonly step?: number;
  readonly level?: number;
  readonly levels?: number;
  readonly bonus?: number;
}
```

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

### ProgressEvent

The sim says a player reached something their profile keeps: an achievement, one of today's goals,
or an end-screen title. The room writes it to the player's profile on
the server; the browser never grants these.

```ts check=skip
interface ProgressEvent {
  readonly type: 'progress';
  readonly player: PlayerId;
  readonly kind: 'achievement' | 'goal' | 'title';
  readonly id: string;
}
```

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

### QEntity

One entity on the wire, values already quantized.

```ts check=skip
interface QEntity {
  readonly id: number;
  readonly kind: number;
  readonly owner: number;
  readonly q: readonly number[];
}
```

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

### RebaseMessage

Server -> client: the room rebuilt its world at a safe point (between
rounds): a new logic module (hot swap, `version` changed) or a fresh
verification segment. The player keeps its id; its entity id may change,
baselines are void and the next snapshot is full.

```ts check=skip
interface RebaseMessage {
  readonly entity: number;
  readonly sim: string;
  readonly version: string;
}
```

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

### RoomConnection

```ts check=skip
interface RoomConnection<W, I> {
  readonly room: Room;
  readonly net: NetClient<W, I>;
  readonly welcome: WelcomeMessage;
  readonly roomId: string;
  bytesIn(): number;
  messagesIn(): number;
  onEarn(cb: (e: EarnMessage) => void): void;
  onRun(cb: (info: unknown) => void): void;
  latestRun(): unknown;
  onRunId(cb: (m: RunIdMessage) => void): void;
  onRebase(cb: (m: RebaseMessage) => void): void;
  signIn(session: string): Promise<SignInResult>;
  onProfile(cb: (p: GameProfile) => void): void;
  latestProfile(): GameProfile | null;
  stake(amount?: number): void;
  onStake(cb: (m: StakeMessage) => void): void;
  latestStake(): StakeMessage | null;
  pot(): void;
  onPot(cb: (m: PotMessage) => void): void;
  command(cmd: CommandMessage): Promise<CommandResult>;
  claim(): Promise<unknown>;
  leave(): Promise<void>;
}
```

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

### RunIdMessage

Server -> client: a fresh referee run started (new runId after a run reset).

```ts check=skip
interface RunIdMessage {
  readonly runId: string | null;
}
```

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

### RunResetEvent

The sim started a fresh run in place (game over or victory screen ended). Referee runs restart.

```ts check=skip
interface RunResetEvent {
  readonly type: 'run.reset';
}
```

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

### SignInMessage

Client -> server: sign in mid-session (a guest who just signed the SIWE message).

```ts check=skip
interface SignInMessage {
  readonly session: string;
}
```

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

### SignInResult

Server -> client: the outcome of a mid-session sign-in.

```ts check=skip
interface SignInResult {
  readonly ok: boolean;
  readonly runId: string | null;
  readonly earnRefused?: EarnRefusal;
}
```

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

### SimAdapter

```ts check=skip
interface SimAdapter<W, I> {
  readonly name: string;
  readonly version: string;
  readonly tickHz: number;
  readonly schema: EntitySchema;
  readonly input: InputCodec<I>;
  readonly maxInputsPerTick?: number;
  createWorld(seed: number, role: 'server' | 'client'): W;
  addPlayer(world: W, player: PlayerId): number;
  removePlayer(world: W, player: PlayerId): void;
  step(world: W, inputsByPlayer: ReadonlyMap<PlayerId, readonly I[]>): readonly SimEvent[];
  snapshot(world: W): readonly EntityState[];
  applySnapshot(world: W, entities: readonly EntityState[]): void;
  hitscans?(world: W, player: PlayerId, input: I): HitscanRequest | null;
  hitboxes?(world: W): readonly Hitbox[];
  applyHit?(world: W, shooter: PlayerId, target: Hitbox): readonly SimEvent[];
  info?(world: W): unknown;
  infoFor?(world: W, player: PlayerId): unknown;
  readonly infoEveryTicks?: number;
  restrictInput?(input: I, rights: PlayerRights): I;
  command?(world: W, player: PlayerId, cmd: SimCommand): boolean;
  startRun?(world: W, player: PlayerId): void;
  disposeWorld?(world: W): void;
}
```

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

### SimCommand

A room-level command from a player (store hooks): a paid revive, a cosmetic.

```ts check=skip
interface SimCommand {
  readonly name: string;
  readonly value?: number;
}
```

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

### SimEvent

```ts check=skip
type SimEvent = EarnEvent | RunResetEvent | ProgressEvent;
```

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

### SnapshotHeader

```ts check=skip
interface SnapshotHeader {
  readonly tick: number;
  readonly baselineTick: number;
  readonly ackSeq: number;
  readonly self: number;
  readonly inputBuffer?: number;
}
```

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

### StakeMessage

Server -> client ('stake'): 'live' the run in progress is staked;
'waiting' a stake is placed for the next run; 'closed' a staked run ended
(`paid` is its stake share); 'refused' the stake was not taken (`reason`).
Amounts are whole coins.

```ts check=skip
interface StakeMessage {
  readonly state: 'live' | 'waiting' | 'closed' | 'refused';
  readonly stake: number;
  readonly ceiling?: number;
  readonly paid?: number;
  readonly reason?: string;
  readonly gear?: readonly string[];
  readonly lost?: readonly string[];
}
```

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

### StakeRequest

Client -> server ('stake'): the player spent a stake (the Kit's
coins.spend(amount, "stake"), committed). The room fixes the stake from
its own ledger when a run starts: always the NEXT run (sign-in or the
next round; a run in progress never restarts), and a
staked run starts from zero earn progress. `amount` (whole coins) is read only
by a room whose store runs in mock mode (local play).

```ts check=skip
interface StakeRequest {
  readonly amount?: number;
}
```

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

### StakeTermsView

A game's buy-in run terms as a client shows them (whole coins).

```ts check=skip
interface StakeTermsView {
  readonly min: number;
  readonly max: number;
  readonly multiple: number;
}
```

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

### WelcomeMessage

```ts check=skip
interface WelcomeMessage {
  readonly player: number;
  readonly entity: number;
  readonly tickHz: number;
  readonly snapshotHz: number;
  readonly sim: string;
  readonly version: string;
  readonly place: string;
  readonly template: string;
  readonly runId: string | null;
  readonly earnLive: boolean;
  readonly earnRefused?: EarnRefusal;
  readonly stake?: StakeTermsView;
  readonly pot?: { readonly entry: number; readonly recycle: number };
}
```

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