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)