How-To: Route UI Requests
Goal: send every player-initiated inventory action from the client through the routing component, receive the outcome, and customize who may touch which inventory.
1. Know the client entry points
Each function below is BlueprintCallable on UCrimsonInventoryRoutingComponent, runs on the owning client, and forwards to a reliable Server_* RPC with a _Validate that rejects null targets, zero counts, and out-of-range values before the body runs.
| Client call | Server RPC | Manager call on success |
|---|---|---|
MoveItem(Target, EntryId, T) | Server_MoveItem | MoveItemByEntry |
TransferItem(From, To, EntryId, Count) | Server_TransferItem | TransferEntryTo with no hint |
TransferItemTo(From, To, EntryId, Count, Hint) | Server_TransferItemTo | TransferEntryTo |
SplitStack(Target, EntryId, Amount) | Server_SplitStack | SplitStackByEntry |
SortInventory(Target, Request) | Server_SortInventory | RequestAsyncSort |
DropItem(Target, EntryId, Count, DropLocation) | Server_DropItem | DropItemByEntry |
LockEntry(Target, EntryId, bLocked) | Server_LockEntry | SetEntryLockFlag with User |
OpenContainer(Container) | Server_RequestOpenContainer | Resolves the scoped inventory, opens a session, fires Client_OnContainerOpened |
CloseContainer() | Server_CloseContainer | Ends the session, fires Client_OnContainerClosed |
TakePickupSlot(PickupActor, SlotType, SlotIndex, RequestedQuantity, Destination) | Server_TakePickupSlot | ACrimsonPickupActorBase::TakeSlot |
TakePickupAll(PickupActor, Destination) | Server_TakePickupAll | ACrimsonPickupActorBase::TakeAll |
2. Send a request and read the result
After every routed request the server broadcasts FCrimsonInventoryOperationResult on Crimson.Inventory.Message.OperationResult to the requesting client (via Client_NotifyOperationResult) and locally on the server. This is the reliable "your request finished" signal: it reaches you even when the mutated inventory is a chest with no owning connection.
| Field | Meaning |
|---|---|
Operation | ECrimsonInventoryOperation: Move, Transfer, Split, Drop, Lock, OpenContainer, TakePickupSlot, TakePickupAll, Sort. |
bSuccess | Whether the server applied it. |
FailureReason | Localized text from the layout, constraint, or access check. Empty on success. |
EntryId | The entry the request targeted, when applicable. |
Bind Event to On Operation Result on the routing component in your inventory screen's Event Construct. In the event, branch on bSuccess and show Failure Reason. Then call Split Stack (Target, Entry Id, Amount = 2) from the split dialog.
Operation = Split, bSuccess = false with a reason; split a stack of 5: bSuccess = true and Crimson.Inventory.Message.StackChanged fires for both the source and the new entry.3. Customize the access policy
CanAccessInventory runs on the server before every routed operation. The default allows: the player's own chain (PlayerController, its PlayerState, its pawn), the player's personal containers (FindPersonalContainer), and any inventory with an open container session - with MaxContainerInteractionDistance enforced between the pawn and the container actor. CanOpenContainer gates OpenContainer separately.
Create a Blueprint child of CrimsonInventoryRoutingComponent and override Can Access Inventory (call the parent first, then add your rule) and, if you use party or map-instance scoped containers, Resolve Party Key / Resolve Map Instance Key. Use that child on the PlayerController.
bSuccess = false and the server logs the access denial. Your override's extra rule admits the case you added.4. Personal containers
GetOrCreatePersonalContainer(ContainerTag, Layout) and FindPersonalContainer(ContainerTag) on the routing component create a per-player manager that lives on the PlayerController (a bank stash, a quest-item pouch). PerPlayer scoped containers resolve to these. They serialize through FCrimsonInventoryRoutingSaveData.
These two functions are C++ only today: PerPlayer containers call them for you (see How-To: Build a World Container), and Get Save Data / Apply Save Data on the routing component round-trip them.
See also
- How-To: Build a World Container
- How-To: Drop and Pick Up Items
- How-To: React to Inventory Messages
- Concept: Routing and Access