> ## Documentation Index
> Fetch the complete documentation index at: https://hyperscape-ai-mintlify-docs-update.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Manifests Overview

> Manifest-driven content system for NPCs, items, and world areas

## Manifest-Driven Design

Hyperscape uses a **manifest-driven architecture** where all game content (NPCs, items, world areas) is defined in external data files rather than hardcoded in logic. This separation enables:

* **Easy content updates** — Edit JSON, restart server
* **Community modding** — No code changes required
* **AI generation** — Generate content with Asset Forge
* **Clean separation** — Data vs logic isolation

<Info>
  All manifests are loaded from `world/assets/manifests/` at runtime by the `DataManager`.
</Info>

***

## Data Architecture

```
packages/shared/src/data/
├── DataManager.ts        # Loads all manifests at runtime
├── npcs.ts               # NPC helper functions (Map populated at runtime)
├── items.ts              # Item helper functions (Map populated at runtime)
├── banks-stores.ts       # Bank and shop definitions
├── world-areas.ts        # Zone and biome definitions
├── world-structure.ts    # World structure configuration
├── avatars.ts            # Avatar/character options
├── skill-icons.ts        # Skill UI icons
├── skill-unlocks.ts      # Skill unlock requirements
├── playerEmotes.ts       # Player emote animations
├── NoteGenerator.ts      # Bank note generation
└── index.ts              # Exports
```

### Manifest Files Location

```
world/assets/manifests/
├── npcs.json             # NPC and mob definitions
├── items.json            # Item definitions
├── stations.json         # Crafting stations (anvils, furnaces, ranges, banks)
└── ... (other manifests)
```

***

## NPCs & Mobs

NPCs are loaded from JSON at runtime into the `ALL_NPCS` Map:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// From packages/shared/src/data/npcs.ts
export const ALL_NPCS: Map<string, NPCData> = new Map();
```

### NPC Data Structure

Each NPC has these properties (from `types/entities/npc-mob-types.ts`):

| Property      | Type                                      | Description                                                     |
| ------------- | ----------------------------------------- | --------------------------------------------------------------- |
| `id`          | `string`                                  | Unique identifier                                               |
| `name`        | `string`                                  | Display name                                                    |
| `category`    | `"mob" \| "boss" \| "quest" \| "neutral"` | NPC type                                                        |
| `stats`       | `NPCStats`                                | Combat stats (attack, strength, defense, health, ranged, level) |
| `drops`       | `DropTable`                               | Loot table with rarity tiers                                    |
| `spawnBiomes` | `string[]`                                | Biomes where NPC spawns                                         |
| `modelPath`   | `string`                                  | Path to 3D model                                                |
| `behavior`    | `"passive" \| "aggressive"`               | Combat behavior                                                 |

### Available 3D Models

**NPCs**:

```
/assets/models/
├── goblin/goblin_rigged.glb     → Goblins
├── thug/thug_rigged.glb         → Bandits
├── human/human_rigged.glb       → Guards, knights, warriors, rangers
├── troll/troll_rigged.glb       → Hobgoblins
└── imp/imp_rigged.glb           → Dark warriors
```

**Stations**:

```
/assets/models/
├── anvil/anvil.glb              → Smithing station
├── furnace/furnace.glb          → Smelting station
```

**Fishing Tools**:

```
/assets/models/
├── fishing-rod-base/fishing-rod-base.glb       → Base fishing rod
└── fishing-rod-standard/fishing-rod-standard.glb → Standard fishing rod
```

**Mining Rocks**:

```
/assets/models/
├── copper-rock/copper-rock.glb                 → Copper ore rock
├── copper-rock/copper-rock-depleted.glb        → Depleted copper rock
├── mithril-rock/mithril-rock.glb               → Mithril ore rock
├── runite-rock/runite-rock.glb                 → Runite ore rock
└── runite-rock/runite-rock-depleted.glb        → Depleted runite rock
```

**Vegetation**:

```
/assets/trees/
└── mushroom.glb                 → Giant mushroom (new)
```

### NPC Helper Functions

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// Get NPC by ID
getNPCById(npcId: string): NPCData | null

// Get NPCs by category
getNPCsByCategory(category: NPCCategory): NPCData[]

// Get NPCs by biome
getNPCsByBiome(biome: string): NPCData[]

// Get NPCs by level range
getNPCsByLevelRange(minLevel: number, maxLevel: number): NPCData[]

// Get combat NPCs (mob, boss, quest)
getCombatNPCs(): NPCData[]

// Get service NPCs (neutral)
getServiceNPCs(): NPCData[]

// Calculate drops with RNG
calculateNPCDrops(npcId: string): Array<{ itemId: string; quantity: number }>

// Calculate combat level (OSRS formula)
calculateNPCCombatLevel(npc: NPCData): number
```

