Files
rivencraft/docs/LEGACY_AGE_GRAMMAR_AUDIT.md
T
2026-10-05 13:09:47 -04:00

17 KiB
Raw Blame History

Mystcraft Legacy Age grammar audit (milestone 5, issue #28)

Reference: Mystcraft-Legacy commit 9bc8ddc, whose build properties identify version 0.13.7.06. The user-provided local Minecraft 1.12.2 extraction (mystcraft-1.12.2-0.13.7.06) has the same version in mcmod.info; its assets/mystcraft/textures/symbolcomponents.png is byte-identical to the source checkout. That extraction contains compiled classes and assets, but no shipped .cfg or .java files. Source-linked behavioral claims below use the corresponding GitHub Java source. This is a behavior specification, not a code port. Any later adapted code needs its own copyright/provenance record under PORTING.md.

What Legacy actually does

Legacy's root rule produces, in order: terrain, biome controller, weather, lighting, optional spawning, suns, moons, starfields, doodads, visuals, small/medium/large features, and effects. Each symbol declares the rule it can satisfy and any preceding modifier tokens it needs in SymbolRules. The written page order therefore matters: modifiers appear before their consumer, while missing grammar branches can be generated. The grammar tree connects authored terminals and inserts missing branches; AgeData does this on first link with an Age-seeded RNG. Weighted rule ranks choose generated symbols; a null rank is not randomly generated, though such a rule can connect authored pages (GrammarGenerator).

Legacy does not reject a book just because it omits terrain, biome, weather, or lighting. It fills the gaps. It also has separate instability accounting for dangling/excess symbols; this audit records those as diagnostics, not as milestone 5 generation effects (AgeController).

Symbol-to-Rivencraft mapping

Legacy category and symbols Existing Rivencraft path Milestone 5 disposition
TerrainNormal, TerrainAmplified, TerrainFlat, TerrainVoid, TerrainNether, TerrainEnd; terrain and sea block modifiers AgeProfile selects noise/flat/void and registered noise settings; random profiles already persist per Age Compile supported terrain shapes into profile/resources. Nether/End and material modifiers require explicit compatible data-pack resources; do not claim exact 1.12 terrain parity.
BioConNative, Single, Tiled, Grid, Tiny, Small, Medium, Large, Huge, plus biome pages AgeTraits.BiomeDistribution has all nine modes; AgeDimensionService has sources for these modes Map modes, consume authored biome IDs in order, then deterministically fill required minimums. Native uses the profile's modern biome preset, not the old BiomeProvider.
LightingNormal, Dark, Bright AgeTraits.Lighting, dimension type construction Compile the choice to a stable dimension type/light behavior. Exact Legacy 1.12 brightness-table rendering is not guaranteed by NeoForge's dimension-type fields.
WeatherNorm, Fast, Slow, Off, On, Cloudy, Rain, Snow, Storm AgeTraits.Weather has matching names except Legacy On maps to ALWAYS Compile weather semantics separately from biome selection. Snow must remain deferred until optional season integration; do not silently substitute another weather mode.
Suns, moons, starfields; angle, phase, period, color/gradient/sunset modifiers One celestialPeriod, celestialAngle, celestialPhase on AgeTraits Compile only the representable single-cycle subset first. Multiple celestial bodies, independent periods, custom stars, gradients and sunsets need a richer definition and renderer, not flattening into one value.
Sky/fog/cloud/grass/foliage/water colors, natural variants, horizon, rainbow Existing sky/dimension visuals and preview Require an explicit modern client/biome-color design; metadata-only symbol pages must not pretend to change rendering.
Caves, ores, huge trees, lakes, floating islands, tendrils, skylands, spheres, spikes, crystals; vanilla villages, strongholds, mineshafts, dungeons, fortresses, obelisks, fissures Current cave profile, authored Floating Islands/Tendrils/Skylands/Spheres/Spikes/Obelisks/Crystal Formations and Dense Ores, and page-gated vanilla Dungeons/Mineshafts/Nether Fortresses/Strongholds/Villages The five Legacy vanilla structure symbols gate Minecraft 1.21.1 generation. Dungeons use monster-room placement; the others use vanilla structure sets. Obelisks use a bespoke 4×4 plinth and 2×12×2 shaft with safe modern placement. Crystal Formations retain Legacy's blue tile and one-in-fifteen attempt rate but use new budding, shard-producing mounds. Fissures and exact 1.12 structure geometry remain separate work.
EnvAccel, explosions, lightning, meteors, scorching; PvP and dummy suppression pages No equivalent Age-definition effect Defer environmental hazards/instability effects to milestone 6, PvP rule to a separately scoped server policy; retain authored IDs without fake behavior.

The Legacy symbol list and page names come from ModSymbols and SymbolRules. Rivencraft's catalog currently holds display metadata only; its built-in set is just standard terrain, native biomes, normal weather, normal lighting, normal time, and caves. OrderedWriting preserves page order, but no compiler yet connects it to AgeTraits or Age profiles.

Symbol-page artwork: symbolcomponents.png

Legacy does not allocate one image tile to each complete Age symbol. The default word image source is mystcraft:textures/symbolcomponents.png, a 512×512 RGBA sheet. It has an 8×8 grid of 64×64 component cells. For zero-based component index n, source pixels begin at x = (n % 8) * 64, y = (n / 8) * 64. GuiUtils.drawComponent uses that mapping for GUI drawing; PageBuilder.PageSprite.stitchWord uses it when composing an item sprite. Cell 0 is the missing-word/question-mark fallback. Each component may be tinted and its alpha layered with the other components of a word.

The complete lookup chain for a unique page is:

  1. WordData.init registers a list of component indices for each named word (for example, Nature uses 5, 6, 8, 10, 11, 12, 15, 16, 17, 22). DrawableWord also permits per-component colors and an alternate image source. Unregistered words get a deterministic component list from their lowercase name hash (DrawableWordManager).
  2. ModSymbols.registerSymbol assigns four poem words to each Age symbol. For example, LightingNormal is Ethereal, Dynamic, Cycle, Balance (registration). The poem, not the symbol ID, selects the component layers.
  3. PageBuilder.PageSprite draws those words above, right, below, and left of the page center, respectively. Their target rectangles on its 160×160 working image are (48,0), (96,48), (48,96), (0,48), each 64×64 (getPageTarget). It scales the composed image to a 128×128 item sprite. GuiUtils.drawSymbol renders the same four-word arrangement directly in book/workstation GUIs.

For Rivencraft, keep symbol semantics (SymbolReference/catalog ID) separate from page artwork (four ordered word names, their component indices/colors, and the shared sheet). Existing built-in page images are static renditions of this process (asset provenance); future symbol pages can compose it at build time or in a client-only renderer. Unknown words and missing symbols need distinct fallbacks, and data-pack-only symbols must remain usable without silently borrowing another symbol's image. Do not copy the Legacy renderer wholesale: its texture-atlas and GUI APIs target 1.12.2.

Verified numeric defaults and bounds

These values are from code, not a supposed shipped .cfg: the inspected Legacy repository contains no default configuration file with numeric min/max fields for age grammar. MystConfig supplies typed config helpers, while symbol enablement uses a Boolean <symbol>.enabled option (SymbolManager). Do not label Rivencraft's present numeric range as a Legacy config range.

Parameter Legacy source value/rule Implementation consequence
Period pages Zero=0, Half=0.5, Full=1, Double=2 (ModSymbols); repeated period modifiers average pairwise (SymbolLength) Authored basic values have min 0 and max 2; no arbitrary continuous written range is established. A sun without a period uses 0.8 + 0.4 * nextDouble()—[0.8, 1.2)—before conversion to ticks (SymbolSunNormal). Rivencraft's random nonzero [0.2, 2.0) is its own existing policy.
Angle pages North/East/South/West = 0/90/180/270 degrees (ModSymbols); repeated values use shortest-arc averaging (ModifierUtils) Canonical angle is [0, 360); consumers may seed a random angle if omitted.
Phase pages Nadir/Rising/Zenith/Setting = 0/90/180/270 degrees (ModSymbols); the sun divides by 360 (SymbolSunNormal) Written phase is [0, 360) degrees, represented by Rivencraft as [0, 1) turns.
Biome count Grammar requires one page for Single, Tiled, Grid; Tiny–Huge have two explicit biome slots plus a biome-list branch (SymbolRules). Single fills to 1 (source), Tiled/Grid to 2 (source), and Tiny–Huge to 3 (source) These are minimums, not maximums. Native uses vanilla's provider and has no authored biome-list requirement (source). Preserve additional authored biomes where the chosen controller can accept them.
Weather normal Rain duration/base 12000/12000, cooldown/base 168000/12000; thunder duration/base 12000/3600, cooldown/base 168000/12000 ticks (SymbolWeatherNormal) These are source constants, not configurable min/max bounds. Other weather controllers need individual review before parity claims.

Compilation and fallback contract for the next issues

  1. A Link-Panel-only book, a legacy page-free book, and any book with no effective supported Age symbols retain the current seed-derived random Age path. Preserve the saved writing untouched.
  2. A supported partial sequence is not invalid: complete missing required branches deterministically from the Age seed, then compile the result. Authored symbols take precedence over generated fillers. This follows Legacy's grammar tree, rather than requiring a full hand-written list.
  3. Unknown/unresolved IDs, unsupported-but-known effects, misplaced modifiers, duplicates, and conflicts must be reported distinctly. Do not silently apply a different effect or discard an authored page. A first compiler may use the existing random Age path for combinations it cannot represent, with an explicit diagnostic; it must never claim such a book was successfully compiled.
  4. Grammar diagnostics are not instability. Milestone 5 decides recognition, ordering, completion, and whether a supported combination can compile. Milestone 6 may use dangling/excess/conflict diagnostics for instability effects. Milestone 7 owns bespoke structures and polish.
  5. Freeze the completed, effective generation definition with the Age identity before creating chunks. Keep page order and original IDs for display/migration, and keep seeded completion deterministic across reloads. New symbol behavior belongs in versioned server data, not the schema-1 display catalog.

The mapping is intentionally narrower than all Legacy symbols. The exact rule and compiler schema are follow-up issues #29–#31; terrain, biome, environment, and feature implementations are #32–#35. No generation behavior or release version changes in this audit.