Add Milestone 7 regression and documentation review (#83)
Build / build (push) Canceled after 0s

This commit is contained in:
dnorberg committed 2026-10-22 21:37:50 -04:00
1 parent 77f15f8599
commit e7e2cf7e5a
12 files changed
+424 -285

No files matched your search

+86 -268
View File
@@ -1,292 +1,110 @@
# Rivencraft # Rivencraft
Rivencraft is a clean, incremental port of the ideas and gameplay of Write a book. Name an Age. Step into a world that did not exist before.
[Mystcraft Legacy](https://github.com/Mystcraft/Mystcraft-Legacy) to Minecraft
1.21.1 on NeoForge.
The bootstrap, books/linking, Ages, writing-system, and Age-grammar milestones are complete. Rivencraft brings the books, writing stations, symbols, and unpredictable Ages
The writing system uses a data-pack symbol catalog and persistent of [Mystcraft Legacy](https://github.com/Mystcraft/Mystcraft-Legacy) to
ordered-writing model. Linking Books and Descriptive Books create persistent Minecraft 1.21.1 on NeoForge. Mystcraft veterans will recognize the writing
Ages from either authored supported symbols or seeded random completion. flow, D'ni-inspired glyphs, libraries, crystals, and instability. Rivencraft
Milestone 6 instability work is in progress: Ages persist frozen instability also lets you author modern terrain, biomes, structures, seasons, and celestial
scores and provider plans, and the bounded runtime implements status effects, bodies. It is an active pre-public-release project, not a byte-for-byte copy of
colored decay, lightning, explosions, meteors, burning, and erosion. The the 1.12.2 mod.
[Milestone 5 acceptance record](docs/MILESTONE_5_ACCEPTANCE.md) lists the
supported grammar, optional integrations, and limits; the
[instability runtime policy](docs/INSTABILITY_RUNTIME.md) records the current
effects and modern safety boundaries.
Milestone 4 now includes stackable blank Pages plus server-created symbol, ## Getting started
unresolved-symbol, and baseline link-panel states. Page visuals follow the
legacy runtime-composition rules. Craft an Ink Vial from two black dye, a glass
bottle, and a water bucket; the bucket is returned. Hold vanilla paper in one
hand and use the Ink Vial in the other to prepare a baseline Link Panel Page.
Each vial holds 16 ink units, and the default link-panel cost is two units.
The spent vial returns a glass bottle. Server owners can adjust the symbol-copy
and link-panel costs in the `writing` section of `rivencraft-server.toml`.
The Ink Mixer now offers a Legacy-style station for producing Link Panels:
insert paper and Ink Vials, then take a Link Panel from the result slot. Each
vial fills its 16-unit basin and returns a glass bottle; taking one Link Panel
uses the full vial. No server tick is needed. The earlier paper-in-one-hand
method still uses the configurable link-panel ink cost. Ink Mixer
additives can roll Disarm, Maintain Momentum, and Intra Linking onto a Link
Panel. Descriptive Books retain Disarm and Momentum; Intra Linking is only
meaningful for same-dimension travel with a Linking Book.
TerraBlender 1.21.1 integration is optional: registered modded biomes receive
Biome pages, with cave and Nether biomes in a separate Cave Biome creative tab.
TerraBlender Overworld/Nether regions extend compatible Age
biome pools. See [the compatibility matrix](docs/TERRABLENDER_COMPATIBILITY.md)
for supported versions and in-game verification.
Serene Seasons 1.21.1 can maintain separate season progress in an Age dimension.
Rivencraft automatically whitelists loaded Ages without a restart when Serene is installed;
season pages can instead opt an Age out or hold it in one season.
See [the optional compatibility guide](docs/SERENE_SEASONS_COMPATIBILITY.md)
for the supported manual configuration and current limits; Rivencraft does not
require Serene Seasons or GlitchCore.
The Writing Desk can copy a selected written page from its collection tabs.
The Writing Desk is now craftable from planks, a glass bottle, and a feather.
It occupies two adjacent blocks, with one shared inventory; loaded paper and
the selected page appear on its Legacy-inspired model.
Desks placed before 0.3.6.1 keep their old one-block footprint until broken
and placed again; leave an adjacent space when replacing one.
Its 88 collection tabs, paper input, ink vial input, empty glass-bottle return,
16-unit ink meter, and inventory persist
through world saves; breaking it drops stored contents. The desk screen is a
functional foundation using Legacy's original desk and scrollbar textures.
Four tabs are visible at once; the controls above and below them move by four
(1–4, 5–8, through 85–88). Each viewer can browse a different group. Existing
four-tab desks retain their collections and supplies when upgraded.
With a notebook selected, pick up a Page from your inventory and click an empty
position on the left surface to store one page there. Clear search/filter/sort
and turn off `ALL` to place pages at specific positions; occupied positions are
never overwritten. A notebook tab exposes all 27 notebook positions (scroll to
reach the rest); a loose-page tab exposes only its one occupied position.
Empty tabs have no page storage until a notebook or page is put in the tab slot.
Click a page on the desk surface to select it for copying. Drag a page from one
notebook position to an empty position to move it, or onto another page to swap
their positions. This also works between notebooks shown in the `ALL` view.
Drag a page out of the panel to turn it back into an item. Drop it over a player
inventory slot or desk tab to place it there; a tab with a notebook adds it to
the first open position. Dropping elsewhere leaves the page on the cursor for
normal inventory placement. The source notebook or tab loses the page only after
a valid drop.
Put vanilla paper in the
upper-left slot and Ink Vials in the upper-right; a copy appears in the
lower-left result slot when the selected page is valid. Taking it consumes one
paper and, by default, one ink. An available vial refills an empty ink meter
when inserted or when copying uses its last ink, and returns a vanilla glass
bottle to the lower-right slot. Removing a bottle also retries a blocked refill.
Refilling waits if that slot is full or contains another item. The `AZ` control sorts
visible pages by name; `ALL` shows pages held across every desk tab. Search and
category filtering narrow the view without granting new pages, and cross-tab
copy selection is checked by the server.
Selecting a stored page on the desk surface shows its Legacy-proportioned
portrait preview and name above the player inventory.
## Book Binder 1. Make an Ink Vial from two black dyes, a glass bottle, and a water bucket.
Craft an Ink Mixer, Writing Desk, and Book Binder.
2. Put paper and an Ink Vial in the Ink Mixer and take a Link Panel Page. Add
ingredients to the basin first if you want a chance of link modifiers.
3. Put leather or an empty Notebook and the Link Panel in the Book Binder.
Name the Age and take the Descriptive Book. A book with only a Link Panel
creates a seeded random Age; add Symbol Pages to author its features.
4. Open the book to create its Age, then click the destination preview to
travel. Bring a bound Linking Book for the return trip: automatic Return
Links are off by default.
For a new survival Age: craft an Ink Vial, an Ink Mixer, a Writing Desk, and a Book Binder. Find new Symbol Pages in Age libraries, or copy pages you already own with
Put vanilla paper and an Ink Vial in the Ink Mixer to make a Link Panel paper and ink at the Writing Desk. The Notebook stores ordered pages, including
Page. Place leather (or an empty Notebook) and the Link Panel in the Book Binder, intentional gaps. Written pages can control terrain, biome distribution,
enter an Age name, and take the finished Descriptive Book. Written symbol Pages weather, lighting, seasons, sky color, suns and moons, decorations, structures,
are optional; without them, the book creates a random Age. To duplicate a Page and more. Incorrect or excessive writing can make an Age unstable; instability
you already own, store it in a Writing Desk tab, select it, supply paper and ink, may bring decay, lightning, explosions, meteors, burning, erosion, and other
and take the copied Page from the output. A Notebook can hold and transfer a hazards. Some combinations are still unsupported and the Binder reports them
larger ordered collection of Pages between desks and the binder. before consuming ingredients.
With JEI installed, Rivencraft displays the Ink Mixer operation in its own Place a Rivencraft book or page on a vanilla Lectern to convert it to a Book
category and the hand-use, copying, binding, and Linking Book crafting flows in a Writing category. Stand. Crystal formations yield shards for Crystal Blocks. A connected crystal
The Link Panel and individual symbol Pages, including registered vanilla biome frame with a Book Receptacle and a bound book forms a portal; frames can stand
pages, appear as separately searchable JEI ingredients. upright or lie flat. Libraries, Book Stands, and portals use Legacy-inspired
Creative inventory separates Link Pages and each symbol category into their own assets and sounds. Handheld travel drops the used book at the departure point,
tabs, including distinct Biome and Biome Generation tabs. Blank Pages are hidden so plan how you will retrieve it.
from creative inventory and JEI.
JEI is optional; vanilla crafting
recipes and all writing interactions work without it. For a development client
with JEI, run `./gradlew runClient -PwithJei=true`.
Four Crystal Shards craft one Crystal Block; eight Crystal Blocks around an ## Requirements and optional integrations
empty crafting-grid center make one Book Receptacle. Picking up a shard unlocks
the block recipe, and picking up a block unlocks the Receptacle recipe. The
existing Ink Vial recipe uses two black dyes, a glass bottle, and a water
bucket; the empty bucket stays in the crafting grid. These JSON recipes appear
in JEI when it is installed and can be replaced by a data pack at
`data/rivencraft/recipe/<recipe_name>.json`. To test a replacement, use a fresh
world or `/reload`, then check the result in a crafting table and vanilla
Crafter. A vanilla Lectern converts to a Rivencraft Book Stand when a Rivencraft
book or page is placed on it; this in-world interaction has no JEI guide.
With Create installed, Crystal Blocks and Book Receptacles have an optional Ponder scene
showing crystal-frame construction, book activation, and a parrot crossing the portal. Use the Ponder shortcut
while hovering either item; Rivencraft does not require Create to run.
Crystal frames may stand vertically or lie flat: a 3×3 Crystal Block ring with
an empty center forms a horizontal portal when a Book Receptacle is attached to
the top or underside of one of its blocks. Insert a bound Linking or Descriptive
Book to activate it; the book remains visible on the receptacle. A Linking Book aimed at its
own dimension still opens a visual portal, but travel requires Intra Linking.
Sky writing has shared Red, Green, Blue, White, and Black pages plus 25 D'ni Install the same gameplay mods on the client and server:
number pages (0–24). Put colors before a Sky, Sun, or Moon page to color that
target; trailing colors tint the sky. A number immediately before a color sets
its strength to number × 10. Without a number, a color gets a seeded random
strength from 0–24. RGB contributions add in any order, White brightens all
channels, Black subtracts from all channels, and omitted channels remain zero.
The resulting sky color also tints book previews and fallback portal surfaces.
An Age may have no suns or moons at all; Static Sky animates with fine-grained
television-like noise. Sun and Moon pages add
independent bodies; preceding color, size, angle, period, phase, and direction
pages configure the next body. The third and each subsequent sun add increasing
instability. Overlapping moon and sun discs produce an eclipse: the moon darkens,
the sun's color brightens at close alignment, and world and sky lighting dim.
Newly generated page-free Ages also choose a deterministic sky,
color, and celestial arrangement from their Age seed; older saved Ages retain
their previous sky.
Craft a Book Binder from three iron ingots and five planks. Put leather or an - Minecraft **1.21.1**, NeoForge **21.1.264 or newer in the 21.1 line**, and
empty Notebook in the left cover slot. Enter a title, then place a Link Panel Java 21.
Page first in the horizontal page strip. Click a page in the strip with a - **Dynamic Dimensions AR Edition 0.9.1** and its **Bad Packets 0.8.2**
written Page on the cursor to insert it before that position; click it with an dependency. These are required for Age dimensions.
empty cursor to take it out. The arrows or mouse wheel scroll through up to
27 written Pages. Clicking the strip with a filled Notebook imports its Pages
at that position and leaves the emptied Notebook on the cursor. The right slot
outputs a Descriptive Book once the title, cover, and Link Panel are present.
Inputs are consumed only when the result is taken.
The completed book receives its Age identity when assembled. With only a Link Rivencraft works without any of these optional integrations:
Panel, it describes a randomly generated Age. Authored writing is compiled once
into a versioned, server-owned Age plan. The plan freezes the Age seed, resolved
symbol meanings, page order, and runtime profile, so later data-pack changes do
not reinterpret an existing Age. An authored terrain page selects its runtime
profile. Built-in pages cover Standard, Amplified, Cave, Island, Flat, and Void;
authored biome, environment, and supported feature pages also affect new Ages.
The
writing is also stored on the book; the Descriptive Book screen's turned pages
show ordered symbols and unresolved IDs. The Descriptive Book screen follows
Legacy's book spread: the title and Age details are on the left, the destination
preview is on the right, and clicks in the bottom corners turn pages. Ordered
symbol pages appear before the final blank spread with their runtime-rendered
pictograms. Link-panel-only books use Rivencraft glyphs for their generated
Age description.
## Linking Book | Mod | What it adds |
| --- | --- |
| JEI | Searchable Pages and guides for the Ink Mixer, Writing Desk, Book Binder, and Linking Book crafting. |
| Create (bundles Ponder) | Ponder book snapshots and a crystal-portal construction guide. |
| Immersive Portals | Live destination views in book previews and crystal portals. In `AUTO` preview mode it takes priority over Ponder. |
| TerraBlender | Eligible biomes from mods using its Overworld/Nether regions become Age biome candidates and Pages. Biomes O' Plenty is one example; it is not hard-coded or required. |
| Serene Seasons (with GlitchCore) | Independent per-Age seasons, including normal seasons, no seasons, and four eternal-season modes. |
| Ruins | Authorable Ruins-template Pages and Ruins structures in Ages. |
Craft an unwritten Linking Book from one Link Panel Page and one leather in any The optional builds used in the latest development checks are JEI
two crafting-grid positions. An unbound book opens a screen where it can be named and bound to the 19.69.0.457, Create 6.0.10, Immersive Portals 6.0.7, TerraBlender 4.1.0.8,
current location. A bound book opens its destination screen and travels when Serene Seasons 10.1.0.9, and Ruins 1.21.1.2NF. See the
its preview panel is clicked. The destination is stored on the item and [compatibility review](docs/MILESTONE_7_COMPATIBILITY_REVIEW.md) for the
survives inventory and world saves. Travel only succeeds if the target evidence and limits of those combinations.
dimension is loaded and a non-fluid, passable landing position can be found
nearby.
The Linking Book uses the same Legacy page layout and bottom-corner page turns
as the Descriptive Book, but without the Descriptive Book's gold cover edges.
Both screens play Minecraft's book-page-turn sound when a page is turned.
Successful book travel plays Mystcraft Legacy's original linking sound at both Without Create or Immersive Portals, book previews use Rivencraft's built-in
the departure and arrival locations. Legacy-style animation. Ecliptic Seasons is **not supported**: its 1.21.1 API
does not offer the live dimension/season control Rivencraft needs.
Right-click an empty vanilla lectern with a Rivencraft book to convert it into ## Saves, settings, and current limits
a Book Stand and place the book on it. Use a Linking Book on the stand by
right-clicking with an empty hand. Sneak-right-click with an empty hand to take
the book back and restore the vanilla lectern. Breaking a Book Stand drops both
the stored book and a vanilla lectern.
Bound Linking Books show a rotating Ponder snapshot when Create is installed. Ages and bound books use persistent UUIDs. Back up the **entire world folder**
Without Create, they use a built-in animated linking panel tinted by the before changing mod versions, data packs, or optional biome mods: the Age
destination sky. The server independently validates every link. registry and dimension data must be restored together. Rivencraft preserves
known older save formats where possible, but pre-public-release worlds are not
promised universal compatibility. Missing custom symbols retain their IDs in
books; missing registry entries or dimension providers can still prevent an
Age from loading. See [current implementation](docs/CURRENT_IMPLEMENTATION.md)
for supported behavior and deliberate limits.
## Descriptive Book Server settings include `descriptive_books.return_link_mode` (default
`DISABLED`), `libraries.loot_mode` (`LEGACY` or `AGE_ONLY`), writing ink costs,
season enrollment, and instability controls. The client setting
`book_preview.mode` chooses `AUTO`, `IMMERSIVE_PORTALS`, `PONDER`, or `LEGACY`.
An operator can inspect Ages and instability with `/rivencraft age` and find
libraries with `/rivencraft library nearest`. The creative-only Link Modifier
can edit link properties and retire an Age; use it carefully and keep backups.
Open a page-free Descriptive Book, name its Age, and press Create. Rivencraft ## Project and development
assigns the book a permanent Age UUID, selects a deterministic base terrain,
creates a dedicated runtime dimension, and prepares a five-by-five cobblestone
arrival platform at the
highest suitable nearby terrain. Solid blocks and tree leaves are valid
footing. Candidate columns are scanned from the top down so cave floors are not
selected, and fluid-covered columns are excluded. If no suitable surface is
available, the platform is generated at Y=63. Reopen the book and click its preview to travel.
The book cannot reopen while its Age is being generated, whether held or on a
Book Stand. Once creation finishes, reopening shows the written book.
Copies of the written book continue to resolve to the same persistent Age
across server restarts.
New Age dimension folders use a Minecraft-safe lowercase form of the assigned This repository is the development source. See the [current implementation](docs/CURRENT_IMPLEMENTATION.md),
name. Conflicts receive incrementing suffixes such as `_2` and `_3`; existing [milestone summaries](docs/MILESTONES.md), [technical document index](docs/README.md),
Age folders are never renamed. and [issues](https://truenas-scale.tail180fb1.ts.net:8443/dnorberg/rivencraft/issues).
Milestone 7 is in progress; its [regression matrix](docs/MILESTONE_7_REGRESSION.md)
distinguishes automated checks from manual checks and known limitations.
Page-free Ages deterministically select one of six base terrains inspired by ```sh
Mystcraft Legacy: Standard, Amplified, Island, Cave, Flat, or Void. The chosen
profile is saved with the Age and does not change when the server restarts.
Linking creates a bound Return Link to the exact source position and orientation
according to the configured Return Link policy.
Server owners can set `descriptive_books.return_link_mode` in Rivencraft's
server config to `DISABLED` (default), `ON_CREATION`, or `ALWAYS`.
Age creation, persistence, lifecycle commands, configuration, backups, and
administrator recovery are documented in [docs/AGES.md](docs/AGES.md).
Data-pack runtime profiles are documented in
[docs/AGE_PROFILES.md](docs/AGE_PROFILES.md).
## Requirements
- A Java 21 JDK
- Minecraft 1.21.1
- NeoForge 21.1.264 or newer in the 21.1 line
- Dynamic Dimensions AR Edition 0.9.1 and Bad Packets 0.8.2 (client and server)
Ruins is optional. When installed, its configured structures have individual
authorable pages; see [Ruins compatibility](docs/RUINS_COMPATIBILITY.md).
Create is optional. When installed, Rivencraft uses its Ponder renderer for
book previews when Immersive Portals is absent. Immersive Portals is also
optional and takes priority in the default `AUTO` mode, providing a live
rotating destination view. Its Explore button enables WASD and jump/sneak
camera movement plus left-drag camera look; right-click returns to the rotating
view. Without either integration, Rivencraft uses its built-in animated linking
panel. Clients can set `book_preview.mode` in
`rivencraft-client.toml` to `AUTO`, `IMMERSIVE_PORTALS`, `PONDER`, or `LEGACY`.
Unavailable optional renderers safely fall back to `LEGACY`.
The complete backend matrix, supported combinations, cleanup behavior, and
known upstream limits are documented in
[docs/PREVIEW_COMPATIBILITY.md](docs/PREVIEW_COMPATIBILITY.md).
## Build and run
```shell
./gradlew build ./gradlew build
./gradlew runClient ./gradlew runGameTestServer
``` ```
The built mod is written to `build/libs/`. The JAR is written to `build/libs/`. Development runs need the required mods;
The default dedicated-server GameTest run is deliberately small. Use see [GameTest guidance](docs/GAMETESTS.md) for focused archived suites.
`./gradlew runGameTestServer -PwithArchivedGameTests=true` for the complete Versions use `x.y.z.b`: major release, completed milestone, release slice,
regression suite before a release or when investigating a related issue. See then fixes/additional work within that slice.
[docs/GAMETESTS.md](docs/GAMETESTS.md).
## Versioning Rivencraft is licensed under LGPL-3.0-or-later. Legacy-derived material is
credited in [NOTICE](NOTICE) and [asset provenance](docs/ASSET_PROVENANCE.md).
Rivencraft versions use `x.y.z.b`:
- `x` changes for a major public release.
- `y` changes when a development milestone is completed.
- `z` changes for each release slice within the current milestone.
- `b` changes for bug fixes and additional work within that release slice.
The build component resets to zero when a new release slice begins. Completing
a milestone increments `y` and resets both `z` and `b` to zero. For example,
milestone 2 development can progress from `0.1.1.0` to `0.1.1.1`, then
`0.1.2.0`; completing the milestone produces `0.2.0.0`.
## Porting approach
Mystcraft Legacy targets Forge for Minecraft 1.12.2. Rivencraft therefore
ports one subsystem at a time onto current registries, codecs, data packs, and
NeoForge APIs instead of importing the legacy source tree wholesale.
See [docs/PORTING.md](docs/PORTING.md) for the roadmap, live Gitea tracking
links, architectural direction, and provenance rules.
## License
Rivencraft is licensed under LGPL-3.0-or-later. Mystcraft Legacy is also
LGPL-3.0; copied or adapted upstream code must retain its copyright and license
notices. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
+11 -10
View File
@@ -11,7 +11,7 @@ suffixes such as `_2` and `_3`.
The selected terrain profile, biome distribution, lighting, weather, celestial The selected terrain profile, biome distribution, lighting, weather, celestial
period, celestial angle, and phase are deterministic and become part of the period, celestial angle, and phase are deterministic and become part of the
saved definition. A five-by-five cobblestone platform with clear headroom is saved definition. A five-by-five non-dropping Crystal Platform with clear headroom is
prepared at a safe arrival point. The completed book and every copy carrying prepared at a safe arrival point. The completed book and every copy carrying
the same UUID resolve to that definition. the same UUID resolve to that definition.
@@ -42,10 +42,11 @@ on demand when an administrator previously unloaded it. Unloading retains the
definition and world folder, so existing books continue to reference the same definition and world folder, so existing books continue to reference the same
Age and later reload the same terrain. Age and later reload the same terrain.
Rivencraft does not automatically delete Ages. Safe permanent deletion needs a Rivencraft does not automatically delete Ages. The operator-only creative Link
complete reference index for books in inventories, containers, Book Stands, Modifier can deliberately retire an unoccupied Age: it unloads the dimension,
and unloaded chunks. Until that exists, retaining the definition prevents an moves its data to a sibling `<world>-retired-ages/<uuid>` archive, and records
administrator action from silently orphaning books. the UUID as dead so existing books cannot silently regenerate it. Back up the
whole world first.
Destination-preview chunk loaders are temporary. Rivencraft releases them when Destination-preview chunk loaders are temporary. Rivencraft releases them when
the book closes, the player travels, the player disconnects, the destination the book closes, the player travels, the player disconnects, the destination
@@ -101,8 +102,8 @@ Use this sequence when a book cannot load an existing Age:
matching dimension data and authoritative world saved data from the same matching dimension data and authoritative world saved data from the same
backup generation. Do not combine them from different backups. backup generation. Do not combine them from different backups.
There is intentionally no delete command in Milestone 3. Do not manually Do not manually delete an Age definition or rename its dimension folder:
delete an Age definition or rename its dimension folder: books may exist in books may exist in inventories, containers, Book Stands, or unloaded chunks.
inventories, containers, Book Stands, or unloaded chunks, and would be `/rivencraft age unload` remains the reversible maintenance operation. The
orphaned. `/rivencraft age unload` is the supported reversible maintenance Link Modifier's retirement control is not reversible through a book UI;
operation. recover its archived data and registry together from a full-world backup.
+96
View File
@@ -0,0 +1,96 @@
# Current implementation (Milestone 7 development)
This is the maintained technical overview of Rivencraft as of the 0.6.11.0
slice. It describes implemented behavior, not every behavior in Mystcraft
Legacy. [The README](../README.md) is the player introduction;
[milestone summaries](MILESTONES.md) explain how the implementation arrived
here. The linked deep dives are retained as historical audits and should be
read with their version dates in mind.
## Books, linking, and previews
- Linking Books bind a named position and direction. Same-dimension use needs
Intra Linking. Descriptive Books refer to a persistent Age UUID and keep
their authored page order. Copies keep that identity.
- Book screens use Legacy-inspired page spreads and destination panels. `AUTO`
selects optional Immersive Portals first, then Create/Ponder, then the built-in
animation. Travel is validated on the server regardless of renderer.
- Handheld travel drops the active book at its departure point as a visible
book entity. Book Stands and crystal portals keep the book in place. Disarm
drops carried items; Maintain Momentum rotates and carries velocity.
- A vanilla Lectern converts to a Book Stand when given a Rivencraft book or
page. A Book Receptacle in a connected Crystal Block frame activates a
vertical or horizontal portal. Immersive Portals can display a live view;
otherwise the Legacy-style animated surface remains. Portal arrivals use
existing safe footing; a Descriptive portal does not generate a platform.
- Automatic Return Links default to `DISABLED`, with `ON_CREATION` and `ALWAYS`
server options. Linking Books do not generate platforms by default; a
creative Link Modifier can explicitly enable that property.
See [preview modes](PREVIEW_COMPATIBILITY.md), [Legacy M7 audit](LEGACY_M7_AUDIT.md),
and [Age administration](AGES.md).
## Ages, writing, and structures
- Dynamic Dimensions AR Edition creates Age worlds. Each Age has a saved UUID,
safe dimension ID, seed, spawn, traits, versioned generation plan, and
optional season mode. Page-free or Link-Panel-only books get seeded random
choices. Authored supported pages override the appropriate choices.
- Terrain choices are Standard, Amplified, Island, Cave, Flat, and Void. Cave
terrain uses cave/Nether biomes and an appropriate spawn search; normal
terrain starts from exposed surfaces. If no safe arrival site exists, the
Age-creation path can construct a non-dropping Crystal Platform at Y=63.
- The server catalog accepts typed data-pack symbols. The Binder preserves
written order and diagnoses conflicts. Symbol Pages are composed at runtime
from Legacy glyph assets; number pages 0–24 set color strength and, when
immediately before a Length, Angle, or Phase modifier, their numeric value.
Celestial pages can create multiple suns/moons with independent color, size,
angle, period, phase, and direction; authored eclipses affect light.
- The Writing Desk stores tabs and copies known Symbol Pages with paper and
ink. Notebooks hold ordered pages; the Binder consumes a Link Panel and cover
to make a finished Descriptive Book. The Ink Mixer makes Link Panels and
rolls Disarm, Intra Linking, and Maintain Momentum from additives. Blank
Pages are internal bases, not a craftable or JEI-listed output.
- Features include terrain additions, decorations, configurable block/fluid
materials, ores, vanilla structures including newer 1.21 structures,
Legacy-style libraries, crystals, obelisks, and star fissures. Optional Ruins
templates gain authorable pages. Some biome/terrain combinations or feature
placements are deliberately unsupported and are diagnosed during binding.
See [symbol semantics](SYMBOL_SEMANTICS.md), [writing data](WRITING_DATA.md),
[generation profiles](AGE_PROFILES.md), and [library/Ruins rules](RUINS_COMPATIBILITY.md).
## Instability and optional mods
Invalid or excessive writing and valuable generated blocks can add
instability. Block abundance is profiled in loaded chunks, so its contribution
and selected effects can change as the Age is explored; the authored plan is
not rewritten. Effects are bounded to loaded Ages and include status effects,
colored decay, lightning, explosions, meteors, burning, and erosion. Operator
commands expose the score and providers; the book GUI does not. See
[scoring](INSTABILITY_SCORE.md) and [runtime policy](INSTABILITY_RUNTIME.md).
JEI, Create/Ponder, Immersive Portals, TerraBlender, Serene Seasons with
GlitchCore, and Ruins are optional. TerraBlender can supply biomes from any mod
using its eligible regions; Biomes O' Plenty is a test example. Serene Seasons
has per-Age normal/no/eternal modes and live Age enrollment. Ecliptic Seasons
is not integrated because its 1.21.1 API lacks supported live registration and
per-Age calendar control. See the [optional-mod matrix](MILESTONE_7_REGRESSION.md).
## Persistence and boundaries
An Age registry definition and its dimension folder belong to the **same
whole-world backup**. Known older book/writing, plan, workstation, and Age
formats have migration or stable-default handling. Unknown symbol IDs remain
in books; missing registry objects or removed dimension mods can still prevent
world loading. The OP-only Link Modifier can retire an unoccupied Age. That
operation marks its UUID dead and moves its dimension data to a sibling
`<world>-retired-ages/<uuid>` folder; it is not ordinary book maintenance.
Do not use it without a backup.
This is not an exact port of every Legacy generator, page, hazard, or client
renderer. Modern safety budgets and NeoForge's dimension/biome APIs require
adaptations. The [Milestone 7 regression matrix](MILESTONE_7_REGRESSION.md)
separates tested behavior from unverified multiplayer/restart/optional-mod
combinations. Issue [#84](https://truenas-scale.tail180fb1.ts.net:8443/dnorberg/rivencraft/issues/84)
is the final Milestone 7 acceptance and release gate.
+4
View File
@@ -1,5 +1,9 @@
# GameTest suites # GameTest suites
The current Milestone 7 results and manual handoffs are in the
[regression matrix](MILESTONE_7_REGRESSION.md). This file documents the test
mechanics and older scenario-specific handoffs.
The default dedicated-server run is a small smoke suite. Its Rivencraft tests The default dedicated-server run is a small smoke suite. Its Rivencraft tests
cover core linking, deterministic Age definition, writing persistence, legacy cover core linking, deterministic Age definition, writing persistence, legacy
data migration, workstation transactions, and forged/replayed menu actions. data migration, workstation transactions, and forged/replayed menu actions.
+65
View File
@@ -0,0 +1,65 @@
# Milestones at a glance
This is the condensed milestone history. The [current implementation](CURRENT_IMPLEMENTATION.md)
is authoritative for what the latest development build does; older acceptance
and audit files remain available as dated evidence, not competing current
instructions. [Gitea milestones](https://truenas-scale.tail180fb1.ts.net:8443/dnorberg/rivencraft/milestones)
hold the live issue status.
## 1 — Bootstrap (complete)
Established the NeoForge 1.21.1/Java 21 project, mod identity, registries,
assets, build, and first automated checks. The port deliberately shares
Mystcraft's concepts while maintaining its own modern package and data model.
See [porting principles](PORTING.md) and [asset provenance](ASSET_PROVENANCE.md).
## 2 — Books and linking (complete)
Introduced persistent Linking and Descriptive Books, conversion of vanilla
Lecterns into Book Stands, named books and Ages, safe travel, destination
previews, and a configurable Return Link policy. Later milestones refined
renderer selection and portal travel. See [preview compatibility](PREVIEW_COMPATIBILITY.md).
## 3 — Ages (complete)
Added persistent runtime dimensions, deterministic random Age traits,
name-derived unique dimension folders, terrain/biome choices, spawn recovery,
and Age lifecycle commands. See [Age administration](AGES.md),
[runtime profiles](AGE_PROFILES.md), and [random weights](RANDOM_AGE_WEIGHTS.md).
## 4 — Writing system (complete)
Introduced Symbol Pages, Link Panels, Notebooks, the Writing Desk, Book Binder,
and Ink Mixer. Writing order and unknown symbol references persist instead of
being inferred from UI text. See [writing data](WRITING_DATA.md),
[descriptive-book presentation](DESCRIPTIVE_BOOK_PRESENTATION.md), and
[Ink Mixer audit](INK_MIXER_MODIFIER_AUDIT.md).
## 5 — Age grammar (complete for the supported subset)
Compiled supported pages into frozen Age plans: terrain, biome distribution,
environment, features, block/fluid materials, structures, crystals, and
fissures. Added optional TerraBlender and Serene Seasons adapters. This was
not a claim of complete Legacy grammar parity. See [M5 acceptance](MILESTONE_5_ACCEPTANCE.md),
[Legacy grammar audit](LEGACY_AGE_GRAMMAR_AUDIT.md),
[symbol schema](SYMBOL_SEMANTICS.md), [TerraBlender](TERRABLENDER_COMPATIBILITY.md),
and [Serene Seasons](SERENE_SEASONS_COMPATIBILITY.md).
## 6 — Instability (complete)
Added authored and live block-abundance scoring, frozen provider plans,
operator diagnostics, bounded status effects, decay, lightning, explosions,
meteors, burning, and erosion. Safety budgets are deliberate modern
adaptations. See [M6 acceptance](MILESTONE_6_ACCEPTANCE.md),
[Legacy instability audit](LEGACY_INSTABILITY_AUDIT.md), and
[runtime policy](INSTABILITY_RUNTIME.md).
## 7 — Structures and polish (in progress)
Added Legacy-layout Age libraries, page-bearing stands, crystal portals and
receptacles, the handheld dropped-book entity, data-driven recipes,
advancements, asset/audio polish, optional Ruins, compatibility updates, and
expanded sky/glyph pages. Issue #83 covers regression, migration, and document
consolidation; issue #84 is the final milestone acceptance gate. See the
[M7 Legacy audit](LEGACY_M7_AUDIT.md), [M7 regression matrix](MILESTONE_7_REGRESSION.md),
and [M7 compatibility review](MILESTONE_7_COMPATIBILITY_REVIEW.md).
+71
View File
@@ -0,0 +1,71 @@
# Milestone 7 regression and migration matrix (issue #83)
This is a **working** acceptance record for the 0.6.11.0 candidate, not the
Milestone 7 completion sign-off. Issue #84 owns the final gate. A passing
GameTest is server-side evidence; it is not proof of client rendering,
multiplayer timing, or every optional-mod combination.
## Automated evidence
| Area | Focused check | Candidate result |
| --- | --- | --- |
| Dedicated server, core linking, book/Age identity, old writing and workstation formats | `./gradlew --offline runGameTestServer`; includes `CoreGameTests`, `AgePersistenceGameTests`, `CrystalPortalGameTests`, M7 crafting/advancement checks | 91/91 required GameTests passed on NeoForge 21.1.264; clean shutdown and fresh-world removal. |
| Deterministic structures and terrain | `./gradlew --offline runGameTestServer -ParchivedGameTestSuites=generation`; includes library template/spacing/loot/stand checks, cave profiles, vanilla structures, crystal formations, fissures | 129/129 passed after correcting one village test to assert its own contribution rather than a seed-dependent total; fresh-world removal. |
| Sky, glyph numbers, seasons, creative/JEI page feed | `./gradlew --offline runGameTestServer -ParchivedGameTestSuites=environment` | 103/103 passed on the current candidate, including issue #94's number-page check; fresh-world removal. |
| Packaged models and data | `Milestone7ResourceGameTests.coreModelsResolveBundledTextures` in the core suite; parses critical block models, checks their Rivencraft texture references and the library NBT resource | Passed in the 91-test core run. This checks resource presence, not visual orientation or transparency. |
| Recipe behavior | `Milestone7CraftingGameTests` and `LinkingBookRecipeGameTests` through the loaded Recipe Manager | Passed in the core run; confirms crystal and receptacle quantities, ink bucket return, no Blank Page crafting, and Linking Book ingredients. |
| Portal state/save-load | `CrystalPortalGameTests` plus `AgePersistenceGameTests` in the core suite | Passed; covers activation/release, fallback orientation, horizontal/underside placement, uninterrupted surface, cooldown, retired Age and seed/plan identity. Full server restart remains manual. |
The generation archive initially failed
`AgeStructureGameTests.mixedEndAndTaigaVillagesChargeForEndPortion` because it
compared the total instability score (1200) with the village-only expectation
(200). A seed-completed sky legitimately supplied an extra sun (+1000). The
production scoring was unchanged; the check now isolates the
`forced_biome_villages` contribution. The rerun passed 129/129. This is a
repaired assertion, not a hidden feature failure.
Every default GameTest run creates a new world with Minecraft's fixed seed 0
and deletes it after pass or fail. See [GameTest guidance](GAMETESTS.md).
Do not retry a storage-stalled GameTest: stop it, remove that automated
scenario, and give its exact steps to the player. No run in this issue has
stalled so far. The older full-archive storage stall is historical and is not
counted as a current pass.
## Old-save boundary (#60)
Issue #60 established a policy of preserving old saves where practical. Tests
cover bare-list `OrderedWriting`, page-free books, unknown symbol IDs, older
Age definitions with stable defaults, plan-v3/plan-v4 interpretation, and
workstation inventory migration. A bound book's UUID and its Age's registered
dimension remain stable through ordinary load. This does **not** imply every
pre-public-release world, removed biome mod, missing dimension provider, or
changed datapack can be opened. Back up the full world; the Age registry and
dimension folders are a unit. The creative Link Modifier can intentionally
retire an Age, archiving its data and marking the UUID dead. That is an explicit
administrative boundary, not a silent migration.
## Manual matrix for the player
Use a backup or disposable save. Record the exact mod list and jar version.
These checks are **pending for 0.6.11.0** unless a later note records an actual
pass. Historical passes on earlier slices should not be silently promoted to
this candidate.
| Scenario | What to verify |
| --- | --- |
| Full restart | Create a random and an authored Age, a library with a looted chest/page stand, an active portal, and a bound book. Stop and restart the server; UUID, terrain, loot removal, stand contents, portal activation, and return travel must persist. |
| Two players | Cross the same portal at nearly the same time, return independently, and use separate book previews. Cooldowns, destination positions, dropped-book ownership/retrieval, and preview chunk loaders must not interfere. |
| Cross-dimension travel | Compare the same Descriptive Book by hand, stand, and portal. Check footing/platform rules, arrival coordinates and facing, Disarm, Maintain Momentum, Intra Linking, and Return Link mode. |
| Client visuals/audio | Compare book spreads, glyphs, D'ni numbers, page/desk/binder/mixer models, 16×16 crystal buds and translucent elements, portal frame/surface order, skies/eclipses, page turns, and Legacy link sounds. A server test cannot observe pixels or audio. |
| Optional renderers | With neither Create nor Immersive Portals, confirm Legacy fallback. With Create alone, confirm Ponder snapshots and portal guide. With Immersive Portals, confirm live view, Explore exit, sky/sound isolation, portal travel, and fallback while chunks load. With both, `AUTO` should choose Immersive Portals. |
| Optional world/recipe mods | Test JEI guides/search, TerraBlender with a biome-producing addon (for example Biomes O' Plenty), Serene's six season modes plus Overworld independence/restart, and Ruins template selection/spawn weighting. Repeat startup without optional mods. |
| Migration | Copy a backed-up older development world. Verify books and Notebooks retain their Age/page IDs, a desk and stand keep contents, old Ages load or provide a clear error, and removing a custom symbol retains its unresolved ID. Do not test by modifying the only copy. |
Historical evidence: the player approved NeoForge 21.1.264 on singleplayer
and a dedicated server with Immersive Portals; JEI 19.69.0.457 guides, Serene
Seasons 10.1.0.9's full per-Age matrix, Ruins generation, and issue #94's
numbered celestials each received an in-game pass on their respective earlier
release slices. See [compatibility review](MILESTONE_7_COMPATIBILITY_REVIEW.md),
[JEI review](MILESTONE_7_JEI_REVIEW.md), [Serene review](MILESTONE_7_SERENE_REVIEW.md),
and [Ruins notes](RUINS_COMPATIBILITY.md). The current candidate's broad
multiplayer/restart/optional-mod matrix remains unverified until tested.
+7 -2
View File
@@ -1,5 +1,9 @@
# Porting roadmap # Porting roadmap
For a concise current status, start with [current implementation](CURRENT_IMPLEMENTATION.md)
and [milestone summaries](MILESTONES.md). This file retains the original
roadmap and architectural rationale.
Rivencraft ports Mystcraft Legacy from Minecraft 1.12.2 to NeoForge 1.21.1. Rivencraft ports Mystcraft Legacy from Minecraft 1.12.2 to NeoForge 1.21.1.
The world-generation, dimension, registry, networking, and rendering APIs have The world-generation, dimension, registry, networking, and rendering APIs have
changed substantially, so the work is divided into independently testable changed substantially, so the work is divided into independently testable
@@ -62,8 +66,9 @@ acceptance issue and all required implementation issues are complete.
**Complete.** See the [Legacy instability audit](LEGACY_INSTABILITY_AUDIT.md) **Complete.** See the [Legacy instability audit](LEGACY_INSTABILITY_AUDIT.md)
and [Milestone 6 acceptance](MILESTONE_6_ACCEPTANCE.md). and [Milestone 6 acceptance](MILESTONE_6_ACCEPTANCE.md).
7. **Structures and polish** — libraries, crystals, portals, recipes, models, 7. **Structures and polish** — libraries, crystals, portals, recipes, models,
sounds, advancements, compatibility, and migration tests. Start with the sounds, advancements, compatibility, and migration tests. **In progress.**
[Milestone 7 Legacy audit](LEGACY_M7_AUDIT.md). See the [Milestone 7 regression matrix](MILESTONE_7_REGRESSION.md) and
[Legacy audit](LEGACY_M7_AUDIT.md).
## Architectural direction ## Architectural direction
+5 -2
View File
@@ -66,8 +66,11 @@ unstable in a particular graphics or mod configuration.
For preview-related releases: For preview-related releases:
1. Run `./gradlew runGameTestServer -PwithArchivedGameTests=true` to verify the complete selection matrix, 1. Run `./gradlew runGameTestServer` for the core selection matrix, Age
core Age creation, persistence, and travel without optional renderers. creation, persistence, and travel without optional renderers. Add the
relevant archives from [GameTest guidance](GAMETESTS.md); if a scenario
stalls, stop it and hand that exact check to a real client rather than
treating the interrupted run as a pass.
2. Open held Linking and Descriptive Books once with each available backend. 2. Open held Linking and Descriptive Books once with each available backend.
3. Open both book types from a Book Stand and confirm Explore is disabled. 3. Open both book types from a Book Stand and confirm Explore is disabled.
4. With Immersive Portals, enter and leave Explore, travel between dimensions, 4. With Immersive Portals, enter and leave Explore, travel between dimensions,
+21
View File
@@ -0,0 +1,21 @@
# Documentation map
Start with the player-facing [project README](../README.md). The two maintained
technical entry points are [current implementation](CURRENT_IMPLEMENTATION.md)
and [milestone summaries](MILESTONES.md). Use [GameTest guidance](GAMETESTS.md)
to run checks. The files below retain detailed design, provenance, and
version-specific test evidence; an older milestone record may describe a
former behavior or loader version.
| Milestone | Detailed records |
| --- | --- |
| M1–M3 | [Porting roadmap](PORTING.md), [Age administration](AGES.md), [Age profiles](AGE_PROFILES.md), [preview compatibility](PREVIEW_COMPATIBILITY.md), [random Age weights](RANDOM_AGE_WEIGHTS.md) |
| M4 | [Writing data](WRITING_DATA.md), [book presentation](DESCRIPTIVE_BOOK_PRESENTATION.md), [Ink Mixer audit](INK_MIXER_MODIFIER_AUDIT.md) |
| M5 | [Acceptance](MILESTONE_5_ACCEPTANCE.md), [Legacy grammar audit](LEGACY_AGE_GRAMMAR_AUDIT.md), [writing grammar](WRITING_GRAMMAR.md), [symbol semantics](SYMBOL_SEMANTICS.md), [TerraBlender](TERRABLENDER_COMPATIBILITY.md), [Serene Seasons](SERENE_SEASONS_COMPATIBILITY.md) |
| M6 | [Acceptance](MILESTONE_6_ACCEPTANCE.md), [regression](MILESTONE_6_REGRESSION.md), [Legacy audit](LEGACY_INSTABILITY_AUDIT.md), [score](INSTABILITY_SCORE.md), [live blocks](LIVE_BLOCK_INSTABILITY.md), [runtime](INSTABILITY_RUNTIME.md), [diagnostics](INSTABILITY_DIAGNOSTICS.md), [status effects](INSTABILITY_STATUS_EFFECTS.md), [decay](INSTABILITY_DECAY.md), [environmental hazards](INSTABILITY_ENVIRONMENTAL.md), [cloud platform](AGE_CLOUD_PLATFORM.md) |
| M7 | [Regression and manual matrix](MILESTONE_7_REGRESSION.md), [Legacy audit](LEGACY_M7_AUDIT.md), [visual/audio](MILESTONE_7_VISUAL_AUDIT.md), [advancements](MILESTONE_7_ADVANCEMENTS.md), [JEI](MILESTONE_7_JEI_REVIEW.md), [Serene review](MILESTONE_7_SERENE_REVIEW.md), [compatibility](MILESTONE_7_COMPATIBILITY_REVIEW.md), [Ruins](RUINS_COMPATIBILITY.md) |
[Asset provenance](ASSET_PROVENANCE.md) applies across milestones. Detailed
audits are intentionally retained for source attribution and migration
history; these three entry points replace the former practice of treating
every dated task note as a current installation guide.
+1 -1
View File
@@ -36,7 +36,7 @@ mod_name=Rivencraft
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=LGPL-3.0-or-later mod_license=LGPL-3.0-or-later
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md. # The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
mod_version=0.6.10.0 mod_version=0.6.11.0
immersive_portals_version=6.0.7 immersive_portals_version=6.0.7
terrablender_version=4.1.0.8 terrablender_version=4.1.0.8
serene_seasons_version_id=pHEgQQUE serene_seasons_version_id=pHEgQQUE
@@ -178,8 +178,11 @@ public final class AgeStructureGameTests {
var age = AgeRegistrySavedData.resolveOrCreate(helper.getLevel(), var age = AgeRegistrySavedData.resolveOrCreate(helper.getLevel(),
new AgeReference(java.util.UUID.randomUUID(), "Mixed " + firstBiome), writing); new AgeReference(java.util.UUID.randomUUID(), "Mixed " + firstBiome), writing);
int expected = firstBiome.equals("the_end") ? 200 : 0; int expected = firstBiome.equals("the_end") ? 200 : 0;
helper.assertValueEqual(age.instability().score(), expected, helper.assertValueEqual(age.instability().breakdown().stream()
"Each Village page must charge 100 if any selected biome needs the override"); .filter(part -> part.reason().equals("forced_biome_villages"))
.mapToInt(AgeInstability.Contribution::points).sum(), expected,
"Each Village page must charge 100 if any selected biome needs the override; "
+ "seed-completed celestial instability is independent");
helper.assertValueEqual(age.instability().breakdown().stream() helper.assertValueEqual(age.instability().breakdown().stream()
.filter(part -> part.reason().equals("forced_biome_villages")).count(), .filter(part -> part.reason().equals("forced_biome_villages")).count(),
firstBiome.equals("the_end") ? 2L : 0L, firstBiome.equals("the_end") ? 2L : 0L,
@@ -0,0 +1,52 @@
package net.dnorberg.rivencraft.gametest;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import net.dnorberg.rivencraft.Rivencraft;
import net.minecraft.gametest.framework.GameTest;
import net.minecraft.gametest.framework.GameTestHelper;
import net.neoforged.neoforge.gametest.GameTestHolder;
import net.neoforged.neoforge.gametest.PrefixGameTestTemplate;
/** Small server-side guard against shipping missing model textures or the library template. */
@GameTestHolder(Rivencraft.MOD_ID)
@PrefixGameTestTemplate(false)
public final class Milestone7ResourceGameTests {
private Milestone7ResourceGameTests() {}
@GameTest(template = "empty")
public static void coreModelsResolveBundledTextures(GameTestHelper helper) {
for (String model : List.of("book_binder", "ink_mixer", "writing_desk",
"book_receptacle", "crystal_block", "crystal_portal")) {
String path = "assets/rivencraft/models/block/" + model + ".json";
try (InputStream stream = resource(path)) {
helper.assertTrue(stream != null, "Missing packaged block model " + path);
JsonObject json = JsonParser.parseReader(new InputStreamReader(stream, StandardCharsets.UTF_8))
.getAsJsonObject();
if (!json.has("textures")) continue;
for (var entry : json.getAsJsonObject("textures").entrySet()) {
String texture = entry.getValue().getAsString();
if (!texture.startsWith("rivencraft:")) continue;
String texturePath = "assets/rivencraft/textures/"
+ texture.substring("rivencraft:".length()) + ".png";
helper.assertTrue(Milestone7ResourceGameTests.class.getClassLoader().getResource(texturePath) != null,
"Model " + model + " references missing texture " + texturePath);
}
} catch (java.io.IOException exception) {
throw new IllegalStateException("Cannot inspect " + path, exception);
}
}
helper.assertTrue(Milestone7ResourceGameTests.class.getClassLoader()
.getResource("data/rivencraft/structure/mystcraft_library.nbt") != null,
"The Legacy library template must be included in the mod JAR");
helper.succeed();
}
private static InputStream resource(String path) {
return Milestone7ResourceGameTests.class.getClassLoader().getResourceAsStream(path);
}
}