7.7 KiB
The Steward — Simulation Definitions
Purpose
Stable IDs and immutable definitions form the vocabulary shared by simulation state, systems, world adapters, scenes, tests, and save migrations.
SimulationIds remains the append-only source for code-facing compatibility
IDs. SimulationContentPack is the no-code authoring manifest and
ContentCatalog transactionally validates and publishes typed definitions in
stable-ID order. The current core pack contains actions, professions,
capability tags, items, resources, storage policies, and enemies. A failed pack
publishes nothing: duplicate IDs, unknown references, unsupported handlers, or
missing presentation cues are authoring errors rather than silent overrides.
Simulation code resolves definitions through the catalog. Presentation cue IDs
remain headless strings and are mapped separately to scenes, materials, icons,
or animation hooks. Runtime quantities and ownership stay in state records;
saves do not contain .tres paths or copied definition balance.
Content-pack contract
Each pack has a stable pack_id, display name, explicit pack dependencies,
required handler IDs, and typed definition arrays. Pack and definition IDs are
unique across the whole catalog. Packs cannot override each other in the first
version, and enumeration is sorted independently of resource load order.
Adding data-only content is:
- create a typed
.tresdefinition; - add it to an explicit pack;
- optionally register its stable presentation cue in the presentation layer;
- place or spawn an instance with its own canonical runtime ID.
Adding a fundamentally new mechanic still requires one bounded reusable handler. The pack declares that dependency so missing runtime support fails validation rather than becoming a partially functioning object.
Action contract
Each executable ActionDefinition contains:
- stable action ID and display name;
- duration and optional preferred profession;
- target family and resource-action metadata;
- optional completion cost;
- actor and target capability tags;
- selection, target, and completion handler IDs;
- reusable typed effects;
- event and presentation cue IDs.
Reusable ActionEffect definitions cover metric/need change, exact inventory
transfer, damage/healing, relationship-dimension change, scheduling an ordinary
action, and site-condition change. ActionCommand carries stable actor/action/
target/item IDs, amount, and expected revision; ActionOffer and ActionResult
are copy-only values. ActionCommandService is the authority boundary and must
revalidate range, capabilities, reservation, permission, cost, and target state
at execution time for either a player or NPC caller.
The current actions are gather food, gather wood, feed animal, deposit food, deposit wood, withdraw food, patrol, study, eat, rest, sleep, wander, and defend. Idle and dead are state sentinels, not executable definitions. The two-leg animal-feeding transaction remains a custom completion handler because it has a real compound pickup/delivery contract and no second shared consumer yet.
Items, resources, and storage
ItemDefinition validates fields by category. Weapons require damage, reach,
cooldown, and an equip slot; materials and consumables do not carry fake weapon
fields. The core pack contains food, wood, herb, sword, and claw. Herb proves a
new non-weapon item and route without a manager branch.
ResourceDefinition owns yielded item, gather action, capability tags, base
capacity/yield/regrowth, access policy, and presentation cue. Placement/state
records retain unique contextual IDs and overrides such as safety risk,
comfort, and discovery priority. Berry patches, trees, and herb patches share
this contract.
StorageDefinition declares accepted item IDs/tags, policy priority, capacity,
settlement scope, deposit/withdraw actions, and presentation cue.
StorageRoutingPolicy ranks compatible destinations deterministically by
priority then stable target ID. Food-to-pantry and wood-to-woodpile remain
covered; herb-to-apothecary proves data-only routing beyond those legacy cases.
Professions and capabilities
Each ProfessionDefinition contains a stable ID, display name, body color, and
prop color. Farmer, woodcutter, guard, scholar, and wanderer are registered in
the core pack. NPC state saves only the ID and rejects unknown definitions.
CapabilityTagDefinition gives actions and targets a validated shared
vocabulary. Tags express composable affordances; they do not mutate state or
replace concrete authority checks.
Enemies and combat
EnemyDefinition carries a behavior profile, combatant ID prefix, faction,
hostility, weapon, health, movement, and visual parameters.
CombatantFactory creates/restores every hostile and rebuilds collision-free
per-prefix allocators. The core boar reuses the wolf-hunt behavior without a
new manager or combat switch; raider and wolf compatibility spawn APIs delegate
to the same factory.
Combatant and faction state use stable IDs. NPC combatants point to their
person ID; hostile records persist enemy_definition_id. Weapons resolve
through the same item catalog used by inventory rather than a parallel combat
item table.
Animals
AnimalDefinition + AnimalCatalog + AnimalFactory apply the same
definition-instance-state-presentation contract to domestic animals. Goat and
sheep reuse the grazer_routine, feeding capability, generic CozyGrazer scene,
state migration, and care system; definition and visual parameters are the only
type-specific pieces. The animal catalog remains isolated until the next
shared content-pack migration adds that record family without destabilizing
the already validated core pack.
Situations and dialogue
Legacy OpportunityStateRecord vocabulary remains for save compatibility.
New emergent content uses typed SituationDefinition resources: reusable
predicates, evidence requirements, dedupe fields, priority/severity,
alternative objectives, exact ordinary resolution patterns, expiry/cooldown,
and dialogue topic IDs. Situation state saves the definition ID and causal
facts; progress is re-derived from authoritative state and WorldEventStore.
DialogueIntentDefinition owns semantic preconditions, score, response intent
IDs, template variants, and optional action metadata. Stable hashing selects a
variant from conversation/turn/intent/topics without consuming shared RNG.
Rendered prose and Dialogue Manager resources are presentation and never
authoritative state.
Validation and authoring report
The catalog rejects:
- missing, empty, or duplicate pack/definition IDs;
- silent cross-pack overrides;
- unknown pack, handler, capability, item, profession, action, storage, behavior-profile, or presentation-cue references;
- category-invalid item fields;
- incomplete or non-positive costs/effects;
- resources or storage routes with inconsistent item/action contracts;
- definition resources that fail to load.
ContentCatalog.get_authoring_report() exposes validity, sorted published IDs,
and exact errors for CLI/editor tooling. Tests prove transactional failure,
deterministic enumeration, core cross-references, boar behavior reuse, shared
goat/sheep behavior, and herb routing.
Deliberate boundary
Definitions own reusable static metadata, not mutable inventory, reservations, relationships, situation progress, entity ownership, or presentation nodes. Handler implementations remain bounded typed strategies. A universal reflection DSL, arbitrary scripts embedded in saves, and a full ECS are outside the contract.
Selection, execution, target resolution, simulation authority, and visual travel remain separate responsibilities. Extend definitions only after a real consumer proves a stable shared field; extend a handler when the mechanic itself is genuinely new.