### Spawn Constants

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// From packages/shared/src/data/npcs.ts
export const NPC_SPAWN_CONSTANTS = {
  GLOBAL_RESPAWN_TIME: 900000,    // 15 minutes per GDD
  MAX_NPCS_PER_ZONE: 10,
  SPAWN_RADIUS_CHECK: 5,          // Don't spawn if player within 5 meters
  AGGRO_LEVEL_THRESHOLD: 5,       // Some NPCs ignore players above this
} as const;
```

***

## Items

Items are loaded from JSON into the `ITEMS` Map. Items are now organized into separate files by type for better organization:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// From packages/shared/src/data/items.ts
export const ITEMS: Map<string, Item> = new Map();
```

### Item Types & Organization

| Type           | Description                                     | File                   |
| -------------- | ----------------------------------------------- | ---------------------- |
| `"weapon"`     | Combat weapons                                  | `items/weapons.json`   |
| `"tool"`       | Skilling tools                                  | `items/tools.json`     |
| `"resource"`   | Gathered materials (ores, logs, bars, raw fish) | `items/resources.json` |
| `"consumable"` | Food that heals                                 | `items/food.json`      |
| `"currency"`   | Coins                                           | `items/misc.json`      |
| `"junk"`       | Burnt food, worthless items                     | `items/misc.json`      |
| `"misc"`       | Everything else                                 | `items/misc.json`      |

### Tier-Based Equipment

Items now use a centralized tier system defined in `tier-requirements.json`. Equipment references their tier (e.g., "bronze", "steel", "rune") and the system looks up requirements automatically:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// Item with tier reference
{
  "id": "bronze_sword",
  "tier": "bronze",  // References tier-requirements.json
  // ... other properties
}
```

**Supported Tiers:**

* **Melee**: bronze, iron, steel, black, mithril, adamant, rune, dragon
* **Tools**: Same as melee (with different skill requirements)
* **Ranged**: leather, studded, green\_dhide, blue\_dhide, red\_dhide, black\_dhide
* **Magic**: wizard, mystic, infinity, ahrims

### Item Helper Functions

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// Get item by ID
getItem(itemId: string): Item | null

// Get items by type
getItemsByType(type: ItemType): Item[]

// Get all weapons
getWeapons(): Item[]

// Get all armor
getArmor(): Item[]

// Get all tools
getTools(): Item[]

// Get all consumables
getConsumables(): Item[]

// Get all resources
getResources(): Item[]

// Get items by skill requirement
getItemsBySkill(skill: string): Item[]

// Get items by level requirement
getItemsByLevel(level: number): Item[]
```

### Shop Items

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// From packages/shared/src/data/items.ts
export const SHOP_ITEMS = [
  "bronze_hatchet",
  "fishing_rod",
  "tinderbox",
  "arrows",
];
```

### Bank Notes

The system supports bank notes for stackable versions of items:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// From packages/shared/src/data/items.ts
export const NOTE_SUFFIX = "_note";

// Check if item can be noted
canBeNoted(itemId: string): boolean

// Get noted variant
getNotedItem(itemId: string): Item | null

// Get base item from note
getBaseItem(itemId: string): Item | null

// Check if ID is a noted item
isNotedItemId(itemId: string): boolean
```

***

## Drop Tables

