Table of Contents

Class UITKItemGridPanel

Namespace
FishMMO.Client
Assembly
FishMMO.Client.dll

Shared behaviour for a panel that draws a character's item container as a grid of slots.

public abstract class UITKItemGridPanel : UITKCharacterControl
Inheritance
Object
Component
Behaviour
MonoBehaviour
UITKItemGridPanel
Derived
Inherited Members
MonoBehaviour.IsInvoking()
MonoBehaviour.CancelInvoke()
MonoBehaviour.StopCoroutine(Coroutine)
MonoBehaviour.StopAllCoroutines()
MonoBehaviour.destroyCancellationToken
MonoBehaviour.useGUILayout
MonoBehaviour.didStart
MonoBehaviour.didAwake
MonoBehaviour.runInEditMode
Behaviour.enabled
Behaviour.isActiveAndEnabled
Component.GetComponent<T>()
Component.TryGetComponent<T>(out T)
Component.GetComponentInChildren<T>()
Component.GetComponentsInChildren<T>()
Component.GetComponentInParent<T>()
Component.GetComponentsInParent<T>()
Component.GetComponents<T>()
Component.GetComponentIndex()
Component.CompareTag(TagHandle)
Component.transform
Component.transformHandle
Component.gameObject
Component.tag
Object.GetEntityId()
Object.GetInstanceID()
Object.GetHashCode()
Object.InstantiateAsync<T>(T)
Object.InstantiateAsync<T>(T, Transform)
Object.InstantiateAsync<T>(T, Vector3, Quaternion)
Object.InstantiateAsync<T>(T, Transform, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion)
Object.Instantiate(Object, Vector3, Quaternion, Transform)
Object.Instantiate(Object)
Object.Instantiate(Object, Scene)
Object.Instantiate<T>(T, InstantiateParameters)
Object.Instantiate<T>(T, Vector3, Quaternion, InstantiateParameters)
Object.Instantiate(Object, Transform)
Object.Instantiate<T>(T)
Object.Instantiate<T>(T, Vector3, Quaternion)
Object.Instantiate<T>(T, Vector3, Quaternion, Transform)
Object.Instantiate<T>(T, Transform)
Object.Destroy(Object)
Object.DestroyImmediate(Object)
Object.DontDestroyOnLoad(Object)
Object.DestroyObject(Object)
Object.FindObjectsOfType<T>()
Object.FindObjectsByType<T>(FindObjectsSortMode)
Object.FindObjectsByType<T>(FindObjectsInactive, FindObjectsSortMode)
Object.FindObjectOfType<T>()
Object.FindFirstObjectByType<T>()
Object.FindAnyObjectByType<T>()
Object.FindFirstObjectByType<T>(FindObjectsInactive)
Object.FindAnyObjectByType<T>(FindObjectsInactive)
Object.FindObjectsByType<T>()
Object.FindObjectsByType<T>(FindObjectsInactive)
Object.ToString()
Object.name
Object.hideFlags

Remarks

The bank and the inventory were separate implementations of the same panel — 87% identical after allowing for their vocabulary, sharing twenty-four identically named private methods. That is why a defect fixed in one stayed in the other: the capacity readout counted icons rather than items, was found and corrected in the inventory, and went on being wrong in the bank until it was reported again from play. A second copy does not double the work of a fix, it halves the chance of one.

What made unifying them straightforward is that the domain model had already done it: IBankController and IInventoryController both derive from IItemContainer, which exposes everything this view needs — the slot list, the emptiness test, the item accessor and the two change events. The panels simply were not using it. Nothing here knows which container it is drawing.

The grid is a view of the replicated container and nothing else: no click writes to a slot. A request goes out, the slot is marked as waiting, and the container being replicated back is what changes what the player sees.

Fields

DRAG_OBJECT_NAME

protected const string DRAG_OBJECT_NAME = "UIDragObject"

Field Value

string

INPUT_DIALOG_NAME

protected const string INPUT_DIALOG_NAME = "UIDialogInputBox"

Field Value

string

TOOLTIP_NAME

protected const string TOOLTIP_NAME = "UITooltip"

Field Value

string

slotViews

Slot views indexed by container slot index.

protected readonly List<UITKItemGridPanel.SlotView> slotViews

Field Value

List<UITKItemGridPanel.SlotView>

Properties

CapacityFillName

Name of the footer capacity bar fill.

protected virtual string CapacityFillName { get; }

Property Value

string

CssHidden

USS class hiding an element.

protected string CssHidden { get; }

Property Value

string

DragType

The drag and operation-tracker identity of this panel's slots.

protected abstract ReferenceButtonType DragType { get; }

Property Value

ReferenceButtonType

EmptyName

Name of the label shown when nothing is stored.

protected virtual string EmptyName { get; }

Property Value

string

FreeName

Name of the footer label counting free slots.

