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

# Adding Content

> Create NPCs, items, and world areas using JSON manifests

## Manifest-Driven Design

Hyperscape uses JSON manifests for game content. Add new NPCs, items, stores, and world areas by editing JSON files in `packages/server/world/assets/manifests/`.

<Info>
  No code changes required—just edit the JSON manifest files and restart the server.
</Info>

## Content Files

All manifests are in `packages/server/world/assets/manifests/`:

### Core Manifests

| File               | Purpose                                             |
| ------------------ | --------------------------------------------------- |
| `npcs.ts`          | NPC and mob definitions                             |
| `items.ts`         | Item properties and stats                           |
| `banks-stores.ts`  | Shop inventories                                    |
| `world-areas.ts`   | Zone configuration                                  |
| `skill-unlocks.ts` | Level requirements                                  |
| `avatars.ts`       | Character models                                    |
| `quests.json`      | Quest definitions with stages and rewards           |
| `stations.json`    | Crafting stations (anvils, furnaces, ranges, banks) |

## Adding NPCs

NPCs are defined with combat stats, drops, and spawn locations:

```typescript theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  id: "goblin",
  name: "Goblin",
  combatLevel: 2,
  stats: {
    attack: 1,
    strength: 1,
    defense: 1,
    constitution: 5
  },
  aggressive: true,
  aggroRange: 3,
  drops: [
    { itemId: "coins", quantity: [1, 10], chance: 1.0 },
    { itemId: "bronze_sword", quantity: 1, chance: 0.05 }
  ],
  respawnTime: 15000
}
```

### Difficulty Levels

| Level | Examples                                  |
| ----- | ----------------------------------------- |
| 1     | Goblins, Bandits, Barbarians              |
| 2     | Hobgoblins, Guards, Dark Warriors         |
| 3     | Black Knights, Ice Warriors, Dark Rangers |

## Adding Items

Items include equipment, resources, and consumables. Add to the appropriate category file in `items/` directory.

### Example: Adding a Weapon

**File**: `packages/server/world/assets/manifests/items/weapons.json`

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "id": "mithril_longsword",
  "name": "Mithril Longsword",
  "type": "weapon",
  "tier": "mithril",
  "equipSlot": "weapon",
  "attackType": "MELEE",
  "weaponType": "longsword",
  "stackable": false,
  "tradeable": true,
  "value": 1300,
  "bonuses": {
    "attack": 26,
    "strength": 25
  }
}
```

### Example: Adding a Tool

**File**: `packages/server/world/assets/manifests/items/tools.json`

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "id": "adamant_pickaxe",
  "name": "Adamant Pickaxe",
  "type": "tool",
  "tier": "adamant",
  "equipSlot": "weapon",
  "stackable": false,
  "tradeable": true,
  "value": 3200,
  "tool": {
    "skill": "mining",
    "priority": 4,
    "rollTicks": 3
  }
}
```

### Example: Adding a Resource

**File**: `packages/server/world/assets/manifests/items/resources.json`

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "id": "mithril_ore",
  "name": "Mithril Ore",
  "type": "resource",
  "stackable": false,
  "tradeable": true,
  "value": 150,
  "notedItemId": "mithril_ore_noted"
}
```

### Tier-Based Requirements

Items with a `tier` property automatically derive level requirements from `tier-requirements.json`:

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "id": "steel_sword",
  "tier": "steel",
  "equipSlot": "weapon",
  "attackType": "MELEE"
  // requirements auto-derived: { attack: 5 }
}
```

No need to manually specify `requirements` if using the tier system.

### Item Types

* **weapon**: Swords, bows, staffs
* **armor**: Helmets, bodies, legs, shields
* **tool**: Hatchets, pickaxes, fishing rods
* **consumable**: Food, potions
* **resource**: Logs, fish, ores, bars
* **currency**: Coins
* **junk**: Burnt food, broken items

## Adding Shops

Shops define available items and prices:

```typescript theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  id: "general_store",
  name: "General Store",
  items: [
    { itemId: "bronze_hatchet", stock: 10, price: 50 },
    { itemId: "fishing_rod", stock: 10, price: 25 },
    { itemId: "tinderbox", stock: 10, price: 15 }
  ]
}
```

## Adding Stations

Stations are interactive objects for crafting and processing:

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "type": "anvil",
  "name": "Anvil",
  "model": "asset://models/anvil/anvil.glb",
  "modelScale": 0.5,
  "modelYOffset": 0.2,
  "examine": "An anvil for smithing metal bars into weapons and tools."
}
```

### Station Types

* **anvil**: Smith bars into equipment
* **furnace**: Smelt ores into bars
* **range**: Cook food with reduced burn chance
* **bank**: Store items

## Adding World Areas

World areas define zones with biomes and mob spawns:

```typescript theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  id: "mistwood_valley",
  name: "Mistwood Valley",
  biome: "forest",
  difficulty: 1,
  spawns: [
    { npcId: "goblin", count: 5 },
    { npcId: "bandit", count: 3 }
  ],
  resources: [
    { type: "tree", count: 10 },
    { type: "fishing_spot", count: 2 }
  ]
}
```

### Biomes

* Mistwood Valley (foggy forest)
* Goblin Wastes (barren lands)
* Darkwood Forest (dense shadows)
* Northern Reaches (frozen tundra)
* Blasted Lands (corrupted areas)

## Adding Recipes

### Smelting Recipe

**File**: `packages/server/world/assets/manifests/recipes/smelting.json`

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "output": "mithril_bar",
  "inputs": [
    { "item": "mithril_ore", "amount": 1 },
    { "item": "coal", "amount": 4 }
  ],
  "level": 50,
  "xp": 30,
  "ticks": 4,
  "successRate": 1.0
}
```

### Smithing Recipe

**File**: `packages/server/world/assets/manifests/recipes/smithing.json`

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "output": "mithril_longsword",
  "bar": "mithril_bar",
  "barsRequired": 2,
  "level": 56,
  "xp": 100,
  "ticks": 4,
  "category": "weapons"
}
```

### Cooking Recipe

**File**: `packages/server/world/assets/manifests/recipes/cooking.json`

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "raw": "raw_shark",
  "cooked": "shark",
  "burnt": "burnt_shark",
  "level": 80,
  "xp": 210,
  "ticks": 4,
  "stopBurnLevel": {
    "fire": 94,
    "range": 89
  }
}
```

### Firemaking Recipe

**File**: `packages/server/world/assets/manifests/recipes/firemaking.json`

```json theme={"theme":{"light":"github-light","dark":"css-variables"}}
{
  "log": "magic_logs",
  "level": 75,
  "xp": 303.8,
  "ticks": 4
}
```

***

## Testing Changes

<Steps>
  <Step title="Edit Manifest">
    Add your content to the appropriate JSON file in `packages/server/world/assets/manifests/`
  </Step>

  <Step title="Restart Server">
    Stop the server (Ctrl+C) and restart with `bun run dev`
  </Step>

  <Step title="Verify In-Game">
    Check that your content appears correctly at `http://localhost:3333`
  </Step>
</Steps>

<Warning>
  **Server restart required**: Unlike code changes, manifest changes require a full server restart to reload.
</Warning>

***

## Validation

### Atomic Loading

Directory-based manifests use **atomic loading**:

* All required files must exist or system falls back to legacy format
* For `items/`: All 5 category files must be present
* For `recipes/`: Individual files are optional (falls back to embedded item data)
* For `gathering/`: Individual files are optional (falls back to `resources.json`)

### Duplicate Detection

The loader validates that no item ID appears in multiple category files:

```
[DataManager] Duplicate item ID "bronze_sword" found in items/weapons.json
```

This prevents data conflicts and ensures each item has a single source of truth.

***

## Best Practices

<AccordionGroup>
  <Accordion title="Use descriptive IDs">
    Use `bronze_sword` not `sword1`. IDs should be self-documenting.
  </Accordion>

  <Accordion title="Follow naming conventions">
    Use snake\_case for IDs: `mithril_platebody`, `oak_logs`, `raw_shrimp`
  </Accordion>

  <Accordion title="Leverage tier system">
    Use `tier` property instead of manually specifying requirements for standard equipment.
  </Accordion>

  <Accordion title="Keep recipes separate">
    Don't embed recipe data in items.json - use dedicated recipe manifest files.
  </Accordion>

  <Accordion title="Test thoroughly">
    Verify level requirements, XP values, and item interactions work as expected.
  </Accordion>
</AccordionGroup>
