fix(interaction): close selection lifecycle review gaps
Bind queued actions and pending inventory requests to exact live incarnations, separate optimistic placement from authoritative responses, and serialize retail-style inventory ownership across UI surfaces. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
d2bb5af453
commit
5acc3f01cf
23 changed files with 2635 additions and 168 deletions
|
|
@ -32,6 +32,9 @@ public sealed class WorldSelectionQueryTests
|
|||
public RetailSelectionMesh? Resolve(uint gfxObjId) => mesh;
|
||||
}
|
||||
|
||||
private sealed record Animation(WorldEntity Entity, uint CurrentMotion)
|
||||
: ILiveEntityAnimationRuntime;
|
||||
|
||||
private sealed class Harness
|
||||
{
|
||||
public readonly ClientObjectTable Objects = new();
|
||||
|
|
@ -131,6 +134,41 @@ public sealed class WorldSelectionQueryTests
|
|||
Assert.Null(h.Query.PickAtCursor(includeSelf: false));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(2)]
|
||||
public void PickRejectsPublishedPartAfterVisibilityLifetimeEnds(int transition)
|
||||
{
|
||||
var h = new Harness();
|
||||
WorldEntity target = h.Add(Target, new Vector3(0f, 0f, -5f), ItemType.Misc);
|
||||
h.Publish(target);
|
||||
Assert.Equal(Target, h.Query.PickAtCursor(includeSelf: false));
|
||||
|
||||
switch (transition)
|
||||
{
|
||||
case 0:
|
||||
Assert.True(h.Runtime.TryApplyState(
|
||||
new SetState.Parsed(
|
||||
Target,
|
||||
(uint)(PhysicsStateFlags.ReportCollisions | PhysicsStateFlags.Hidden),
|
||||
InstanceSequence: 1,
|
||||
StateSequence: 2),
|
||||
out _));
|
||||
break;
|
||||
case 1:
|
||||
Assert.True(h.Runtime.WithdrawLiveEntityProjection(Target));
|
||||
break;
|
||||
default:
|
||||
Assert.True(h.Runtime.UnregisterLiveEntity(
|
||||
new DeleteObject.Parsed(Target, 1),
|
||||
isLocalPlayer: false));
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.Null(h.Query.PickAtCursor(includeSelf: false));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClosestTargetIncludesOnlyVisibleLivingHostileMonsters()
|
||||
{
|
||||
|
|
@ -150,6 +188,43 @@ public sealed class WorldSelectionQueryTests
|
|||
new Vector3(1f, 0f, 0f),
|
||||
ItemType.Misc,
|
||||
SelectedObjectHealthPolicy.BfAttackable);
|
||||
h.Add(
|
||||
0x7000_0013u,
|
||||
new Vector3(3f, 0f, 0f),
|
||||
ItemType.Creature,
|
||||
SelectedObjectHealthPolicy.BfAttackable | SelectedObjectHealthPolicy.BfPlayer);
|
||||
WorldEntity pet = h.Add(
|
||||
0x7000_0014u,
|
||||
new Vector3(4f, 0f, 0f),
|
||||
ItemType.Creature,
|
||||
SelectedObjectHealthPolicy.BfAttackable);
|
||||
h.Objects.Get(pet.ServerGuid)!.PetOwnerId = Player;
|
||||
WorldEntity dead = h.Add(
|
||||
0x7000_0015u,
|
||||
new Vector3(5f, 0f, 0f),
|
||||
ItemType.Creature,
|
||||
SelectedObjectHealthPolicy.BfAttackable);
|
||||
h.Runtime.SetAnimationRuntime(
|
||||
dead.ServerGuid,
|
||||
new Animation(dead, MotionCommand.Dead));
|
||||
WorldEntity hidden = h.Add(
|
||||
0x7000_0016u,
|
||||
new Vector3(6f, 0f, 0f),
|
||||
ItemType.Creature,
|
||||
SelectedObjectHealthPolicy.BfAttackable);
|
||||
Assert.True(h.Runtime.TryApplyState(
|
||||
new SetState.Parsed(
|
||||
hidden.ServerGuid,
|
||||
(uint)(PhysicsStateFlags.ReportCollisions | PhysicsStateFlags.Hidden),
|
||||
InstanceSequence: 1,
|
||||
StateSequence: 2),
|
||||
out _));
|
||||
WorldEntity pending = h.Add(
|
||||
0x7000_0017u,
|
||||
new Vector3(7f, 0f, 0f),
|
||||
ItemType.Creature,
|
||||
SelectedObjectHealthPolicy.BfAttackable);
|
||||
Assert.True(h.Runtime.WithdrawLiveEntityProjection(pending.ServerGuid));
|
||||
|
||||
ClosestCombatTarget? closest = h.Query.FindClosestHostileMonster();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue