Schema & Types
The @world-forge/schema package defines every type in a world project. This page covers the key types and validation rules.
WorldProject
Section titled “WorldProject”The top-level container that holds an entire authored world:
interface WorldProject { id: string; name: string; description: string; version: string; genre: string; mode?: AuthoringMode; // dungeon | district | world | ocean | space | interior | wilderness tones: string[]; difficulty: string; narratorTone: string;
map: WorldMap; zones: Zone[]; connections: ZoneConnection[]; districts: District[]; landmarks: Landmark[]; dialogues: DialogueDefinition[];
playerTemplate?: PlayerTemplate; buildCatalog?: BuildCatalogDefinition; progressionTrees: ProgressionTreeDefinition[];
factionPresences: FactionPresence[]; pressureHotspots: PressureHotspot[];
entityPlacements: EntityPlacement[]; itemPlacements: ItemPlacement[]; encounterAnchors: EncounterAnchor[]; spawnPoints: SpawnPoint[]; assets: AssetEntry[]; assetPacks: AssetPack[]; // ... crafting, market, visual layers}AuthoringMode
Section titled “AuthoringMode”World Forge separates genre (fantasy, cyberpunk) from mode (dungeon, ocean, space). Genre is flavor — mode is scale. They are orthogonal: a cyberpunk dungeon and a pirate ocean are both valid.
type AuthoringMode = 'dungeon' | 'district' | 'world' | 'ocean' | 'space' | 'interior' | 'wilderness';The mode field on WorldProject is optional — projects without it default to 'dungeon' everywhere. Mode governs:
- Grid defaults —
createEmptyProject(mode)applies mode-specific width, height, and tile size - Connection vocabulary — each mode suggests relevant connection kinds (e.g., ocean uses channel/route, space uses docking/warp)
- Object creation defaults — connections default to the mode’s primary kind (dungeon→door, ocean→channel), entities default to mode-appropriate role (dungeon→enemy, district→npc), encounters use mode-relevant types, and zones use mode-specific name patterns (Chamber, Waters, Sector, etc.)
- Preset filtering — presets with
modesarrays are hidden when incompatible with the current mode - Guide text — the checklist adapts step labels per mode (e.g., “Add a chamber” vs “Add a sea zone”)
- Advisory validation — mode-specific suggestions (e.g., “Consider adding secret connections” for dungeons)
- Speed Panel suggestions — mode-specific quick actions appear in a dedicated MODE section (e.g., “Add Secret Connection” for dungeons)
| Mode | Grid | Tile | Key Connections |
|---|---|---|---|
| dungeon | 30×25 | 32 | door, stairs, passage, secret, hazard |
| district | 50×40 | 32 | road, door, passage, portal |
| world | 80×60 | 48 | road, portal, passage |
| ocean | 60×50 | 48 | channel, route, portal, hazard |
| space | 100×80 | 64 | docking, warp, passage, portal |
| interior | 20×15 | 24 | door, stairs, passage, secret |
| wilderness | 60×50 | 48 | trail, road, passage, hazard |
A distinct area in the world with spatial coordinates, neighbors, and environmental properties:
gridX,gridY,gridWidth,gridHeight— position on the spatial gridneighbors— IDs of adjacent zonesexits— labeled transitions with target zone IDslight(0-10) andnoise(0-10) — ambient levelshazards— environmental dangersinteractables— objects players can inspect or useparentDistrictId— which district this zone belongs to
EntityPlacement
Section titled “EntityPlacement”Places an entity in a zone with optional authored data:
entityId,zoneId,role— identity, location, and role (npc/enemy/merchant/boss/companion)name— display name (defaults to entityId)stats— authored stat block (e.g.,{ vigor: 4, instinct: 3, will: 1 })resources— resource pools (e.g.,{ hp: 12, stamina: 4 })ai— AI profile override (e.g.,{ profileId: 'aggressive', goals: ['guard-crypt'] })tags— additional tags merged with role defaultsdialogueId— links to a dialogue treecustom— freeform metadata for companion abilities, personal goals, etc.
DialogueDefinition
Section titled “DialogueDefinition”A branching conversation tree:
id— unique identifierspeakers— entity IDs involved in the conversationentryNodeId— where the conversation startsnodes— map of node ID toDialogueNode
Each DialogueNode has a speaker, text, and optional choices. Each DialogueChoice can have conditions (gates) and effects (state changes). Effects use DialogueEffect with a type, optional target (actor/target/zone), and params.
PlayerTemplate
Section titled “PlayerTemplate”Defines the player character’s starting state:
name— display name (e.g., “Wanderer”)baseStats,baseResources— starting stat/resource poolsstartingInventory— item IDs placed in inventory at game startstartingEquipment— slot-to-item-ID map for equipped itemsspawnPointId— where the player startsdefaultArchetypeId,defaultBackgroundId— optional build catalog refs
BuildCatalogDefinition
Section titled “BuildCatalogDefinition”Character creation data for the engine:
archetypes— class-like choices with stat priorities, progression trees, granted verbsbackgrounds— origin stories with stat modifiers and faction modifierstraits— perks and flaws with effects (stat-modifier, resource-modifier, grant-tag, verb-access, faction-modifier)disciplines— specialized abilities with granted verbs, passives, and drawbackscrossTitles— special titles granted by archetype + discipline combinationsentanglements— synergy effects between archetype and discipline
ProgressionTreeDefinition
Section titled “ProgressionTreeDefinition”Skill/ability trees with:
currency— what resource is spent to unlock nodes (e.g., “xp”)nodes— each withcost, optionalrequires(prerequisite node IDs), andeffects
AssetEntry
Section titled “AssetEntry”A single entry in the project’s asset manifest:
id— unique identifierkind—portrait,sprite,background,icon, ortilesetlabel— display namepath— relative path or URI to the media filetags— freeform tags for filteringpackId— optional reference to anAssetPack.idprovenance— optional metadata (source, author, license, createdAt)
AssetPack
Section titled “AssetPack”A named, versioned grouping of assets for portability:
id,label,version— identity and semver versiondescription— what this pack containstags,theme— categorization (e.g.,dark-fantasy)source— provenance (hand-drawn,ai-generated,stock)license,author— ownership metadatacompatibility— optionalPackCompatibilitywithminSchemaVersionandengineVersion
Assets reference their pack via packId. Deleting a pack cascades by clearing packId on all member assets.
Scene Data Assembly
Section titled “Scene Data Assembly”assembleSceneData(zoneId, project) is a pure function that extracts all visual data bound to a zone into a single SceneData structure:
- background/tileset — resolved asset or
{ id, missing: true }marker - entities — placements with resolved portrait/sprite assets and missing flags
- landmarks — with resolved icon assets and missing flags
- items — with resolved icon assets and missing flags
- spawns — spawn points in this zone
- ambient — ambient layers that include this zone
- connections — connected zone names with optional conditions
- light — the zone’s light level (0-10)
This is the data source for the editor’s Scene Preview component and can be used independently for testing or tooling.
Viewport Math
Section titled “Viewport Math”The viewport.ts module provides pure math functions for 2D viewport transforms. No React, no DOM — just coordinate math.
interface ViewportState { panX: number; panY: number; zoom: number; }interface WorldBounds { minX: number; minY: number; maxX: number; maxY: number; }Transform model: screenX = (worldX - panX) * zoom, applied via ctx.setTransform(zoom, 0, 0, zoom, -panX * zoom, -panY * zoom).
| Function | Purpose |
|---|---|
screenToWorld | Convert screen pixel to world pixel coordinates |
worldToScreen | Convert world pixel to screen pixel coordinates |
screenToGrid | Convert screen pixel to tile grid coordinates |
computeContentBounds | Compute world-pixel bounding box of all authored content |
fitBoundsToViewport | Compute viewport that fits bounds into a canvas, centered |
centerOnPoint | Compute viewport centered on a world point at current zoom |
centerOnZone | Compute viewport that frames a specific zone with padding |
zoomAtPoint | Apply zoom delta while keeping cursor world-point stationary |
Constants: MIN_ZOOM = 0.1, MAX_ZOOM = 5.0, DEFAULT_VIEWPORT = { panX: 0, panY: 0, zoom: 1 }.
Validation
Section titled “Validation”validateProject() runs 54 structural checks:
- At least one spawn point exists
- At least one default spawn point
- Zone ID uniqueness
- District ID uniqueness
- Zone neighbors reference existing zones
- Symmetrical neighbor relationships
- District zone references exist
- Entity placements reference valid zones
- Item placements reference valid zones
- Spawn points reference valid zones
- Connections reference valid zones
- Landmarks reference valid zones
- Dialogue ID uniqueness
- Entry node exists in dialogue
- All nextNodeId references point to existing nodes
- No unreachable nodes in dialogue trees
- Entity dialogueId references existing dialogue
- Player template spawn point exists
- Starting inventory items exist in item placements
- Starting equipment items exist in item placements
- Default archetype exists in build catalog
- Default background exists in build catalog
- Archetype ID uniqueness + progression tree refs
- Background ID uniqueness
- Trait ID uniqueness + incompatibility refs
- Discipline ID uniqueness
- Cross-title archetype + discipline refs
- Entanglement archetype + discipline refs
- Progression tree ID uniqueness
- Node ID uniqueness within tree
- Required node refs exist
- Root node existence (at least one node without requirements)
- Asset ID uniqueness
- Asset path non-empty
- Zone background/tileset asset ref existence + kind match
- Entity portrait/sprite asset ref existence + kind match
- Item icon asset ref existence + kind match
- Landmark icon asset ref existence + kind match 39-42. Orphaned asset detection
- Pack ID uniqueness
- Pack label non-empty
- Pack version non-empty
- Asset packId references existing pack
- Orphaned pack detection (no assets reference this pack)
- Pack version format (semver x.y.z) 49-54. Encounter, faction, and pressure hotspot structural checks
Advisory Validation
Section titled “Advisory Validation”advisoryValidation(project) returns mode-specific suggestions that never block export. These appear in the editor as a collapsible blue section below hard validation errors.
Each mode generates relevant suggestions — for example, dungeon mode suggests adding secret connections and trap hazards, ocean mode suggests channel connections and port zones. Universal suggestions (e.g., “add at least 2 zones”, “add connections between zones”) apply to all modes.
interface AdvisoryItem { path: string; // e.g. 'connections' or 'zones' message: string; // human-readable suggestion severity: 'info' | 'suggestion';}