NPCs have tiered drop tables:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
interface DropTable {
  defaultDrop: {
    enabled: boolean;
    itemId: string;
    quantity: number;
  };
  always: Drop[];      // 100% chance
  common: Drop[];      // High chance
  uncommon: Drop[];    // Medium chance
  rare: Drop[];        // Low chance
  veryRare: Drop[];    // Very low chance
}

interface Drop {
  itemId: string;
  minQuantity: number;
  maxQuantity: number;
  chance: number;      // 0.0 - 1.0
}
```

### Drop Calculation

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// From packages/shared/src/data/npcs.ts
export function calculateNPCDrops(npcId: string): Array<{ itemId: string; quantity: number }> {
  const npc = getNPCById(npcId);
  const drops: Array<{ itemId: string; quantity: number }> = [];

  // Add default drop if enabled
  if (npc.drops.defaultDrop.enabled) {
    drops.push({
      itemId: npc.drops.defaultDrop.itemId,
      quantity: npc.drops.defaultDrop.quantity,
    });
  }

  // Process all tiers with RNG
  const processDrop = (drop: Drop) => {
    if (Math.random() < drop.chance) {
      const quantity = Math.floor(
        Math.random() * (drop.maxQuantity - drop.minQuantity + 1) + drop.minQuantity
      );
      drops.push({ itemId: drop.itemId, quantity });
    }
  };

  npc.drops.always.forEach(processDrop);
  npc.drops.common.forEach(processDrop);
  npc.drops.uncommon.forEach(processDrop);
  npc.drops.rare.forEach(processDrop);
  npc.drops.veryRare.forEach(processDrop);

  return drops;
}
```

***

## World Areas

World areas define zones, biomes, and spawn points:

```
packages/shared/src/data/
├── world-areas.ts        # Zone definitions
└── world-structure.ts    # World layout
```

### Zone Properties

| Property     | Description                       |
| ------------ | --------------------------------- |
| `id`         | Unique zone identifier            |
| `name`       | Display name                      |
| `biome`      | Biome type (forest, plains, etc.) |
| `difficulty` | 0-3 difficulty level              |
| `mobs`       | NPCs that spawn here              |
| `resources`  | Trees, fishing spots, etc.        |
| `isSafe`     | Whether it's a safe zone          |

***

## Banks & Stores

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
// From packages/shared/src/data/banks-stores.ts
// Defines bank locations and shop inventories
```

Each starter town has:

* **Bank** — Item storage facility
* **General Store** — Basic equipment vendor

***

## Stations

Crafting stations are interactive objects that enable processing skills like smithing, smelting, and cooking:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
interface StationData {
  type: string;           // "anvil" | "furnace" | "range" | "bank" | "runecrafting_altar" | "altar"
  name: string;           // Display name
  model: string;          // Path to 3D model
  modelScale: number;     // Scale multiplier
  modelYOffset: number;   // Vertical offset
  examine: string;        // Examine text
}
```

### Available Stations

| Station                | Purpose                             | Model                                | Scale | Y Offset |
| ---------------------- | ----------------------------------- | ------------------------------------ | ----- | -------- |
| **Anvil**              | Smith bars into equipment           | `asset://models/anvil/anvil.glb`     | 0.5   | 0.2      |
| **Furnace**            | Smelt ores into bars, craft jewelry | `asset://models/furnace/furnace.glb` | 1.5   | 1.0      |
| **Range**              | Cook food with reduced burn chance  | TBD                                  | 1.0   | 0        |
| **Bank**               | Store items                         | TBD                                  | 1.0   | 0        |
| **Runecrafting Altar** | Convert essence into runes          | Per-altar model                      | 1.0   | 0        |

### Station Models

3D models for crafting stations in the assets repository:

```
models/
├── anvil/
│   ├── anvil.glb           # Optimized model (scale: 0.5, yOffset: 0.2)
│   ├── anvil_raw.glb       # Raw model
│   ├── concept-art.png     # Concept art
│   └── metadata.json       # Model metadata
└── furnace/
    ├── furnace.glb         # Optimized model (scale: 1.5, yOffset: 1.0)
    ├── furnace_raw.glb     # Raw model
    ├── concept-art.png     # Concept art
    └── metadata.json       # Model metadata
```

