Skip to main content

Overview

Hyperscape uses manifest-driven design where game content is defined in TypeScript data files rather than hardcoded in logic. This enables content creation without modifying game systems.

Design Philosophy

Separation of Concerns

Benefits

  • Content creators can add items, NPCs, areas without deep coding
  • Designers iterate quickly on balance
  • Developers focus on systems, not data
  • Modders can extend content easily

Manifest Files

Manifests are JSON files that define game content. They are stored in packages/server/world/assets/manifests/ and served from the CDN in production.

Manifest Loading

Development:
  • Manifests loaded from local filesystem: packages/server/world/assets/manifests/
  • Assets cloned from HyperscapeAI/assets via Git LFS during bun install
  • CDN fetching skipped if local manifests exist (allows local modifications)
  • Local CDN serves assets at http://localhost:8080
Production (Railway + Cloudflare):
  • Manifests fetched from CDN at server startup: PUBLIC_CDN_URL/manifests/
  • Cached locally in packages/server/world/assets/manifests/
  • Only re-fetched if content changes (HTTP ETag validation)
  • Assets served directly from Cloudflare R2 CDN (no local clone)
  • Frontend served from Cloudflare Pages (separate from game server)
CI/Test Environments:
  • Set CI=true or SKIP_ASSETS=true to skip asset download
  • Set SKIP_MANIFESTS=true or NODE_ENV=test to allow starting without manifests
  • Useful for unit tests that don’t need full game content

Fetch Implementation

The fetchManifestsFromCDN function in packages/server/src/startup/config.ts handles manifest synchronization:
This ensures the server always has the latest content without requiring redeployment when manifests change.

Manifest Directory Structure

All manifests are in world/assets/manifests/:
The skill-unlocks.json manifest is served to clients via the /api/data/skill-unlocks API endpoint for use in the Skill Guide Panel UI.

Manifest Structure

NPCs (npcs.json)

NPC data is loaded from JSON manifests at runtime by DataManager:
NPC definitions are in world/assets/manifests/npcs.json, not hardcoded in TypeScript.

Items Directory

Items are now organized into separate JSON files by category for better maintainability:
All item files are loaded atomically by DataManager - if any required file is missing, the system falls back to the legacy items.json format.

Tools (tools.json)

Tools include a tool object specifying skill, priority, and optional bonus mechanics:

Tool Properties

Mining Pickaxe Bonus Speed: Dragon and crystal pickaxes have a chance to mine faster: The bonus roll is determined server-side to maintain determinism and prevent client/server desyncs.
Tools with equipSlot: "weapon" can be equipped and used for combat. The tier system automatically derives level requirements from tier-requirements.json.

Inventory Actions

Items can define explicit inventoryActions for OSRS-accurate context menus:
The first action becomes the left-click default. Supported actions: If inventoryActions is not specified, the system falls back to type-based detection using item-helpers.ts.

Gathering Resources (gathering/)

gathering/woodcutting.json - Trees and log yields:
Tree Model System:
  • modelPath: Primary model for the tree type
  • modelVariants: Array of model variants for visual diversity (optional)
  • modelScale: Scale multiplier for tree models
  • LOD support: Models include LOD levels (_lod1.glb, _lod2.glb) for performance
  • 12 tree types: bamboo, birch, cactus, chinaPine, coconut, dead, fir, knotwood, maple, oak, palm, pine
  • Wind pine: Single-model tree type for tundra biome (uses modelPath only)
gathering/mining.json - Ore rocks with OSRS-accurate success rates:
Mining Depletion: Rocks always deplete after one ore (depleteChance: 1.0). The depletedModelPath and depletedModelScale define the visual appearance of depleted rocks.

Gathering Resources

Resource gathering data is split by skill for better organization:
Each manifest defines the resources, their requirements, XP rewards, and drop tables.

Processing Recipes

Processing recipes are organized by skill:
These manifests define inputs, outputs, level requirements, XP rewards, and tick-based timing.

Station Configurations

World stations (anvils, furnaces, ranges, banks, altars) are configured in stations.json:
This allows 3D models and configurations to be updated without code changes. The modelScale and modelYOffset properties control the visual appearance of stations in the world.

Stations (stations.json)

Defines crafting stations and interactive objects in the world:
Station types include:
  • Anvil — Smith bars into equipment
  • Furnace — Smelt ores into bars
  • Range — Cook food with reduced burn chance
  • Bank — Store items
  • Altar — Restore prayer points

Manifest Loading

Server-Side Loading

The server loads manifests in two ways depending on the environment: Production/CI:
Development:
Manifest Files Fetched:
  • Root: biomes.json, npcs.json, prayers.json, stations.json, etc.
  • Items: items/food.json, items/weapons.json, items/tools.json, etc.
  • Gathering: gathering/fishing.json, gathering/mining.json, etc.
  • Recipes: recipes/cooking.json, recipes/smithing.json, etc.
Total: 25+ manifest files fetched and cached at startup. Caching:
  • Manifests cached locally in world/assets/manifests/
  • HTTP cache headers: max-age=300, must-revalidate (5 minutes)
  • Compares content before writing to avoid unnecessary disk I/O
Error Handling:
  • Logs warnings for failed fetches
  • Falls back to existing local manifests if CDN unavailable
  • Throws error only if no manifests exist at all (prevents broken startup)

Client-Side Loading

The client fetches manifests from CDN via DataManager:

DataManager

The DataManager class loads all manifests and populates runtime data structures. Smithing, cooking, and other processing skills use recipe manifests: Smelting Recipe (recipes/smelting.json):
Smithing Recipe (recipes/smithing.json):

Tier Requirements (tier-requirements.json)

Defines level requirements by equipment tier:

Prayers (prayers.json)

Defines prayer bonuses, drain rates, and conflicts:
Prayer Fields:
  • id — Unique prayer ID (lowercase, underscores, max 64 chars)
  • name — Display name
  • description — Effect description for tooltip
  • icon — Emoji icon for UI
  • level — Required Prayer level (1-99)
  • category — “offensive”, “defensive”, or “utility”
  • drainEffect — Drain rate (higher = faster drain)
  • bonuses — Combat stat multipliers (attackMultiplier, strengthMultiplier, defenseMultiplier)
  • conflicts — Array of prayer IDs that conflict with this prayer
Prayer bonuses are multipliers applied to base stats. A value of 1.05 means +5%, 1.10 means +10%.

Station Configuration (stations.json)

Defines world stations with 3D models:

Data Providers

Manifest Distribution

Development vs Production

Hyperscape uses different manifest loading strategies for development and production: Development (Local):
  • Manifests loaded from packages/server/world/assets/manifests/
  • Assets cloned via Git LFS during bun install
  • CDN serves from local Docker nginx container
Production (Railway/Cloudflare):
  • Manifests fetched from CDN at server startup
  • Cached locally in packages/server/world/assets/manifests/
  • Assets served from Cloudflare R2

CDN Manifest Fetching

The server automatically fetches manifests from the CDN on startup:
Fetching Behavior:
  • Production/CI: Always fetches from CDN to ensure latest data
  • Development: Skips fetch if local manifests exist (allows local development)
  • Caching: Compares content before writing to avoid unnecessary disk I/O
  • Fallback: Uses existing local manifests if CDN fetch fails
Benefits:
  • Update game content by deploying new manifests to CDN
  • No server redeployment needed for content changes
  • Server always has latest game data
  • Reduces deployment size (manifests not bundled in Docker image)
Environment Variable:
This architecture allows content updates (new items, NPCs, balance changes) to be deployed by updating manifests on the CDN, without requiring server redeployment or downtime.

DataManager

The DataManager class in packages/shared/src/data/DataManager.ts loads all manifests from JSON files and populates runtime data structures:

Manifest Loading

DataManager supports two loading modes:
  1. Filesystem (server-side): Loads from packages/server/world/assets/manifests/
  2. CDN (client-side): Fetches from PUBLIC_CDN_URL/manifests/
