
652
21
Biome Cleaner 1.0.2 for NeoForge 1.21.1
Release2 нед. назад
Список изменений
Fixed
- Non-deterministic cleanup from CI cache contamination (algorithm-core): When
checkNeighborStability's retry loop excluded a cycling region and found a different region of the same biome, the result was cached as context-independent (CI). Concurrent threads could read a stale CI entry computed under a different visiting set, producing non-deterministic output. Retry-dependent results are now propagated as context-dependent. - Width check always classifies all quarts as thin (algorithm-core): The width BFS search range (
widthThreshold / 2) produced a maximum computed width exactly equal to the threshold. Combined with the<=comparison, every quart was classified as thin, causing universal 8-connectivity and making the width cache pure overhead. Increased BFS range by +1 so interior quarts correctly use 4-connectivity. - Phase 2 exploration budget ignores per-biome threshold (algorithm-core): Phase 2 exploration used the global
sizeThresholdinstead of the per-biome override passed as a parameter. Regions between the global and per-biome thresholds were incorrectly classified as stable. Phase 2 now uses the per-biome threshold directly. - Thread pool double-decrement on scale-down (warmup):
activeThreadCountwas decremented twice when a worker exited via the scale-down path — once in the scale-down check and again in thefinallyblock. AddedscaleDownExitflag so thefinallyblock only decrements for shutdown exits. - Thread pool shutdown deadlock (warmup):
shutdown()heldworkerLockduringThread.join(), but workerfinallyblocks needed the same lock forworkers.remove(). Workers blocked for the full 5-second join timeout on every shutdown. Now snapshots the worker list and joins without holding the lock. - Warming queue submit race loses FULL tasks (warmup): Non-atomic get-then-put in
submit()allowed concurrent LIGHT submissions to overwrite FULL tasks for the same chunk position. Replaced withConcurrentHashMap.compute()for atomic deduplication. - Warming queue poll ABA race deletes new task mapping (warmup):
poll()used one-argremove(posKey)which unconditionally deleted the mapping, destroying new tasks submitted between the get and remove. Changed to two-argremove(posKey, task)consistent with other removal paths. - Cone angle rules 3 & 4 inversion (warmup): Rules 3 and 4 increased
coneAngleto "widen" the cone, but lowerconeAngleactually produces a more negativecosTrailingThresholdwhich includes more chunks. The rules were narrowing when they should widen, creating a positive feedback loop. Also added!adjustedguard to Rule 3 to prevent double-stepping with Rule 2. - Last player chunk position overwrites in multiplayer (warmup): Single static
lastPlayerChunkPoswas overwritten per player during the tick loop, so JFRchunkDistancemetrics used only the last player's position. Now stores all player positions and computes distance to the nearest player. - Per-player queue pruning destroys other players' tasks (warmup):
removeOutsideRadius()pruned the global queue using a single player's position, removing all other players' tasks. AddedremoveOutsideAllPlayers()that only removes tasks outside ALL players' radii, with the coordinator batching all requests per cycle for a single pruning pass. - Global tuning with aggregate multiplayer metrics (warmup): Aggregate hit/miss/late metrics diluted individual player problems — one player's poor metrics were hidden by other players' good metrics. Tuning thresholds now scale by player count to detect when any single player would trigger the rule.
- Prepared store capacity insufficient for multiplayer (warmup): Fixed 5000-entry
BoundedPreparedChunkStorewas shared across all players. At 8+ players, FIFO eviction removed prepared results before consumption. Capacity is now dynamic:max(5000, playerCount * 700). - Reached chunks unbounded memory growth (warmup):
reachedChunksset grew without bound, accumulating ~72 bytes per chunk with no eviction. Added periodic distance-based eviction (every ~50 seconds) that removes entries far from all online players. - Cave carver surface uses wrong biome (cleaner-mod): Carvers re-applied surface rules using the raw
BiomeSourceinstead of the mod-modified chunk palette, causing wrong surface blocks at cave entrances (e.g., snow in birch forest). NewCarverBiomeMixinredirectsBiomeManager.withDifferentSource()inapplyCarvers()to use the chunk palette biomes. - Climate sampler mismatch causes non-deterministic cleanup (algorithm-core): The algorithm's noise function uses
randomState.sampler()(flattened, no interpolation), while vanilla'sfillBiomesFromNoiseusesNoiseChunk.cachedClimateSampler()(bilinearly interpolated within cells). At biome boundaries, these samplers can resolve a quart to different biomes, causing the chunk palette and the algorithm's view to disagree. When the algorithm processes the quart first with the wrong biome, it writes a stale entry to the sharedStabilityCache, which then poisons later chunks that need to replace the true palette biome. Whether the bug manifests depends on chunk processing order (affected by warming timing and player movement), breaking determinism. Fix:ChunkCleanupEngine.process()now scans each chunk's palette before algorithm execution, overrides mismatchedNoiseCacheentries via the newNoiseCache.overrideEntry(), and tracks affected quarts in asamplerMismatchQuartsset soprocessSingleQuartskips any stale stability cache entries for them.
Файлы
biomecleaner-mc1.21.1-1.0.2-neoforge.jar(201.23 KiB)
ОсновнойМетаданные
Канал релиза
Release
Номер версии
1.0.2
Загрузчики
NeoForge
Версии игры
1.21.1
Загрузок
55
Дата публикации
2 нед. назад
