Files
rivencraft/docs/WRITING_DATA.md
T
2026-10-01 17:28:20 -04:00

8.9 KiB
Raw Blame History

Writing and symbol data

Milestone 4 stores what a player wrote without deciding what that writing does to an Age. Milestone 5 owns grammar validation and symbol interaction, and translation into biome, noise, dimension-type, and other world-generation configuration. Milestone 6 owns instability effects. See the Legacy grammar audit for the source-backed Milestone 5 contract.

Symbol catalog

The authoritative server catalog loads JSON resources from data/<namespace>/rivencraft/symbols/<path>.json. The resource ID is the symbol ID. For example, data/rivencraft/rivencraft/symbols/terrain/standard.json defines rivencraft:terrain/standard.

Schema version 1 contains display metadata only:

{
  "schema_version": 1,
  "name": "symbol.rivencraft.terrain.standard",
  "description": "symbol.rivencraft.terrain.standard.description",
  "category": "rivencraft:terrain"
}

name and description are translation keys, not arbitrary formatted text or executable behavior. category is a namespaced organizational identifier. Milestone 5 adds server-authoritative schema v2 semantics with a typed role and bounded value. Existing v1 definitions remain readable but display-only; updating an ID to v2 never rewrites saved pages or books. Invalid definitions are logged and excluded by the server. Menus and future page synchronization must obtain resolved display metadata from the server; clients never make a symbol valid by naming it.

Rivencraft ships a catalog covering terrain, biomes, lighting, weather, sky, celestial behavior, and features. The parser and compiler apply supported schema-v2 pages to newly created Ages; omitted branches retain seeded defaults.

Persistent writing

SymbolReference stores only a namespaced symbol ID. WritingEntry is either a symbol reference or a baseline link-panel marker. OrderedWriting retains up to 256 entries in exact player-authored order. All three contracts have both persistent codecs and bounded network codecs.

Assembled Descriptive Books store OrderedWriting schema version 1 alongside their Age reference. Books assembled in 0.3.7.2 saved writing as a bare list; that form still loads as version 1 without reordering or dropping unknown IDs. Older page-free books without writing continue to work unchanged. Copying a book copies its writing and Age reference; merely copying it never creates a new Age. The Book Binder creates the Age when its finished output is taken. The Descriptive Book screen can inspect the ordered pages by turning them from the bottom corners and identifies unresolved IDs using server-provided symbol metadata. Page-free books continue to use random Age generation.

Removing a data pack never removes its IDs from saved writing. A missing ID is resolved as client-safe Unresolved Symbol display metadata while retaining the original namespaced ID for diagnostics and later restoration. This is deliberately different from treating an unknown symbol as valid grammar.

Pages

The single stackable rivencraft:page item has a bounded, persistent rivencraft:page_content component. Its explicit states are blank, symbol, unresolved symbol, and baseline link panel. Symbol and unresolved-symbol pages retain their namespaced symbol reference; unresolved pages can be inspected and removed but are rejected as usable writing until their data pack returns.

Only server-side writing operations may create a known symbol page or link panel from vanilla paper. The shared PageItem creation and validation gates reject new pages for identifiers absent from the server catalog. The Writing Desk refuses to copy an unresolved page, and the Book Binder keeps such a page removable but will not assemble a book from it until its symbol resolves again.

The item model uses server-assigned custom-model data derived from the symbol identifier. Built-in pages reproduce Mystcraft Legacy's four-word poem composition from its page background and symbol-component sheet. Data-pack symbols without a bundled resource-pack model use the legacy question-mark fallback while keeping their real identifier and display metadata.

The Notebook surface displays pages by their persistent slot index instead of packing occupied pages together. Empty positions through the last placed page appear darkened. While carrying a Page, all available positions are shown for placement. The surface draws the native 30×40 portrait page region from Legacy's book UI atlas; symbols are layered at a uniform scale, while the square item models remain unchanged in inventories.

A Notebook holds 27 ordered positions. Its pages, names, gaps, and unresolved IDs are saved on the item, so moving the Notebook between an inventory, Desk, and Binder does not rearrange them. A loose Page in a Desk tab exposes just one position; a Notebook exposes all 27. The Desk has 88 persistent collection tabs, shown four at a time. Use the up/down tab controls to move by four, put paper and Ink Vials in their input slots, select a stored page, and take the copy from the virtual output. Taking it spends one paper and the configured symbol-copy ink cost. The AZ, ALL, search, and category controls only change which stored pages are displayed; the server rechecks the actual source before copying. Moving a page within the Desk or dragging it into the inventory removes the original only when the destination accepts it.

The Book Binder takes a leather or empty-Notebook cover, an Age title, one Link Panel, and optionally up to 27 ordered written Pages. A filled Notebook can be imported at a chosen strip position; the empty Notebook remains recoverable. The preview result is virtual. Taking the completed Descriptive Book commits the inputs once, creates its Age identity, and saves schema-versioned OrderedWriting plus the Age reference on the book. Link-Panel-only books create random Ages. Supported written pages change the corresponding Age generation branch; missing branches use seeded defaults. Inputs, title, and pending Age identity survive Binder save/load; breaking the Binder returns stored inputs. The completed book retains both its writing and Age identity through item save/load and copying.

An Ink Vial is crafted from two black dye, a glass bottle, and a water bucket. The bucket remains after crafting. Each vial holds 16 ink units, stored in a persistent, network-synchronized component; only vials with identical remaining ink stack together. When depleted, a vial returns a glass bottle that can be used to craft another. The animated item texture comes from Mystcraft Legacy.

The server config sets ink costs independently for symbol copying (default one unit) and baseline link-panel preparation (default two units). To prepare a panel, hold vanilla paper in one hand and use an Ink Vial in the other. The server checks the held items and sufficient ink before consuming anything. A stack of paper yields exactly one Link Panel Page per use; if the inventory is full, the result is dropped instead of deleted. Symbol copying is implemented by the Writing Desk: it previews a copy of the selected resolved page, then spends paper and ink only when that copy is taken. The desk's 16-unit ink meter refills from an Ink Vial when needed and returns a vanilla glass bottle. Link-property modifiers are deferred beyond this baseline flow.

The Ink Mixer is the station version of Link Panel preparation. Put paper and Ink Vials in its inputs and take the Link Panel from its virtual output. Its 16-unit basin refills only when needed and only if the glass-bottle output has space. The basin and inputs persist through save/load; breaking the Mixer returns stored items. A Link Panel plus leather also crafts an unwritten Linking Book. JEI, when installed, displays the Mixer operation and the writing, binding, and Linking Book crafting flows; it is not required to play.

Migration and validation

The 0.3.7.2 bare-list OrderedWriting form reads as schema version 1 without changing entry order. Descriptive Books with no writing component keep their existing Age behavior. Old eight-slot Desks migrate their four collections, ink supply, paper, bottle return, and legacy output into the 88-tab layout; saved inputs are never silently discarded. Missing symbol IDs survive page, Notebook, Binder, and assembled-book persistence instead of being substituted or erased.

The core and archived dedicated-server GameTests together exercise codec and item round-trips, legacy data, workstation NBT reload, break drops, full-inventory refusal, forged menu IDs, and replayed output requests. World saves and chunk unloads use the same block entity NBT persistence path as those reload tests. This does not replace a manual smoke test of loading an older world before updating a production save.

Milestone 4 stops at preserving author intent and offering a playable random Age fallback. Milestone 5 will define symbol grammar and validation, translate valid writing into actual Age generation, and introduce symbol and ink modifiers.