protected virtual string FreeName { get; }

Property Value

string

OwnContainer

This panel's own container, or null when the character does not have one yet.

protected IItemContainer OwnContainer { get; }

Property Value

IItemContainer

OwnInventoryType

This panel's container, as the server names it in a request.

protected abstract InventoryType OwnInventoryType { get; }

Property Value

InventoryType

Prefix

Element and USS name prefix for this panel, without a trailing dash.

protected abstract string Prefix { get; }

Property Value

string

Remarks

Every panel-specific name is this prefix plus a fixed suffix — "bank-used" and "inv-used", "bank-slot__lock--pending" and "inv-slot__lock--pending". Ten constants followed that pattern in each panel without exception, so one string replaces all twenty. A panel whose markup does not follow it should override the names below rather than bend the prefix.

QuickTransferTarget

The container a shift-click sends an item to, or null when this panel has nowhere to send one.

protected virtual ReferenceButtonType? QuickTransferTarget { get; }

Property Value

ReferenceButtonType?

UsedName

Name of the footer label counting occupied slots.

protected virtual string UsedName { get; }

Property Value

string

Methods

ApplyPerOpenContent()

Re-reads the whole grid from the character, rebuilding it only if it is stale.

protected void ApplyPerOpenContent()

BeginDragFromSlot(UITKDragObject, IItemContainer, int)

Starts a drag from an occupied slot.

protected void BeginDragFromSlot(UITKDragObject dragObject, IItemContainer container, int slotIndex)

Parameters

dragObject UITKDragObject
container IItemContainer
slotIndex int

CompleteDropOntoSlot(UITKDragObject, IItemContainer, int)

Drops whatever the drag is carrying onto slotIndex.

protected void CompleteDropOntoSlot(UITKDragObject dragObject, IItemContainer container, int slotIndex)

Parameters

dragObject UITKDragObject
container IItemContainer
slotIndex int

Remarks

This replaced a call to the containers' own CanSwapItemSlots, whose entire body is return !(fromInventory == InventoryType.Inventory && from == to). It does not look at the containers at all, so it approved moves out of empty slots, out of locked slots, and into indices past the end; and because the one case it does check names InventoryType.Inventory, it never even caught a bank slot dropped on itself. The server rejects all of it, so nothing was corrupted — what it cost was a round trip and, before ItemOperationFailedBroadcast, silence.

CompleteUnequipInto(UITKDragObject, int)

Sends an unequip whose destination is this container.

protected void CompleteUnequipInto(UITKDragObject dragObject, int equipmentSlot)

Parameters

dragObject UITKDragObject
equipmentSlot int

HandleSlotLeftClick(int)

Left-click: completes an in-progress drag or begins dragging this slot's item.

protected virtual void HandleSlotLeftClick(int slotIndex)

Parameters

slotIndex int

HandleSlotRightClick(int)

Right-click on a slot: offers to split the stack in it. Issue #198.

protected virtual void HandleSlotRightClick(int slotIndex)

Parameters

slotIndex int

The slot that was clicked.

Remarks

A panel with a better use for the click (the inventory wears what can be worn) overrides this and falls back to it for everything else, so a stack of arrows splits the same way in the bag and in the bank.

Hide(bool)

Hides the panel and abandons anything it had in flight.

public override void Hide(bool overrideIsAlwaysOpen)

Parameters

overrideIsAlwaysOpen bool

When true, the call is a no-op.

Remarks

Closing is not a neutral act: walking out of range of the interactable that opened the panel is one of the ways the server refuses an operation, so a slot left marked as waiting after the panel closes has a very good chance of never being answered.

IsSlotBlocked(int)

Reports whether a slot is unavailable for a new request, for any reason.

protected bool IsSlotBlocked(int slotIndex)

Parameters

slotIndex int

Returns

bool

OnAfterShow()

Fills the grid on every show, including the very first one.

protected override void OnAfterShow()

Remarks

THE CONTRACT: enabling the document re-clones the UXML, so anything written before Show() is discarded. OnAfterStarting covers later opens, but on the first ever open hasStarted is still false and ReinitializeIfTreeReplaced bails out before calling it — and a panel opened by a broadcast has its first open triggered by something the player did rather than at startup. Both hooks do the work, and both are idempotent.

OnAfterStarting()

Rebuilds the grid after the visual tree has been replaced.

protected override void OnAfterStarting()

OnClientSet()

Joins the shared operation tracker. Derived panels extend this to register broadcasts.

public override void OnClientSet()

OnClientUnset()

Leaves the shared operation tracker. Derived panels extend this to unregister broadcasts.

public override void OnClientUnset()

OnDestroying()

Destroys all runtime slot elements and drops every subscription when the control is destroyed.

public override void OnDestroying()

OnPostSetCharacter()

Builds the grid for the newly set character and subscribes to slot events.

