fix #211: index login-equipped items under player

Project PlayerDescription equipment through the same contained-by-wielder ownership and ordered contents index as live WieldObject updates. Preserve equip masks and priorities so retail GetObjectAtLocation selects Missile for an already-equipped crossbow instead of sending a server-rejected Melee request.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 10:40:29 +02:00
parent e74efc5c06
commit ab98cda26b
6 changed files with 150 additions and 12 deletions

View file

@ -537,7 +537,13 @@ public static class GameEventWiring
items.RecordMembership(inv.Guid, containerTypeHint: inv.ContainerType);
}
foreach (var eq in p.Value.Equipped)
items.RecordMembership(eq.Guid, equip: (EquipMask)eq.EquipLocation);
{
items.RecordMembership(
eq.Guid,
containerId: ownerGuid,
equip: (EquipMask)eq.EquipLocation,
priority: eq.Priority);
}
// D.5.1 Task 4: forward shortcut bar entries to the caller so the
// toolbar can read them without holding a parser reference.

View file

@ -481,11 +481,14 @@ public sealed class ClientObjectTable
/// <summary>
/// PlayerDescription manifest: record that this guid is the player's
/// (in inventory or equipped at <paramref name="equip"/>), creating an
/// empty entry if CreateObject hasn't arrived yet. Never touches
/// icon/name/type/effects — that data comes from CreateObject.
/// empty entry if CreateObject hasn't arrived yet. Equipped entries may
/// specify the player as <paramref name="containerId"/> so login and live
/// WieldObject updates share the same contained-by-wielder projection.
/// Never touches icon/name/type/effects — that data comes from CreateObject.
/// </summary>
public ClientObject RecordMembership(uint guid, uint containerId = 0,
EquipMask equip = EquipMask.None, uint? containerTypeHint = null)
EquipMask equip = EquipMask.None, uint? containerTypeHint = null,
uint? priority = null)
{
bool existed = _objects.TryGetValue(guid, out var obj);
if (!existed || obj is null) // keep: satisfies nullable flow analysis
@ -495,15 +498,12 @@ public sealed class ClientObjectTable
}
uint oldContainer = obj.ContainerId;
if (containerId != 0)
{
obj.ContainerId = containerId;
obj.CurrentlyEquippedLocation = EquipMask.None;
}
else
{
obj.CurrentlyEquippedLocation = equip;
}
obj.CurrentlyEquippedLocation = equip;
if (equip != EquipMask.None)
obj.ContainerSlot = -1;
if (containerTypeHint is { } hint) obj.ContainerTypeHint = hint;
if (priority is { } p) obj.Priority = p;
Reindex(obj, oldContainer);
if (!existed) ObjectAdded?.Invoke(obj); else ObjectUpdated?.Invoke(obj);
return obj;