The loading is atomic for directory-based manifests - all required files must exist or it falls back to legacy single-file format.

CDN Manifest Fetching

The server automatically fetches manifests from the CDN at startup:
Fetching behavior: Manifest files fetched (30+ files):
  • Root: npcs.json, stores.json, world-areas.json, prayers.json, skill-unlocks.json, etc.
  • Items: items/weapons.json, items/tools.json, items/resources.json, items/food.json, items/misc.json
  • Gathering: gathering/woodcutting.json, gathering/mining.json, gathering/fishing.json
  • Recipes: recipes/cooking.json, recipes/firemaking.json, recipes/smelting.json, recipes/smithing.json
Caching:
  • Manifests cached in packages/server/world/assets/manifests/
  • Content comparison: Only changed files are written to disk
  • HTTP cache headers: 5-minute cache with revalidation
  • Startup logs: X fetched, Y updated, Z failed
This architecture allows updating game content by uploading new manifests to R2 without redeploying the server. The server will fetch the latest manifests on next restart.

Adding Content

Development Workflow

1

Choose the right manifest

Determine which manifest file to edit based on content type:
  • Items: manifests/items/weapons.json, tools.json, resources.json, food.json, or misc.json
  • NPCs/Mobs: manifests/npcs.json
  • Gathering Resources: manifests/gathering/woodcutting.json, mining.json, or fishing.json
  • Processing Recipes: manifests/recipes/cooking.json, firemaking.json, smelting.json, or smithing.json
  • Stations: manifests/stations.json
  • World Areas: manifests/world-areas.json
2

Edit manifest locally

Add your content following the existing structure. Use tier-based requirements for equipment:
3

Test locally

Restart the server to reload manifests:
Verify the content appears correctly in-game.
4

Deploy to staging

  1. Commit changes to a feature branch
  2. Create PR and merge to staging branch
  3. GitHub Actions uploads manifests to R2 staging bucket
  4. Railway redeploys staging server
  5. Server fetches updated manifests from staging CDN
5

Deploy to production

After testing in staging:
  1. Merge stagingmain
  2. GitHub Actions uploads to production R2 bucket
  3. Railway redeploys production server
  4. Server fetches updated manifests from production CDN
  • Items: manifests/items/weapons.json, tools.json, resources.json, food.json, or misc.json
  • NPCs/Mobs: manifests/npcs.json
  • Gathering Resources: manifests/gathering/woodcutting.json, mining.json, or fishing.json
  • Processing Recipes: manifests/recipes/cooking.json, firemaking.json, smelting.json, or smithing.json
  • Stations: manifests/stations.json
  • Quests: manifests/quests.json
  • World Areas: manifests/world-areas.json
You can update manifests in production without redeploying the server:
  1. Upload new manifest to R2:
  2. Restart the server (Railway dashboard or API)
  3. Server fetches latest manifests from R2 on startup
Always test manifest changes in staging before uploading to production R2.

Validation

Manifests are JSON files validated at runtime by DataManager:
  • Schema validation: Invalid fields logged as warnings
  • Duplicate detection: Duplicate item IDs across files cause errors
  • Reference checking: Invalid itemId/npcId references caught at runtime
  • Atomic loading: Items directory loads all files or falls back to legacy format
Invalid JSON syntax will cause server startup to fail. Use a JSON validator before committing changes.

Data Providers

The manifest system uses specialized data providers for efficient lookups: These providers build optimized lookup tables at startup for fast runtime queries.

PrayerDataProvider Usage

Access prayer definitions at runtime:
Prayer Loading:
  • Loaded by DataManager at startup
  • Validates prayer ID format, bonuses, and conflicts
  • Builds optimized lookup tables by level and category
  • Provides type-safe access methods

StationDataProvider Usage

Access station configurations at runtime:
Station Model Loading:
  • Models loaded via ModelCache with transform baking
  • modelYOffset raises model so base sits on ground
  • Graceful fallback to blue box placeholder if model fails
  • Shadows and raycasting layers configured automatically

Quests (quests.json)

