Public Access
441 lines
23 KiB
Markdown
441 lines
23 KiB
Markdown
# Porting plan
|
||
|
||
Mystcraft Legacy contains more than 700 Java source files and targets Minecraft
|
||
1.12.2. The Minecraft world-generation, dimension, registry, networking, and
|
||
rendering APIs have all changed substantially since that release. The port is
|
||
split into independently testable milestones.
|
||
|
||
## Milestones
|
||
|
||
1. **Bootstrap** — NeoForge 1.21.1 build, mod metadata, item registration, and
|
||
CI. **Complete.**
|
||
2. **Books and linking** — descriptive/linking book data components, lectern-like
|
||
interaction, safe teleportation, and return links. **Complete.**
|
||
3. **Ages** — dimension definitions backed by data packs, deterministic seeds,
|
||
lifecycle management, and persistence. Make the legacy-style animated
|
||
linking panel the built-in destination preview. Provide optional
|
||
Create/Ponder and Immersive Portals integrations as alternative rotating-
|
||
snapshot renderers. The configurable preview modes are `AUTO`,
|
||
`IMMERSIVE_PORTALS`, `PONDER`, and `LEGACY`; `AUTO` prefers Immersive
|
||
Portals when it is installed, then Create/Ponder, and finally the built-in
|
||
legacy animation.
|
||
4. **Writing system** — pages, symbols, notebooks, desks, and book assembly.
|
||
5. **Age grammar** — translate symbol combinations into modern biome, noise,
|
||
dimension-type, and worldgen configuration. Optional integrations with
|
||
TerraBlender provide composable biome-region generation, while Serene
|
||
Seasons and Ecliptic Seasons allow Age generation to participate in their
|
||
respective seasonal systems. True Always Snow weather will be introduced
|
||
with these season integrations; until then, its persisted trait uses
|
||
biome-dependent precipitation. None of these integrations are required for
|
||
Rivencraft's core world generation.
|
||
6. **Instability** — deterministic validation and effects with server-safe
|
||
behavior.
|
||
7. **Structures and polish** — libraries, crystals, portals, recipes, models,
|
||
sounds, advancements, compatibility, and migration tests.
|
||
|
||
## Provenance rules
|
||
|
||
- New code uses the `net.dnorberg.rivencraft` package.
|
||
- Adapted Mystcraft code must retain its upstream copyright notice and be
|
||
tracked in this document or a nearby source comment.
|
||
- Do not copy generated, binary, or third-party dependency content from the
|
||
legacy repository.
|
||
- Preserve LGPL-3.0-or-later compatibility for the complete distributed mod.
|
||
|
||
## First vertical slice
|
||
|
||
The first functional target is: create a Descriptive Book, bind it to one
|
||
server-managed Age definition, travel to that Age, and use a Linking Book to
|
||
return. This exercises persistence, networking, dimensions, and safety before
|
||
the symbol grammar is introduced.
|
||
|
||
### Milestone 2 progress
|
||
|
||
- [x] Persistent, network-synchronized link-target data component.
|
||
- [x] Linking Book binding with dimension, block position, yaw, and pitch.
|
||
- [x] Server-authoritative cross-dimension travel with world-border, collision,
|
||
and fluid checks.
|
||
- [x] Nearby landing search and clear failure messages.
|
||
- [x] Descriptive Book identity and Age reference components.
|
||
- [x] Temporary vanilla-dimension Descriptive Book travel with return-link creation.
|
||
- [x] Lectern-to-Book-Stand conversion, displayed book, activation, removal,
|
||
persistence, and drops.
|
||
- [x] Book-screen foundation with server-authoritative naming, binding, and
|
||
explicit link activation.
|
||
- [x] Ponder dependency and isolated destination-preview level boundary.
|
||
- [x] Server-provided destination snapshots rendered as rotating Ponder scenes.
|
||
- [x] Book Stand floating names synchronized from the stored book stack.
|
||
- [x] Open the stored book screen from a Book Stand with server-validated linking.
|
||
- [x] Automated in-game tests for binding, persistence, and travel.
|
||
|
||
The temporary shapeless Linking Book recipe makes the linking subsystem easy
|
||
to test. It can move into the writing/bookbinder progression when that system
|
||
is implemented.
|
||
|
||
Age references use UUIDs rather than dimension keys. Milestone 3 will own the
|
||
mapping from that stable identity to server data and a runtime dimension. This
|
||
keeps saved books valid if an Age is migrated or regenerated.
|
||
|
||
Vanilla lecterns accept extensible item tags when inserting books, but their
|
||
block entity still validates only vanilla writable and written books. To avoid
|
||
an invalid lectern state, inserting a Rivencraft book converts the lectern into
|
||
a visually compatible Rivencraft Book Stand. Removing the book converts it
|
||
back.
|
||
|
||
Mystcraft Legacy did not impose an item cooldown when linking. Rivencraft's
|
||
initial cooldown used Minecraft's item-type cooldown system, which delayed all
|
||
Linking Book stacks at once. Version 0.1.3 removes that cooldown to match the
|
||
legacy behavior.
|
||
|
||
Version 0.1.4 moves Linking Book binding and travel behind a book screen. The
|
||
client requests an action, while the server revalidates the held book and owns
|
||
all changes to its destination and custom name. Descriptive Book Age references
|
||
now carry a display name alongside their stable UUID, with backward-compatible
|
||
decoding for existing UUID-only data.
|
||
|
||
Version 0.1.5 ensures the book interaction listener opens screens only for the
|
||
logical-client event. This avoids calling the render system from the integrated
|
||
server thread when a book is used in singleplayer.
|
||
|
||
Version 0.1.6 gives the Linking Book screen an open-book layout inspired by the
|
||
legacy interface. The destination preview occupies the left page, the book name
|
||
and destination details occupy the right page, and the preview itself is the
|
||
link action; the separate Link and Done buttons have been removed.
|
||
|
||
Version 0.1.7 suppresses Minecraft's default full-screen menu blur for the
|
||
Linking Book screen. The open-book texture supplies the GUI background while
|
||
the world remains sharp behind it.
|
||
|
||
Version 0.1.8 renders all Linking Book destination details in the same dark ink
|
||
color as the book name for consistent contrast against the parchment.
|
||
|
||
Version 0.1.9 synchronizes the Book Stand's stored stack to clients and renders
|
||
its display name as a camera-facing label above the book.
|
||
|
||
Version 0.1.10 corrects the nameplate transform and matches Minecraft's normal
|
||
plus see-through text passes so angled stand geometry cannot hide the label.
|
||
|
||
Version 0.1.11 opens the stored book interface when a Book Stand is used with
|
||
an empty hand. Linking Books travel through the preview panel, and the server
|
||
revalidates the stand position, interaction distance, stored item, and target.
|
||
|
||
Version 0.1.12 replaces the Linking Book screen's convenience text draws with
|
||
explicit no-shadow rendering for clearer dark ink on the parchment texture.
|
||
|
||
Version 0.1.13 requests a bounded, server-validated 9-by-7-by-9 block snapshot
|
||
from the held book or nearby Book Stand and renders it as a clipped, rotating
|
||
Ponder world section on the Linking Book's left page.
|
||
|
||
Version 0.1.14 expands the destination snapshot to 9-by-7-by-17 blocks along
|
||
the Z axis, rescales the rotating scene to expose that depth, and colors the
|
||
panel background with the destination biome's sky color.
|
||
|
||
Version 0.1.15 adds three dedicated-server GameTests covering Linking Book
|
||
component serialization, successful safe travel with restored orientation, and
|
||
rejection of fully blocked destinations. The test suite uses a minimal bundled
|
||
structure template and runs with `./gradlew runGameTestServer`.
|
||
|
||
Version 0.1.16 makes destination previews sample a centered 17-by-7-by-17
|
||
volume. The Ponder scene uses a scale that keeps its full horizontal diagonal
|
||
inside the panel, so the complete snapshot remains available during its orbit.
|
||
|
||
Version 0.1.17 changes destination previews to a 9-by-128-by-9 volume: a
|
||
square horizontal footprint with a vertical slice spanning 64 blocks below and
|
||
63 blocks above the recorded linking location.
|
||
|
||
Version 0.1.18 changes the preview cache to 9-by-64-by-9, spanning 32 blocks
|
||
below and 31 above the link point. Its camera is centered on a 9-by-7-by-9
|
||
window around the link point so the book retains a readable close-up.
|
||
|
||
Version 0.1.19 renders the complete 9-by-64-by-9 snapshot in that Ponder
|
||
scene while retaining the target-centered camera framing.
|
||
|
||
Version 0.1.20 uses a cubic 18-by-18-by-18 snapshot. The renderer remaps the
|
||
link point within that cube so its existing target-centered camera framing is
|
||
unchanged.
|
||
|
||
Version 0.1.21 treats air and leaf blocks as passable linking destinations;
|
||
links no longer require a solid floor beneath the player.
|
||
|
||
Version 0.2.0 completes Milestone 2. Until Milestone 3 provides generated Age
|
||
dimensions, Descriptive Book UUIDs deterministically resolve to vanilla
|
||
dimensions and create a bound Return Link to the source on successful travel.
|
||
|
||
Version 0.2.1 gives Descriptive Books the same open-parchment layout and
|
||
left-page link interaction as Linking Books.
|
||
|
||
Version 0.2.2 adds the same server-provided Ponder destination preview to
|
||
Descriptive Books. If no snapshot is available, the left page shows an
|
||
animated linking-panel fallback.
|
||
|
||
Version 0.2.3 requires Descriptive Book destinations to have a sturdy floor,
|
||
while Linking Books continue to permit passable floorless destinations.
|
||
|
||
Version 0.2.4 expands Descriptive Book arrival validation with an outward,
|
||
terrain-aware search for an alternate grounded location near an unsafe target.
|
||
|
||
Version 0.2.5 uses dimension-appropriate preview skies for vanilla Nether and
|
||
End destinations instead of their inherited Overworld biome sky tint.
|
||
|
||
Version 0.2.6 expands destination snapshots to a 32-by-32-by-32 cube while
|
||
keeping the existing target-centered Ponder camera position.
|
||
|
||
Version 0.2.7 persists each Age's first successful visit and creates its
|
||
Return Link only for that initial arrival.
|
||
|
||
Version 0.2.8 makes Return Link creation a server setting: `ON_CREATION`
|
||
(default), `ALWAYS`, or `DISABLED`.
|
||
|
||
Version 0.2.9.0 begins Milestone 3 with a server-owned, world-persistent Age
|
||
registry. Each Age UUID resolves exactly once to an immutable random seed,
|
||
generation profile, generation-version marker, canonical name, and creation
|
||
time. The temporary vanilla-dimension adapter remains in place until runtime
|
||
Age dimensions are introduced by a later release slice.
|
||
|
||
Version 0.2.10.0 makes page-free Descriptive Books playable. Naming an
|
||
unwritten book creates a dedicated, persistent vanilla-like Age through the
|
||
Dynamic Dimensions API. Each Age reloads with its server, retains its terrain,
|
||
and receives a five-by-five cobblestone platform with cleared arrival headroom.
|
||
|
||
Version 0.2.10.1 improves Age arrival placement. Non-Nether Ages select the
|
||
highest sturdy surface near the origin and fall back to a platform at Y=63 when
|
||
no suitable natural footing exists.
|
||
|
||
Version 0.2.10.2 allows leaf blocks to count as proper natural footing when
|
||
selecting the highest arrival surface.
|
||
|
||
Version 0.2.10.3 scans each candidate column downward from the dimension's top
|
||
before choosing footing, preventing cave floors from being selected as the Age
|
||
arrival surface. Columns covered by fluid remain ineligible.
|
||
|
||
Version 0.2.10.4 restores Mystcraft Legacy's standard linking sound for both
|
||
Linking and Descriptive Books. Successful travel plays the sound at its source
|
||
and destination with the legacy volume and pitch variation.
|
||
|
||
Version 0.2.10.5 derives each new Age's saved dimension folder from its
|
||
player-assigned name. Names are converted to safe lowercase resource paths,
|
||
and folder conflicts receive `_2`, `_3`, and later numeric suffixes. Existing
|
||
UUID-based dimension folders remain unchanged for save compatibility.
|
||
|
||
Version 0.2.10.6 prevents a Descriptive Book from reopening while its Age is
|
||
being generated. Screen opening now waits for the server's current copy of the
|
||
held or displayed book, so a delayed interaction opens only the completed Age.
|
||
|
||
Version 0.2.11.0 adds a dependency-free, legacy-style portal bloom as the
|
||
fallback destination preview for Linking and Descriptive Books. Clients with
|
||
Create installed retain the rotating Ponder snapshot; clients without Create
|
||
use the destination-tinted animation with the original effect's paired noisy
|
||
spirals.
|
||
|
||
Version 0.2.11.1 makes Create genuinely optional. Ponder remains a compile-time
|
||
API for the Create integration, while generated mod metadata no longer requires
|
||
Ponder and marks Create as an optional client dependency.
|
||
|
||
Version 0.2.12.0 introduces the first legacy-inspired Age generator profiles.
|
||
New page-free Ages deterministically select and persist Standard, Amplified,
|
||
Island, Cave, Flat, or Void base terrain. Existing `random_vanilla` Ages remain
|
||
mapped to their original Overworld generator for save compatibility. Terrain
|
||
alterations such as Skylands, Tendrils, Spheres, and Floating Islands remain
|
||
future Age-grammar work layered above these base profiles.
|
||
|
||
Version 0.2.12.1 displays the persisted terrain generator on the description
|
||
side of written Descriptive Books. Newly written books receive the synchronized
|
||
profile immediately, while older books are backfilled from the server-owned Age
|
||
registry when opened.
|
||
|
||
Version 0.2.13.0 constructs Standard, Amplified, Cave, and Island terrain from
|
||
Minecraft's worldgen registries instead of borrowing generator instances from
|
||
the vanilla levels. Noise settings and biome-source parameter lists therefore
|
||
honor the server's loaded data packs. Automated coverage also verifies that a
|
||
live Age's seed equals its immutable saved definition; Dynamic Dimensions
|
||
derives both from the Overworld seed and the Age dimension identifier.
|
||
|
||
Version 0.2.16.13 gives Cave and Island/Skylands Ages Overworld biomes, sky,
|
||
weather, lighting, and day/night behavior while retaining distinct terrain.
|
||
Caves remain enclosed. Skylands use Minecraft's uniform floating-island noise
|
||
and Overworld-like surfaces without the End's central dragon island.
|
||
|
||
Version 0.2.16.14 replaces the Explore text control with a compact eye symbol.
|
||
Books opened from a Book Stand display the control disabled, preventing
|
||
exploration while the book is mounted.
|
||
|
||
Version 0.2.16.15 restores Immersive Portals chunk loading for snapshots opened
|
||
from Book Stands. Snapshot chunk loading is independent from whether the Explore
|
||
control is enabled, so mounted books retain live terrain without allowing the
|
||
player to enter Explore mode.
|
||
|
||
Version 0.2.17.0 begins persistent random Age traits. New page-free Ages select
|
||
and save a legacy-inspired biome distribution, lighting mode, weather mode, and
|
||
celestial period, angle, and phase. The celestial ranges follow Legacy's random
|
||
symbol fallbacks: period 0.2–2.0, angle 0–360 degrees, and phase 0–1. Existing
|
||
Ages load with normal Legacy defaults instead of being rerolled. This immutable
|
||
trait layer is the foundation for applying each choice to modern worldgen.
|
||
|
||
Version 0.2.18.0 applies each Age's persisted lighting trait to its runtime
|
||
dimension. Normal Lighting retains Overworld skylight and ambient brightness;
|
||
Bright Lighting uses Legacy's 0.25 ambient-light floor; Dark Lighting disables
|
||
dimension skylight while retaining local block light. The latter is the closest
|
||
server-safe modern equivalent to Legacy's removed per-dimension light-table
|
||
scaling hook.
|
||
|
||
Version 0.2.18.1 prevents Cave Ages from choosing a spawn on their upper roof.
|
||
Their grounded arrival search now begins with the floor below player Y=64 and
|
||
works downward. If it finds no suitable footing, the existing floor-Y=63
|
||
platform fallback places the player at Y=64.
|
||
|
||
Version 0.2.19.0 applies persisted weather traits to loaded Ages. Normal uses
|
||
Minecraft's normal weather cycle. Fast and Slow use Legacy's original duration
|
||
and cooldown ranges at half and double normal speed for Minecraft's combined
|
||
rain/thunder weather timer. Off keeps an Age clear;
|
||
Always, Cloudy, Rain, and Snow maintain non-thundering precipitation; Storm
|
||
maintains rain and thunder. Minecraft still chooses rain versus snow from biome
|
||
temperature, so dedicated Snow/Rain biome overrides remain future work.
|
||
|
||
Version 0.2.20.0 applies persisted celestial timing to each Age. The saved
|
||
period controls NeoForge's per-dimension clock rate, with a period of 1 matching
|
||
a vanilla 20-minute day, 0.2 running five times faster, and 2 running at half
|
||
speed. The saved phase sets the clock only during first-spawn initialization;
|
||
later loads continue from saved world time. Celestial angle remains persisted
|
||
for a future custom sky renderer because vanilla dimension data cannot rotate
|
||
the sun's render plane.
|
||
|
||
Version 0.2.20.1 restores Legacy's Zero Length celestial modifier as a rarer
|
||
random outcome using its effective one-in-seven grammar weight. Zero Length
|
||
freezes an Age at its generated phase without changing the global daylight
|
||
cycle, while nonzero Ages retain their independently scaled clocks.
|
||
|
||
Version 0.2.20.2 gives Zero Length Ages a stationary per-dimension clock rate
|
||
instead of advancing and correcting their time once per tick. This keeps the
|
||
integer day time fixed while preventing the client skybox from visually
|
||
bouncing between adjacent celestial positions.
|
||
|
||
Version 0.2.21.0 begins applying persisted biome-distribution traits. Native
|
||
Distribution retains Minecraft's data-pack-aware Overworld climate source.
|
||
Single Biome Distribution deterministically selects one registered biome from
|
||
the Age seed and uses it throughout compatible noise-based terrain. Flat and
|
||
Void profiles retain their profile-specific biome sources. Legacy's scaled,
|
||
tiled, and grid layouts require dedicated modern biome sources and remain the
|
||
next distribution work.
|
||
|
||
Version 0.2.21.1 changes Cave Ages from Nether noise settings to Minecraft's
|
||
cave noise settings. Caves remain enclosed, but use stone, water, and
|
||
Overworld-like surfaces together with the persisted Native or Single biome
|
||
distribution. This prevents Nether terrain generation from leaking into newly
|
||
generated Cave Age chunks.
|
||
|
||
Version 0.2.22.0 applies Tiled Biome Distribution using two deterministic
|
||
Age-seeded biomes in the legacy diagonal-checkerboard layout. Each square is
|
||
16 chunks (256 blocks) wide, matching Mystcraft Legacy's coordinate shift, and
|
||
uses Minecraft's serializable checkerboard biome source so the layout remains
|
||
stable across server reloads.
|
||
|
||
Version 0.2.22.1 includes the server-owned Age traits in the validated
|
||
Descriptive Book screen response and displays the terrain, biome distribution,
|
||
lighting, weather, day length, celestial angle, and celestial phase on the
|
||
book's right-hand description page. This works for held books and Book Stands
|
||
without copying mutable Age-generation data onto the item.
|
||
|
||
Version 0.2.23.0 applies Grid Biome Distribution using two deterministic
|
||
Age-seeded biomes in Legacy's diagonal checkerboard layout. Each cell is one
|
||
16-by-16-block chunk, and the built-in serializable biome source reconstructs
|
||
the same layout whenever the Age reloads.
|
||
|
||
Version 0.2.24.0 applies Tiny Biome Distribution using three deterministic
|
||
Age-seeded biomes and softly bounded seeded regions. Tiny begins at Legacy's
|
||
smallest 16-block nominal scale; the serializable biome source retains its
|
||
seed, selected biomes, and scale across Age reloads.
|
||
|
||
Version 0.2.25.0 completes the scaled biome distributions. Small, Medium,
|
||
Large, and Huge reuse Tiny's seeded, softly bounded regions at nominal widths
|
||
of 32, 64, 128, and 256 blocks. Every size selects three deterministic biomes
|
||
and serializes the selection, Age seed, and scale with the runtime dimension.
|
||
|
||
Version 0.2.14.0 restores the legacy Linking and Descriptive Book artwork for
|
||
inventory items and gives each book its matching open-book texture when placed
|
||
on a Book Stand. Return Linking Books created inside another Age also retain and
|
||
display that Age's saved name instead of exposing its dimension identifier.
|
||
|
||
Version 0.2.14.1 gives every newly bound Linking Book a friendly destination
|
||
label. Standard books and Return Links use saved Age names inside Rivencraft
|
||
Ages and the familiar Overworld, The Nether, and The End names in vanilla
|
||
dimensions. Existing vanilla links receive the same presentation at display
|
||
time without requiring item migration.
|
||
|
||
Version 0.2.15.0 adds the client-side book-preview mode configuration and the
|
||
selection policy for `AUTO`, `IMMERSIVE_PORTALS`, `PONDER`, and `LEGACY`.
|
||
`AUTO` uses Ponder when Create is present and otherwise uses the built-in
|
||
legacy animation. Explicit optional modes fall back to `LEGACY` when their
|
||
renderer is unavailable.
|
||
|
||
Version 0.2.16.0 implements the optional Immersive Portals GUI renderer. Its
|
||
default view orbits the live destination like the Ponder snapshot. The Explore
|
||
control switches to a movable remote camera using movement keys and mouse drag;
|
||
right-click resets the camera and restores the passive book GUI. A validated
|
||
per-player chunk loader exists only while the screen is open and is released
|
||
on close. `AUTO` now prefers Immersive Portals, then Ponder, then `LEGACY`.
|
||
|
||
Version 0.2.16.1 corrects Immersive Portals detection to use its NeoForge mod
|
||
ID, `immersive_portals_core`. Rivencraft now also refreshes Immersive Portals'
|
||
integer dimension map whenever saved or newly created Ages are loaded, before
|
||
their chunks can be synchronized to a player.
|
||
|
||
Version 0.2.16.2 routes book travel through Immersive Portals' seamless
|
||
teleport API when that mod is installed, preserving its client-world registry
|
||
during links between Ages and vanilla dimensions. The Explore control is also
|
||
positioned fully below the live snapshot window on both book screens.
|
||
|
||
Version 0.2.16.3 restores the full window viewport immediately after drawing
|
||
an Immersive Portals snapshot. Book titles, destination details, and controls
|
||
therefore render in their normal page positions instead of being compressed
|
||
inside the snapshot rectangle.
|
||
|
||
Version 0.2.16.4 clears the Immersive Portals GUI framebuffer between remote
|
||
world renders, preventing moving camera frames from accumulating into a sky
|
||
smear. The framebuffer now follows Immersive Portals' shared-target lifecycle
|
||
so a queued end-of-frame render cannot target a texture destroyed on GUI close.
|
||
|
||
Version 0.2.16.5 expands live-preview chunk loading to Immersive Portals'
|
||
reference eight-chunk radius. Rivencraft prepares the central 3x3 destination
|
||
chunks and requests an immediate tracking update when the GUI opens, providing
|
||
terrain for the first useful snapshot while the remaining chunks stream in.
|
||
|
||
Version 0.2.16.6 makes Linking and Descriptive Book screens non-pausing. The
|
||
integrated server now continues ticking in single-player while a book is open,
|
||
allowing live preview chunks to generate and stream into the snapshot.
|
||
|
||
Version 0.2.16.7 handles configured movement bindings directly in both book
|
||
screens while Explore mode is active. Movement, jump, and sneak now move the
|
||
remote camera even though Minecraft suspends normal gameplay key states while
|
||
a GUI is open.
|
||
|
||
Version 0.2.16.8 links Explore mode to real player movement in the current
|
||
dimension. Entering Explore anchors the source player and destination camera;
|
||
walking, jumping, falling, or being moved shifts the snapshot camera by the
|
||
same displacement while the book remains open and normal collision still
|
||
applies.
|
||
|
||
The preview code is separated behind a renderer interface and uses an isolated
|
||
Ponder level populated from server-authoritative destination snapshots.
|
||
|
||
## Version policy
|
||
|
||
Versions follow `x.y.z.b`:
|
||
|
||
- `x`: major release point.
|
||
- `y`: number of completed milestones.
|
||
- `z`: release slice within the active milestone.
|
||
- `b`: bug-fix and additional-work iteration within that release slice.
|
||
|
||
Starting a release slice increments `z` and resets `b` to zero. Completing a
|
||
milestone increments `y` and resets both `z` and `b` to zero. The first
|
||
milestone-2 slice is therefore `0.1.1.0`; a fix on that slice is `0.1.1.1`;
|
||
and milestone 2 completion is `0.2.0.0`.
|
||
|
||
## Milestone 1 acceptance record
|
||
|
||
- The project builds on a Java 21 JDK with `./gradlew build`.
|
||
- Mod identity and dependencies are declared in generated NeoForge metadata.
|
||
- Registrations are isolated by registry type and use deferred registration.
|
||
- The Descriptive Book loads with a model, name, tooltip, and creative tab.
|
||
- CI builds every pushed commit and pull request.
|