fix(vendor): Slice 6 review corrections — ownership-checked retire, live slider display, drag-proof shop rows, hardened buy reservation
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
All nine findings from the buy-arc review, at root: F1 the materializer's retire pass re-checks ownership (guid->vendorId map; remove only while the live object's ContainerId still equals the recording vendor) — buying a player-sold UNIQUE no longer deletes the item you just purchased; the discriminating reparent-then-refresh test pins it. F2 the cost/name display subscribes to the live split state and shares ONE quantity computation with Buy (retail re-renders per slider tick: RecvNotice_StackSliderChanged 0x004C4500) — the sentence and the charge can no longer disagree. F3 shop rows never mint drag payloads (UiItemSlot.AllowDragSource gates both IsDragSource AND GetDragPayload — the second gate was caught by this pass's own test). F4 sendBuy reports whether anything was sent; a null-session buy cancels the reservation instead of leaking BusyCount forever. F5 the retire loop snapshots, isolates per-guid observer failures, and clears its tracking in finally and Dispose — teardown convergence can no longer wedge. F6 auto-select is retail's unconditional first-filtered-item shape (pc:201180-201184; the survival-check was our invention and the comment claiming otherwise is corrected). F7 non-stack buys clamp to quantity 1 locally (BuySingleItem pc:201669). F8 the Add button is hard-disabled until staging exists. F9 AP-161/162/163 rewritten to the post-fix reality. Clean-room complete solution: 11,378 passed / 4 skipped / 0 failed. The #350 render-ledger overflow observed this session is under separate investigation and is NOT addressed here. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
97cf873870
commit
3c9fc57adb
11 changed files with 670 additions and 116 deletions
|
|
@ -140,7 +140,7 @@ public class UiItemSlot : UiElement
|
|||
|
||||
/// <inheritdoc/>
|
||||
public override object? GetDragPayload()
|
||||
=> ItemId != 0 && !_primaryPressConsumed
|
||||
=> AllowDragSource && ItemId != 0 && !_primaryPressConsumed
|
||||
? new ItemDragPayload(ItemId, SourceKind, SlotIndex, this, Shortcut)
|
||||
: null;
|
||||
|
||||
|
|
@ -158,7 +158,8 @@ public class UiItemSlot : UiElement
|
|||
internal override void SetDragSourceActive(bool active, object? payload)
|
||||
{
|
||||
// ItemList_BeginDrag ghosts physical lists, but explicitly excludes shortcut lists
|
||||
// (along with vendor/salvage lists, which acdream does not model as ItemDragSource).
|
||||
// (along with vendor/salvage lists — see AllowDragSource above, F3: those never
|
||||
// reach here at all, since IsDragSource is false for them).
|
||||
// Keep the source's full cell icon in place and reveal the authored grey mesh over it.
|
||||
SetWaitingState(active && SourceKind != ItemDragSource.ShortcutBar);
|
||||
}
|
||||
|
|
@ -171,13 +172,35 @@ public class UiItemSlot : UiElement
|
|||
internal void SetWaitingState(bool waiting)
|
||||
=> _waiting = waiting && ItemId != 0;
|
||||
|
||||
/// <summary>
|
||||
/// F3 (Slice 6 review): opt-out for lists whose rows must NEVER initiate
|
||||
/// a drag, regardless of occupancy — retail's <c>ItemList_BeginDrag</c>
|
||||
/// explicitly excludes vendor/salvage lists from drag-drop (see the
|
||||
/// <see cref="SetDragSourceActive"/> comment above). Before shop items
|
||||
/// had real <see cref="ClientObjectTable"/> identity (Slice 6.1) a
|
||||
/// dragged shop guid failed every destination's existence guard as a
|
||||
/// harmless no-op; once it resolved, the SAME drag would pass a pack
|
||||
/// drop's <c>PutItemInContainer</c>, persist a dangling shortcut-bar
|
||||
/// entry, or fire <c>PlaceIn3D</c> — reparenting a vendor's stock
|
||||
/// without ever going through Buy. Gating the SOURCE here (rather than
|
||||
/// asking every destination handler to reject a vendor-tagged payload)
|
||||
/// means the drag never starts at all, so no future drop handler can
|
||||
/// regress this by forgetting a check. Defaults true — every existing
|
||||
/// physical list (inventory, paperdoll, container, shortcut bar) is
|
||||
/// unaffected; <see cref="VendorUiController"/> is the only caller that
|
||||
/// sets it false.
|
||||
/// </summary>
|
||||
public bool AllowDragSource { get; set; } = true;
|
||||
|
||||
/// <summary>An OCCUPIED slot is a drag source — a press-and-move picks up the item
|
||||
/// rather than moving the toolbar window. An EMPTY slot is NOT a drag source, so a
|
||||
/// press-and-move there falls through to the IA-12 whole-window-drag, keeping the bar
|
||||
/// movable by its empty cells / chrome. Drives <see cref="UiRoot"/>'s mousedown
|
||||
/// window-vs-item disambiguation (retail moves the window via a dragbar, never cells;
|
||||
/// our whole-window-drag approximation reconciles by gating on occupancy).</summary>
|
||||
public override bool IsDragSource => ItemId != 0;
|
||||
/// our whole-window-drag approximation reconciles by gating on occupancy).
|
||||
/// <see cref="AllowDragSource"/> is an additional, independent gate (F3) — false for
|
||||
/// vendor rows regardless of ItemId.</summary>
|
||||
public override bool IsDragSource => ItemId != 0 && AllowDragSource;
|
||||
|
||||
/// <summary>Walk up to the containing <see cref="UiItemList"/> (the drop handler owner).</summary>
|
||||
protected UiItemList? FindList()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue