docs(workspace): adopt declarative-first principle for content

This commit is contained in:
Serkyo 2026-07-12 15:49:33 +02:00
parent 41ba2e5d5c
commit 5c61ecc209
2 changed files with 6 additions and 1 deletions

View file

@ -15,11 +15,14 @@ The data-pack loader reads the declarative files and **calls the same Lua API**
Each data-pack schema is treated as a stable contract, versioned as deliberately as the Lua API.
**Amendment (declarative-first):** the choice between JSON and Lua is not free per content item. Anything expressible as data — the static fields of a block, item, recipe, loot table, biome, or tag — is authored as data and lives in `data/`; Lua is reserved for behavior (logic that runs on an event or tick). A pure-data block therefore needs no Lua at all. Consequently a data pack *can* register a block, item, or other primitive on its own, provided that primitive is purely declarative; the moment it needs behavior, that behavior half comes from a Lua mod. To avoid hand-authoring large volumes of near-identical files, modders may use **datagen**: code that emits `data/` files at build time, on the author's machine, before the pack ships. Datagen output (not its code) is the shipped artifact, and never runs at load time, so the single runtime load path is preserved.
The canonical load order, later layers overriding earlier ones, is: base game → data packs → Lua mods → resource packs (resource packs last so client visuals win).
## Consequences
- One source of truth for registration; declarative content and scripted content cannot diverge in behaviour because they end at the same API.
- Declarative-first means data is the default and code the exception: a new primitive gets a data schema first, and a Lua-only registration path signals a gap in that schema. The base game dogfoods the datapack path, keeping pure-data `core` content in `data/` and only behavioural systems in `scripts/`.
- Accepting a schema is a long-lived commitment, since data packs in the wild depend on it.
- Resource packs remain entirely client-side with no server involvement, and are kept conceptually separate from data packs.
- Full subsystem detail (load order, repo and user-data layout, resolution semantics) lives in [`docs/packs.md`](../packs.md).

View file

@ -18,7 +18,9 @@ No parallel registration system is built. The loader reads the declarative files
data/blocks/stone.json → loader → blocks.register{ id = "stone", ... }
```
The loader belongs in `scripting` (or a sibling crate if it grows). Engine first-party content may use either JSON or Lua, whichever fits. Every data-pack schema is a stable contract, the same as the Lua API, version it deliberately.
The loader belongs in `scripting` (or a sibling crate if it grows). Every data-pack schema is a stable contract, the same as the Lua API, version it deliberately.
**Declarative-first (ADR-0007):** JSON and Lua are not free alternatives. Anything expressible as data — the static fields of a block, item, recipe, loot table, biome, or tag — is authored as data in `data/`; Lua is reserved for behavior (logic that runs on an event or tick). A pure-data block therefore needs no Lua, and a data pack can register such a primitive on its own; only its behavior half (if any) comes from a Lua mod. Engine first-party content follows the same rule, keeping pure-data `core` content in `data/` and only behavioral systems in `scripts/`. To avoid hand-authoring large volumes of near-identical files, modders may use **datagen**: code that emits `data/` files at build time, before the pack ships — its output, not its code, is the shipped artifact, and it never runs at load time.
## Canonical load order