3.9 KiB
Changelog — Dynmap NeoForge 1.21.1 Port
All changes relative to the upstream neoforge-1.20.6 module.
[2026-03-07] — Final clean state (pre-PR)
Reverted
touchChunk()helper method extraction — inlined back to match 1.20.6 structure- Was purely cosmetic; upstream CONTRIBUTING.md prohibits refactoring in PRs
- No behavior change, no runtime impact
Fixed — whitespace
ForgeMapChunkCache.java— formatting-only diffs corrected to match 1.20.6 style
[2026-03-07] — canOcclude() deadlock fix
Changed
DynmapPlugin.initializeBlockStates()(lines ~248, ~259):isSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)→canOcclude()propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)→isAir()isSolid()→canOcclude()
Why
isSolidRender() / propagatesSkylightDown() / isSolid() all trigger a Guava
LoadingCache lookup in ModernFix's reduce_blockstate_cache_rebuilds mixin. During
world load with modernfix + ferritecore (present in ATM10), this causes a
BlockState$Cache.<init> deadlock — lazy/deferred block state initialization enters
an infinite loop in VoxelShape calculation for certain complex mod block states.
The watchdog kills the server after ~60 seconds.
canOcclude() and isAir() read precomputed booleans directly from the block state
with no cache involvement. Functionally equivalent for Dynmap's purposes, safe with
all mods including modernfix and ferritecore.
Test result
- ✅ ATM10 5.5, 445 mods, NeoForge 21.1.219 — 3/3 clean boots
- ✅
[Dynmap] version 3.7-SNAPSHOT-Dev is enabled - ✅ 17 worlds loaded, web server started on 0.0.0.0:8123
[2026-03-07] — Runtime fixes + build improvements
Fixed — API changes (1.21.1)
DynmapPlugin:ServerTickEventlistener updated toServerTickEvent.Post- NeoForge 21.x made
ServerTickEventabstract; registering the base class no longer works
- NeoForge 21.x made
DynmapPlugin.initializeBlockStates(): replacedisSolidRender(null, ...)withisSolidRender(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)- 1.21.1 actually uses the BlockGetter parameter; passing null causes NPE
- (Superseded by canOcclude() fix above — kept here for history)
DynmapPlugin:getLastAvailable()→getLatestChunk()— API renamedDynmapPlugin:getStatus()→getPersistedStatus()— API renamedDynmapPlugin:ChatHandlerinner class → direct method withaddListener()- NeoForge 1.21.1 changed event registration; inner class pattern no longer supported
NBT.java:contains()reimplemented with manual type checking (behavior changed in 1.21.1)NBT.java:getAsString()null safety added (behavior changed in 1.21.1)
Fixed — Build
build.gradle: userdev plugin 7.0.133 → 7.1.20 (NeoForge 21.1.x requirement)build.gradle: NeoForge dep 20.6.62-beta → 21.1.219gradle-wrapper.properties: 8.7 → 8.14 (required for userdev 7.1.20)- All
fabric-*/build.gradle: loom 1.6.11 → 1.8.13 (required for Gradle 8.14 compat) neoforge.mods.toml: loader/version ranges updated for 1.21.1- Access transformer: SRG names → mojmap names
- Heap caps: Gradle daemon
-Xmx2g, forked javac-Xmx3g
⚠️ Known discrepancy (from earlier commit message)
- An early commit message claimed
visibleChunkMapwas replaced withgetChunks() - This was inaccurate.
visibleChunkMapis still in the code and works fine in NeoForge 1.21.1
[2026-03-07] — Initial 1.21.1 compile fix pass
Fixed — Compile errors (43 total)
- All compile errors resolved from
neoforge-1.20.6→neoforge-1.21.1baseline:net.minecraftforge.*→net.neoforged.*(full package migration)MinecraftForge.EVENT_BUS→NeoForge.EVENT_BUS- Access transformer updated for 1.21.1 private field patterns
Format note
Entries are dated by session (not release), since this is a port-in-progress.