fix(interaction): bind selection to live incarnations

Carry local WorldEntity identity through render hits, lighting pulses, and deferred movement actions so GUID reuse cannot target a replacement. Reset all session-owned selection and ItemHolder state and prevent combat auto-target during teardown.
This commit is contained in:
Erik 2026-07-21 07:07:58 +02:00
parent c271383714
commit 047a4c83b5
19 changed files with 374 additions and 42 deletions

View file

@ -808,6 +808,9 @@ public sealed class LiveEntityRuntimeTests
guid, 0x01010001u, id => Entity(id, guid))!;
Assert.NotEqual(first.Id, second.Id);
Assert.False(runtime.TryGetInteractionEligibleRecord(guid, first.Id, out _));
Assert.True(runtime.TryGetInteractionEligibleRecord(guid, second.Id, out var current));
Assert.Same(second, current.WorldEntity);
Assert.Equal(2, resources.RegisterCount);
Assert.Equal(1, resources.UnregisterCount);
}
@ -1428,6 +1431,7 @@ public sealed class LiveEntityRuntimeTests
Assert.False(entity.IsDrawVisible);
Assert.Empty(runtime.WorldEntities);
Assert.False(runtime.TryGetInteractionEligibleEntity(guid, out _));
Assert.False(runtime.TryGetInteractionEligibleRecord(guid, entity.Id, out _));
Assert.True(runtime.TryApplyState(new SetState.Parsed(
guid,
@ -1437,6 +1441,9 @@ public sealed class LiveEntityRuntimeTests
Assert.Equal(RetailHiddenTransition.BecameVisible, visible.HiddenTransition);
Assert.True(entity.IsDrawVisible);
Assert.True(runtime.TryGetInteractionEligibleEntity(guid, out var eligible));
Assert.True(runtime.TryGetInteractionEligibleRecord(guid, entity.Id, out var eligibleRecord));
Assert.Same(entity, eligibleRecord.WorldEntity);
Assert.False(runtime.TryGetInteractionEligibleRecord(guid, entity.Id + 1u, out _));
Assert.Same(entity, eligible);
Assert.Same(entity, Assert.Single(runtime.WorldEntities).Value);
Assert.Same(entity, Assert.Single(spatial.Entities));