The quests.json manifest defines quest content with stages, requirements, and rewards:
Properties:
  • id — Unique quest identifier
  • name — Display name shown in quest log
  • description — Brief quest summary
  • difficulty — Quest difficulty: novice, intermediate, experienced, master
  • questPoints — Quest points awarded on completion
  • replayable — Whether quest can be repeated after completion
  • requirements — Prerequisites to start the quest
    • quests — Required completed quests
    • skills — Minimum skill levels (e.g., {"woodcutting": 15})
    • items — Required items in inventory
  • startNpc — NPC ID to start the quest
  • stages — Ordered list of quest objectives
    • type — Stage type: dialogue, kill, gather, interact
    • description — Objective description shown to player
    • target — Target entity/item ID
    • count — Required count for completion
  • onStart — Items and dialogue triggered when quest starts
  • rewards — Quest completion rewards
    • questPoints — Quest points awarded
    • items — Item rewards
    • xp — Skill XP rewards (e.g., {"attack": 100})
Stage Types:
  • dialogue — Talk to an NPC
  • kill — Defeat a specific number of enemies
  • gather — Collect resources (woodcutting, mining, fishing)
  • interact — Use items or interact with objects
Quest progress is tracked server-side. Players can view active and completed quests in the quest log interface.

Prayers (prayers.json)

The prayers.json manifest defines OSRS-accurate prayer abilities with stat bonuses and drain mechanics:
Properties:
  • id — Unique prayer identifier
  • name — Display name shown in prayer book
  • description — Effect description for tooltip
  • icon — Icon asset path for prayer book UI
  • level — Prayer level required to unlock
  • category — Prayer type: offensive, defensive, or utility
  • drainEffect — Drain rate (higher = faster drain)
  • bonuses — Stat multipliers applied when active
    • attackMultiplier — Attack bonus (e.g., 1.05 = +5%)
    • strengthMultiplier — Strength bonus
    • defenseMultiplier — Defense bonus
  • conflicts — Array of prayer IDs that cannot be active simultaneously
Categories:
  • Offensive — Attack and strength bonuses (Burst of Strength, Clarity of Thought)
  • Defensive — Defense bonuses (Thick Skin, Rock Skin, Steel Skin)
  • Utility — Special effects (future: Protect from Melee, Rapid Heal)
Conflict System: Prayers in the same category typically conflict. Activating a prayer automatically deactivates conflicting prayers (OSRS-accurate behavior).
Prayer drain rates follow OSRS formulas. The drainEffect value determines how quickly prayer points deplete while the prayer is active.

Quests (quests.json)

Defines multi-stage quests with objectives, requirements, and rewards:
Quest Properties:
  • id — Unique quest identifier (snake_case)
  • name — Display name shown in quest journal
  • description — Quest summary
  • difficultynovice, intermediate, experienced, master
  • questPoints — Quest points awarded on completion
  • replayable — Whether quest can be repeated (typically false)
  • requirements — Prerequisites to start quest
    • quests — Array of quest IDs that must be completed
    • skills — Skill level requirements (e.g., { "attack": 10 })
    • items — Required items in inventory
  • startNpc — NPC ID that starts the quest
  • stages — Array of quest objectives
  • onStart — Items granted when quest starts (optional)
  • rewards — Rewards granted on completion
Stage Types:
  • dialogue — Talk to NPC (auto-completes via dialogue system)
  • kill — Kill specific mob type (target: mob type, count: number)
  • gather — Gather items (target: item ID, count: number)
  • interact — Interact with entities (target: entity type, count: number)

