adventure: drain Pete's equip queue and apply it for real

Poll Pete for equip/unequip orders an owner placed on the web, run them through
the real magic-item equip path so bond caps and slot eviction still hold, and
file a verdict. Same reverse pipe as mischief, with one difference that matters:
the equip action is not idempotent, so a re-offered order after a lost ack would
double-move the item. An equip_applied_orders ledger keyed on the order guid is
the guard: applied once, re-offers only re-file the stored verdict.

The delicate remove-before-equip ordering that prevents item duplication is now
one shared applyMagicEquip/applyMagicUnequip core, called by both the DM
resolver and this poller, so the anti-dup ordering can't drift between two
copies. Items now carry their inventory row id to Pete as the equip handle.
This commit is contained in:
prosolis
2026-07-17 08:44:44 -07:00
parent 32520eb7ec
commit 7960838b3f
6 changed files with 468 additions and 91 deletions

View File

@@ -242,6 +242,14 @@ func itemViews(items []AdvItem) []peteclient.ItemView {
v.Desc = eff.Desc
v.Effect = magicItemEffectSummary(eff)
v.Attunement = eff.Attunement
// The row id is the equip handle: a slotted magic item is the one thing
// the web equip path can wear, so only it carries an id. Mundane gear (the
// branch below) and unslotted curios get none, so no Equip button. This
// runs for vault rows too — a vault magic item would carry an id — but Pete
// offers the button on the backpack panel alone, so that's inert, not a leak.
if eff.Slot != "" {
v.ID = it.ID
}
} else if it.Slot != "" {
// Shop equipment resolves by (slot, tier) — Name is decorative.
v.Desc = equipmentDefByTier(it.Slot, it.Tier).Description