# @netforge/engine API reference

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

The API a game is written against: `game`, `prefab`, `weapon`, `upgrade`, `director`, `system`, `earn`, `store` and the headless test harness `engine.test.run`. Declarative and Zod-validated, with no DOM, renderer or netcode. This is the only module `src/game.ts` may import.

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

Generated from `packages/engine/src/index.ts` by `apps/forge-docs/scripts/api.mjs`. Signatures are what the TypeScript compiler reports for the current source; long types are cut and say so.

| Kind | Count |
|---|---|
| Functions | 23 |
| Classes | 1 |
| Constants | 38 |
| Types | 83 |

## Functions

### achievement

Declare an achievement (counted per player per run; it unlocks keepers, never coins).

```ts check=skip
function achievement(id: string, def: AchievementInput): AchievementDef;
```

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

### card

A card (at most 40).

```ts check=skip
function card(id: string, def: CardInput): CardDef;
```

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

### cardTable

The table: hero health, hand and board sizes, the gauntlet, the starter deck and the AI tiers (one per game).

```ts check=skip
function cardTable(def: CardTableInput): CardTableDef;
```

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

### creature

A creature players meet, fight and catch (at most 24).

```ts check=skip
function creature(id: string, def: CreatureInput): CreatureDef;
```

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

### director

Declare the spawn director (at most one per game): who spawns, how many,
how fast and how tough, over the run's clock. See directorSchema.

```ts check=skip
function director(def: DirectorInput): DirectorDef;
```

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

### dungeon

Build a dungeon floor from a spec. Throws GameDefinitionError with readable lines on a bad spec.

```ts check=skip
function dungeon(spec: DungeonSpec): DungeonLayout;
```

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

### economy

Declare the game's coin model (at most once). Without it a game uses the
recommended default: coins buy cosmetics, unlocks and in-run consumables,
never permanent stat power. economy({ store: "cosmetics" }) sells looks
only; economy({ metaUpgrades: true }) opts in to metaUpgrade(...).

```ts check=skip
function economy(def?: EconomyInput): EconomyDef;
```

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

### game

Declare the game. Exactly one per game module; it is the module's default export.

```ts check=skip
function game(def: GameInput): GameDef;
```

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

### keeper

Declare a keeper (a playable character): a start weapon and a signature
passive. Players pick one before their first level; at most 15.

```ts check=skip
function keeper(id: string, def: KeeperInput): KeeperDef;
```

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

### marsh

The marsh: its size, camp, starters, grass, blocked tiles and warden (one per game).

```ts check=skip
function marsh(def: MarshInput): MarshDef;
```

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

### metaUpgrade

Declare a meta upgrade: a permanent stat bonus a player buys with coins,
level by level (opt-in: economy({ metaUpgrades: true })). The engine caps
meta power at +15% per stat and +30% in total, and costs grow
geometrically. The store shows every level's bonus and price.

```ts check=skip
function metaUpgrade(id: string, def: MetaUpgradeInput): MetaUpgradeDef;
```

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

### mission

Declare a daily goal (the HUD shows three a day; it pays nothing).

```ts check=skip
function mission(id: string, def: MissionInput): MissionDef;
```

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

### move

A move creatures use in battle (at most 48).

```ts check=skip
function move(id: string, def: MoveInput): MoveDef;
```

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

### plant

A plant players buy and level (at most 8).

```ts check=skip
function plant(id: string, def: PlantInput): PlantDef;
```

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

### prefab

Declare a prefab: a spawnable entity template.

```ts check=skip
function prefab(id: string, def: PrefabInput): PrefabDef;
```

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

### saltFlat

The flat: shift length, tending, raking, the chain's ratios and the shared contract (one per game).

```ts check=skip
function saltFlat(def: SaltFlatInput): SaltFlatDef;
```

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

### system

Declare a system. `setup` runs once when a run starts and schedules work with `every`, `after`, `onTick`.

```ts check=skip
function system(name: string, setup: SystemSetup): void;
```

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

### title

Declare an end-screen title ("The Butcher": the most kills).

```ts check=skip
function title(id: string, def: TitleInput): TitleDef;
```

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

### tower

A tower players build (at most 8).

```ts check=skip
function tower(id: string, def: TowerInput): TowerDef;
```

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

### towerBoard

The board: its size, the creeps' road, lives and starting gold (one per game).

```ts check=skip
function towerBoard(def: TowerBoardInput): TowerBoardDef;
```

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

