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) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-13 18:48:01 +02:00
parent a6e4b5709f
commit 08be296dcd

View file

@ -3766,11 +3766,22 @@ public sealed class GameWindow : IDisposable
/// </summary>
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)