### Crafting Stations

Stations are defined in `stations.json`:

* **Anvil** - Used for smithing bars into equipment
* **Furnace** - Used for smelting ores into bars
* **Cooking Range** - Used for cooking food (reduces burn chance)
* **Bank Booth** - Used for accessing bank storage

Each station defines its 3D model, scale, position offset, and examine text.

### Tool Metadata

The `tools.json` manifest defines tool-specific properties:

* **Skill** - Which skill the tool is used for
* **Tier** - Tool tier (bronze, iron, steel, etc.)
* **Priority** - Tool selection priority (higher = better)
* **Roll Ticks** - For mining pickaxes, ticks between roll attempts

This metadata is separate from item definitions to keep tool mechanics centralized.

## Skill Progression

***

***

## Crafting Stations

Stations are defined in `stations.json` and represent interactive objects in the world used for processing skills:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
interface Station {
  type: string;           // "anvil" | "furnace" | "range" | "bank"
  name: string;           // Display name
  model: string | null;   // Path to 3D model
  modelScale: number;     // Model scale multiplier
  modelYOffset: number;   // Vertical position offset
  examine: string;        // Examine text
}
```

### Available Stations

| Station           | Purpose                            | Model                        | Scale | Y Offset |
| ----------------- | ---------------------------------- | ---------------------------- | ----- | -------- |
| **Anvil**         | Smithing bars into equipment       | `models/anvil/anvil.glb`     | 0.5   | 0.2      |
| **Furnace**       | Smelting ores into bars            | `models/furnace/furnace.glb` | 1.5   | 1.0      |
| **Cooking Range** | Cooking food (reduced burn chance) | TBD                          | 1.0   | 0        |
| **Bank Booth**    | Accessing bank storage             | TBD                          | 1.0   | 0        |

Stations are placed in world areas and interact with the corresponding recipe manifests (`recipes/smithing.json`, `recipes/smelting.json`, etc.).

***

## Tool Metadata

The `tools.json` manifest defines tool-specific properties separate from item definitions:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
interface ToolMetadata {
  itemId: string;         // References items/tools.json
  skill: string;          // "woodcutting" | "mining" | "fishing"
  tier: string;           // Tool tier
  levelRequired: number;  // Minimum skill level
  priority: number;       // Tool selection priority (higher = better)
  rollTicks?: number;     // Mining only: ticks between roll attempts
}
```

### Tool Priority System

When multiple tools are available, the system selects the highest priority tool:

**Woodcutting Hatchets**:

| Tool    | Priority  |
| ------- | --------- |
| Crystal | 1 (best)  |
| Dragon  | 2         |
| Rune    | 3         |
| Adamant | 4         |
| Mithril | 5         |
| Steel   | 6         |
| Iron    | 7         |
| Bronze  | 8 (worst) |

**Mining Pickaxes** (also includes `rollTicks` for mining speed):

| Tool    | Priority | Roll Ticks |
| ------- | -------- | ---------- |
| Crystal | 1        | 3          |
| Dragon  | 2        | 3          |
| Rune    | 3        | 3          |
| Adamant | 4        | 4          |
| Mithril | 5        | 5          |
| Steel   | 6        | 6          |
| Iron    | 7        | 7          |
| Bronze  | 8        | 8          |

***

## Vegetation & Biomes

### Vegetation Assets

