The inventory system stores per-character items in MariaDB and exposes them to the game server through an in-memoryDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/kenzz55/ue5-iocp-mmo-server/llms.txt
Use this file to discover all available pages before exploring further.
PlayerInventory struct. Every mutation carries a monotonically increasing revision counter, and the client must echo the current expected_revision back with every request. If the revision has changed since the client last received a snapshot — for example because a server-side effect consumed an item — the operation is rejected and the client must re-read the full snapshot before retrying. A 16-byte client_request_id provides idempotency so retries over an unreliable connection never produce duplicate effects.
In-Memory Structures
PlayerInventory and InventoryItem are defined in Game/Inventory.h and held directly inside the PlayerEntity that lives in GameWorld.
loaded is false until InventoryPersistence::LoadInventoryAsync completes after EnterGame. The snapshot packet is sent to the client as soon as loaded becomes true.
Protobuf Messages
Items are serialised over the wire with theInventoryItem protobuf message:
Packet Flow
S_InventorySnapshot (0x0251) — initial load
Sent by the server immediately after inventory is loaded from the database following The client should store
C_EnterGameReq. Contains the complete item list.revision locally and use it as expected_revision in subsequent move and use requests.C_InventoryMoveReq (0x0252) — move item
Reposition or split a stack from one slot to another. All fields are required.
Client-generated random 16-byte identifier. The server deduplicates on
(character_id, client_request_id) in the inventory_operations table.Must equal the server’s current
revision; otherwise the operation is rejected.The instance being moved.
Current slot index of the item.
Target slot index. Must be within
[0, capacity).Number of units to move; must be ≤ current stack size.
C_InventoryUseReq (0x0254) — use item
Consume one unit of a usable item and trigger its effect.The server reads
effect_type and effect_value from the item’s template row. If effect_type = 1 (Heal), GameWorld::HealPlayer() is called with effect_value hit-points before the persistence result is sent back.ItemEffectType enum (C++)S_InventoryOperationResult (0x0253) — response to move or use
Returned after both
C_InventoryMoveReq and C_InventoryUseReq. On success snapshot contains the full updated inventory.Whether the operation was applied.
Error detail when
success is false.Echoed back so the client can match the response to its pending request.
Full updated inventory including new revision.
Optimistic Concurrency
The server rejects any operation whoseexpected_revision does not match the current server-side revision. This prevents stale writes without requiring a distributed lock.
Persistence
InventoryPersistence (defined in Persistence/InventoryPersistence.h) manages a thread pool that executes all database I/O off the game-simulation thread.
Common/Config.h:
| Constant | Value | Purpose |
|---|---|---|
InventoryDbWorkerCount | 2 | Thread pool size for inventory DB jobs |
MaxInventoryDbQueueSize | 4096 | Maximum queued jobs before back-pressure |
Database Schema
character_inventories
item_instances
inventory_operations (idempotency log)
item_templates
Created by 003_item_templates.sql:
004_item_effects.sql then adds the effect columns and sets values for existing templates: