From 08be296dcd4c67307fa6fe1532a32c832ed129d0 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 13 May 2026 18:48:01 +0200 Subject: [PATCH] fix(phys L.2g slice 1c): translate ServerGuid -> entity.Id for ShadowObjectRegistry B.4b visual test revealed the L.2g pipeline was a phantom: - Server SetState arrives with parsed.Guid = ServerGuid (0x7A9B4015) - ShadowObjectRegistry keys by local entity.Id (0x000F4245) - UpdatePhysicsState(0x7A9B4015, ...) misses the lookup -> no-op - Cached state stays 0x00010008 forever - CollisionExemption.ShouldSkip sees the unchanged state - Door keeps blocking the player Translate in OnLiveStateUpdated by looking up the WorldEntity via _entitiesByServerGuid and using entity.Id as the registry key. Also extends the [setstate] diagnostic to include entityId=0x... so the next visual-test grep can confirm the translation lands. This was the actual blocker the user reported as "I cant go through it" -- ACE was flipping ETHEREAL, our pipeline acknowledged it in the diagnostic, but the cached state for the resolver-side check never moved. Both L.2g slice 1's unit tests and slice 1b's collision exemption widening were correct in isolation; the integration between them was broken by the ID-space mismatch. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/AcDream.App/Rendering/GameWindow.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 292c6b5..8e0fa7b 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -3766,11 +3766,22 @@ public sealed class GameWindow : IDisposable /// private void OnLiveStateUpdated(AcDream.Core.Net.Messages.SetState.Parsed parsed) { - _physicsEngine.ShadowObjects.UpdatePhysicsState(parsed.Guid, parsed.PhysicsState); + // L.2g slice 1c (2026-05-13): the server addresses entities by + // ServerGuid (parsed.Guid, e.g. 0x7A9B4015), but + // ShadowObjectRegistry's cell index is keyed by local entity.Id + // (e.g. 0x000F4245). Translate via _entitiesByServerGuid before + // mutating the registry — otherwise the lookup misses and the + // state flip silently no-ops, leaving doors blocked even though + // ACE flipped the ETHEREAL bit. + uint registryKey = parsed.Guid; + if (_entitiesByServerGuid.TryGetValue(parsed.Guid, out var entity)) + registryKey = entity.Id; + + _physicsEngine.ShadowObjects.UpdatePhysicsState(registryKey, parsed.PhysicsState); if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeBuildingEnabled) Console.WriteLine(System.FormattableString.Invariant( - $"[setstate] guid=0x{parsed.Guid:X8} state=0x{parsed.PhysicsState:X8} instSeq={parsed.InstanceSequence} stateSeq={parsed.StateSequence}")); + $"[setstate] guid=0x{parsed.Guid:X8} entityId=0x{registryKey:X8} state=0x{parsed.PhysicsState:X8} instSeq={parsed.InstanceSequence} stateSeq={parsed.StateSequence}")); } private static bool IsRemoteLocomotion(uint motion)