Class TradeSession
- Namespace
- FishMMO.Server.Implementation.World.SceneServer
- Assembly
- FishMMO.Server.dll
The state of one open trade between two characters.
public sealed class TradeSession
- Inheritance
-
TradeSession
- Inherited Members
Remarks
Pure state with the rules that govern it, and nothing else: no network, no containers,
no Unity. TradeSystem resolves characters and inventories, validates what a
request refers to, and then asks this object whether the change is allowed and records
it here. That split is what lets the acceptance rules be tested as a truth table.
TWO STAGES: CONFIRM, THEN ACCEPT. Confirming says "this is my final offer". While both sides have confirmed the table is LOCKED: no item and no currency on either side can be changed at all, and only then may either party accept. That is what removes the last-minute switch as a category rather than as a race — there is no instant at which one player is reading a table the other can still edit. Changing your mind means revoking your confirmation first, which unlocks the table and clears both acceptances, in full view of the other player.
THE INVARIANT: every change to either offer clears both confirmations and both acceptances, and bumps Version. There is no way to alter what is on the table that leaves consent of either kind standing. TryConfirm(long, bool, uint) and TryAccept(long, bool, uint) both refuse a request that quotes any version but the current one, so a click that was in flight while the table changed lands as a no-op rather than as consent to something the player never saw.
Constructors
TradeSession(long, long, long, int)
public TradeSession(long id, long firstCharacterID, long secondCharacterID, int maxOfferSlots)
Parameters
Fields
Commit
The in-flight commit, or null.
public TradeSession.CommitState Commit
Field Value
First
public readonly TradeSession.Party First
Field Value
ID
Process-unique session number, for log lines.
public readonly long ID
Field Value
MaxOfferSlots
The most slots one side may offer, fixed at creation from the system asset.
public readonly int MaxOfferSlots
Field Value
NextRangeCheckTime
Server time of the next range check. Owned by the system's tick.
public double NextRangeCheckTime
Field Value
Second
public readonly TradeSession.Party Second
Field Value
Properties
BothAccepted
True when both sides have accepted the frozen table.
public bool BothAccepted { get; }
Property Value
IsLocked
True when both sides have confirmed their offers: the table is frozen and the only things either party may do are accept, revoke, or cancel.
public bool IsLocked { get; }
Property Value
Phase
public TradePhase Phase { get; }
Property Value
Version
Increments on every change to either side. Quoted back by accepts.
public uint Version { get; }
Property Value
Remarks
Starts at 1 so a zeroed TradeAcceptBroadcast — one a client never filled in —
can never match.
Methods
BuildStateFor(long)
The state message for characterID's side of the table.
public TradeStateBroadcast BuildStateFor(long characterID)
Parameters
characterIDlong
Returns
Close()
Ends the session. Idempotent.
public void Close()
Involves(long)
True when the character is one of the two parties.
public bool Involves(long characterID)
Parameters
characterIDlong
Returns
PartnerOf(long)
The side that is NOT characterID, or null when they are not a party.
public TradeSession.Party PartnerOf(long characterID)
Parameters
characterIDlong
Returns
PartyOf(long)
The side belonging to characterID, or null.
public TradeSession.Party PartyOf(long characterID)
Parameters
characterIDlong
Returns
TryAccept(long, bool, uint)
Accepts, or withdraws acceptance of, the frozen table as it stands at
version.
public TradeOfferRefusal TryAccept(long characterID, bool accept, uint version)
Parameters
Returns
Remarks
Stage two of two, and only reachable while IsLocked: there is nothing to accept until both sides have declared their offers final. The version quote is kept even though the table cannot change while locked, because an accept sent before a revoke-change-relock cycle would otherwise arrive as consent to a table the player never saw.
Withdrawing never fails on version: a player taking consent back must always be able to, whatever they were looking at. Only granting it is gated.
TryAddOffer(long, TradeOffer)
Puts an item on the table for characterID.
public TradeOfferRefusal TryAddOffer(long characterID, TradeOffer offer)
Parameters
characterIDlongofferTradeOffer
Returns
TryBeginCommit()
Moves an open session into Committing.
public bool TryBeginCommit()
Returns
- bool
False unless the session was open, locked, and both sides had accepted.
TryConfirm(long, bool, uint)
Confirms, or revokes the confirmation of, this side's offer as final at
version.
public TradeOfferRefusal TryConfirm(long characterID, bool confirm, uint version)
Parameters
Returns
Remarks
Stage one of two. Once BOTH sides have confirmed the table is locked and nothing on it can change; that is what makes the accept that follows a decision about a settled table rather than a race against the other player's next click.
Revoking clears both acceptances. An acceptance is consent to a frozen table, and a revocation unfreezes it — so consent given on that basis cannot survive, on either side. The other party's CONFIRMATION is left standing: they have not changed their mind about their own offer, and making them re-click for someone else's revocation is noise. Any actual change to the table clears everything, as ever.
Revoking never fails on version, for the same reason withdrawing an acceptance does not: taking consent back must always be possible, whatever the player was looking at.
TryRemoveOffer(long, int, out TradeOffer)
Takes the offer made from slot back off the table.
public TradeOfferRefusal TryRemoveOffer(long characterID, int slot, out TradeOffer removed)
Parameters
characterIDlongslotintremovedTradeOffer
Returns
TrySetCurrency(long, long)
Sets the currency on the table for characterID.
public TradeOfferRefusal TrySetCurrency(long characterID, long amount)
Parameters
Returns
Remarks
Setting the same amount again is still a change: it bumps the version and clears acceptances. A client that re-sends its own value has told the server "I changed something", and the cost of honouring that literally is one extra round of accepts — far cheaper than a rule that lets some writes through without clearing consent.