diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 5cd2ec4b..9c06063f 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -6248,6 +6248,42 @@ outdoors at the angle that previously erased it. # Recently closed +## #192 — Login to a non-Holtburg position sometimes showed stabs/scenery floating in the wrong place + +**Status:** DONE (2026-07-09, `fa9aedca`, user visual gate passed: "Looks good"). User-reported +while testing tonight's A7 lighting/particle fixes; traced via a threading/lifecycle read of the +login path, not inference. `WorldSession` transitions to `InWorld` immediately after the login +handshake (`WorldSession.cs:608`) — well before the player's own spawn `CreateObject` (which +carries their real position) has arrived over the network. The streaming gate's old condition +(`!IsLiveModeWaitingForLogin || liveInWorld`) opened the instant `InWorld` fired, letting the +background streaming worker (`LandblockStreamer`'s dedicated `Thread`) build real landblocks +using whatever `_liveCenterX/Y` held at that moment — the Holtburg startup placeholder, not a +"not known yet" sentinel. A landblock that started building in that window bakes its world +offset from that placeholder at build time; if the build was still in flight when the real spawn +arrived and recentered the world (`ForceReloadWindow`, which only unloads already-*resident* +landblocks), it finished and got applied anyway — stale-positioned geometry landing wherever the +guess put it relative to whatever streamed in afterward with the corrected center. Explains both +observed traits: "sometimes" (depends on whether a pre-real-data build happened to be mid-flight +at the exact recenter moment — a genuine timing race) and specifically at login to a +non-Holtburg position (nothing to race against if the real spawn coincides with the placeholder). +User explicitly pushed back on "just use a different/no placeholder" — correctly: any placeholder +racing against the real answer reproduces the identical bug. Fix: +`AcDream.Core.World.StreamingReadinessGate.ShouldStream` requires an explicit `liveCenterKnown` +flag (true only once the player's own spawn has been processed) in addition to `liveInWorld` — +nothing streams in live mode until the real position is confirmed, so no placeholder value is +ever acted upon. Preserves the pre-existing `#106` gate-3 fix this gate originally existed for +(auto-entry waits for terrain under the spawn; terrain streaming must not wait for chase mode in +turn, or the two deadlock) since `liveCenterKnown` becomes true independently of chase mode, +driven purely by the spawn packet's arrival. The stricter render gate (`GameWindow.cs:9596`, +hides ALL world geometry until chase mode engages) was already a partial safety net and is +unchanged — this fix stops the stale geometry from ever being *built*, rather than relying on the +render gate to hide it until the reveal. Files: `src/AcDream.Core/World/StreamingReadinessGate.cs` +(pure, unit-tested gate predicate — the regression test asserts `liveInWorld` alone must NOT open +the gate), `src/AcDream.App/Rendering/GameWindow.cs` (`_liveCenterKnown` flag + call site). Core +2680+2skip / App 741+2skip / UI 425 / Net 385 green. + +--- + ## #93 — Indoor lighting broken (M1.5 lighting umbrella) **Status:** DONE (2026-07-09). Two real root causes found + fixed (A7.L1): (1)