Definitions
Definitions are reusable YAML structures that can be inherited using the $extends directive at any nesting level. Definitions can be parameterized with $with bindings and validated with $params declarations.
Defining Definitions
Section titled “Defining Definitions”Definitions are declared in a top-level definitions section:
spec: version: "1.0"
definitions: baseCondition: awaken: false masterpiece: false params: evolutionProb: 1.0 requiredMoney: 10000
rareCondition: $extends: baseCondition params: evolutionProb: 0.8 requiredMoney: 50000Definition names must match pattern [A-Za-z_][A-Za-z0-9_]*.
Using $extends
Section titled “Using $extends”The $extends directive inherits from a definition:
evolutions: create: - targetTemplateId: 10121 conditions: - $extends: baseCondition targetEnchantStep: 9 result: resultTemplateId: 12265$extends works at any mapping level - top-level entities, nested blocks, deeply nested objects.
Definitions can be combined with ID List Expansion to apply templates to multiple IDs at once.
Deep Merge Semantics
Section titled “Deep Merge Semantics”When extending a definition, values are merged using deep merge rules:
| Parent | Child | Result |
|---|---|---|
{a: 1} | {b: 2} | {a: 1, b: 2} |
{a: 1} | {a: 2} | {a: 2} (child wins) |
{a: {x: 1}} | {a: {y: 2}} | {a: {x: 1, y: 2}} (recursive) |
[1, 2] | [3, 4] | [3, 4] (replace) |
"foo" | "bar" | "bar" (replace) |
Key rules:
- Objects merge recursively
- Lists replace entirely (no element merging)
- Scalars replace
- Child values always win over parent values
$remove Directive
Section titled “$remove Directive”The $remove directive removes inherited keys after merge:
definitions: fullItem: name: "Base Item" tradable: true internalId: 12345 debugFlag: true
items: create: - $extends: fullItem $remove: - internalId - debugFlag name: "Player Item"Result: {name: "Player Item", tradable: true}
Rules:
$removemust be a list of key names- Processed after deep merge
- Removes top-level keys only
- Removing non-existent keys is allowed
$with parameter binding
Section titled “$with parameter binding”The $with directive adds scoped value bindings to $extends, making definitions reusable templates. A definition declares placeholder references ($NAME) in its body; the call site provides concrete values via $with:
definitions: Greeting: message: hello target: $WHO
result: upsert: - $extends: Greeting $with: { WHO: world }Result: {message: hello, target: world}
$with value resolution
Section titled “$with value resolution”$with values are resolved against the current variable scope before injection. Values can reference file-scoped variables:
variables: SOURCE_ID: 12265 TARGET_ID: 12273
definitions: Item: source: $SRC target: $TGT
items: create: - $extends: Item $with: { SRC: $SOURCE_ID, TGT: $TARGET_ID }Result: {source: 12265, target: 12273}
$with shadowing
Section titled “$with shadowing”$with bindings shadow file-scoped variables of the same name:
variables: HP: 100
definitions: Stats: hp: $HP
result: create: - $extends: Stats $with: { HP: 999 }Result: hp: 999 (not 100).
Nested $with propagation
Section titled “Nested $with propagation”$with bindings propagate into nested $extends chains through scope inheritance. Each $extends block forms a scope boundary — nested blocks receive the outer scope:
definitions: Inner: value: $X
Outer: nested: $extends: Inner $with: { X: $Y }
result: create: - $extends: Outer $with: { Y: 42 }Result: {nested: {value: 42}}
The outer $with: { Y: 42 } provides Y to the scope. The nested $with: { X: $Y } resolves $Y to 42 from the inherited scope, then binds X: 42 for Inner.
Definition name as binding
Section titled “Definition name as binding”$with can pass definition names for dynamic $extends resolution inside definition bodies:
definitions: BasePath: cost: 500
Item: path: $extends: $PATH_DEF extra: true
result: create: - $extends: Item $with: { PATH_DEF: BasePath }Result: {path: {cost: 500, extra: true}}
The $extends: $PATH_DEF inside Item resolves $PATH_DEF to BasePath via the inherited scope. The resolved value must be a valid definition name (E501 if not).
$with with $remove
Section titled “$with with $remove”$with and $remove can be combined. $remove is processed before substitution, so removed fields with unresolved placeholders do not trigger E520:
definitions: Base: a: 1 b: 2 c: $VAL
result: create: - $extends: Base $with: { VAL: 3 } $remove: [b]Result: {a: 1, c: 3}
$with rules
Section titled “$with rules”$withrequires$extendsas a sibling (E540)$withvalue must be a YAML mapping (E541)- Binding names must match
[A-Za-z_][A-Za-z0-9_]*(E542) - Binding values must be scalars or scalar lists — mappings and sequences containing non-scalar elements are not allowed (E543)
- Substitution is whole-value only:
$NAMEmust be the entire scalar value. Substrings like"prefix_$NAME"remain as literal strings $withis stripped from output
$params declaration
Section titled “$params declaration”$params declares required parameter names on a definition. It is validated at expansion time — if required parameters are not provided via $with bindings or file-scoped variables, E544 fires with an actionable message.
definitions: Item: $params: [SOURCE, TARGET] source: $SOURCE target: $TARGET
result: create: - $extends: Item $with: { SOURCE: 1, TARGET: 2 }$params validation rules
Section titled “$params validation rules”| Scenario | Behavior |
|---|---|
$with provides all required params | No error |
$with provides extra params beyond $params list | Allowed |
File-scoped variables satisfy all required params (no $with) | No error |
Required param missing from both $with and scope | E544 |
$params is not a sequence of strings | E545 |
Duplicate names in $params | E545 |
$params used outside definitions: | E507 |
$params is definition metadata — it is extracted and stripped at registration time, never appearing in output.
Multi-level inheritance
Section titled “Multi-level inheritance”Definitions can extend other definitions:
definitions: baseWeapon: combatItemType: EquipWeapon maxStack: 1 tradable: true
lancerWeapon: $extends: baseWeapon requiredClass: ["Lancer"] attackRange: 3.0
lancerWeaponTier2: $extends: lancerWeapon requiredLevel: 30 rareGrade: Uncommon
items: create: - id: 10001 $extends: lancerWeaponTier2 name: steel_lanceMaximum inheritance depth is 10 levels.
Cross-Module Definitions
Section titled “Cross-Module Definitions”Exporting Definitions
Section titled “Exporting Definitions”Export definitions for use in other modules:
spec: version: "1.0"
exports: definitions: - baseCondition - rareCondition
definitions: baseCondition: awaken: false masterpiece: false
rareCondition: $extends: baseCondition params: evolutionProb: 0.8Importing and Using
Section titled “Importing and Using”Import a package and reference definitions with namespace qualification:
spec: version: "1.0"
imports: - from: core
evolutions: create: - targetTemplateId: 10121 conditions: - $extends: core.baseCondition targetEnchantStep: 9 - $extends: core.rareCondition targetEnchantStep: 12Multi-File Packages
Section titled “Multi-File Packages”Packages can split definitions across multiple files. All files within a package share the same namespace:
packages/weapons/ index.yml # imports ./bases.yml, exports baseSword bases.yml # defines baseSword → registered as weapons.baseSwordResolution Rules
Section titled “Resolution Rules”- Unqualified names (
baseCondition) resolve to local definitions first - Qualified names (
core.baseCondition) resolve to the specified package - If an unqualified name matches multiple packages, an error is raised (use qualified name)
Variables in definitions
Section titled “Variables in definitions”Module-level variables can be used inside definition bodies. Variable substitution runs after $extends merge, so inherited fields containing $VAR references resolve correctly:
variables: BASE_HP: 1000
definitions: baseStats: hp: $BASE_HP mp: 500
warriors: create: - $extends: baseStats name: fighterAfter resolution: hp: 1000, mp: 500.
When $with bindings are present, they shadow file-scoped variables of the same name within the definition body. See $with shadowing above.
Variables can also be imported from other modules and used in local definitions. See Variables for declaration syntax, types, and cross-module export/import.
Error codes
Section titled “Error codes”| Code | Meaning |
|---|---|
E501 | Unknown definition reference |
E502 | Circular definition inheritance |
E503 | Inheritance depth exceeds limit (10) |
E504 | Ambiguous definition (multiple matches) |
E506 | Unsupported YAML feature (anchors/aliases) |
E507 | Unknown directive |
E509 | Duplicate definition name |
E510 | Invalid definition name |
E511 | Invalid $remove directive |
E512 | Exported definition not found |
E540 | $with without $extends |
E541 | Invalid $with value (not a mapping) |
E542 | Invalid $with binding name |
E543 | Invalid $with binding value (mapping or non-scalar sequence element) |
E544 | Missing required parameter ($params unsatisfied) |
E545 | Invalid $params declaration |
E501: Unknown definition
Section titled “E501: Unknown definition”items: create: - $extends: nonexistent # E501Also fires when $extends: $PARAM resolves via $with to a name that is not a known definition.
E502: Circular inheritance
Section titled “E502: Circular inheritance”definitions: a: $extends: b b: $extends: a # E502: CircularE506: Unsupported YAML feature
Section titled “E506: Unsupported YAML feature”YAML anchors (&), aliases (*), and merge keys (<<) are not supported:
definitions: base: &base # E506: Anchors not allowed level: 10
items: create: - <<: *base # E506: Merge keys not allowedUse $extends instead.
E540: $with without $extends
Section titled “E540: $with without $extends”result: create: - id: 1 $with: { X: 2 } # E540: $with requires $extendsE541: Invalid $with value
Section titled “E541: Invalid $with value”result: create: - $extends: Template $with: not_a_mapping # E541: Expected mappingE543: Invalid $with binding value
Section titled “E543: Invalid $with binding value”result: create: - $extends: Template $with: X: nested: value # E543: Mappings not allowedBinding values follow the same type restrictions as variables: scalars and scalar lists only.
E544: Missing required parameter
Section titled “E544: Missing required parameter”definitions: Item: $params: [SOURCE, TARGET] source: $SOURCE target: $TARGET
result: create: - $extends: Item $with: { SOURCE: 1 } # E544: Missing TARGETE545: Invalid $params declaration
Section titled “E545: Invalid $params declaration”definitions: Item: $params: not_a_list # E545: Expected sequence of strings id: 1Also fires for duplicate parameter names ($params: [ID, ID]).