### upgrade

Declare a passive upgrade offered at level-up (survivor template).

```ts check=skip
function upgrade(id: string, def: UpgradeInput): UpgradeDef;
```

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

### waves

The waves (one per game).

```ts check=skip
function waves(def: WavesInput): WavesDef;
```

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

### weapon

Declare a weapon (survivor template): it fires by itself; players gain and level weapons at level-up.

```ts check=skip
function weapon(id: string, def: WeaponInput): WeaponDef;
```

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

## Classes

### GameDefinitionError

Thrown for any invalid declaration; `issues` are agent-readable lines.

```ts check=skip
class GameDefinitionError {
  constructor(where: string, issues: readonly string[]);
  readonly issues: readonly string[];
}
```

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

## Constants

### AI_BEHAVIOURS

Enemy behaviours the sim runs (roles). Every big hit is telegraphed with
a ground marker that fills before it lands.
 - chase (default): runs at the nearest player. tank: chase, for slow heavy prefabs (give it mass).
 - idle / none: stands still.
 - runner: aims where the player will be in 0.5 s. Fast and fragile.
 - charger: inside attack.range (6 m) stops, shows a lane for 0.55 s, dashes 3.4x along it for 0.6 s, recovers 1 s.
 - ranged: keeps ~80% of attack.range (10 m), backs off, shows an aim line 0.3 s, fires a slow shot (attack.speed 7 m/s).
 - bomber: next to a player stops, arms a 1 s fuse circle (attack.radius 2.5 m), explodes for 1.4x damage; the blast hurts enemies too.
 - shielder: every 6 s shields the 6 nearest allies for 35% of their health, 8 s.
 - healer: every 3.5 s heals the 6 nearest allies 7%.
 - summoner: keeps its distance and calls attack.count (2) attack.summon adds every 7 s, at most 4 alive.
 - flee: runs from the nearest player. wander: drifts.
Anything else is rejected at build time, never silently ignored.

```ts check=skip
const AI_BEHAVIOURS: readonly ["none", "chase", "idle", "tank", "runner", "charger", "ranged", "bomber", "shielder", "healer", "summoner", "flee", "wander"];
```

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

### APPEARANCE_PARTS

Attachments an appearance can add. Each sits on an anchor the body plan has (head, face, back, tail, body, wheels).

```ts check=skip
const APPEARANCE_PARTS: readonly ["horns", "ears_long", "ears_round", "antenna", "crown", "hat_cap", "hat_top", "mustache", "tail", "tail_bolt", "wings", "armor", "backpack", "big_wheels"];
```

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

### appearanceSchema

```ts check=skip
const appearanceSchema: z.ZodObject<{ tint: z.ZodOptional<z.ZodString>; accent: z.ZodOptional<z.ZodString>; scale: z.ZodOptional<z.ZodNumber>; parts: z.ZodDefault<z.ZodArray<z.ZodEnum<{ horns: "horns"; ears_long: "ears_long"; ears_round: "ears_round"; antenna: "antenna"; crown: "crown"; hat_cap: "hat_cap"; hat_top: "hat_top"; mustache: "mustache"; tail: "tail"; tail_bolt: "tail_bolt"; wings: "wings"; armor: "armor"; backpack: "backpack"; big_wheels: "big_wheels"; }>>>; }, z.core.$strict>;
```

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

### CARD_STATS

Store upgrade stats a card battler reads: hero health, unit attack, starting mana, starting hand.

```ts check=skip
const CARD_STATS: readonly ["maxHealth", "might", "haste", "amount"];
```

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

### COLLECTOR_STATS

Store upgrade stats a collector game reads: team attack, team health, team defence, extra snares, healing between battles.

```ts check=skip
const COLLECTOR_STATS: readonly ["might", "maxHealth", "armor", "amount", "regen"];
```

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

### DECAL_PRESETS

Ground decals left behind (scorch marks, splats, shock rings).

```ts check=skip
const DECAL_PRESETS: readonly ["none", "scorch", "splat", "ring"];
```

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

### dungeonSchema

```ts check=skip
const dungeonSchema: z.ZodObject<{ seed: z.ZodNumber; rooms: z.ZodNumber; cell: z.ZodDefault<z.ZodNumber>; size: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>; corridor: z.ZodDefault<z.ZodNumber>; loops: z.ZodDefault<z.ZodNumber>; }, z.core.$strict>;
```

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

