fix: 1.12 bug sweep — mod container, planet config, JEI guard, per-dim time/beds, planet weather sync#22
Conversation
- pick java/java.exe by os.name in server harness - accept .so/.dylib LWJGL markers in client native scan, not only .dll - mark gradlew executable Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 3-attempt loop on BindException in child JVM transcript - awaitReadyOrBindFailure polls for ready/failure marker - Split bootstrapServerFiles into writeEula + per-attempt props - destroyAndJoin helper cleans up failed attempts between retries Mitigates TASK-16 shape #1 (port-bind TOCTOU) observed under parallel testServer forks in downstream AdvancedRocketry repo.
- New start(server, username) overload for distinct per-client names - Move --username/--uuid out of legacyArgs block (FG6 MainClient also honours them) - Without this fix FG6 legacydev generated random Player### names
The coremod's only job is bootstrapping mixins (done in the plugin constructor); the DummyModContainer "advancedrocketrycore" registered empty lifecycle handlers and nothing referenced its modid. It only added a phantom entry to the title-screen "loaded" count without ever becoming "active", producing the off-by-one reported in dercodeKoenig#71. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Loading planetDefs.xml with a subset of mods crashed at the <laserDrillOres> path: doesOreNameExist is true for a reserved ore name even when no items are registered under it, so getOres(...).get(0) hit an empty list. Resolve the ore name once (trimmed), guard the empty list, and copy() the prototype stack before mutating its count. Also make config loading fault-tolerant: a single malformed planet is now logged and skipped instead of aborting the whole file (XMLPlanetLoader .readAllPlanets per-planet isolation), and genuinely fatal/structural failures propagate via loadPlanetsOrThrow so Forge produces a normal crash report instead of the old silent FMLCommonHandler.exitJava that closed the window with no report. Fixes dercodeKoenig#77 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ketry#73) The oregen config persists only through the per-world planetDefs.xml round-trip (it is not written to per-dimension NBT), so this regression test guards writeXML -> readAllPlanets preserving <oreGen> — the bug kaduvill traced to 2019, already fixed in the 1.12 base. Also files TASK-45: <oreGen> clumpSize/chancePerChunk clamp to a floor of 1 (and empty <oreGen> falls back to the global default), making "disable this ore per planet" inexpressible — likely the real cause behind the Advanced-Rocketry#73 report of zeroed veins still generating ore. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…vanced-Rocketry#76) PacketDimInfo.executeClient called ARPlugin.requestGasGiantRefresh() unconditionally. ARPlugin implements mezz.jei.api.IModPlugin, so touching it loads JEI classes and NoClassDefFoundErrors when JEI isn't installed — re-introducing issue Advanced-Rocketry#76 via the dimension-sync path (the startup path kaduvill already guarded in ClientProxy). Wrap the call in Loader.isModLoaded("jei") and drop the top-level ARPlugin import. Also files TASK-46: CompatibilityMgr is vestigial (all consumers gone or commented out); left in place pending a revive-vs-remove decision. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Hi! Saw the activity on dercodeKoenig#71 (comment) but was wondering if this PR really fixes that or if it's ment to only close: Advanced-Rocketry#71 Correct me if i'm wrong ofcours! Hm, is your fork the one that actually is used for the mod hosted here? https://www.curseforge.com/minecraft/mc-mods/advanced-rocketry-2 . Wasn't sure as the source on that page refers to dercodeKoenig. |
… and TASK-48 (per-dim WorldInfo delegation) TASK-47 captures the converged design for issue Advanced-Rocketry#66: derived WorldInfo swallows the sleep time-skip and vanilla's 24000-rounding misses planetary dawn. Fix = per-dim time owned by the custom WorldInfo plus a WorldServer sleep-site mixin rounding to rotationalPeriod. TASK-48 spins off the research into a feature request to make other overworld-delegated WorldInfo state (GameRules, spawn, difficulty, terrain type, game type) per-dimension. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AR planets are WorldServerMulti whose WorldInfo is a DerivedWorldInfo —
setWorldTime is a no-op there, so the vanilla sleep skip was silently
swallowed and time never advanced ("beds do nothing"). And planets render
day/night from rotationalPeriod (= (1/gravity)^3 * 24000, != 24000 for
almost every planet), so vanilla's 24000-rounded wake misses planetary dawn.
The custom WorldInfo (ARWeatherWorldInfo) now owns per-dimension worldTime
and worldTotalTime in PlanetWeatherState (NBT-persisted, seeded from the
delegate on first wrap), so each dimension's clock and sleep are independent
of the overworld. The wrapper is now installed on all AR planets regardless
of the custom-weather toggle (weather behaviour stays gated by config via
weatherManaged). MixinWorldServer @redirects the sleep-block setWorldTime to
round to the dimension's rotationalPeriod (planetary dawn) for AR worlds.
Tests: SleepWakeTimeTest (dawn-rounding math), PlanetWeatherState per-dim
time NBT round-trip + seeding, ARWeatherWorldInfoTest rewritten for per-dim
time ownership + unmanaged-weather delegation. Server weather isolation
suites stay green (mixin applies; decoupling doesn't regress weather).
TASK-47.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The custom WorldInfo now owns per-dimension time as well as weather (TASK-47), so the weather-only name no longer fits. Pure mechanical rename of the class, its test, and all references (types + string-literal class-name assertions in the server/client wiring tests + probe comments). Marks TASK-47 shipped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- new `artest infra railgun-fire` probe verb + `countItemsInPortList` helper drive the source-side TileRailgun.attemptCargoTransfer path - RailgunFiringContractTest (2 server): same-dim shot fires (cargo input→output); unloaded-dest shot fails silently with cargo preserved - root cause = destination dim unloaded (Forge getWorld→null, railgun force-loads only its own chunk) + zero player feedback on every gate - bug ledger Batch #2 entry #8; README pyramid regenerated to 848 (+2 server) per SOP §2.5; TASK-49 Done row + ledger summary synced - production fix (load dest dim + per-cause feedback) pending Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AdvancedRocketryPlugin's coremod constructor called MixinBootstrap.init()
unconditionally. Under a Mixin host (MixinBooter) in a packaged jar, Mixin is
already bootstrapped on the LaunchClassLoader and our config comes from the
MixinConfigs manifest attribute; re-running init() from this coremod
(AppClassLoader) re-initiates loading of GlobalProperties$Keys on a second
classloader → LinkageError ("loader constraint violation") → FML crashes at
launch. Wrap the self-bootstrap in try/catch: dev (no host) self-registers as
before; under a host the error is swallowed and the manifest drives it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- new sops/development/bug-report-workflow.md: repro-first pipeline (mandatory testClient e2e + testServer when catchable) → trace report → user decides (Path A confirmed-bug task / Path B fix-now) - introduces `Type: Bug report — confirmed` + `Priority: urgent` task header fields (additive to the task-lifecycle status enum) - session-start duty to re-surface open confirmed bugs lives in the SOP (required reading), not in Navigator tooling - linked from DEVELOPMENT-README required-reading section Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ced-Rocketry#61) Issue Advanced-Rocketry#61 "Railgun does not work": the paired-railgun item teleport failed SILENTLY when the destination railgun's dimension wasn't loaded (sender on planet A, receiver on planet B, player on A) — the railgun force-loads only its own chunk, so DimensionManager.getWorld(destDim) returned null and attemptCargoTransfer bailed with no feedback. Fix (Option 1 — load destination on fire + player feedback): - attemptCargoTransfer now initDimension()s a registered-but-unloaded destination (TileSpaceElevator idiom); the dest railgun's own onLoad ticket sustains it after the first cold shot - new FireStatus enum set at every branch (NO_TARGET / TARGET_UNAVAILABLE / TARGET_FULL / DIFFERENT_SYSTEM / FIRED), synced via the tile description packet and shown as a red GUI line; 4 msg.railgun.status.* lang keys Repro tests flipped to the corrected behaviour (SOP Path B): - server RailgunFiringContractTest (3): same-dim fires; registered- unloaded dest loaded on fire (destLoadedBefore:false→destLoaded:true); unloadable dest reports TARGET_UNAVAILABLE, cargo preserved - client RailgunCargoTransitE2ETest (2): same-dim fires; unloadable dest reported, cargo preserved - infra railgun-fire probe extended with destLoadedBefore + fireStatus All green (testUnit 267 / testIntegration 89 / railgun server 3 + client 2, skipped=0). Pyramid → 851. Ledger #8 fixed; TASK-49 closed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- new sops/development/issue-reference-discipline.md: in this GitHub fork network (Advanced-Rocketry root → StannisMod → dercodeKoenig) a bare #NN leaks to the root and notifies unrelated 2015 issues; always fully-qualify as owner/AdvancedRocketry#NN using the owner from the issue link the user gave (StannisMod or dercodeKoenig), never the root - linked from DEVELOPMENT-README required-reading + bug-report-workflow Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Yeah, sorry, I rushed things a bit. I’m no longer sure my changes will ever make it into the CurseForge release, so I’ll keep the issues open for now. Yep, I'm one of the maintainers of AR:R. Was in long-lasting vacation, returned with fresh mind and ideas. They will be implemented in this repo instead of official (dercodeKoenig's). Already based on upstream 2.2.9 version (special thanks for kaduvill). P.S. version 2.2.9 was published from kaduvill's repo, so currently we don't have "official" repo XD If anyone wants to test a newer, separately maintained version of AR, feel free to try my repo ) |
Adds two ClientBot capabilities needed to test client-side input/render behaviour end-to-end (not just server-authoritative state read back via probes): - setKey(keyCode, pressed) / holdKey / releaseKey: injects a real KeyBinding press/release on the client (KeyBinding.setKeyBindState + an isPressed edge via onTick), so mod input handlers polling key state on ClientTickEvent fire their real packet path. - reportRidingEntity(): client-side view of the entity the player is riding (class, id, pos, motion) — the authoritative way to assert what the client actually renders, catching position-sync / interpolation regressions. Bridge handlers run on the client thread like the rest. Version 0.4.2 -> 0.4.3.
Adds ClientBot.readStaticField(className, fieldName): reflectively reads a static field on the client and returns String.valueOf(value) (+ isNull, type). Lets a test assert arbitrary client-side mod state — rendered HUD text, render flags, etc. — without the framework depending on the mod. Version 0.4.3 -> 0.4.4.
ClientBot.setLook(yaw, pitch) drives the real EntityPlayerSP look (current and prev-tick fields) so tests can exercise mouse-aimed controls through the genuine client path rather than a server probe. report_state now reports playerYaw/playerPitch, and report_riding_entity reports the ridden entity's rotationYaw/rotationPitch, making camera-binding and look-tracking behaviour observable client-side.
WorldServer's constructor runs calculateInitialWeather() against the vanilla DerivedWorldInfo — whose isRaining() delegates to the overworld — BEFORE MixinWorldServerMulti installs the per-dim wrapper. A planet world (re)created while the overworld rains is therefore born with rainingStrength=1.0 even though its per-dim weather is clear; the per-tick lerp then drags it back to 0, streaming SPacketChangeGameState(7) to every player entering the dim — a ~5 s phantom-rain fade on arrival (mostly hidden behind the loading screen on first-generation visits, which is why upstream looked immune in manual tests). Reseed the strength fields from the wrapped (effective) state right after the swap. Field writes, not setters: setRainStrength/setThunderStrength are @SideOnly(CLIENT) and absent on a dedicated server. Pins: - WeatherBaselineTest now asserts both planets (lazily constructed while the overworld rains) report rainStrength/thunderStrength 0.0 — red before this fix (read back 1.0). - WeatherClientSyncE2ETest gains a phantom-fade leg: rain the overworld, teleport the real client to a never-constructed planet, client-visible rainStrength must hold at exactly 0 across the would-be fade window. Also tightens the A→B arrival check (strength, not just the flag) and fixes the comment mis-attributing the rain ramp to a client-side lerp (WorldClient.updateWeather() is empty in 1.12.2 — the ramp is the server lerp streamed one packet per tick).
Vanilla CommandWeather hard-codes server.worlds[0]: run while standing on an AR planet it silently mutates the OVERWORLD's weather and leaves the planet untouched — with per-dim weather enabled there was no command-level way to change a planet's weather at all (the enableCustomPlanetWeather config docstring already promised otherwise). Port the CommandEvent redirect from the upstream per-dim weather PR (the /advancedrocketry weather subcommand itself was already ported): when the sender stands on an AR planet, cancel vanilla /weather and re-issue it as /advancedrocketry weather with the same arguments.
# Conflicts: # src/main/java/zmaster587/advancedRocketry/asm/AdvancedRocketryPlugin.java
Records kaduvill's experimental directional-gravity prototype (EntityLivingBase move/jump/look hooks + EntityRenderer.orientCamera, ~95% commented out upstream) as a backlog feature request. The hook skeleton left our tree with ClassTransformer's deletion in 877d149; the prototype remains readable at c1c791d and the commented-out math still sits in client/ClientHelper.java. Surfaced by the 2026-06-10 kaduvill-port audit — never functional upstream, so a feature request rather than a porting regression.
AR's client/server e2e harness iterates in lockstep with AR's tests (every recent FTF release was driven by an AR test need), while the external artifact forced a clone-sibling + publishToMavenLocal setup step and let branches skew across framework versions (0.4.2 vs 0.4.5). Vendor the sources via git subtree (history preserved); the external repo stays available for other consumers — AR just no longer depends on the published artifact. git-subtree-dir: testframework git-subtree-mainline: 82797ca git-subtree-split: 25fa6cd
Wires the subtree into the build: testframework/src/main/java joins the test source set (same RFG-patched dev classpath the tests link against, which is what the :dev classifier provided), and the published com.github.stannismod.forge:forge-test-framework artifact leaves the dependency list together with the sibling-checkout publishToMavenLocal setup step. Verified: testUnit, testIntegration, server harness (WeatherBaselineTest) and real-client e2e (WeatherClientSyncE2ETest) all green with the framework served from classes dirs.
testframework: ClientBot.sendChat routes one chat line through EntityPlayerSP.sendChatMessage (the real CPacketChatMessage path), so the server handles the command with a PLAYER sender — permissions, the sender's dimension and CommandEvent hooks all run their production path. Console-driven commands can't reproduce sender-position-dependent behaviour; this probe unlocks that whole test class. WeatherCommandRedirectE2ETest: a real client standing on an AR planet types vanilla /weather rain; asserts the planet's per-dim state flips to raining, the client renders the rain (flag past the 0.2 strength threshold the begin-raining broadcast keys on), and the OVERWORLD stays clear — the assertion that fails without the CommandEvent redirect (vanilla CommandWeather writes to server.worlds[0]). Reverse /weather clear leg included. Red-proven: with the redirect reverted the planet never starts raining and the test fails.
testframework: ClientBot.reportMods exposes Loader.getModList / getActiveModList sizes + loaded modids — the exact lists the vanilla main menu renders as 'N mods loaded, M mods active' via FMLCommonHandler.getBrandings. ModCountParityE2ETest pins dercodeKoenig#71 at the player-visible layer: every loaded mod is active (the title-screen counts agree) and the vestigial advancedrocketrycore container is gone. Red-proven: with ModContainer.java + the plugin's getModContainerClass restored from 7f8ee7f^ the probe reports advancedrocketrycore in the loaded list and the test fails.
…ault tolerance XMLPlanetLoaderTest already pins the parser guards (reserved-but-empty ore name, per-planet isolation); what only a real dedicated server can prove is the headline of dercodeKoenig#77 — the server BOOTS with a dirty planetDefs.xml instead of dying in a silent exitJava. Fixture: one well-formed planet + one with a non-numeric rainMarker (throws deep inside readPlanetFromNode). Asserts the server comes up, the malformed planet is skipped, and the good planet is registered and round-trips its config.
…cketry#66 gap) Closes the 'no sleeping-player harness' gap recorded in TASK-47. testframework: ClientBot.interactBlock right-clicks a block through PlayerControllerMP.processRightClickBlock — the real CPacketPlayerTryUseItemOnBlock path — so server-side interaction code (reach checks, Block.onBlockActivated, bed trySleep) runs against the real player. artest: new 'dim time <dim>' probe — per-dimension clock readout (worldTime/totalTime/rotationalPeriod/isDaytime) with the same lazy load-and-pin semantics as the weather probes. PlanetBedSleepE2ETest: a real client sleeps in a real bed on a planet with rotationalPeriod=30000 at planet-night; the sleep skip must land on a multiple of 30000 (planetary dawn) and the overworld clock must keep ticking from its own time, proving per-dim isolation. Red-proven: with MixinWorldServer removed from the mixin config the skip lands at vanilla's 24000 — mid-night on this planet, the original Advanced-Rocketry#66 symptom — and the test fails (observed worldTime=24481).
…ptions - Entries #9-#12 (issues Advanced-Rocketry#71, Advanced-Rocketry#77, Advanced-Rocketry#76, Advanced-Rocketry#66) were fixed before their ledger rows existed; backfilled with their current pins. - Records the user-approved (2026-06-10) client-e2e exceptions per the bug-report-workflow SOP: Advanced-Rocketry#76 (no no-JEI harness profile) and the client half of Advanced-Rocketry#77 (server-tier boot pin covers the substance). - TASK-47 + README: the 'no sleeping-player harness' gap is closed by PlanetBedSleepE2ETest.
testframework grows four generic probes: use_item (real CPacketPlayerTryUseItem), report_chat (client chat overlay, i18n resolved — what the player reads), report_player_items (client-rendered held/armor/main stacks incl. NBT), report_entities (entities the client world actually sees). The three WorldCommand tests stop driving /ar through the exec-as-player server probe (the exact surrogate honest-client-e2e.md forbids) and TYPE the command in the real client chat via sendChat. Outcomes are now observed at the player layer: client position (reportState), client dimension (reportWeather), client-rendered inventory (reportPlayerItems — /ar station give chip), the chat overlay (reportChat — torch/sealant replies and vanilla player-not-found), with server probes kept only as arrange + cross-side oracles. All 8 test methods green.
…ng reads HovercraftRideE2ETest + ElevatorCapsuleRideE2ETest keep mounting as a server probe (an SOP-allowed arrange step) and drive the actual ride contracts through the real client input surface: the forward key (W) feeds MovementInput → CPacketInput → server player.moveForward → getPassengerMovingForward(), and sneak (LSHIFT) exercises the vanilla wants-to-stop-riding dismount. All riding/motion assertions now read the CLIENT view via reportRidingEntity (mount sync, ridden-entity class and id, lateral movement of the rendered craft), with the old server probes demoted to cross-side oracles. drive-ridden-entity / set-move-forward probe calls are gone from both tests. 6 methods green.
…r reads
The five item tests stop simulating right-clicks through try-* server
probes and click through the real client: useItem (CPacketPlayerTryUseItem)
for in-air uses, interactBlock for the seal detector's block target, with
held-item sync polled before each click (TheOneProbe's join-gift note
otherwise races the equip).
- ItemHovercraftSpawnE2ETest: aim via setLook + useItem; client world
entity count (report_entities) + client-rendered held stack consumption.
- OreScannerRightClickClientE2ETest: the resolved-satellite branch now
asserts the OreMapping GUI actually OPENS on the client screen — the
old probe pinned only 'no crash' and could not see that the GUI never
opened for long satellite ids (ItemOreScanner casts the stored id to
int before the registry lookup; the new arrange probe uses an int-safe
id and documents the truncation hazard).
- ItemAtmosphereAnalzerReadoutE2ETest: both readout lines asserted on the
client chat overlay, i18n resolved ('Atmosphere Type: …air',
'Breathable: yes').
- ItemSealDetectorPlayerMessagesE2ETest: fixtures lifted to open air, the
player perches next to the block and clicks it; branch replies asserted
as the resolved chat text the player reads, server mirror kept as the
cross-side oracle.
- ItemBiomeChangerSatelliteActionE2ETest: real click + posList growth via
the new poslist-size oracle.
artest grows arrange-only splits of the old combined probes
(player equip-orescanner / equip-biomechanger, satellite poslist-size);
probe-infra shape tests tied to the retired try-* stimuli are removed.
12 methods green.
…-player infra Per honest-client-e2e.md (user-approved): AdvancementsE2ETest, LowGravFallDamageE2ETest, AtmospherePlayerEventE2ETest and VacuumGuardsE2ETest drove server-side handler contracts exclusively through server probes — the client harness only supplied a connected player. They move down the pyramid as AdvancementsTriggerTest, LowGravFallDamageTest, AtmospherePlayerEventTest, VacuumGuardsTest. Player supply on the headless tier: new artest verbs - player ensure-fake <dim> <x> <y> <z> — persistent bare EntityPlayerMP (NOT a Forge FakePlayer: PlayerAdvancements.grantCriterion hard-refuses those), never spawned into a world (a connectionless player in the EntityTracker NPEs on send-to-self), invulnerable, cross-dim moves fire the same PlayerChangedDimensionEvent Forge's transfer fires; - player tick-living <n> — posts one LivingUpdateEvent per server tick, reproducing a ticking player's cadence (%20 trigger windows included). Found and fixed along the way (production hardening, all NPE-on- connectionless-player crashes any mod-spawned FakePlayer could hit): - EntityEventHandler.onJoinWorld / onPlayerChangedDimension sendPacket on null connection (+ CCE-tightening to instanceof EntityPlayerMP); - PlanetWeatherManager.syncToPlayer same; - AtmosphereHandler.onTick: effect paths (potion sync, PacketOxygenState via new AtmosphereType.sendToRealPlayer) crash the server tick loop for connectionless players in non-breathable dims — effects now skip them, cache/sync bookkeeping still runs. Also documented-by-test: 'artest server wait' executes ON the server thread, so its sleep loop blocks ticking — the relocated tests wait off-thread in the test JVM instead (probe defect noted for follow-up). 12 methods green across the four classes.
- RocketBuilderGuiE2ETest: after Scan→Build the CLIENT world must render the assembled EntityRocket (report_entities) — the spawn reaching the player's screen, not just the server registry. - ItemSpaceArmorUseFluidE2ETest / ItemSpaceChestSubInventoryDrainE2ETest / GasChargePadFillsPressureTankE2ETest: the CLIENT-rendered chest-slot NBT (report_player_items armor[2], 'air:'/'Amount:') now asserts the drain/hold/refill the suit HUD draws from, with the server probes kept as cross-side oracles. 8 methods green.
- New audits/2026-06-11-honest-e2e-delta.md: sweep verdicts (9 honest / 6 partial / 13 false-green / 1 mislabeled → all remediated), framework capabilities added, the four production FakePlayer-compat NPEs fixed, the open 'artest server wait' blocks-the-server-thread defect, and the accepted RailgunCargoTransit PARTIAL. - 2026-05-27 master audit: stale ARWeatherWorldInfoTest pin reference fixed to ARDimensionWorldInfoTest. - honest-client-e2e SOP: harness-extension section rewritten for the vendored testframework/ flow + current capability list; documented the server-wait trap.
Full-suite validation: testServer fully green (1h11m). testClient green except three load-shaped failures under sibling-session contention: GuidanceComputerGuiE2ETest and one ItemSealDetector method passed on re-run (the latter's chat poll widened to a 20-line window / 200-tick cap — harness FORGE_TEST_DONE markers share the overlay and can push the reply down); WorldCommandFetchModeratorTest's first client bridge dies at world-join only while sibling Minecraft clients hold the same display — green standalone after the rewrite, recorded in the 2026-06-11 delta as environment contention, re-check on a quiet box.
…) into feature/postponed Brings the 1.12 bug-sweep — mod-container removal, tolerant planetDefs, JEI guard, per-dim time/beds, planet weather sync, railgun Advanced-Rocketry#61 — plus TASK-45..51 docs and the vendored testframework/ build, onto the weight/wear feature line. Conflict resolution: - mixins.advancedrocketry.json: auto-merged cleanly — ARMixinPlugin (weave-gates the weather mixins) + MixinWorldServer both retained. - 4 client-e2e suites (Advancements / AtmospherePlayerEvent / LowGravFallDamage / VacuumGuards) deleted on 1.12 — accepted; coverage moved to server tier (1:1 named replacements exist). - WeatherCycleDisableTest: ARWeatherWorldInfo -> ARDimensionWorldInfo (1.12 class rename) so the probe-class assertion matches. - bug-ledger #8/#9 collision (postponed weight/TASK-45 vs 1.12 railgun/ PR#22) resolved by chronological renumber #8..#14; README pointer + inline entries + pyramid counter (regenerated 874) updated to match. compileJava + compileTestJava green (JDK25/RFG). Test suites not run.
Updates the planet-weather feature branch to current 1.12 (per-dim WorldInfo wrapper, perDimWorldInfo master switch, weight/wear). Only conflict was the bug-ledger doc: feature/better_weather had independently used ledger #8 for the canDoRainSnowIce density-scale fix, which collided with 1.12 #8 (weight-rework); renumbered chronologically to #15, matching the postponed<->1.12 convention.
Bundles several
1.12bug fixes reported upstream, plus the per-dim weather-sync fixes and the test-infrastructure work that grew out of verifying them.1. Remove vestigial dummy mod container (dercodeKoenig#71)
AdvancedRocketryPlugin) now only bootstraps mixins; itsgetASMTransformerClass()already returns empty.DummyModContainer(advancedrocketrycore) had only empty lifecycle handlers and no code referenced its modid.Changes:
getModContainerClass()returnsnull; deletedasm/ModContainer.java. Mixin + main-mod loading are driven by the jar manifest (FMLCorePlugin+FMLCorePluginContainsFMLMod) and the plugin'sIEarlyMixinLoader.Pinned by:
ModCountParityE2ETest— real client reads the exactLoaderlists the menu line renders (newreport_modsbot probe); red-proven against the restored container.2. Tolerant planetDefs.xml loading (dercodeKoenig#77)
Creating a world with a subset of mods crashed with
IndexOutOfBoundsExceptionat the<laserDrillOres>path, and the crash killed the game via a silentFMLCommonHandler.exitJava(no crash report).OreDictionary.doesOreNameExististruefor a reserved ore name even when no items are registered (providing mod not installed), sogetOres(...).get(0)hit an empty list. Plus an inconsistenttrim()and a missingcopy().copy()the prototype before mutating count.readAllPlanetsper-planet isolation) instead of aborting the whole file.loadPlanetsOrThrow, so Forge produces a normal crash report rather than silently closing the window.Pinned by:
XMLPlanetLoaderTest(reserved-but-empty ore, per-planet isolation, oregen round-trip) +PlanetDefsFaultToleranceTest(server tier: boots with a dirty file, malformed planet skipped, good planet survives). Client e2e: approved exception (the symptom is the client window closing on a server-side startup crash; the boot pin covers the substance).3. JEI NoClassDefFoundError guard (dercodeKoenig#76)
PacketDimInfo.executeClientcalledARPlugin.requestGasGiantRefresh()unconditionally.ARPlugin implements mezz.jei.api.IModPlugin, so touching it loads JEI classes andNoClassDefFoundErrors when JEI isn't installed — re-introducing dercodeKoenig#76 via the dimension-sync path (the startup path was already guarded upstream inClientProxy).Changes: wrap the call in
Loader.isModLoaded("jei"), drop the top-levelARPluginimport. Audited allintegration.jeireferences outside the package — no other unguarded live refs remain.Coverage: approved exception per the bug-report SOP — reproducing needs a client without JEI on the classpath and both harnesses always carry JEI; no no-JEI profile planned. Recorded in the bug ledger (entry #11).
4. Oregen round-trip regression pin (dercodeKoenig#73)
dercodeKoenig#73 (oregen not sticking to the worldsave) is already fixed in the
1.12base (kaduvill). Added a regression test pinningwriteXML → readAllPlanetspreserving the per-planet<oreGen>block, since that XML round-trip is the only place oregen is persisted (it is not in per-dimension NBT).5. Per-dimension time so beds work on planets (dercodeKoenig#66)
Sleeping on an AR planet skipped no time. AR planets are
WorldServerMultiwhoseWorldInfois aDerivedWorldInfo—setWorldTimeis a no-op there, so the vanilla sleep skip was silently swallowed and time never advanced. And planets render day/night fromrotationalPeriod((1/gravity)^3 * 24000, ≠ 24000 for almost every planet), so vanilla's 24000-rounded wake misses planetary dawn.WorldInfo(renamedARWeatherWorldInfo→ARDimensionWorldInfo) now owns per-dimensionworldTime/worldTotalTimeinPlanetWeatherState(NBT-persisted, seeded from the delegate on first wrap), so each dimension's day/night and sleep are independent of the overworld — in the spirit of the per-dim weather.weatherManaged(off → weather delegates to vanilla, time still per-dim).MixinWorldServer@Redirects the sleep-blocksetWorldTimeto round to the dimension'srotationalPeriod(planetary dawn) for AR worlds; non-AR worlds keep vanilla behaviour.Pinned by:
SleepWakeTimeTest(dawn math),ARDimensionWorldInfoTest(per-dim clock ownership), and the livePlanetBedSleepE2ETest— a real client sleeps in a real bed (newinteract_blockbot probe) on a 30000-tick planet; the skip must land on a multiple of 30000 while the overworld clock keeps ticking. Red-proven: withoutMixinWorldServerthe skip lands at vanilla 24000 — mid-night on that planet, the original symptom.6. Phantom-rain fade on entering a clear planet (new)
WorldServer's constructor runscalculateInitialWeather()against the vanillaDerivedWorldInfo(which delegatesisRaining()to the overworld) before the per-dim wrapper installs. A planet world (re)created while the overworld rains is born withrainingStrength = 1.0even though its per-dim weather is clear; the per-tick lerp then drags it down, streamingSPacketChangeGameState(7)to every arriving player — a ~5 s "phantom rain" fade (mostly hidden behind the loading screen on first-generation visits, which made upstream look immune in manual tests).Fix:
wrapWorldInfoIfNeededreseedsrainingStrength/thunderingStrength(direct field writes — the setters are@SideOnly(CLIENT)) from the wrapped state right after the swap.Pinned by:
WeatherBaselineTest(planets lazily constructed during overworld rain must read strength 0.0 — red-proven at 1.0 without the reseed) + a phantom-fade leg inWeatherClientSyncE2ETest(real client teleports to a never-constructed planet under overworld rain; client-visiblerainStrengthmust hold at exactly 0 across the would-be fade window).7. Vanilla /weather redirected to the per-dim variant on planets (new)
Vanilla
CommandWeatherhard-codesserver.worlds[0]: run while standing on an AR planet it silently mutates the overworld's weather and leaves the planet untouched — with per-dim weather there was no command-level way to change a planet's weather at all. Ports theCommandEventredirect from the upstream per-dim weather PR (authored by jchung01; the/advancedrocketry weathersubcommand itself was already ported): on an AR planet, vanilla/weatheris cancelled and re-issued as/advancedrocketry weatherwith the same arguments.Pinned by:
WeatherCommandRedirectE2ETest— a real client on a planet types/weather rainvia the newsend_chatbot probe (realCPacketChatMessage, so the server sees a player sender); the planet rains, the client renders it, the overworld stays clear. Red-proven: with the redirect reverted the planet never starts raining.8. Test framework vendored + merge of
1.12testframework/(history preserved) and compiles inside the test source set; the published artifact + sibling-checkoutpublishToMavenLocalstep are gone from the build. The external repo lives on for other consumers. Three bot capabilities were added in lockstep with the tests above:send_chat,report_mods,interact_block; plus anartest dim time <dim>per-dim clock probe.1.12brings the standalone-client launch fix (mixins registered via MixinBooter'sIEarlyMixinLoader; the coremod no longer touches Spongepowered classes on the AppClassLoader). Conflict resolved keeping this branch'sgetModContainerClass() = null(see fix 1).Backlog filed (not in this PR)
<oreGen>clumpSize/chancePerChunkclamp to a floor of 1 (and empty<oreGen>falls through to the global default), making "disable this ore per planet" inexpressible — likely the real cause behind [BUG] Ore generation does not respect config. dercodeKoenig/AdvancedRocketry#73's "zeroing veins still spawns ore".CompatibilityMgris vestigial; kept pending a revive-vs-remove decision.WorldInfostate per-dimension (GameRules incl.doDaylightCycle/doWeatherCycle, spawn, difficulty…) — feature request, needs design.Tests
All four suites green on this branch:
testUnit,testIntegration,testServer(incl. the weather set +CommandsSmokeTest),testClient(real-client e2e).Per the bug-report SOP, every fix above carries either reproduction-grade pins (red-proven where noted) or an explicitly approved exception, and the bug ledger (entries #9–#12) records both. New tests in this PR:
ModCountParityE2ETest,PlanetDefsFaultToleranceTest,PlanetBedSleepE2ETest,WeatherCommandRedirectE2ETest, theWeatherClientSyncE2ETestphantom-fade leg,WeatherBaselineTeststrength pins,SleepWakeTimeTest,ARDimensionWorldInfoTest,XMLPlanetLoaderTestore/malformed/round-trip cases.Related
NoClassDefFoundError: zmaster587/advancedRocketry/integration/jei/ARPlugindercodeKoenig/AdvancedRocketry#76Test plan
./gradlew compileJava— green./gradlew testUnit testIntegration— green./gradlew testServerweather/commands/planet subset — greenModCountParityE2ETest)PlanetDefsFaultToleranceTest)PlanetBedSleepE2ETest)/weatheron a planet rains the planet, not the overworld — automated (WeatherCommandRedirectE2ETest)NoClassDefFoundError: ARPluginon world join (approved automation exception — harness always carries JEI)