Table of Contents

Class ItemStackTransfer

Namespace
FishMMO.Shared
Assembly
FishMMO.Shared.dll

Moves quantity between two stacks in place: a split takes part of one stack into another slot, a merge pours one stack into a matching one. Issue #198.

public static class ItemStackTransfer
Inheritance
ItemStackTransfer
Inherited Members

Remarks

Both operations conserve quantity and are all-or-nothing. Every refusal happens before anything is written, and the one write that can still fail afterwards — placing a freshly split instance into its slot — is undone by putting the amount back on the source. A failure therefore leaves the original stack exactly as it was; it never destroys the remainder. ItemStackSplitMergeTests pins that.

Split and merge are designed as a pair. A split can land on an empty slot (a new instance is created) or on a matching stack with room (the amount is poured across), and a merge is what a whole stack dropped onto a matching stack does instead of swapping. Between them a player can move any quantity anywhere, and neither can strand quantity the other cannot recombine.

The boundaries are fixed here, not left to the arithmetic. Splitting zero is refused. Splitting the whole stack, or more than it holds, is refused: taking everything is a move, and the swap that already exists is the operation for it. A destination that is neither empty nor a matching stack with room for the whole amount is refused rather than partly filled, so the server's answer is either "done as asked" or "nothing happened".

Nothing here persists or broadcasts. The server handler owns writing the rows and telling the owner; the client never calls this at all — it learns the outcome from the set-slot messages the server sends, exactly as it does for a grant.

Methods

CanMergeInto(Item, Item)

True when source dropped onto destination should merge rather than swap.

public static bool CanMergeInto(Item destination, Item source)

Parameters

destination Item

The stack being dropped onto.

source Item

The stack being dropped.

Returns

bool

Remarks

Agrees with AddToStack(Item) on purpose, including its refusal of a FULL donor: pouring a full stack into a partial one leaves the donor holding exactly what the destination held, which is a swap by another name — so a swap is what happens.

CanSplitOnto(Item, Item, uint)

True when amount split off source could land on the item in a destination slot, which must be null (empty) or a matching stack with room for all of it.

public static bool CanSplitOnto(Item occupant, Item source, uint amount)

Parameters

occupant Item

Whatever the destination slot holds, or null.

source Item

The stack being split.

amount uint

How much is being taken off it.

Returns

bool

IsValidSplitAmount(Item, uint)

True when amount is a quantity that can be split off source: at least one, and strictly less than the stack holds.

public static bool IsValidSplitAmount(Item source, uint amount)

Parameters

source Item
amount uint

Returns

bool

Remarks

The whole stack is not a valid split amount. Taking everything is a move, and the existing swap is the operation for that; a split that could take everything would be a second way of moving an item, with a second set of rules to keep in step.

TryMerge(IItemContainer, int, IItemContainer, int, out Item, out Item, out bool)

Pours the stack in fromSlot into the matching stack in toSlot, as much as fits.

public static bool TryMerge(IItemContainer from, int fromSlot, IItemContainer to, int toSlot, out Item source, out Item destination, out bool sourceEmptied)

Parameters

from IItemContainer

Container holding the donor.

fromSlot int

Slot of the donor.

to IItemContainer

Container holding the receiving stack. May be from.

toSlot int

Slot of the receiving stack.

source Item

The donor.

destination Item

The receiving stack.

sourceEmptied bool

True when the donor was fully absorbed and its slot cleared.

Returns

bool

True when quantity moved. False leaves both containers untouched.

Remarks

The donor keeps whatever did not fit and stays in its slot; when everything fit the donor's slot is emptied and sourceEmptied reports it, so the caller can delete the row. The donor instance is handed back either way and is not destroyed here — the caller still needs its identity and version for the delete.

TrySplit(IItemContainer, int, IItemContainer, int, uint, out Item, out Item, out bool)

Takes amount off the stack in fromSlot and puts it in toSlot: into a new instance when that slot is empty, onto the matching stack already there when it is not.

public static bool TrySplit(IItemContainer from, int fromSlot, IItemContainer to, int toSlot, uint amount, out Item source, out Item destination, out bool destinationCreated)

Parameters

from IItemContainer

Container holding the stack being split.

fromSlot int

Slot of the stack being split.

to IItemContainer

Container receiving the split half. May be from.

toSlot int

Slot receiving the split half.

amount uint

How much to take. Must be at least 1 and less than the stack holds.

source Item

The stack that was split, now smaller by amount.

destination Item

The item now in toSlot: a new instance with ID = 0 when destinationCreated is true, otherwise the stack that was already there.

destinationCreated bool

True when a new instance was allocated for the split half.

Returns

bool

True when quantity moved. False leaves both containers untouched.