### earn

Earn rules (every game must have at least one).

```ts check=skip
const earn: { rule(id: string, def: EarnRuleInput): EarnRuleDef; stake(def: EarnStakeInput): EarnStakeDef; pot(def: EarnPotInput): EarnPotDef; };
```

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

### EFFECT_KINDS

```ts check=skip
const EFFECT_KINDS: readonly ["damage", "heal", "draw", "buff"];
```

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

### EFFECT_TARGETS

Who an effect hits. "enemy": the player picks an enemy unit or the enemy
hero; "enemy_hero"; "all_enemies": every enemy unit; "own_hero";
"own_unit": the player picks one of their units; "all_own": every unit
they have. draw ignores the target.

```ts check=skip
const EFFECT_TARGETS: readonly ["enemy", "enemy_hero", "all_enemies", "own_hero", "own_unit", "all_own"];
```

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

### ELEMENTS

The four elements, a cycle: each one is strong against the next and weak
against the one before (root soaks tide, tide shorts spark, spark cracks
stone, stone crushes root). Strong hits deal 1.5x, weak ones 0.67x.

```ts check=skip
const ELEMENTS: readonly ["root", "tide", "spark", "stone"];
```

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

### engine

`engine.test.run({ ticks, bots, assert })`: the headless playtest.

```ts check=skip
const engine: { readonly test: { readonly run: (opts: HarnessOptions) => Promise<HarnessReport>; }; };
```

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

### IDLE_MAX_TEND

The longest tending window (seconds): a works nobody touches for this long stops.

```ts check=skip
const IDLE_MAX_TEND: 300;
```

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

### IDLE_MIN_SHIFT

The shortest shift (seconds): earn rules pay once a shift, so this bounds what one seat can earn an hour.

```ts check=skip
const IDLE_MIN_SHIFT: 600;
```

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

### IDLE_STATS

Store upgrade stats an idle game reads: plant output (might), raking speed (haste), salt a rake (amount).

```ts check=skip
const IDLE_STATS: readonly ["might", "haste", "amount"];
```

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

### LOOK_PRESETS

Lighting presets of the engine's render stack (sun, sky, fog and grading together).

```ts check=skip
const LOOK_PRESETS: readonly ["night", "dusk", "day", "studio"];
```

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

### META_MAX_LEVELS

Most levels of one meta upgrade, most meta upgrades per game, and the slowest cost growth (geometric).

```ts check=skip
const META_MAX_LEVELS: 5;
```

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

### META_MAX_PER_STAT

Hard caps (engine-enforced, not a game setting): +15% to any one stat from meta upgrades, +30% across all of them.

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

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

### META_MAX_TOTAL

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

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

### META_MAX_UPGRADES

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

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

### META_MIN_GROWTH

```ts check=skip
const META_MIN_GROWTH: 1.5;
```

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

### META_STATS

Stats a meta upgrade may raise (each a percentage of the base).

```ts check=skip
const META_STATS: readonly ["speed", "maxHealth", "magnet", "might", "haste", "area"];
```

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

### MOVE_EFFECTS

```ts check=skip
const MOVE_EFFECTS: readonly ["none", "drain", "heal", "guard"];
```

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

### PARTICLE_PRESETS

GPU particle presets the engine draws (one draw call for all of them).

```ts check=skip
const PARTICLE_PRESETS: readonly ["sparks", "burst", "embers", "smoke", "hitSpark", "dust", "magic"];
```

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

### PLANT_KINDS

```ts check=skip
const PLANT_KINDS: readonly ["pump", "pan", "kiln"];
```

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

### POT_REASON

The coin spend reason a PvP pot entry is spent under.

```ts check=skip
const POT_REASON: "pot";
```

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

### SOUND_CUES

Procedural sound cues of the feel kit (no audio files needed).

```ts check=skip
const SOUND_CUES: readonly ["none", "hit", "crunch", "boom", "zap", "chime", "thud"];
```

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

### STAKE_MAX_COINS

