fix(interaction): publish pending keyboard pickups

Route F-key pickup through the same ItemHolder backpack placement entry point as double-click activation so the inventory reserves the destination slot before the request is sent.
This commit is contained in:
Erik 2026-07-21 07:08:30 +02:00
parent 047a4c83b5
commit 52dbb5749e
4 changed files with 43 additions and 17 deletions

View file

@ -303,6 +303,25 @@ public sealed class ItemInteractionController : IDisposable
return ExecuteUseActions(decision.Actions);
}
/// <summary>
/// Retail keyboard pickup entry point. <c>CPlayerSystem::PlaceInBackpack</c>
/// publishes the waiting destination slot before issuing the move request,
/// exactly like double-click pickup through ItemHolder.
/// </summary>
public bool PlaceWorldItemInBackpack(uint itemGuid)
{
if (itemGuid == 0u || _placeInBackpack is null)
return false;
uint containerId = _backpackContainerId();
if (containerId == 0u)
containerId = _playerGuid();
const int placement = 0;
PendingBackpackPlacementRequested?.Invoke(itemGuid, containerId, placement);
_placeInBackpack(itemGuid, containerId, placement);
return true;
}
/// <summary>
/// Retail paperdoll drop entry point. The paperdoll resolves the exact
/// target side/location; this shared interaction owner performs AutoWield's
@ -418,18 +437,7 @@ public sealed class ItemInteractionController : IDisposable
switch (action.Kind)
{
case ItemPolicyActionKind.PlaceInBackpack:
if (_placeInBackpack is null)
break;
uint containerId = _backpackContainerId();
if (containerId == 0u)
containerId = _playerGuid();
const int placement = 0;
PendingBackpackPlacementRequested?.Invoke(
action.ObjectId,
containerId,
placement);
_placeInBackpack(action.ObjectId, containerId, placement);
acted = true;
acted |= PlaceWorldItemInBackpack(action.ObjectId);
break;
case ItemPolicyActionKind.WieldRight:
case ItemPolicyActionKind.WieldLeft: