Fix ChunkStreamer.EnsureLoadedAround leaving pre-warmed chunks stuck
EnsureLoadedAround skipped Get() for any active chunk already in _inflight. That worked for the MonoGame TacticalRenderer, which calls Get() during its own draw loop and incidentally drains pre-warm tasks. But subscribers to OnChunkLoaded (e.g. the Godot port) saw no event when a previously-pre-warmed chunk transitioned into the active set on a later frame — the chunk stayed in _inflight forever, presenting as permanently-uncached gaps in the rendered world. Fix: drop the !_inflight.ContainsKey(cc) guard. Get() already handles all three paths (cache hit, inflight drain, fresh generate), so passing every active chunk through Get() guarantees OnChunkLoaded fires once per chunk regardless of how it was scheduled. Same flavour of bug as M1's MoistureGen FastNoiseLite race — cross-process / event-driven consumers exercise paths the in-process pull-based test fixtures never hit. 708/708 tests still pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -127,12 +127,19 @@ public sealed class ChunkStreamer
|
|||||||
active.Add(new ChunkCoord(cx, cy));
|
active.Add(new ChunkCoord(cx, cy));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Synchronously generate any missing active chunks (the player needs
|
// Synchronously make every active chunk live in the cache. Get()
|
||||||
// them this frame). Pre-warm the next ring on the threadpool.
|
// handles all three paths: hit cache, drain a pre-warmed inflight
|
||||||
|
// task, or generate fresh. The previous version skipped chunks in
|
||||||
|
// _inflight, which left them stuck there indefinitely once they
|
||||||
|
// entered the active set on a later frame — visible to renderers
|
||||||
|
// that subscribe to OnChunkLoaded (e.g. the Godot port) as
|
||||||
|
// permanently-uncached gaps. The MonoGame TacticalRenderer dodged
|
||||||
|
// this by calling Get() inside its draw loop; M4 of the port made
|
||||||
|
// that drain unnecessary by fixing it here.
|
||||||
foreach (var cc in active)
|
foreach (var cc in active)
|
||||||
{
|
{
|
||||||
if (!_cache.ContainsKey(cc) && !_inflight.ContainsKey(cc))
|
if (!_cache.ContainsKey(cc))
|
||||||
_ = Get(cc); // synchronous generate + cache
|
_ = Get(cc); // hits cache, drains inflight, or generates
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int cy = centre.Y - chunkRadius - 1; cy <= centre.Y + chunkRadius + 1; cy++)
|
for (int cy = centre.Y - chunkRadius - 1; cy <= centre.Y + chunkRadius + 1; cy++)
|
||||||
|
|||||||
Reference in New Issue
Block a user