Highest stake one run may take, in coins (the source reader's bound too).

```ts check=skip
const STAKE_MAX_COINS: 1000000;
```

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

### STAKE_MAX_MULTIPLE

PLACEHOLDER: the most a stake's payout ceiling may be, as a multiple of the stake.

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

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

### STAKE_REASON

The coin spend reason a buy-in run's stake is spent under (the referee reads it at run start).

```ts check=skip
const STAKE_REASON: "stake";
```

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

### STAT_KINDS

```ts check=skip
const STAT_KINDS: readonly ["speed", "maxHealth", "magnet", "might", "haste", "regen", "armor", "area", "amount"];
```

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

### store

Store SKUs: upgrades and cosmetics priced in the game's coins (and/or USDG).

```ts check=skip
const store: { sku(id: string, def: SkuInput): SkuDef; };
```

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

### STYLES

Art styles of the asset library.

```ts check=skip
const STYLES: readonly ["pixel", "lowpoly", "toon", "voxel", "ps1", "handdrawn"];
```

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

### TEMPLATES

Templates carry the genre machinery; the model adds content and rules.

```ts check=skip
const TEMPLATES: readonly ["survivor", "arena", "dungeon", "racer", "platformer", "tower-defense", "party", "idle", "cards", "collector"];
```

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

### TITLE_STATS

What end-screen titles rank players by.

```ts check=skip
const TITLE_STATS: readonly ["kills", "damage", "revives", "downs", "level", "pickups"];
```

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

### TOWER_KINDS

```ts check=skip
const TOWER_KINDS: readonly ["bolt", "splash", "frost", "chain"];
```

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

### TOWER_STATS

Store upgrade stats a tower defense game reads: tower damage, fire rate, range, and team lives.

```ts check=skip
const TOWER_STATS: readonly ["might", "haste", "area", "maxHealth"];
```

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

### WEAPON_KINDS

```ts check=skip
const WEAPON_KINDS: readonly ["nova", "bolt", "orbit", "blaster", "beam", "cone", "chain", "aura", "meteor", "boomerang"];
```

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

## Types

### AchievementDef

```ts check=skip
type AchievementDef = z.output<typeof achievementSchema>;
```

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

### AchievementInput

```ts check=skip
type AchievementInput = z.input<typeof achievementSchema>;
```

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

### AppearanceDef

```ts check=skip
type AppearanceDef = z.output<typeof appearanceSchema>;
```

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

### AppearanceInput

```ts check=skip
type AppearanceInput = z.input<typeof appearanceSchema>;
```

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

### AppearancePart

```ts check=skip
type AppearancePart = (typeof APPEARANCE_PARTS)[number];
```

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

### AssetId

```ts check=skip
type AssetId = string;
```

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

### CardDef

```ts check=skip
type CardDef = z.output<typeof cardSchema>;
```

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

### CardInput

```ts check=skip
type CardInput = z.input<typeof cardSchema>;
```

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

### CardTableDef

```ts check=skip
type CardTableDef = z.output<typeof cardTableSchema>;
```

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

### CardTableInput

```ts check=skip
type CardTableInput = z.input<typeof cardTableSchema>;
```

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

### CreatureDef

```ts check=skip
type CreatureDef = z.output<typeof creatureSchema>;
```

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

### CreatureInput

```ts check=skip
type CreatureInput = z.input<typeof creatureSchema>;
```

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

### Curve

```ts check=skip
type Curve = z.output<typeof curveSchema>;
```

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

### CurveInput

```ts check=skip
type CurveInput = z.input<typeof curveSchema>;
```

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

### DecalPreset

```ts check=skip
type DecalPreset = (typeof DECAL_PRESETS)[number];
```

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

### DirectorDef

```ts check=skip
type DirectorDef = z.output<typeof directorSchema>;
```

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

### DirectorInput

```ts check=skip
type DirectorInput = z.input<typeof directorSchema>;
```

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

### DungeonLayout

```ts check=skip
interface DungeonLayout {
  readonly field: { readonly halfSize: number; readonly pillars: [number, number, number][]; readonly walls: Box[]; readonly floors: Box[] };
  readonly rooms: readonly DungeonRoom[];
  readonly start: DungeonRoom;
  readonly boss: DungeonRoom;
  roomAt(x: number, z: number): number;
}
```

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

### DungeonRoom

```ts check=skip
interface DungeonRoom {
  readonly id: number;
  readonly x: number;
  readonly z: number;
  readonly hx: number;
  readonly hz: number;
  readonly depth: number;
  readonly links: readonly number[];
}
```

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

### DungeonSpec

```ts check=skip
type DungeonSpec = z.input<typeof dungeonSchema>;
```

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

### EarnPotDef

```ts check=skip
type EarnPotDef = z.output<typeof earnPotSchema>;
```

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

### EarnPotInput

```ts check=skip
type EarnPotInput = z.input<typeof earnPotSchema>;
```

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

### EarnRuleDef

```ts check=skip
type EarnRuleDef = z.output<typeof earnRuleSchema>;
```

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

### EarnRuleInput

```ts check=skip
type EarnRuleInput = z.input<typeof earnRuleSchema>;
```

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

### EarnStakeDef

```ts check=skip
type EarnStakeDef = z.output<typeof earnStakeSchema>;
```

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

### EarnStakeInput

```ts check=skip
type EarnStakeInput = z.input<typeof earnStakeSchema>;
```

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

### EconomyDef

```ts check=skip
type EconomyDef = z.output<typeof economySchema>;
```

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

### EconomyInput

```ts check=skip
type EconomyInput = z.input<typeof economySchema>;
```

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

### EdgeSide

Where `spawnEdge` places enemies around the target player's screen.

```ts check=skip
type EdgeSide = "any" | "ahead" | "behind" | "north" | "south" | "east" | "west";
```

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

### Element

```ts check=skip
type Element = (typeof ELEMENTS)[number];
```

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

### FeelDef

```ts check=skip
type FeelDef = z.output<typeof feelSchema>;
```

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

### FunMetrics

How fun the opening and the run felt to the bots, measured (GAME-DESIGN.md).
Horde games (survivor-like) are measured over the first run; arena games
over every life. Fields that do not apply to the genre are null.

```ts check=skip
interface FunMetrics {
  readonly genre: "horde" | "arena" | "race";
  readonly firstThreatSeconds: number | null;
  readonly firstRewardSeconds: number | null;
  readonly levelAt: { readonly "60": number | null; readonly "180": number | null; readonly "360": number | null; readonly "540": number | null };
  readonly deathsBeforeMinute: number | null;
  readonly onScreenAt30: number | null;
  readonly contactHitsFirstMinute: number | null;
  readonly telegraphedDeathShare: number | null;
  readonly spawnsOnScreen: number | null;
  readonly survivalSeconds: number | null;
  readonly spawnToDamageSeconds: number | null;
  readonly spawnDeathShare: number | null;
  readonly killSpread: number | null;
  readonly leadChanges: number | null;
  readonly bossKills: readonly { readonly prefab: string; readonly seconds: number }[];
  readonly downsBySource: Readonly<Record<string, number>>;
  readonly firstHitSeconds?: number | null;
  readonly lowestHealthBy120?: number | null;
  readonly firstEliteSeconds?: number | null;
  readonly firstBossSeconds?: number | null;
  readonly downTimeShare?: number | null;
  readonly finishSeconds?: number | null;
  readonly finishRate?: number | null;
  readonly mishapsPerRound?: number | null;
  readonly firstCoinSeconds?: number | null;
  readonly routes?: readonly { readonly course: number; readonly found: boolean; readonly seconds: number | null }[];
}
```

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

### GameDef

```ts check=skip
type GameDef = z.output<typeof gameSchema>;
```

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

### GameInput

```ts check=skip
type GameInput = z.input<typeof gameSchema>;
```

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

### GameManifest

```ts check=skip
interface GameManifest {
  readonly game: GameDef;
  readonly prefabs: ReadonlyMap<string, PrefabDef>;
  readonly weapons: ReadonlyMap<string, WeaponDef>;
  readonly upgrades: ReadonlyMap<string, UpgradeDef>;
  readonly systems: ReadonlyMap<string, SystemSetup>;
  readonly earnRules: ReadonlyMap<string, EarnRuleDef>;
  readonly stake: EarnStakeDef;
  readonly pot: EarnPotDef | null;
  readonly skus: ReadonlyMap<string, SkuDef>;
  readonly director: DirectorDef | null;
  readonly keepers: ReadonlyMap<string, KeeperDef>;
  readonly achievements: ReadonlyMap<string, AchievementDef>;
  readonly missions: ReadonlyMap<string, MissionDef>;
  readonly titles: ReadonlyMap<string, TitleDef>;
  readonly economy: EconomyDef;
  readonly metaUpgrades: ReadonlyMap<string, MetaUpgradeDef>;
  readonly content: ReadonlyMap<string, unknown>;
}
```

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

### HarnessAssertion

Headless test harness: run a game on the server sim
with bot players and report what happened.

When a game module has been declared (game(), prefabs, weapons, systems,
earn rules), it runs that game exactly as the room server does: compiled
content in engine-sim, the systems on the GameRunner, earn rules counted
per player. With no game declared it runs the week-2 engine-sim arena
(the built-in chaser spawner) with scripted bots.

```ts check=skip
interface HarnessAssertion {
  readonly name: string;
  readonly check: (report: HarnessReport) => boolean;
}
```

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

### HarnessOptions

```ts check=skip
interface HarnessOptions {
  readonly ticks: number;
  readonly bots: number;
  readonly enemies?: number;
  readonly seed?: number;
  readonly tickRate?: number;
  readonly assert?: readonly HarnessAssertion[];
  readonly bot?: "basic" | "human";
  readonly picks?: "random" | "greedy";
  readonly enemyMix?: boolean;
}
```

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

### HarnessReport

```ts check=skip
interface HarnessReport {
  readonly ticks: number;
  readonly bots: number;
  readonly deaths: number;
  readonly kills: number;
  readonly wave: number;
  readonly runs: { readonly won: number; readonly lost: number };
  readonly maxLevel: number;
  readonly peakEnemies: number;
  readonly topScore: number;
  readonly scorers: number;
  readonly earned: Readonly<Record<string, number>>;
  readonly msPerTick: number;
  readonly p99MsPerTick: number;
  readonly earnEmitted: number;
  readonly softlock: boolean;
  readonly fun?: FunMetrics;
  readonly rules?: { readonly template: string; readonly checks: readonly { readonly ok: boolean; readonly line: string }[]; readonly progress: number };
  readonly failed: readonly string[];
}
```

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

### KeeperDef

```ts check=skip
type KeeperDef = z.output<typeof keeperSchema>;
```

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

### KeeperInput

```ts check=skip
type KeeperInput = z.input<typeof keeperSchema>;
```

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

### LookDef

```ts check=skip
type LookDef = z.output<typeof lookSchema>;
```

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

### LookInput

```ts check=skip
type LookInput = z.input<typeof lookSchema>;
```

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

### LookPreset

```ts check=skip
type LookPreset = (typeof LOOK_PRESETS)[number];
```

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

### MarshDef

```ts check=skip
type MarshDef = z.output<typeof marshSchema>;
```

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

### MarshInput

```ts check=skip
type MarshInput = z.input<typeof marshSchema>;
```

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

### MetaStat

```ts check=skip
type MetaStat = (typeof META_STATS)[number];
```

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

### MetaUpgradeDef

```ts check=skip
type MetaUpgradeDef = z.output<typeof metaUpgradeSchema>;
```

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

### MetaUpgradeInput

```ts check=skip
type MetaUpgradeInput = z.input<typeof metaUpgradeSchema>;
```

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

### MissionDef

```ts check=skip
type MissionDef = z.output<typeof missionSchema>;
```

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

### MissionInput

```ts check=skip
type MissionInput = z.input<typeof missionSchema>;
```

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

### MoveDef

```ts check=skip
type MoveDef = z.output<typeof moveSchema>;
```

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

### MoveInput

```ts check=skip
type MoveInput = z.input<typeof moveSchema>;
```

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

### ParticlePreset

```ts check=skip
type ParticlePreset = (typeof PARTICLE_PRESETS)[number];
```

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

### PlantDef

```ts check=skip
type PlantDef = z.output<typeof plantSchema>;
```

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

### PlantInput

```ts check=skip
type PlantInput = z.input<typeof plantSchema>;
```

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

### PlayerView

A read-only view of one player, as game logic sees it.

```ts check=skip
interface PlayerView {
  readonly id: number;
  readonly position: readonly [number, number, number];
  readonly health: number;
  readonly alive: boolean;
  readonly kills: number;
  readonly deaths: number;
  readonly bot: boolean;
}
```

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

### PrefabDef

```ts check=skip
type PrefabDef = z.output<typeof prefabSchema>;
```

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

### PrefabInput

```ts check=skip
type PrefabInput = z.input<typeof prefabSchema>;
```

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

### SaltFlatDef

```ts check=skip
type SaltFlatDef = z.output<typeof saltFlatSchema>;
```

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

### SaltFlatInput

```ts check=skip
type SaltFlatInput = z.input<typeof saltFlatSchema>;
```

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

### SkuDef

```ts check=skip
type SkuDef = z.output<typeof skuSchema>;
```

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

### SkuGrant

```ts check=skip
type SkuGrant = z.output<typeof skuGrantSchema>;
```

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

### SkuInput

```ts check=skip
type SkuInput = z.input<typeof skuSchema>;
```

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

### SoundCue

```ts check=skip
type SoundCue = (typeof SOUND_CUES)[number];
```

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

### SpawnEdgeOptions

```ts check=skip
interface SpawnEdgeOptions {
  readonly count: number;
  readonly around?: number;
  readonly side?: EdgeSide;
  readonly spread?: number;
  readonly scale?: { readonly health?: number; readonly damage?: number; readonly xp?: number };
  readonly elite?: boolean;
}
```

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

### SpawnRingOptions

```ts check=skip
interface SpawnRingOptions {
  readonly count: number;
  readonly radius: number;
  readonly around?: number;
}
```

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

### Style

```ts check=skip
type Style = (typeof STYLES)[number];
```

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

### SystemContext

What a system can do. Deliberately small: no renderer, no network, no
physics handles. Systems run only on the authoritative side (the room
server and the headless harness); clients receive the results in
snapshots. Everything here is still deterministic (tick timers and the
sim's own random), because run verification replays it.

```ts check=skip
interface SystemContext {
  readonly tick: () => number;
  readonly time: () => number;
  readonly players: () => readonly PlayerView[];
  readonly every: (seconds: number, fn: (n: number) => void) => void;
  readonly after: (seconds: number, fn: () => void) => void;
  readonly onTick: (fn: () => void) => void;
  readonly spawn: (prefab: string, at: readonly [number, number, number], opts?: { readonly elite?: boolean }) => void;
  readonly spawnRing: (prefab: string, opts: SpawnRingOptions) => void;
  readonly spawnEdge: (prefab: string, opts: SpawnEdgeOptions) => number;
  readonly emit: (event: string, players?: readonly number[]) => void;
  readonly random: () => number;
  readonly alive: (prefab?: string) => number;
  readonly on: (event: string, fn: (players: readonly number[]) => void) => void;
  readonly respawnDead: () => void;
  readonly end: (outcome: "won" | "lost") => void;
  readonly spawnPickup: (prefab: string, at: readonly [number, number, number]) => void;
  readonly announce: (text: string, opts?: { readonly tone?: "info" | "danger" | "reward" }) => void;
  readonly bossAlive: () => boolean;
  readonly pauseDirector: (seconds: number) => void;
  readonly surge: (multiplier: number, seconds: number) => void;
  readonly upcoming: (label: string, seconds: number) => void;
  readonly xpBoost: (multiplier: number, seconds: number) => void;
  readonly scatter: (prefab: string, count: number) => number;
  readonly clear: (prefab: string) => number;
  readonly onScreen: (x: number, z: number) => boolean;
}
```

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

### SystemSetup

```ts check=skip
type SystemSetup = (ctx: SystemContext) => void;
```

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

### Template

```ts check=skip
type Template = (typeof TEMPLATES)[number];
```

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

### TitleDef

```ts check=skip
type TitleDef = z.output<typeof titleSchema>;
```

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

### TitleInput

```ts check=skip
type TitleInput = z.input<typeof titleSchema>;
```

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

### TitleStat

```ts check=skip
type TitleStat = (typeof TITLE_STATS)[number];
```

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

### TowerBoardDef

```ts check=skip
type TowerBoardDef = z.output<typeof towerBoardSchema>;
```

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

### TowerBoardInput

```ts check=skip
type TowerBoardInput = z.input<typeof towerBoardSchema>;
```

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

### TowerDef

```ts check=skip
type TowerDef = z.output<typeof towerSchema>;
```

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

### TowerInput

```ts check=skip
type TowerInput = z.input<typeof towerSchema>;
```

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

### UpgradeDef

```ts check=skip
type UpgradeDef = z.output<typeof upgradeSchema>;
```

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

### UpgradeInput

```ts check=skip
type UpgradeInput = z.input<typeof upgradeSchema>;
```

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

### WavesDef

```ts check=skip
type WavesDef = z.output<typeof wavesSchema>;
```

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

### WavesInput

```ts check=skip
type WavesInput = z.input<typeof wavesSchema>;
```

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

### WeaponDef

```ts check=skip
type WeaponDef = z.output<typeof weaponSchema>;
```

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

### WeaponInput

```ts check=skip
type WeaponInput = z.input<typeof weaponSchema>;
```

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