Public Access
162 lines
8.9 KiB
Markdown
162 lines
8.9 KiB
Markdown
# 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](LEGACY_AGE_GRAMMAR_AUDIT.md) 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:
|
||
|
||
```json
|
||
{
|
||
"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](SYMBOL_SEMANTICS.md)
|
||
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.
|
||
|
||
## Ink and baseline link panels
|
||
|
||
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](GAMETESTS.md) 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.
|