Public Access
This commit is contained in:
1 parent
7b5597dd47
commit
783a33456d
17 files changed
+612
-37
No files matched your search
+3
-2
@@ -18,12 +18,13 @@ core tests when investigating an issue:
|
||||
./gradlew runGameTestServer -ParchivedGameTestSuites=desk
|
||||
./gradlew runGameTestServer -ParchivedGameTestSuites=grammar,binder
|
||||
./gradlew runGameTestServer -ParchivedGameTestSuites=generation
|
||||
./gradlew runGameTestServer -ParchivedGameTestSuites=instability
|
||||
```
|
||||
|
||||
Available suite names are `linking`, `environment`, `writing`, `grammar`,
|
||||
`generation`, `desk`, `binder`, `mixer`, and `recipe`. The `generation` archive
|
||||
`generation`, `desk`, `binder`, `mixer`, `recipe`, and `instability`. The `generation` archive
|
||||
keeps the detailed feature, structure, ore, crystal, and fissure regressions
|
||||
out of the default smoke run. Three checks formerly registered twice in the
|
||||
out of the default smoke run. The `instability` archive adds multi-player loaded-chunk selection, policy gates, and protected-block checks without rerunning the default scoring and migration tests. Three checks formerly registered twice in the
|
||||
core and their archives now run only through the core wrapper. Run all
|
||||
Rivencraft tests before a
|
||||
release or after broad cross-system changes:
|
||||
|
||||
@@ -4,12 +4,21 @@ Each new Age stores an `InstabilityPlan` beside its frozen `Instability` score.
|
||||
|
||||
The saved provider IDs are independent of installed handlers. A missing optional handler leaves its ID and level intact and is skipped at runtime. A syntactically invalid saved ID or unsupported plan version fails loading explicitly; an unknown but valid ID is preserved and logged once when encountered. Disabling instability or world mutation never rewrites a saved score or provider plan. Saves from #64 with a frozen score but no provider plan are selected once from that score and Age seed, then marked dirty for persistence. Older pre-score Ages remain neutral and inert.
|
||||
|
||||
From 0.5.8.11, [live block profiling](LIVE_BLOCK_INSTABILITY.md) adds a separate
|
||||
effective score and provider plan once 400 Age and Overworld chunks have been
|
||||
sampled. The authored score/plan described above remain saved as the base;
|
||||
the effective provider selection can change as block abundance is observed.
|
||||
|
||||
The server scheduler runs only for loaded `rivencraft:age/*` levels with a player present and an Age definition. It uses only chunks already loaded near those players, never requests a chunk, and rotates among eligible Ages when the per-tick cap is reached. Configuration bounds the cooldown (minimum 20 ticks), active Ages, handlers and actions per Age, effective provider level, and examined loaded chunks. A handler must claim a shared action permit before each effect. A throwing handler is logged and quarantined temporarily without stopping the server. World-mutating handlers are enabled by default to match Legacy; the setting can still disable them. These limits are guards for upcoming providers, not proof that an arbitrary third-party handler cannot misuse world APIs.
|
||||
|
||||
Issue #67 registers the non-world-mutating potion handlers; see [status-effect policy](INSTABILITY_STATUS_EFFECTS.md). Issue #68 adds configurable [colored decay](INSTABILITY_DECAY.md), enabled by default for newly generated configs. Issue #69 adds lightning and explosions; issue #70 adds [meteor, scorching, and erosion](INSTABILITY_ENVIRONMENTAL.md). The runtime rejects Overworld and preview dimension IDs; its player requirement excludes unattended snapshot chunk loaders. GameTests cover deterministic selection, save round-trips, score-only migration, unknown IDs, scope checks, fair admission, and action caps.
|
||||
|
||||
Issue #72 adds [server config, per-Age controls, diagnostics, and book feedback](INSTABILITY_DIAGNOSTICS.md). Its operator controls never rewrite a frozen score or provider plan.
|
||||
|
||||
The Milestone 6 [regression and migration record](MILESTONE_6_REGRESSION.md)
|
||||
maps the automated acceptance checks and lists the in-game restart, optional-mod,
|
||||
and hazard-visual scenarios still requiring verification.
|
||||
|
||||
# Lightning and explosions (#69)
|
||||
|
||||
The `lightning` and `explosions` cards now run only in loaded Rivencraft Ages with players. Legacy rolled once per chunk per tick: explosions at 1/1000 and lightning at 1/5000 during thunder or 1/100000 otherwise. Each selected hazard card gets an independent roll every scheduler pass, rather than waiting for the rotating two-provider sample. The roll uses up to 81 already-loaded chunks near Age players and the exact probability of at least one Legacy opportunity over that many chunk-ticks. It permits at most one event per hazard type per pass. A per-Age saved sequence and last-event time prevent the same roll/event from replaying after a restart. Lightning also skips an existing bolt at the target.
|
||||
|
||||
@@ -6,6 +6,10 @@ The baseline is explicitly zero for page-free and Link-Panel-only random Ages, a
|
||||
|
||||
The score is calculated after the Age plan and effective traits are chosen, then saved with the Age identity before its dimension is generated. The same UUID returns the existing definition, including the same score, on repeated use. Spawn updates preserve it. Reload only deserializes the frozen breakdown; it never reruns the current grammar or catalog. An older Age definition without `Instability` is migrated to a persisted version-1 neutral score of zero, rather than retroactively scoring its writing. A future scoring-rule change must introduce an explicit new schema/migration policy, not silently reinterpret existing Ages. Issue #66 added the frozen provider selection; issues #67–#70 added the current handlers. See the [runtime policy](INSTABILITY_RUNTIME.md).
|
||||
|
||||
This is now the **authored base** score. [Live block profiling](LIVE_BLOCK_INSTABILITY.md)
|
||||
keeps its sample counts separately and may add a changing effective block score
|
||||
without rewriting the authored breakdown or its saved base provider plan.
|
||||
|
||||
Unknown or unsupported pages remain invalid for *new* Ages. Their absence from a later registry does not change an already saved score. Focused GameTests cover stable/defective writing, random baseline and bright lighting, repeated identity, save round-trip, and missing-symbol/old-save behavior.
|
||||
|
||||
`/rivencraft age instability` inspects the Age containing the command source; an optional dimension ID inspects an unloaded or different registered Age. It reports immutable base score, stability bonus, runtime penalty, and effective score. The pinned Legacy tree defines player-death and player-presence bonus classes but does not register them as default providers, so Rivencraft leaves player-driven modifiers disabled: bonus and penalty are zero and effective equals base. There is therefore no mutable bonus save to migrate in this release. No death, PvP event, player identity, or dimension transition can transfer stability between Ages. Any future opt-in mechanic must persist separately from `Instability`, define caps and reset behavior, and must not rewrite the generation plan or frozen provider plan.
|
||||
@@ -4,7 +4,7 @@ This is the behavior contract used to implement Milestone 6. It is pinned to [My
|
||||
|
||||
## Score, grammar, and selection in Legacy
|
||||
|
||||
Legacy's [`AgeController`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/com/xcompwiz/mystcraft/world/AgeController.java) calculates `debug + symbol + block + book/base + bonus`, then applies difficulty 0/1/2/3 multipliers of 0.25/0.5/1/1.75. Global instability is enabled by default; an Age also has its own enable flag. The unmodified score is not simply “number of bad pages.” Block profiling may delay a usable score: `blockinstability` is null until **more than** 400 Age chunks are profiled, and `getInstabilityScore()` returns zero until then. It is recalculated after additional profiling. [`ChunkProfiler`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/com/xcompwiz/mystcraft/world/profiling/ChunkProfiler.java) compares watched block abundance with a baseline, subtracting only positive excess above each baseline. The baseline is profiled or read from balance config; [`InstabilityDataCalculator`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/com/xcompwiz/mystcraft/world/profiling/InstabilityDataCalculator.java) sets its default tolerance to 1.05, and default `useconfigs=false`. We should not copy its 400-chunk profiling delay or dynamic block scan into 1.21.1 without a separate performance case.
|
||||
Legacy's [`AgeController`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/com/xcompwiz/mystcraft/world/AgeController.java) calculates `debug + symbol + block + book/base + bonus`, then applies difficulty 0/1/2/3 multipliers of 0.25/0.5/1/1.75. Global instability is enabled by default; an Age also has its own enable flag. The unmodified score is not simply “number of bad pages.” Block profiling may delay a usable score: `blockinstability` is null until **more than** 400 Age chunks are profiled, and `getInstabilityScore()` returns zero until then. It is recalculated after additional profiling. [`ChunkProfiler`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/com/xcompwiz/mystcraft/world/profiling/ChunkProfiler.java) compares watched block abundance with a baseline, subtracting only positive excess above each baseline. The baseline is profiled or read from balance config; [`InstabilityDataCalculator`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/com/xcompwiz/mystcraft/world/profiling/InstabilityDataCalculator.java) sets its default tolerance to 1.05, and default `useconfigs=false`. Rivencraft's later [bounded implementation](LIVE_BLOCK_INSTABILITY.md) retains the threshold and tolerance, but not Legacy's spatial accessibility formula or unbounded profiling.
|
||||
|
||||
| Input | Verified Legacy behavior | Rivencraft M6 interpretation |
|
||||
| --- | --- | --- |
|
||||
@@ -15,7 +15,7 @@ Legacy's [`AgeController`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9b
|
||||
| Unsupported/unmatched page | Legacy logs unmatched symbols during reconstruction and skips their logic; its `AgeData.getBaseInstability()` still has a TODO for calculating instability from pages. This is not a sound compatibility contract. | Remains fatal for *new* books until semantic and runtime support exists; never silently erase the page or pretend its effect applied. Existing saved books retain their IDs. |
|
||||
| Other penalties/bonuses | `AgeController.addInstability(int)` is available to symbol logic. The base/book score is persisted as a `short`; Legacy's [`InstabilityBonusManager`](https://github.com/Mystcraft/Mystcraft-Legacy/blob/9bc8ddc061845df0cd5ea47f4fdef773cff786ae/src/main/java/com/xcompwiz/mystcraft/instability/bonus/InstabilityBonusManager.java) also has dynamic player death/behavior components. | Persist a versioned score breakdown for Age writing and environmental contributions. Do not infer death/troll mechanics from the mere existence of Legacy classes. |
|
||||
|
||||
The complete Legacy `instabilityModifier` audit found direct feature-page costs only for Mineshafts, Nether Fortresses, Strongholds, and Villages. Their first three occurrences cost zero; the fourth and every later occurrence adds 100. Every other Legacy feature class inherited `SymbolBase`'s zero modifier. Rivencraft applies that exact rule to the four matching pages. By project balance decision, Bastions, Trial Chambers, Ancient Cities, Shipwrecks, Ocean Ruins, Pillager Outposts, Ruined Portals, Nether Fossils, Buried Treasure, and Trail Ruins use the same repeat rule. Matching Legacy features such as Caves, Crystal Formations, Dense Ores, Dungeons, Floating Islands, Huge Trees, Deep/Surface Lakes, Obelisks, Ravines, Skylands, Spheres, Spikes, Star Fissures, and Tendrils have no direct page cost. Legacy could still derive instability later from excess profiled blocks, especially ores, but that separate 400-chunk profiling system is intentionally not ported. Other modern-only Rivencraft features remain neutral.
|
||||
The complete Legacy `instabilityModifier` audit found direct feature-page costs only for Mineshafts, Nether Fortresses, Strongholds, and Villages. Their first three occurrences cost zero; the fourth and every later occurrence adds 100. Every other Legacy feature class inherited `SymbolBase`'s zero modifier. Rivencraft applies that exact rule to the four matching pages. By project balance decision, Bastions, Trial Chambers, Ancient Cities, Shipwrecks, Ocean Ruins, Pillager Outposts, Ruined Portals, Nether Fossils, Buried Treasure, and Trail Ruins use the same repeat rule. Matching Legacy features such as Caves, Crystal Formations, Dense Ores, Dungeons, Floating Islands, Huge Trees, Deep/Surface Lakes, Obelisks, Ravines, Skylands, Spheres, Spikes, Star Fissures, and Tendrils have no direct page cost. Legacy could still derive instability later from excess profiled blocks, especially ores. From 0.5.8.11, Rivencraft has a [bounded live block-profile adaptation](LIVE_BLOCK_INSTABILITY.md) using the 400-chunk threshold, including diamond blocks as a deliberate non-Legacy extension. Other modern-only Rivencraft features remain neutral unless they increase watched-block abundance.
|
||||
|
||||
Bright Lighting adds 500 for every authored occurrence. A generated Bright Lighting controller also adds 500. This is independent of the 500-point extra-controller cost, so two authored Bright Lighting pages produce 1,500 total: 500 for each symbol and 500 for the repeated controller.
|
||||
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
# Live block-instability profiling (0.5.8.11)
|
||||
|
||||
Mystcraft Legacy measures the abundance of watched blocks in generated chunks,
|
||||
compares that abundance with a baseline, and adds only positive excess to the
|
||||
Age's instability. Its `InstabilityBlockManager` and `ChunkProfiler` are
|
||||
available in the user's local 0.13.7.06 archive. Legacy's Age-side threshold
|
||||
is more than 400 profiled chunks; its default tolerance is 1.05. The Legacy watched
|
||||
blocks include coal, lapis, iron, emerald, redstone, gold and diamond ores,
|
||||
quartz ore, glowstone, and crystal blocks. Diamond **blocks** are not on that
|
||||
default list, but are included here at the player's request.
|
||||
|
||||
Rivencraft samples up to 1,024 distinct, newly generated chunks per dimension,
|
||||
at most four per server tick. It never generates a chunk merely to profile it.
|
||||
The Overworld is sampled as the baseline; an Age needs 401 samples and the
|
||||
baseline needs 500 before the live block component contributes points. Counts and sampled chunk
|
||||
positions persist per dimension, preventing reloads from double-counting.
|
||||
For each watched block, Rivencraft compares average blocks per sampled chunk
|
||||
and charges `max(0, Age average − 1.05 × Overworld average) × weight`, rounded
|
||||
to the nearest point. The block component is capped at 100,000 points.
|
||||
|
||||
Legacy weights are used for its watched blocks: coal/lapis 5, iron 60, emerald
|
||||
200, redstone 250, gold 750, diamond 4,000, quartz/crystal 20, and glowstone
|
||||
50. Deepslate variants inherit their ore's weight. Modern/high-value extensions
|
||||
include diamond, emerald, gold, iron, raw gold, raw iron and netherite storage
|
||||
blocks, plus ancient debris. Netherite blocks cost 8,000 per excess block per
|
||||
sampled chunk; ancient debris costs 4,000. Modded blocks are not automatically
|
||||
classified as valuable; this avoids charging unknown decorative materials.
|
||||
|
||||
The authored score and provider plan remain saved as the Age's immutable base.
|
||||
Only Ages created with instability schema v2 participate; existing v1 Ages
|
||||
retain their previously frozen scores/plans, including neutral pre-scoring
|
||||
Ages. This avoids silently rescoring existing worlds.
|
||||
The live block component creates a deterministic **effective** score and
|
||||
provider plan from that base plus the persisted profile; new cards can become
|
||||
active as sampled abundance rises. The command `/rivencraft age instability`
|
||||
shows both the saved base and the currently profiled block component. An
|
||||
unloaded Age has no active profile view until its dimension is loaded again.
|
||||
Turning an effect off does not delete counts or reroll the same effective plan.
|
||||
|
||||
This is not byte-for-byte Legacy profiling. Legacy has a spatial accessibility
|
||||
map and two factors per block, actively builds a dummy-world baseline, and can
|
||||
recompute after subsequent chunk profiling. Rivencraft uses a simpler
|
||||
per-chunk abundance metric, a real-world Overworld baseline, a sample/work cap,
|
||||
and a saved authored base so modern servers remain bounded and restart-safe.
|
||||
The greater-than-400-chunk activation delay is retained. Because only newly
|
||||
generated chunks are sampled, old already-explored worlds may need substantial
|
||||
new exploration before their Overworld baseline is ready. A mod that mutates
|
||||
blocks after the chunk-load event may not be reflected in the first sample.
|
||||
|
||||
## Manual check handed to the player
|
||||
|
||||
The first focused GameTest run after adding the chunk-load listener stalled in
|
||||
its initial 50-test batch and was stopped. It is **not** a passing test result.
|
||||
Do not retry that stalled scenario automatically. In a disposable world:
|
||||
|
||||
1. Create one Age with an authored Diamond Block + Rocks (or Floating Islands)
|
||||
combination and a comparison Age using Stone for the same feature. Explore
|
||||
enough distinct chunks in each Age for `/rivencraft age instability` to show
|
||||
a profiled-block contribution. Explore the Overworld too if its baseline has
|
||||
not reached 400 chunks. The diamond Age should score higher and can gain
|
||||
provider cards; the stone Age should not get a diamond-block contribution.
|
||||
2. Leave and restart the world. Re-enter both Ages and compare their scores and
|
||||
provider IDs/levels. Reloading old chunks must not increase the sample
|
||||
count or score by itself. Generating more diamond-rich chunks may change the
|
||||
effective score and provider set; disabling instability must suppress their
|
||||
effects without erasing the profile.
|
||||
3. Check a naturally generated diamond-ore Age without authored diamond-block
|
||||
features. If its ore abundance is near the Overworld baseline, it should
|
||||
receive little or no ore contribution. Check that profiling does not make
|
||||
chunk loading noticeably stall, and report any exception or server hang.
|
||||
|
||||
Do not use a valued save for this check. The game jar builds, but live chunk
|
||||
profiling still needs this player-run validation before release.
|
||||
@@ -0,0 +1,95 @@
|
||||
# Milestone 6 instability regression and migration check (#73)
|
||||
|
||||
This is the release-slice acceptance record for instability, not a promise of
|
||||
general old-save compatibility. The latter remains issue #60. Run the focused
|
||||
archive with `./gradlew build runGameTestServer -ParchivedGameTestSuites=instability`;
|
||||
it includes the default smoke suite.
|
||||
For 0.5.8.10 on 2026-10-10, that dedicated GameTest server passed all 55 required tests
|
||||
with no optional content/client integrations installed (the required Dynamic
|
||||
Dimensions and Bad Packets dependencies were present). The full archive was not run;
|
||||
it has a previously documented storage stall, so do not count it as passing.
|
||||
The 0.5.8.11 run with live block profiling stalled in its initial batch and
|
||||
was stopped; it is **not** a passing result. The live profiling scenario is
|
||||
handed to the player in [the block-profile checklist](LIVE_BLOCK_INSTABILITY.md).
|
||||
|
||||
## Automated coverage
|
||||
|
||||
| Requirement | Existing default test or focused archive |
|
||||
| --- | --- |
|
||||
| Stable writing, defective writing, score explanations, repeated use of the same book | `AgePersistenceGameTests.instabilitySeparatesStableAndDefectiveWriting` |
|
||||
| Frozen score, age-scoped writing cost, random baseline | `AgePersistenceGameTests.randomBaselineAndBrightBalanceAreFrozen`, `auditedSymbolCostsAreCountedAndAgeScoped` |
|
||||
| Complete Age definition, score and provider-plan save/load | `AgePersistenceGameTests.authoredPlanRetainsResolvedMeaningAndAgeIdentity`; `AgeInstabilityRuntimeGameTests.selectionIsDeterministicAndFrozen` |
|
||||
| Old pre-scoring Ages, score-only saves, removed symbols, unavailable handlers | `AgePersistenceGameTests.missingRegistryEntryDoesNotReinterpretAnOldAge`, `instabilitySeparatesStableAndDefectiveWriting`; `AgeInstabilityRuntimeGameTests.savedPlanSurvivesAgeUpdatesAndMissingHandlers` |
|
||||
| Per-Age controls and changed config without score/plan reroll | `AgeInstabilityRuntimeGameTests.perAgeControlsPersistWithoutChangingScoresOrOtherAges`; `Milestone6RegressionGameTests.disablingEffectsCannotRerollFrozenPlan` |
|
||||
| Hazard cooldown and attempt sequence across saved-state reload | `AgeInstabilityRuntimeGameTests.hazardCooldownAndAttemptSequenceSurviveReload` |
|
||||
| Active-Age rotation, action/tick budget | `AgeInstabilityRuntimeGameTests.ageScopeRotationAndActionBudgetAreBounded` |
|
||||
| Multiplayer loaded-chunk-only candidate selection, deduplication and cap | `Milestone6RegressionGameTests.multiplayerCandidatesStayLoadedDeduplicatedAndCapped` |
|
||||
| Decay loaded-chunk target and spawn protection | `AgeDecayGameTests.targetMustRemainInChosenLoadedChunk`, `savedSpawnAndPlatformAreProtected` |
|
||||
| Explosion policy gates and protected blocks | `Milestone6RegressionGameTests.disabledGriefAndProtectedBlocksStayUntouched` |
|
||||
| No Overworld status or decay provider | `AgeStatusEffectGameTests.overworldCannotRunAnAgeStatusProvider`; `AgeDecayGameTests.overworldCannotRunDecayProvider` |
|
||||
|
||||
These tests exercise saved-data serialization and deterministic policies. They
|
||||
do **not** simulate a complete process restart, an actual multiplayer server,
|
||||
optional-mod installation, or real terrain and hazard visuals. The three new
|
||||
checks live only in the `instability` archive to avoid duplicating default tests.
|
||||
|
||||
## Migration outcome and known gaps
|
||||
|
||||
- Pre-scoring Milestone 5 Ages load with a neutral score and no effects; they
|
||||
are not retroactively rescored under current writing rules.
|
||||
- Score-only Ages receive a deterministic provider plan once from their saved
|
||||
score and Age seed. An already-saved score and plan retain their meaning when
|
||||
pages, handlers, or runtime config change. Unknown but syntactically valid
|
||||
provider IDs are preserved and skipped if their handler is unavailable.
|
||||
- Missing symbol definitions do not reinterpret a frozen instability score.
|
||||
That check is narrower than arbitrary missing biome, block, or worldgen
|
||||
registry entries: loading a world with removed data packs is not guaranteed.
|
||||
Broad save compatibility and migration remain tracked in #60.
|
||||
- In-process roundtrips cannot prove that Age dimensions reload correctly
|
||||
after a full stop/start. Check that in a real client/server world. Do not add
|
||||
another GameTest for it if it hits the documented storage stall; hand the
|
||||
exact scenario to the player instead.
|
||||
- The dedicated GameTest run establishes classloading with no optional runtime
|
||||
flags. It does not establish classloading with every optional integration
|
||||
installed, nor the reverse of removing one from an existing save.
|
||||
|
||||
## Manual in-game matrix
|
||||
|
||||
Use a fresh test world, then keep one save for the restart and data-pack checks.
|
||||
Record the seed, mod list, age name, and `/rivencraft age instability` output
|
||||
before and after each change. Do not deliberately remove a required registry
|
||||
entry from a valued world; copy the test save first.
|
||||
|
||||
1. Bind a low-instability book and a deliberately unstable book. Reuse each
|
||||
book and verify the Age name, dimension ID, score, selected providers and
|
||||
provider levels remain unchanged. Exit the Ages, stop Minecraft completely,
|
||||
restart and re-enter; compare the same diagnostic values.
|
||||
2. With two survival players in one unstable Age and a third player in the
|
||||
Overworld, verify effects stay in the Age, follow the Age players, and do
|
||||
not appear in the Overworld. Move both Age players away, let old chunks
|
||||
unload, and confirm hazards do not keep remote chunks loaded or operate
|
||||
there. Confirm controls on one Age do not alter a second Age.
|
||||
3. Disable global instability, then world mutation, then one provider. Verify
|
||||
the suppressed effect stops and the frozen score/plan do not change after
|
||||
re-enabling or restarting. With block destruction disabled, trigger an
|
||||
explosion in an expendable Age; check that arrival platforms, portals,
|
||||
block entities and protected blocks survive. Check lightning, explosion,
|
||||
decay, status-effect, burning, meteor and erosion visuals where selected.
|
||||
4. With Biomes O' Plenty or another TerraBlender biome mod, confirm recognized
|
||||
biome pages still author an Age and the instability diagnostics remain
|
||||
stable after restart. Repeat with Serene Seasons installed, then absent in
|
||||
a disposable copy; confirm its Age season behavior and that Rivencraft
|
||||
itself still loads. JEI should display the relevant pages and recipes when
|
||||
installed, while the mod works without it.
|
||||
5. Check the book preview separately with its fallback animation, Ponder/Create,
|
||||
and Immersive Portals when available. Opening a book should not change
|
||||
player location, instability diagnostics, or ambient audio in the actual
|
||||
Age. Do not install both season mods together for this matrix.
|
||||
6. On a copied save, remove or alter a **nonessential** data pack providing
|
||||
a writing symbol or optional handler, then reload. Existing saved scores
|
||||
and provider plans must not reroll. If a referenced worldgen registry entry
|
||||
prevents load, record it against issue #60 rather than treating #73's
|
||||
frozen-instability guarantee as general missing-registry support.
|
||||
|
||||
The matrix is guidance for a player-run pass; none of these six scenarios is
|
||||
claimed as completed by the automated result above.
|
||||
Reference in new issue
Block a user