The `vegetation.json` manifest defines procedural vegetation assets for world generation:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
interface VegetationAsset {
  id: string;                       // Unique asset ID
  model: string;                    // Path to GLB model
  category: string;                 // Asset category
  baseScale: number;                // Base scale multiplier
  scaleVariation: [number, number]; // [min, max] scale variation
  randomRotation: boolean;          // Randomize Y-axis rotation
  weight: number;                   // Spawn probability weight
  maxSlope: number;                 // Maximum terrain slope (0-1)
  minSlope?: number;                // Minimum terrain slope
  alignToNormal: boolean;           // Align to terrain normal
  yOffset: number;                  // Vertical position offset
}
```

**Vegetation Categories**:

* `tree` - Large trees
* `bush` - Small bushes and shrubs
* `fern` - Ground ferns
* `flower` - Decorative flowers
* `grass` - Grass patches
* `rock` - Decorative rocks
* `fallen_tree` - Fallen logs
* `mushroom` - Giant mushrooms (added in recent update)

### Biome Vegetation Layers

Biomes in `biomes.json` define procedural vegetation layers that reference vegetation assets:

```typescript theme={"theme":{"light":"github-light","dark":"tokyo-night"}}
interface VegetationLayer {
  category: string;           // Matches vegetation.json categories
  density: number;            // Spawn density
  assets: string[];           // Asset IDs (empty = all in category)
  minSpacing: number;         // Minimum distance between instances
  clustering: boolean;        // Group assets together
  clusterSize?: number;       // Size of clusters
  noiseScale: number;         // Perlin noise scale
  noiseThreshold: number;     // Noise threshold for spawning
  avoidWater: boolean;        // Don't spawn in water
  minHeight?: number;         // Minimum terrain height
  maxHeight?: number;         // Maximum terrain height
}
```

**Recent Updates**:

* Mushroom vegetation added to all biomes with varying densities (2-30)
* Tree density reduced in plains biome (8 → 5)
* Mushroom clustering varies by biome (cluster size 3-8)

***

## Adding New Content

<Steps>
  <Step title="Choose the right manifest">
    * Items: Add to appropriate file in `items/` directory
    * Gathering: Add to `gathering/woodcutting.json`, `mining.json`, or `fishing.json`
    * Recipes: Add to appropriate file in `recipes/` directory
    * NPCs: Add to `npcs.json`
  </Step>

  <Step title="Follow existing patterns">
    Use the same structure as existing entries. For tiered equipment, specify the `tier` field.
  </Step>

  <Step title="Generate 3D model (optional)">
    Use Asset Forge to create a new model, or use existing models
  </Step>

  <Step title="Restart server">
    The DataManager loads manifests on startup
  </Step>

  <Step title="Test in game">
    Verify the new content appears correctly
  </Step>
</Steps>

<Warning>
  Do NOT add game data directly to TypeScript files. Keep all content in JSON manifests for clean separation and easy modding.
</Warning>

## Recent Changes

### Manifest Refactor (PR #3)

The manifest system was recently refactored for better scalability and organization:

* **Items split by type**: Weapons, tools, resources, food, and misc are now in separate files
* **Gathering resources**: Woodcutting, mining, and fishing data moved to dedicated files
* **Recipe system**: New recipes directory for smelting, smithing, cooking, and firemaking
* **Centralized requirements**: `tier-requirements.json` provides OSRS-accurate level requirements
* **Skill unlocks**: `skill-unlocks.json` documents progression milestones

### New Vegetation (PR #4)

Mushroom vegetation added to biomes with configurable density, clustering, and spawn parameters.

***

***

## GitHub Integration

The repository now includes Claude Code GitHub Actions for automated assistance:

* **`.github/workflows/claude.yml`** - Responds to `@claude` mentions in issues and PRs
* **`.github/workflows/claude-code-review.yml`** - Automated code review on pull requests
* **`.github/workflows/update-docs.yml`** - Automatically updates documentation when manifests change

## Detailed Documentation

<CardGroup cols={2}>
  <Card title="NPC Data Structure" icon="users" href="/wiki/data/npcs">
    Complete NPC schema, aggro types, drop tables, spawn constants, and helper functions.
  </Card>

  <Card title="Item Data Structure" icon="box-open" href="/wiki/data/items">
    Item types, stats, requirements, equipment slots, noted items, and shop items.
  </Card>

  <Card title="Gathering & Crafting" icon="hammer" href="/wiki/game-systems/skills">
    Woodcutting, mining, fishing, smelting, smithing, cooking, and firemaking systems.
  </Card>

  <Card title="Tier Requirements" icon="shield" href="/wiki/data/items">
    Centralized equipment and tool level requirements by tier.
  </Card>
</CardGroup>
