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:
Erik 2026-07-21 09:01:02 +02:00
parent d2bb5af453
commit 5acc3f01cf
23 changed files with 2635 additions and 168 deletions

View file

@ -6,7 +6,13 @@ namespace AcDream.App.Interaction;
internal interface IPlayerInteractionMovementSink
{
bool BeginApproach(InteractionApproach approach);
/// <summary>
/// Cancels any preceding MoveTo, invokes <paramref name="armAfterCancel"/>,
/// then installs the new movement. The callback boundary lets the intent
/// owner arm completion state before an already-facing TurnTo can finish
/// synchronously, without letting the preceding cancellation clear it.
/// </summary>
bool BeginApproach(InteractionApproach approach, Action? armAfterCancel = null);
}
/// <summary>
@ -20,7 +26,7 @@ internal sealed class PlayerInteractionMovementSink(
private readonly Func<PlayerMovementController?> _player = player
?? throw new ArgumentNullException(nameof(player));
public bool BeginApproach(InteractionApproach approach)
public bool BeginApproach(InteractionApproach approach, Action? armAfterCancel = null)
{
PlayerMovementController? controller = _player();
if (controller?.MoveTo is null)
@ -47,11 +53,16 @@ internal sealed class PlayerInteractionMovementSink(
Height = approach.TargetHeight,
};
// PerformMovement cancels at its head. Do it explicitly before the
// intent is armed so cancellation of the preceding move cannot clear
// the new request; the internal second call is then a retail no-op.
controller.Movement.CancelMoveTo(WeenieError.ActionCancelled);
armAfterCancel?.Invoke();
// P1's wire MoveToObject store marks the command non-autonomous.
// The speculative local install must do the same or the next raw-input
// pump overwrites it before ACE's authoritative movement arrives.
controller.SetLastMoveWasAutonomous(false);
controller.Movement.PerformMovement(movement);
return true;
return controller.Movement.PerformMovement(movement) == WeenieError.None;
}
}