Files
gamedev-the-steward/docs/FEATURE_CONTENT_AND_AUTHORED_DATA.md
2026-08-13 00:26:55 +02:00

140 lines
6.6 KiB
Markdown

# Feature slice: authored content and presentation data
This slice is the no-code extension boundary for content that reuses existing
behavior. It is implemented by `SimulationContentPack`, `ContentCatalog`, the
typed definition resources under `simulation/definitions/`, and the separate
`PresentationCatalog` under `world/presentation/`.
## The four layers
| Layer | Lives in | Contains | Never contains |
| --- | --- | --- | --- |
| Definition | `.tres` resources and typed `Resource` classes | immutable IDs, balance, capabilities, effects, handlers, cue IDs | mutable amount, owner, reservation, node references |
| Instance descriptor | placement/provider nodes and regional records | stable runtime ID, context/location, authored overrides | script/callable/`NodePath` authority |
| State record | `simulation/state/` | primitive mutable values, IDs, history/event references | scene assets or resource paths |
| Presentation binding | `world/presentation/` and scene providers | cue-to-scene/material/icon/animation metadata | simulation quantities or quest authority |
Definitions are current-build balance. A save stores the definition ID and
mutable instance state; it does not freeze the `.tres` path or copy the full
resource. Renaming an ID requires an alias/migration, not a silent replacement.
## Content packs and catalog publication
`SimulationContentPack` groups typed arrays for:
- actions, professions, capability tags;
- items, resources, storages;
- enemies and animals;
- situations, dialogue intents, and template catalogs;
- event types and social consequences;
- required pack IDs and required handler IDs.
`ContentCatalog.create_core()` loads `simulation/definitions/packs/core.tres`.
`ContentCatalog.rebuild()` sorts packs and every definition by stable ID,
collects references into temporary dictionaries, validates the complete graph,
and publishes only if there are no errors. A failed rebuild clears the
published catalog; it never exposes a partially valid pack.
Validation currently rejects duplicate IDs, unknown references, missing
handlers, unsupported situation predicates, missing presentation cues, invalid
categories, invalid event/consequence references, duplicate template keys, and
malformed typed action contracts. `get_authoring_report()` is the deterministic
machine-readable inventory used by tests and tooling.
The first built-in handler contract is `activity_metric_delta`. It requires an
activity target, exactly one positive safety/knowledge metric effect, typed
optional `player_multiplier`/`npc_productivity` values, a known completion
event, and a routable completion-cost item. This closes the gap where an
authored action could publish but produce a fact that the validator could not
restore.
## Adding data-only content
### New item and route
1. Add an `ItemDefinition` with a category and stable `item_id`.
2. Add a `StorageDefinition` that accepts the item ID or one of its tags, or
update an existing typed storage route.
3. Add both to a pack and make sure the `StorageRoutingPolicy` can rank a
compatible storage.
4. Add a `PresentationCueDefinition` only if the item needs a visual.
5. Add a conservation/routing test. The herb/apothecary route is the reference
example; food/pantry and wood/woodpile preserve legacy coverage.
### New resource
1. Add a `ResourceDefinition` with yielded item, gather action, capacity/yield,
regrowth, access policy, capability tags, and a cue ID.
2. Place a `ResourceNode` with a unique contextual ID and meaningful
`safety_risk`, `comfort_distance`, `discovery_priority`, and interaction
point.
3. Register it through the nearest `ActiveWorldAdapter`; do not add a global
array or manager branch.
4. Test player/NPC selection, depletion, reservation, unload/rebind, and
save/restore authority.
### New animal
1. Add an `AnimalDefinition` with behavior/routine/feed capability IDs and a
stable presentation cue.
2. Add it to `core_animals.tres` or an explicit content pack.
3. Spawn through `AnimalFactory` and persist its `animal_definition_id` in
`AnimalStateRecord`.
4. Reuse `AnimalNode`, `AnimalRoutineSite`, and the grazer visual where the
existing contract fits. The goat/sheep pair proves this path.
### New enemy
1. Add an `EnemyDefinition` with `behavior_profile_id`, faction, item/weapon
references, hostile flag, and cue ID.
2. Register it in a pack. `CombatantFactory` owns deterministic per-prefix ID
allocation and restore collision checks.
3. Spawn through `ConflictSystem.spawn_enemy()`; keep `spawn_wolf()` only as a
compatibility wrapper.
4. Reuse a behavior profile when possible. `enemy_boar` deliberately reuses
`wolf_hunt`; no combat switch was added.
### New situation or dialogue content
See [Events through dialogue](FEATURE_EVENTS_KNOWLEDGE_SITUATIONS_DIALOGUE.md).
The authored resources must reference existing predicate IDs, event types,
intent IDs, template catalogs, and action/item definitions. A definition may
describe an unresolved condition, but it cannot create substitute world facts.
## Presentation catalogs
`PresentationCatalog` accepts `PresentationCatalogResource` entries whose
`PresentationCueDefinition` contains stable cue metadata and optional asset
paths. It validates metadata headlessly and loads scenes only at the world
boundary. `AnimalDefinition`, enemy definitions, resource definitions, and
other simulation content carry only a cue ID. This keeps headless tests and
saves independent of imported meshes/materials.
Presentation catalogs may be absent in a headless `AnimalFactory` or regional
simulation. Missing optional presentation is an explicit no-visual result, not
a reason to fail simulation state loading.
## What requires code
Data-only authoring is guaranteed only when the new combination uses existing
typed predicates, capabilities, effects, handlers, behavior profiles, and cue
contracts. Add one reusable typed handler when a new mechanic needs a new
authority rule. The handler must provide validation, a reason trace, atomic
mutation semantics, world facts, save fields/migration if needed, and a real
consumer test. Do not solve a new mechanic with a reflection DSL or a script
per content asset.
## Reference tests
- `tests/content_catalog_test.gd`
- `tests/simulation_definitions_test.gd`
- `tests/unit/test_authored_situation_dialogue_content.gd`
- `tests/unit/test_activity_content_catalog_contract.gd`
- `tests/unit/test_content_routing_foundations.gd`
- `tests/animal_definition_contract_test.gd`
- `tests/unit/test_combatant_factory.gd`
- `tests/unit/test_presentation_catalog.gd`
The [simulation definitions contract](SIMULATION_DEFINITIONS.md) is the
authoritative field-level reference; this guide explains the extension path.