Files
rivencraft/docs/SYMBOL_SEMANTICS.md
2026-10-22 22:32:12 -04:00

6.3 KiB
Raw Permalink Blame History

Server-authoritative symbol semantics (schema v2)

Milestone 5 issue #29 adds typed meaning to the existing data-pack symbol catalog. Put definitions at data/<namespace>/rivencraft/symbols/<path>.json; the file ID becomes the stable symbol ID. For example, data/example/rivencraft/symbols/terrain/highlands.json defines example:terrain/highlands:

{
  "schema_version": 2,
  "name": "symbol.example.terrain.highlands",
  "description": "symbol.example.terrain.highlands.description",
  "category": "example:terrain",
  "semantics": {
    "role": "terrain",
    "value": "example:highlands"
  },
  "poem": "Terrain Form Tradition Flow"
}

name and description are translation keys. category is for display and sorting; it does not determine grammar. semantics.role and its typed value are server-owned. The terrain value above names an Age runtime profile that the compiler resolves and validates. A syntactically valid resource ID alone does not guarantee the profile or feature exists.

poem is optional, client-safe artwork metadata: exactly four alphabetic words, ordered top, right, bottom, left. The client layers their glyphs from the shared Legacy component sheet at runtime. GUI thumbnails use the full transparent artwork over their page backgrounds; item icons use the same artwork reduced from 16 to 13 pixels across, over the page texture. Unregistered words use a stable generated component combination; when a symbol has no poem, the six original built-in IDs retain their Legacy poems and other IDs produce four stable fallback words. This affects appearance only, never Age generation. Generated images are cached up to 256 entries and discarded on resource reload.

The Writing Desk retains 88 collection tabs, numbered from zero as in Legacy. Legacy's ModWords.constructNumber defines 0 as component 1 and 1–24 by overlaying a unit mark (1–4) and a five-step mark (5–20) from the bottom row of symbolcomponents.png in the same square. Legacy's Writing Desk has 25 tabs (0–24) and scrolls its four-tab window one tab at a time. Thus the supplied Legacy screenshots labeled 1–4, 5–8, and so on show overlapping windows, not 88 distinct numerals. Rivencraft retains its previously requested four-at-a-time navigation and 88 tabs. Its additional tab numbers use positional base 25: each place is an overlaid Legacy digit, with the places side by side (25 = 1,0). The two glyphs are sized and positioned to fit the tab. Hovering reveals the decimal tab index for accessibility. The generated-word mechanism renders page-free Descriptive Book text as layered glyphs instead of Minecraft's enchantment font. The Age name stays readable.

Role Value type and allowed values
terrain Canonical namespaced Age profile ID.
biome_controller native, single, tiled, grid, tiny, small, medium, large, or huge.
biome Canonical namespaced biome ID.
lighting normal, dark, or bright.
sky overworld, nether, or end.
weather normal, fast, slow, off, always, cloudy, rain, snow, or storm.
season no_seasons, seasons, eternal_winter, eternal_summer, eternal_fall, or eternal_spring. Seasonal effects other than No Seasons require optional Serene Seasons.
celestial normal_time (the first representable single-cycle behavior).
period_modifier JSON number in [0, 2]; zero is stopped time. An immediately preceding D'ni number page overrides it with digit × 0.08.
angle_modifier JSON number in [0, 360) degrees. An immediately preceding D'ni number page overrides it with digit × 15°, wrapping 360° to 0°.
phase_modifier JSON number in [0, 360) degrees; the compiler converts it to turns. An immediately preceding D'ni number page overrides it with digit × 15°, wrapping 360° to 0°.
size_modifier JSON scale in [0.25, 3]. An immediately preceding D'ni number page overrides it with a linear 0.25×–3× scale: digit 0 is 0.25× and digit 24 is 3×. Without a number, Small/Normal/Large remain 0.5×/1×/2×.
block Canonical namespaced material ID for a compatible following feature; registered full-collision blocks and source fluids receive generated Pages.
feature Canonical namespaced feature-effect ID; the compiler must recognize and validate it. This includes supported decorations and structures.

These are schema bounds, not claims that Legacy shipped numeric config ranges. See the Legacy grammar audit for the source values and biome-count rules. Roles outside this table—including multiple suns, gradients, and hazards—are intentionally unsupported by schema v2. Their meaning requires a later versioned extension, not an unvalidated free-form field. Recognized schema values can still be rejected by the current compiler when their runtime effect is unsupported, such as angle modifiers or direct Rain/Snow weather pages.

The server rejects a v2 definition with an unknown top-level or semantics field, missing/incorrectly typed field, unknown role or choice, malformed/non-canonical resource ID, or out-of-range/non-finite number. An invalid definition is logged with its file ID and excluded from the active catalog. Saved pages and books still retain that ID, allowing the player to recover them if the data pack is corrected. A reload atomically replaces the catalog rather than mutating saved writing.

Schema v1 definitions remain readable as display-only symbols; existing packs need not be rewritten merely to show or copy pages. A v1 definition cannot add a semantics field. To make one eligible for Age grammar parsing, publish a v2 definition with the same file path and ID, adding a valid role and value. Do not rename the page ID or reorder a book's OrderedWriting. The client receives only display metadata; semantic definitions are not serialized to it. The ordered-writing parser validates new books, and the server compiles supported writing into a frozen Age plan before Binder inputs are consumed.

The six built-in definitions demonstrate terrain, biome-controller, lighting, weather, celestial, and feature roles. A third-party pack may add its own definitions under its namespace. Use an explicit semantic role even when the display category has the same name; the two fields serve different purposes.