public override void OnPostSetCharacter()

OnPreSetCharacter()

Unsubscribes from slot events before the character is replaced.

public override void OnPreSetCharacter()

OnPreUnsetCharacter()

Drops every subscription and in-flight operation before the character goes away.

public override void OnPreUnsetCharacter()

OnSlotLockChanged(IItemContainer, int, bool)

Called when the lock state of a slot changes.

public void OnSlotLockChanged(IItemContainer container, int slot, bool isLocked)

Parameters

container IItemContainer
slot int
isLocked bool

OnSlotUpdated(IItemContainer, Item, int)

Called when a slot's item changes.

public void OnSlotUpdated(IItemContainer container, Item item, int slotIndex)

Parameters

container IItemContainer
item Item
slotIndex int

Remarks

The slot arriving from the server IS the acknowledgement of whatever this panel asked for, so the pending mark is released here rather than on a separate reply message.

OnStarting()

Queries named elements and wires up the close button.

public override void OnStarting()

OnTick()

Times out item operations whose reply never arrived.

protected override void OnTick()

RegisterExtraSlotCallbacks(VisualElement, int)

Lets a panel register additional callbacks on a freshly created slot.

protected virtual void RegisterExtraSlotCallbacks(VisualElement slotRoot, int slotIndex)

Parameters

slotRoot VisualElement

The slot element being created.

slotIndex int

The slot's index, already captured for closures.

Remarks

Registered here rather than after the fact because these elements are discarded and rebuilt, so a panel that attached its handlers elsewhere would lose them on the next rebuild.

ReleaseAndClearDrag()

Abandons this panel's in-flight operations and any drag that started here.

protected void ReleaseAndClearDrag()

ResolveContainer(ReferenceButtonType)

Resolves the character's container for a drag source type.

protected IItemContainer ResolveContainer(ReferenceButtonType type)

Parameters

type ReferenceButtonType

Returns

IItemContainer

SendQuickTransferRequest(int, int)

Sends the request that moves an item out of this panel and into QuickTransferTarget.

protected virtual void SendQuickTransferRequest(int fromSlot, int toSlot)

Parameters

fromSlot int

Slot in this panel the item is leaving.

toSlot int

Slot in the target container it is going to.

Remarks

The broadcast belongs to the DESTINATION container, not this one — moving into the bank is a bank swap whoever asked for it — so the panel losing the item is the one that has to name the other panel's request.

SendSplitRequest(int, int, InventoryType, uint)

Asks the server to split part of a stack into one of this panel's slots. Issue #198.

protected abstract void SendSplitRequest(int fromSlot, int toSlot, InventoryType fromInventory, uint amount)

Parameters

fromSlot int

Slot holding the stack being split.

toSlot int

Slot in this panel the split half is going to.

fromInventory InventoryType

Container holding the stack being split.

amount uint

How much to take off it.

Remarks

As with SendSwapRequest(int, int, InventoryType), the request names its DESTINATION container, so the panel receiving the split half is the one that sends it.

SendSwapRequest(int, int, InventoryType)

Asks the server to move an item into one of this panel's slots.

protected abstract void SendSwapRequest(int fromSlot, int toSlot, InventoryType fromInventory)

Parameters

fromSlot int

Slot the item is leaving.

toSlot int

Slot in this panel it is going to.

fromInventory InventoryType

Container the item is leaving.

Remarks

The only part of a drop that differs between panels: the request carries the same three fields either way, but the broadcast type names its destination container.

TryPromptSplit(int)

Asks how much of the stack in slotIndex to pick up, then starts a drag carrying just that much.

protected void TryPromptSplit(int slotIndex)

Parameters

slotIndex int

Slot holding the stack to split.

Remarks

Shift-click already means "send to the other container" (issue #197) and press-drag already means "move the whole stack", so the split is asked for another way: a right-click on a stack of two or more opens a quantity prompt, and accepting it picks the split half up as a drag. The drop then names its destination exactly as a drag of the whole stack would, which is what lets the split reuse every check a drop makes.

Nothing is written on this client at any point. The prompt starts a drag, the drop sends a request, and the two slots repaint when the server sends them back — the same contract as every other item operation here.

TryQuickTransfer(int)

Moves an item to the other open container without a drag.

protected void TryQuickTransfer(int slotIndex)

Parameters

slotIndex int

Slot holding the item to send.

Remarks

Banking a bagful is the operation players repeat most, and doing it by drag means one press, one aim and one release per item across two panels.

The destination is the first free slot this client can see, and the request is the same swap a drag onto that slot would send. That is deliberate: it carries exactly the risk the drag it replaces already carries, no more. A slot this client believes is empty and the server does not would swap two items rather than move one — but the player aiming a drag at that same slot gets the same outcome, so quick transfer is not introducing a class of mistake, only saving the aiming.