KINBARROW modding reference
v0.2.0+main.e011511f4 dataset 4a103dcdb658a75a

Layout rules

The content tree — the contract for the data/ tree.

data/
├── README.md                      this contract
├── tables/                        one registry per file
│   ├── skills.srd.ron             Table<SkillDef>       (18)
│   ├── weapons.srd52.ron          Table<Weapon>         (38)
│   ├── weapon_masteries.srd52.ron Table<WeaponMasteryAssignment> (36)
│   ├── armor.srd52.ron            Table<Armor>          (12 + shield)
│   ├── cr_xp.srd52.ron            Table<CrXp>           (34)
│   ├── encounter_xp_budgets.srd52.ron Table<EncounterXpBudget> (20)
│   ├── advancement.srd.ron        Table<AdvancementRow> (20)
│   ├── multiclass_spell_slots.srd.ron Table<SpellSlotRow> (20, SRD Multiclass Spellcaster table)
│   ├── damage_kinds.srd.ron       Table<VocabRow>       (13 — open vocabulary)
│   ├── schools.srd.ron            Table<VocabRow>       (8 — open vocabulary)
│   ├── creature_types.srd.ron     Table<VocabRow>       (14 — open vocabulary)
│   ├── languages.srd.ron          Table<VocabRow>       (16 — open vocabulary)
│   ├── quality_profiles.ron       Table<QualityProfile> (5 classes × 7 tiers, ours)
│   ├── alignment.ron              AlignmentRules        (moral motive weights, ours)
│   ├── material_classes.ron       Table<MaterialClass>  (5, ours — [](../docs/adr/0070-vocabularies-are-registries.md))
│   └── terrain_tags.ron           Table<TerrainTag>     (7, ours — [](../docs/adr/0070-vocabularies-are-registries.md))
├── professions/                   ours — one profession per file (17; the
│   └── {fisher,brewer,baker,farmer,miller,tanner,smith,mason,merchant,innkeeper,
│       harbor_clerk,fixer,noble,guildmaster,captain,priest,sage}.ron — canonical
│       set mirrors crates/engine/src/professions.rs
├── buildings/                     ours — one building TYPE per file (21)
│   └── {smithy,tannery,carpentry,masonry,weaver,ovens,mill,mash_house,tavern,
│       fields,dock,mine,lumber_camp,pasture,manor,guildhall,watch_house,house,
│       town_wall,shrine,tower}.ron
├── races/                         one race per file, subraces inside as variants
│   └── {dwarf,elf,halfling,human,dragonborn,gnome,half_elf,half_orc,tiefling}.srd.ron
├── classes/                       one class per file, the SRD subclass inside
│   └── {fighter,rogue,cleric,barbarian,monk,paladin,ranger,bard,druid,sorcerer,warlock,wizard}.srd52.ron  (12)
├── feats/                         OPEN collection: one feat per file
│   ├── grappler.srd.ron           SRD 5.1's ONE feat (prereq-only; riders ledgered)
│   └── {alert,savage_attacker,boon_of_truesight}.srd52.ron  the SRD 5.2.1 feats
│                                   with engine substrate ; the rest is a mod surface
├── spells/                        OPEN collection: one spell per file
│   └── {fire_bolt,magic_missile,fireball,cure_wounds,…}.srd*.ron (83: 79 SRD 5.1,
│                                   4 SRD 5.2.1),
│                                   every one scoped to the class list the book
│                                   gives it — ; ALL of them, since the
│                                   one non-SRD file left for the private
│                                   book-mod tree at . No shipped spell
│                                   pulls: Effect::Pull's lock builds its own)
├── magic_items/                   OPEN collection: one magic item per file
│   └── {plus_one_longsword,plus_one_chain_shirt,ring_of_protection,
│       cloak_of_protection,wand_of_magic_missiles}.srd.ron  (5: the SRD starter set)
│       ring_of_resistance_{acid,…,thunder}.srd.ron  (10: the SRD 5.1 Ring of Resistance gem table, one row per line)
├── conditions/                    OPEN collection: one condition per file
│   └── {blinded,charmed,deafened,frightened,grappled,…}.srd52.ron  (14)
│                                   unconditional ConditionComponent reads plus
│                                   contextual ConditionFact entries
│       {ability_guided_weapon,innately_sorcerous,raging,reckless,
│        walking_speed_flight}.ron  (5 Original class-helper conditions)
├── traps/                          OPEN collection: one trap per file
│   └── {poison_needle,poison_darts,fire_breathing_statue}.srd.ron  (3: the SRD
│                                   "Traps" device samples; the container trap is
│                                   the poison needle — the rest a mod surface)
├── diseases/                       OPEN collection: one disease per file
│   └── {sewer_plague,sight_rot,cackle_fever}.srd.ron  (3: the SRD "Diseases"
│                                   sample diseases — a contraction save, an
│                                   incubation, an effect (exhaustion/condition/
│                                   check penalty), and a long-rest recovery save
│                                   track; the rest a mod surface)
├── creatures/                     OPEN collection: one entity per file,
│   ├── humanoids/                 in stable taxonomic folders
│   │   └── {commoner,guard,bandit}.srd.ron
│   ├── beasts/wolf ; undead/{skeleton,zombie} ; dragons/black_dragon_wyrmling
│   ├── fiends/dretch ; elementals/magma_mephit ; giants/ogre ; oozes/gray_ooze
│   ├── constructs/animated_armor ; monstrosities/worg ; fey/satyr
│   └── celestials/pegasus ; aberrations/gibbering_mouther ; plants/awakened_shrub
│                                   (the  bestiary — one per type)
├── goods/                         ours (unsuffixed) — one material/tool per file
│   └── iron_ore, iron_ingot, coal, timber, hide, leather, cotton, cloth,
│       sinew, bedroll, bed, smiths_tools, leatherworkers_tools,
│       carpenters_tools, weavers_tools  (.ron, source: Original)
├── expected/
│   └── npc_blocks.srd.ron         verification corpus (see Derivations)
├── art/                           runtime pictures a row names by path (see below)
│   └── furniture/                 one per furnishing good's `art:` field
└── names/                         ours (unsuffixed) — per-race name tables
  • Art is named by path, and a mod layers it. A furnishing good’s art: names a picture inside art/, e.g. "furniture/trestle-table.webp". It is drawn from above facing north (back edge at the top, width_cells across, length_cells down, 128 px per cell) and the board rotates it for the other facings. A mod’s own art/ is searched before this one, so a mod replaces a picture by shipping the same path or adds one under a new path. A path that resolves nowhere fails the load. Every picture carries a provenance header that says whether it is an AI placeholder or who made it and under what licence; stamp one with cargo xtask art stamp ( ).

  • Registries vs. entities. Compact row collections (the SRD’s tables) live as ONE registry file per set under tables/. Collections that will someday hold tens of thousands of entries (creatures, and later items, spells,…) grow one-file-per-entity inside stable taxonomic folders — creatures/humanoids/ plus the thirteen monster folders (beasts/, undead/, dragons/, fiends/, elementals/, giants/, oozes/, constructs/, monstrosities/, fey/, celestials/, aberrations/, plants/) the bestiary filled, one exemplar per non-humanoid type. magic_items/ is the README’s own “later items” made real — an entity collection, not a tables/ registry, because the SRD’s Magic Items chapter grows to thousands and a mod adds one as a file. Both kinds are OPEN: mods add weapons, armor, races, and creatures (the moddable-data amendment — data loads at boot). A creature’s optional doors field is a closed set of Encounter, Battle, Form, and Summon; when absent it defaults to all four. Author at least one distinct door to narrow which builders and catalogues may enumerate the body. A swarm (any creature with swarm_member_size) never opens Form, whatever its list says: a form takes one body, and a swarm is many.

  • Suffix + source provenance. A provenance suffix marks files whose content derives from an SRD, and names WHICH one: .srd.ron for SRD 5.1, .srd52.ron for SRD 5.2.1. Every file’s top-level value also carries a required source field (Srd51, Srd52, or Original in the base), and the two must agree — data_lock’s the_suffix_and_the_source_field_agree fails the build otherwise, so the path can be trusted without opening the file. Book mods use their matching Phb2024, Dmg2024, Mm2024, Tce, or Xge source; the loader refuses a missing source, a book source in base data, or a book/namespace mismatch. That is what makes *.srd*.ron auditable against the repository’s ATTRIBUTION.md, which states the two grants separately. Files without a suffix (names/, goods/) are ours.

  • id equals filename. For one-entity-per-file collections, the file stem IS the entity’s id: half_elf.srd.ron ↔ id: "half_elf", guard.srd.ron ↔ id: "guard". The future parse-everything lock test asserts this. Ids are snake_case throughout — chosen over kebab because the pre-existing names/ files (half_orc.ron) already use it, and the race key contract (below) shares filename ids with them.

  • No organization by tunables. Directories follow stable taxonomy ONLY — never CR, level, cost, or any other property that balancing may move. By-CR (or any) access is a load-time index. This is derive-don’t-store applied to layout.