From c5f98b276ed757c417f2dfd2966d4b3c3478d96b Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 10 May 2026 07:25:07 +0200 Subject: [PATCH] =?UTF-8?q?fix(A.5=20T7-T9):=20migrate=20entity.Position?= =?UTF-8?q?=3D=20=E2=86=92=20SetPosition;=20add=20Promoted=20arm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code review on commits 295bce9/a0741bd/4be392b flagged 1 Important + 3 Minor issues. Apply the actionable two: Important: 6 sites in GameWindow.cs (lines 3900, 4017-4024, 4138, 4270, 4315) wrote entity.Position = X directly, bypassing T8's SetPosition mutator and therefore never marking AabbDirty. When T18 lands the dispatcher's "if AabbDirty refresh" cull gate, these direct writes would silently leave AABB stale (frustum culls dynamic entities at their previous positions). Migrated all 6 sites to SetPosition(). Minor: Added a silent case LandblockStreamResult.Promoted arm in StreamingController.Tick with a TODO(A.5 T13) marker. Today the streamer never produces Promoted, so the arm is unreachable; the explicit case prevents a future reader from wondering why the case is missing. Deferred Minor: surfaceCache thread-safety XML doc comment + style consistency on System.Collections.Generic using directive — non- load-bearing cosmetic. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/AcDream.App/Rendering/GameWindow.cs | 14 +++++++------- src/AcDream.App/Streaming/StreamingController.cs | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 7c53a03..2e3e849 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -3897,7 +3897,7 @@ public sealed class GameWindow : IDisposable // position by adding the residual back (so the visual doesn't jerk // for one frame before the residual decay kicks in on the next tick). System.Numerics.Vector3 preSnapPos = entity.Position; - entity.Position = worldPos; + entity.SetPosition(worldPos); entity.Rotation = rot; // Commit B 2026-04-29 — keep the shadow registry in sync with @@ -4017,11 +4017,11 @@ public sealed class GameWindow : IDisposable if (!update.IsGrounded) { // Undo the unconditional entity hard-snap at the top of the - // function (entity.Position = worldPos): the body is mid-arc + // function (entity.SetPosition(worldPos)): the body is mid-arc // and TickAnimations will write entity = body next frame // anyway. Setting entity = body now prevents a 1-frame // teleport-to-server-then-yank-back rubber-band. - entity.Position = rmState.Body.Position; + entity.SetPosition(rmState.Body.Position); return; } @@ -4130,12 +4130,12 @@ public sealed class GameWindow : IDisposable } // Sync the visible entity to the body — overrides the unconditional - // entity.Position = worldPos snap at the top of this function. + // entity.SetPosition(worldPos) snap at the top of this function. // For the far-snap branch this is a no-op (body == worldPos); for // the near-enqueue branch this prevents a 1-frame teleport-then- // yank-back rubber-band as TickAnimations chases worldPos via the // queue. - entity.Position = rmState.Body.Position; + entity.SetPosition(rmState.Body.Position); return; } @@ -4267,7 +4267,7 @@ public sealed class GameWindow : IDisposable rmState.ServerVelocity); } - entity.Position = rmState.Body.Position; + entity.SetPosition(rmState.Body.Position); entity.Rotation = rmState.Body.Orientation; } @@ -4312,7 +4312,7 @@ public sealed class GameWindow : IDisposable resolved.Position.X, resolved.Position.Y, resolved.Position.Z); // 3. Snap player entity + controller. - entity.Position = snappedPos; + entity.SetPosition(snappedPos); entity.Rotation = rot; _playerController.SetPosition(snappedPos, resolved.CellId); diff --git a/src/AcDream.App/Streaming/StreamingController.cs b/src/AcDream.App/Streaming/StreamingController.cs index c320429..53b0030 100644 --- a/src/AcDream.App/Streaming/StreamingController.cs +++ b/src/AcDream.App/Streaming/StreamingController.cs @@ -107,6 +107,12 @@ public sealed class StreamingController Console.WriteLine( $"streaming: worker CRASHED: {crashed.Error}"); break; + case LandblockStreamResult.Promoted: + // TODO(A.5 T13): merge promoted entities into existing + // GpuWorldState entry via AddEntitiesToExistingLandblock. + // Today the streamer never produces Promoted (only LoadNear / + // LoadFar), so this arm is unreachable and silently consumed. + break; } } }