Security: Quest IDs are validated with isValidQuestId() to prevent injection attacks. Max length: 64 characters, pattern: `^[a-z][a-z0-9_]--- title: “Manifest-Driven Design” description: “Data-driven content through TypeScript manifest files” icon: “file-json”

Overview

Hyperscape uses manifest-driven design where game content is defined in TypeScript data files rather than hardcoded in logic. This enables content creation without modifying game systems.

Design Philosophy

Separation of Concerns

Benefits

  • Content creators can add items, NPCs, areas without deep coding
  • Designers iterate quickly on balance
  • Developers focus on systems, not data
  • Modders can extend content easily

Manifest Files

All manifests are in world/assets/manifests/:

Manifest Structure

NPCs (npcs.json)

NPC data is loaded from JSON manifests at runtime by DataManager:
NPC definitions are in world/assets/manifests/npcs.json, not hardcoded in TypeScript.

Items Directory

Items are now organized into separate JSON files by category for better maintainability:
All item files are loaded atomically by DataManager - if any required file is missing, the system falls back to the legacy items.json format.

Tools (tools.json)

Tools include a tool object specifying skill, priority, and optional bonus mechanics:

Tool Properties

Mining Pickaxe Bonus Speed: Dragon and crystal pickaxes have a chance to mine faster: The bonus roll is determined server-side to maintain determinism and prevent client/server desyncs.
Tools with equipSlot: "weapon" can be equipped and used for combat. The tier system automatically derives level requirements from tier-requirements.json.

Inventory Actions

Items can define explicit inventoryActions for OSRS-accurate context menus:
The first action becomes the left-click default. Supported actions: If inventoryActions is not specified, the system falls back to type-based detection using item-helpers.ts.

Gathering Resources (gathering/)

gathering/woodcutting.json - Trees and log yields:
gathering/mining.json - Ore rocks with OSRS-accurate success rates:
Mining Depletion: Rocks always deplete after one ore (depleteChance: 1.0). The depletedModelPath and depletedModelScale define the visual appearance of depleted rocks.

Gathering Resources

Resource gathering data is split by skill for better organization:
Each manifest defines the resources, their requirements, XP rewards, and drop tables.

Processing Recipes

Processing recipes are organized by skill:
These manifests define inputs, outputs, level requirements, XP rewards, and tick-based timing.

Station Configurations

World stations (anvils, furnaces, ranges, banks) are configured in stations.json:
This allows 3D models and configurations to be updated without code changes. The modelScale and modelYOffset properties control the visual appearance of stations in the world.

Terrain Flattening

Stations can optionally flatten terrain underneath for level building surfaces: How it works:
  • Station footprint calculated from model bounds × scale
  • Flat zone created with dimensions: (footprint + padding × 2)
  • Terrain height sampled at station center position
  • Smoothstep blending (t² × (3 - 2t)) creates natural transitions
  • Spatial indexing using terrain tiles (100m) for O(1) lookup
Terrain flattening ensures stations sit on level ground even on hills or slopes, improving visual quality and preventing floating/clipping issues.

Stations (stations.json)

Defines crafting stations and interactive objects in the world:
Station Properties:
  • type — Station identifier (anvil, furnace, range, bank, altar)
  • name — Display name
  • model — Path to 3D model asset
  • modelScale — Scale multiplier for the model
  • modelYOffset — Vertical position offset
  • examine — Text shown when examining the station
  • flattenGround — Whether to flatten terrain under the station
  • flattenPadding — Radius of flattened area around station
  • flattenBlendRadius — Blend radius for smooth terrain transition
Station Types:
  • Anvil — Smith bars into equipment
  • Furnace — Smelt ores into bars
  • Range — Cook food with reduced burn chance
  • Bank — Store items
  • Altar — Restore prayer points

DataManager

Smithing, cooking, and other processing skills use recipe manifests: Smelting Recipe (recipes/smelting.json):
Smithing Recipe (recipes/smithing.json):

Tier Requirements (tier-requirements.json)

Defines level requirements by equipment tier:

Station Configuration (stations.json)

Defines world stations with 3D models:

Data Providers

DataManager

The DataManager class in packages/shared/src/data/DataManager.ts loads all manifests from JSON files and populates runtime data structures:

Manifest Loading

DataManager supports two loading modes:
  1. Filesystem (server-side): Loads from packages/server/world/assets/manifests/
  2. CDN (client-side): Fetches from http://localhost:8080/assets/manifests/
The loading is atomic for directory-based manifests - all required files must exist or it falls back to legacy single-file format.

Adding Content

World Areas with Station Spawns (world-areas.json)

World areas now support data-driven station spawning:
Station Location Properties:
  • type — Station type (bank, anvil, furnace, range, altar)
  • position — [x, y, z] coordinates in world space
  • rotation — Optional quaternion rotation
StationSpawnerSystem:
  • Reads stations field from WorldArea definitions
  • Spawns station entities at configured positions
  • Replaces hardcoded station spawning in EntityManager
  • Uses getStationsInArea() helper for querying

Step 1: Choose the Right Manifest

Determine which manifest file to edit based on content type:
  • Items: manifests/items/weapons.json, tools.json, resources.json, food.json, or misc.json
  • NPCs/Mobs: manifests/npcs.json
  • Gathering Resources: manifests/gathering/woodcutting.json, mining.json, or fishing.json
  • Processing Recipes: manifests/recipes/cooking.json, firemaking.json, smelting.json, or smithing.json
  • Stations: manifests/stations.json (station types and models)
  • World Areas: manifests/world-areas.json (station spawn locations)
  • Quests: manifests/quests.json (quest definitions)

Step 2: Edit Manifest

Add your content following the existing structure. Use tier-based requirements for equipment:

Step 3: Restart Server

Manifests are loaded at server startup. Restart to apply changes:

Step 4: Verify

Check the game to ensure content appears correctly. Use the Skills panel to verify level requirements.

Validation

Manifests are JSON files validated at runtime by DataManager:
  • Schema validation: Invalid fields logged as warnings
  • Duplicate detection: Duplicate item IDs across files cause errors
  • Reference checking: Invalid itemId/npcId references caught at runtime
  • Atomic loading: Items directory loads all files or falls back to legacy format
Invalid JSON syntax will cause server startup to fail. Use a JSON validator before committing changes.

Data Providers

The manifest system uses specialized data providers for efficient lookups: These providers build optimized lookup tables at startup for fast runtime queries.

StationDataProvider Usage

Access station configurations at runtime:
Station Model Loading:
  • Models loaded via ModelCache with transform baking
  • modelYOffset raises model so base sits on ground
  • Graceful fallback to blue box placeholder if model fails
  • Shadows and raycasting layers configured automatically

Quests (quests.json)

The quests.json manifest defines quest content with multi-stage progression, requirements, and rewards:
Quest Properties:
  • id — Unique quest identifier
  • name — Display name shown in quest journal
  • description — Brief quest summary
  • difficulty — Quest difficulty (novice, intermediate, experienced, master, grandmaster)
  • questPoints — Quest points awarded on completion
  • replayable — Whether quest can be repeated after completion
  • requirements — Prerequisites to start the quest
    • quests — Required completed quests
    • skills — Required skill levels (e.g., {"woodcutting": 15})
    • items — Required items in inventory
  • startNpc — NPC ID that starts the quest
  • stages — Array of quest stages in order
  • onStart — Items given and dialogue triggered when quest starts
  • rewards — Items, XP, and quest points awarded on completion
Stage Types:
  • dialogue — Talk to an NPC
  • kill — Kill a specific number of NPCs/mobs
  • gather — Collect items through gathering skills
  • interact — Interact with objects or process items
Available Quests:
  • Goblin Slayer — Combat tutorial (kill 15 goblins)
  • Lumberjack’s First Lesson — Woodcutting and firemaking tutorial
  • Fresh Catch — Fishing and cooking tutorial
  • Torvin’s Tools — Mining, smelting, and smithing tutorial
Quest progress is tracked server-side. Each stage must be completed in order before advancing to the next stage.

Prayers (prayers.json)

The prayers.json manifest defines OSRS-accurate prayer abilities with stat bonuses and drain mechanics:
Properties:
  • id — Unique prayer identifier
  • name — Display name shown in prayer book
  • description — Effect description for tooltip
  • icon — Icon asset path for prayer book UI
  • level — Prayer level required to unlock
  • category — Prayer type: offensive, defensive, or utility
  • drainEffect — Drain rate (higher = faster drain)
  • bonuses — Stat multipliers applied when active
    • attackMultiplier — Attack bonus (e.g., 1.05 = +5%)
    • strengthMultiplier — Strength bonus
    • defenseMultiplier — Defense bonus
  • conflicts — Array of prayer IDs that cannot be active simultaneously
Categories:
  • Offensive — Attack and strength bonuses (Burst of Strength, Clarity of Thought)
  • Defensive — Defense bonuses (Thick Skin, Rock Skin, Steel Skin)
  • Utility — Special effects (future: Protect from Melee, Rapid Heal)
Conflict System: Prayers in the same category typically conflict. Activating a prayer automatically deactivates conflicting prayers (OSRS-accurate behavior).
Prayer drain rates follow OSRS formulas. The drainEffect value determines how quickly prayer points deplete while the prayer is active.
.

Model Bounds (model-bounds.json)

The model-bounds.json manifest contains pre-calculated bounding box data for all 3D models in the game. This data is used for spatial calculations, collision detection, and tile-based placement:
Properties:
  • bounds — Minimum and maximum coordinates of the model’s bounding box
  • dimensions — Calculated width (x), height (y), and depth (z) of the model
  • footprint — Tile-based footprint for placement (width × depth in tiles)
  • generatedAt — Timestamp of when bounds were calculated
  • tileSize — Base tile size used for footprint calculations (typically 1.0)
Use Cases:
  • Placement Validation — Ensure entities fit within available space
  • Collision Detection — Fast AABB checks for physics and interactions
  • Tile Occupancy — Calculate which tiles an entity occupies
  • Spatial Queries — Optimize raycasting and proximity checks
The bounds are automatically generated from the actual 3D model geometry and updated when models change.

Best Practices

  1. Use descriptive IDs: bronze_sword not sword1
  2. Follow naming conventions: snake_case for IDs
  3. Organize by category: Use the directory structure (items/, recipes/, gathering/)
  4. Test after changes: Verify in-game before committing
  5. Keep data flat: Avoid deep nesting in manifest structures
  6. Use tier system: Leverage TierDataProvider for equipment requirements instead of hardcoding
  7. Validate JSON: Use a JSON validator before committing to catch syntax errors

Manifest Loading Order

DataManager loads manifests in this order:
  1. Tier requirements (tier-requirements.json) - Needed for item normalization
  2. Model bounds (model-bounds.json) - Needed for station footprint calculation
  3. Items (items/ directory or items.json fallback)
  4. NPCs (npcs.json)
  5. Gathering resources (gathering/*.json)
  6. Recipe manifests (recipes/*.json)
  7. Skill unlocks (skill-unlocks.json)
  8. Prayers (prayers.json)
  9. Quests (quests.json)
  10. Stations (stations.json) - Uses model bounds for footprints
  11. World areas (world-areas.json)
  12. Stores (stores.json)
This order ensures dependencies are loaded before dependent data (e.g., model bounds before stations).

Build-Time Manifests

Model Bounds Extraction

The model-bounds.json manifest is auto-generated during build:
Process:
  1. Scans world/assets/models/**/*.glb files
  2. Parses glTF position accessor min/max values
  3. Calculates bounding boxes and footprints at scale 1.0
  4. Writes to world/assets/manifests/model-bounds.json
Output Format:
Runtime Usage:
  • StationDataProvider loads this manifest at startup
  • Combines model bounds × modelScale from stations.json
  • Calculates final collision footprint for each station type
  • No manual footprint configuration needed
Do not edit model-bounds.json manually. It is regenerated on every build when GLB files change.

Quests (quests.json)

Defines multi-stage quests with requirements and rewards:
Stage Types:
  • dialogue — Talk to an NPC
  • kill — Kill specific mobs (with count)
  • gather — Gather resources (with count)
  • interact — Interact with objects (with count)
  • craft — Craft items (with count)
Difficulty Levels:
  • novice — Beginner quests
  • intermediate — Medium difficulty
  • experienced — Advanced quests
  • master — Expert-level quests
See Quest System for full documentation.