Resources, Items, and Crafting
This page owns the distinction between settlement-side resources, actor-held items, and the crafting layer that transforms one into the other.
Resource / Item / Crafting Distinctions
- Resources are settlement-facing or world-facing quantities such as grain, timber, stone, ore, fuel, or warding materials.
- Items are held objects such as tools, weapons, armor, supplies, relics, or crafted goods.
- Crafting is the transformation layer that consumes available inputs and produces useful outputs.
- Labels such as Gold, Food, Wood, Metal, and Stone are resource-stockpile or UI labels. They are not the primary settlement channel canon.
Core Grounds Ore and Material Carve-Out
- The Core Grounds may support small-batch ore processing, smelting, or material refinement at the repair forge or workshop scale.
- This serves the MC's personal repair, craft, and expedition needs — it is not the main ore extraction economy.
- Settlement-scale ore extraction, smelting capacity, and industrial material throughput belong to the Settlement layer.
Design Rules
- Keep the resource layer readable at strategic scale.
- Keep item identity meaningful for the MC and other named characters.
- Let crafting bridge the two layers instead of collapsing them into one generic inventory bucket.
- Tools, facilities, sites, and skills should influence what can be crafted and how efficiently it can be done.
Current Direction
- Early acts care about fuel, food, shelter inputs, basic tools, and survival gear.
- Settlement acts introduce processing chains, workshops, storage, and larger throughput questions.
- Later acts expand into rarer materials, military supply, ritual support, and realm-scale logistics.
Recipe Contract
Recipes are registry-only metadata. A Recipe describes the inputs, outputs,
and lifecycle of a crafting transformation; it is never instantiated as an
entity in the game world. The committed shape is authored at
legacy/v1/examples/valenar/Content/economy/recipes/contracts.secs lines
1-8:
contract Recipe
{
root_scope Recipe;
registry_only;
method void OnCreated();
}
registry_only is the qualifier that pins this contract as data-only.
Recipe templates register against the contract for type-system
participation and for designer authoring, but no RecipeEntity is ever
materialized — the crafting machine, workshop, or tool reads the recipe
template by id and consumes inputs / produces outputs against its own
entity slot.
The method void OnCreated() declaration is a designer-facing lifecycle
hook reserved for recipe-registration-time bookkeeping (e.g., binding
the recipe into a workshop's available-recipe catalog). Because the
contract is registry_only, OnCreated never runs against a Recipe
instance — it runs at template registration time, not at activation.
Registry-Only Enforcement
registry_only is enforced through three runtime properties:
- Activation rejection (implemented). Any attempt to activate a
template against a
registry_onlycontract is rejected with the SECS0803 diagnostic inlegacy/v1/src/SECS.Engine/TemplateActivator.cslines 103-107. TheContractDeclaration.IsRegistryOnlyflag atlegacy/v1/src/SECS.Abstractions/Contracts/ContractDeclaration.cslines 13-16 is the canonical schema-side check. create_entityrejection (deferred). The host'screate_entityhelper must reject creation calls againstregistry_onlycontracts with the same diagnostic. This path is tracked indocs/design/FUTURE_WORK.mdline 50 as a remaining gap.- Startup validation (deferred). At engine startup the registry
should run a
registry.Validate()boot-time check confirming that noTemplateEntryis bound against aregistry_onlycontract in a way that would permit activation by side-channel. This validation is also tracked indocs/design/FUTURE_WORK.mdline 50.
The three enforcement points together form the registry-only contract: no entity may materialize, no creation call may bypass the check, and no registry state may exist in which the first two checks could be silently sidestepped.
Current Runtime Status
- Activation rejection: shipped (TemplateActivator.cs lines 103-107
throw
InvalidOperationExceptionwith SECS0803). create_entityrejection: not shipped (host helper does not yet enforce the check; tracked in FUTURE_WORK.md line 50).- Startup validation: not shipped (
registry.Validate()does not yet enforce the registry-only invariant; tracked in FUTURE_WORK.md line 50).
Live Recipe templates today rely on the activation rejection alone. The two deferred checks are required for full registry-only contract coverage; until they land, a host author who bypasses the activator (direct entity construction, bypassed registry helpers) could theoretically materialize a Recipe instance. The activator rejection is the canonical enforcement and is sufficient for the current Generated/ stand-in surface, but the contract is not fully closed until all three checks ship.
Runtime Backing Status
Status at this doc's acceptance time: partial.
- Host/runtime owner:
legacy/v1/src/SECS.Engine/TemplateActivator.cs(activation rejection);legacy/v1/src/SECS.Engine/SecsRegistry.cs(registry- side validation hook); a future host-helper boundary ownscreate_entityrejection. - Generated/.secs owner:
legacy/v1/examples/valenar/Content/economy/recipes/contracts.secs(live source);legacy/v1/examples/valenar/Generated/Declarations.cscarries the matchingContractDeclarationrows withIsRegistryOnly = true. - Read-model/UI owner: not applicable; recipes are registry metadata and have no per-instance UI surface beyond the workshop/tool selection screens that read recipe templates by id.
- Tests: activator rejection is covered by existing engine tests for
SECS0803;
create_entityrejection and startup-validation tests are deferred to the future engine-validation wave. - Known gaps:
create_entityrejection, startup validation. Both are tracked indocs/design/FUTURE_WORK.mdline 50. - Illegal fallback behavior: silent activation of a
registry_onlytemplate is forbidden. A host that bypassesTemplateActivatorto materialize a Recipe entity is a tenet failure, NOT a workaround. The contract is enforce-at-three-points or it is broken; partial enforcement does not authorize silent activation through the unenforced points. - Next closure wave: a future engine-validation wave authors the
create_entityrejection path and theregistry.Validate()boot-time check.
AAA Precedent
The registry-only recipe pattern draws on three AAA references:
- Factorio recipes (primary) — Factorio's
data.raw.recipeis the canonical modern reference. A recipe row is registry-only metadata consumed by crafting machines; recipes are never instantiated as entities in the game world. The crafting machine looks up the recipe by id, consumes inputs from its own inventory slot, and produces outputs into its output slot. The recipe itself is data, not an entity. Thecontract Recipe { registry_only; }shape is structurally identical to Factorio's data-stage recipe definition. - Dwarf Fortress reactions (secondary) — Dwarf Fortress'
reaction_standard.txtand per-mod reaction RAWs are registry- only metadata consumed by workshops. A reaction is never an entity; it is a row that workshops query at production time. - Minecraft datapacks (tertiary) — Minecraft's per-pack
recipes/JSON files are registry-only data loaded at world-load time; recipes are never instantiated entities. Minecraft's datapack-driven recipe registry is the modern AAA realization of "recipe is data, not an entity" outside the procedural-generation space.
The pattern is universal across shipped AAA: recipes are data, never
entities. The registry_only qualifier on contract Recipe is the
SECS expression of that pattern.