Trade
Escrowed player-to-player exchange (atomic TryExchange over Inventory).
Configuration 1
Every tunable lives in an options object — there are no magic numbers to hunt for.
TradeOptions
Tunables for escrowed player-to-player trading. No hardcoded literals in the service.
-
int MaxOfferSlots { get; set; }Most bag slots one side may put on the table. Bounds the cost of an offer edit, which is O(offered × bag) and produces a state push to BOTH sides: an uncapped, non-deduplicated int[] let two colluding sessions send thousands of repeated indices per message and turn each one into a large serialized payload. A generous cap for any real trade UI.
Wire messages 8
The protocol this piece speaks. Ids are allocated per piece so they can never collide.
TradeProposeRequest Client → server: propose a trade to an online player by display name.
TradeProposed Server → target: someone proposed a trade.
TradeAcceptRequest Client → server: accept a proposal.
TradeOfferRequest Client → server: replace my offer with these inventory slots (empty = offer nothing).
TradeConfirmRequest Client → server: lock in the trade as offered. Both confirmations trigger the atomic swap.
TradeCancelRequest Client → server: walk away (nothing is exchanged).
TradeStateChanged Server → both parties: the trade table as it stands. Any offer change resets confirmations.
TradeCompleted Server → both parties: the trade ended (swap done, failed, or cancelled).
Unity services you inject 1
Crossplay binds these in the client context. Inject and call them from your own MonoBehaviours and presenters.
ITradeClient
The Trade piece, client side: propose/accept/offer/confirm/cancel, and observe the table state (any change resets confirmations server-side). The exchange itself is server-authoritative and atomic — completion arrives as Completed. No UI; your game renders the table.
-
event Action<TradeProposed> ProposedSomeone proposed a trade to you.
-
event Action<TradeStateChanged> StateChangedThe trade table changed (offers/confirmations, from your perspective).
-
event Action<TradeCompleted> CompletedThe trade ended (swap done, failed, or cancelled).
-
void Propose(string targetName)Proposes a trade to an online player by display name.
-
void Accept(long tradeId)Accepts a received proposal.
-
void Offer(int[] slots)Replaces your offer with these inventory slot indices (empty = nothing).
-
void Confirm()Locks in the table as shown; both confirmations trigger the atomic swap.
-
void Cancel()Walks away — nothing is exchanged.
UI views you can replace 1
Each ships a working uGUI panel you can drag into a scene. Substitute your own view to keep the logic and change the look — the presenter never knows.
ICrossplayTradeView
Narrow contract the presenter drives. UI-only: render calls in, user intents out.