fix(items): preserve wand stance and corpse use order
Keep active-combat AutoWield intent through ACE's pre-wield transition and queued trailing peace notice, while allowing explicit combat input to supersede it. Queue one-shot item interactions until the frame's movement edge has been serialized, so a movement release cannot cancel ACE's server-side corpse approach callback. Release build succeeds and all 5,890 runnable tests pass with five intentional skips. Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
parent
0392c6d721
commit
e6dd8bf6fa
10 changed files with 303 additions and 22 deletions
|
|
@ -165,6 +165,7 @@ public sealed class GameWindow : IDisposable
|
|||
private readonly AcDream.App.Physics.RemotePhysicsUpdater _remotePhysicsUpdater;
|
||||
private readonly AcDream.App.Input.LocalPlayerProjectionController _localPlayerProjection;
|
||||
private readonly AcDream.App.Input.LocalPlayerOutboundController _localPlayerOutbound;
|
||||
private readonly AcDream.App.Input.OutboundInteractionQueue _outboundInteractions = new();
|
||||
private readonly AcDream.App.Input.RetailLocalPlayerFrameController _localPlayerFrame;
|
||||
private readonly AcDream.App.World.RetailLiveFrameCoordinator _liveFrameCoordinator;
|
||||
private AcDream.App.Physics.RemoteTeleportController? _remoteTeleportController;
|
||||
|
|
@ -2917,6 +2918,7 @@ public sealed class GameWindow : IDisposable
|
|||
_magicRuntime?.Reset();
|
||||
_itemInteractionController?.ClearBusy();
|
||||
_selection.Reset();
|
||||
_outboundInteractions.Clear();
|
||||
_pendingPostArrivalAction = null;
|
||||
_particleVisibility.Reset();
|
||||
try
|
||||
|
|
@ -10775,6 +10777,12 @@ public sealed class GameWindow : IDisposable
|
|||
// remote objects. Its outbound movement snapshot is completed here,
|
||||
// before SmartBox dispatch can apply F751/ForcePosition.
|
||||
_localPlayerFrame.AdvanceBeforeNetwork(dt);
|
||||
// Retail input ordering: movement edges reach MoveToState before a
|
||||
// later Use/PickUp action from the same input frame. ACE cancels an
|
||||
// active server MoveTo chain when it receives MoveToState, so sending
|
||||
// Use directly from Silk's key callback inverted that order and left
|
||||
// the client walking to a corpse whose server callback was cancelled.
|
||||
_outboundInteractions.Drain();
|
||||
_scriptRunner?.PublishTime(_physicsScriptGameTime);
|
||||
if (_liveEntities is { } liveEntities)
|
||||
{
|
||||
|
|
@ -12966,7 +12974,7 @@ public sealed class GameWindow : IDisposable
|
|||
|
||||
case AcDream.UI.Abstractions.Input.InputAction.SelectionPickUp:
|
||||
if (_selection.SelectedObjectId is uint pickupTarget)
|
||||
SendPickUp(pickupTarget);
|
||||
_outboundInteractions.Enqueue(() => SendPickUp(pickupTarget));
|
||||
else
|
||||
_debugVm?.AddToast("Nothing selected");
|
||||
break;
|
||||
|
|
@ -13004,6 +13012,7 @@ public sealed class GameWindow : IDisposable
|
|||
var nextMode = AcDream.Core.Combat.CombatInputPlanner.ToggleMode(
|
||||
Combat.CurrentMode,
|
||||
defaultMode);
|
||||
_itemInteractionController?.NotifyExplicitCombatModeRequest();
|
||||
_liveSession.SendChangeCombatMode(nextMode);
|
||||
Combat.SetCombatMode(nextMode);
|
||||
string text = $"Combat mode {nextMode}";
|
||||
|
|
@ -13237,7 +13246,15 @@ public sealed class GameWindow : IDisposable
|
|||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[B.7] pick-info guid=0x{guid:X8} itemType=0x{rawItemType:X8} pwd=0x{pwdBits:X8} use={useStr} useRadius={radStr} scale={pickScale:F2} setup={setupStr} color=({col.R},{col.G},{col.B})"));
|
||||
_debugVm?.AddToast($"Selected: {label}");
|
||||
if (useImmediately) SendUse(guid);
|
||||
if (useImmediately)
|
||||
{
|
||||
// Route world double-click through the same retail
|
||||
// ItemHolder policy as keyboard Use. This both establishes
|
||||
// ClientUISystem::groundObject for containers and preserves
|
||||
// movement-release-before-Use wire ordering.
|
||||
_outboundInteractions.Enqueue(() =>
|
||||
_itemInteractionController?.ActivateItem(guid));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -13259,7 +13276,9 @@ public sealed class GameWindow : IDisposable
|
|||
// the same policy owner used by the toolbar. Keeping a second classifier here
|
||||
// made BF_CORPSE containers look pickupable and sent PutItemInContainer,
|
||||
// which ACE correctly rejected as Stuck (0x0029).
|
||||
_itemInteractionController?.UseSelectedOrEnterMode(sel);
|
||||
uint selected = sel;
|
||||
_outboundInteractions.Enqueue(() =>
|
||||
_itemInteractionController?.UseSelectedOrEnterMode(selected));
|
||||
}
|
||||
|
||||
private void SendUse(uint guid)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue