Content Packs Intro

Audience: Everyone Status: ✅ Ready

A content pack is where a TelosMUD game actually lives. The engine ships with no rooms, no mobs, no classes, and no rules — all of that is supplied by a pack. This page introduces the two packs that ship in the repository, explains how a running world decides which packs are active, and points you at the deeper authoring and operations references. It’s the bridge from “I have a running engine” to “I have a world.”

What a content pack is

A pack is a directory tree of YAML under internal/content/packs/<name>/: a pack.yaml manifest, one file per pack-global section (attributes, abilities, channels, loot tables, and so on), and a zones/ subtree describing rooms, items, mobs, and resets. The loader merges that tree into a single pack. Behavior that static data can’t express is attached as sandboxed Lua on def-table hooks and entity triggers. Everything a player experiences as “the game” — the stat list, the damage types, the classes, the world map — is pack data, not engine code. The full format is documented in Pack Authoring and the Pack Entity Reference.

The packs that ship

Two packs are embedded in the binary (the whole packs/ tree is compiled in via internal/content/demo.go):

core — the minimal bootstrap pack

core (internal/content/packs/core) is deliberately tiny: a single lobby zone with a start room and antechamber, plus a small attribute/resource scaffold so a logged-in player is coherent (has vitals). It exists so a fresh or empty deployment — no seeded content yet, or Postgres unreachable — still boots at least one start room instead of rejecting every login with “this world has no rooms yet.” It is always loaded underneath the real content source, and real content layers on top via a last-write-wins merge. The core zone name and the core: ref prefix are a reserved namespace: a real pack must not ship them, and a load-time lint plus the reload-broadcast gate enforce that so bootstrap scaffolding can never be clobbered.

demo — the reference world

demo (internal/content/packs/demo) is a complete, playable world: the classic midgaard + darkwood + crypt zones, with mobs, items, abilities, loot, crafting, channels, and chargen — a full example every builder can read as a template. It is the same tree the unit tests load, and make seed (which runs telos-seed) imports it into the pack='demo' definition rows for a live stack. See Demo Pack for a guided tour.

The demo is a dev fixture, not a shipped world. Only telos-seed still embeds it; every other published image is built with the nofixture tag and carries just the core bootstrap pack. A real deployment gets its world by pulling a content pack from the external store into Postgres — see Content-Pack Operations. So the demo is what you seed locally; it is not what a production fleet runs.

Design-target packs (not yet built)

Three further packs are planned to demonstrate that the engine is genuinely game-system agnostic — they do not exist in code yet: SRD5 (D&D 5e SRD), WoW (a WoW-like d20 ruleset), and D6 Space (OpenD6 dice pool).

How a world’s pack set is chosen

There is no runtime enable/disable toggle — a pack is not switched on with a command. “Which packs are active” is determined by two things:

  1. What content is present in Postgres. telos-seed writes the demo pack into pack='demo' rows; telos-pull imports a versioned pack from an external store. A pack has to be seeded or pulled before it can be loaded. The per-pack logical version is tracked in content_pack_registry (pack, version), pack-level scalars like default_combat live in pack_meta, and content_version is the version authority the reload path checks.
  2. The world’s enabled pack set. Each telos-world shard loads the packs named in its content_packs config list (the TELOS_CONTENT_PACKS env var, comma-separated). An empty list falls back to the default — the demo pack for a bare dev run; for a pulled version the pack list is manifest-driven, so the importer reads it from the pulled version.

So to change what’s live you change what is seeded/pulled and what the enabled set names, then reload or reboot the shard — not a per-pack on/off switch. The core bootstrap pack is always present regardless. The operational mechanics — seeding, pulling versions, and coordinated hot-reload across shards — are covered in Content Pack Operations.

Where to go next