Skip to main content

Documentation 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.

The game database schema is applied automatically when the MariaDB container starts for the first time. Docker mounts the ServerSolution/Infra/mariadb/init/ directory to /docker-entrypoint-initdb.d inside the container, and MariaDB executes every .sql file in lexicographic order — meaning migrations 001 through 005 run in sequence on a fresh volume. A consolidated Schema.sql at the solution root reflects the final combined state and can be used to provision a non-Docker database directly.
The allow_dev_fallback=true flag in Database.ini keeps the hardcoded test / 1234 credential pair functional even when the MySQL server is unreachable. This lets frontend or client engineers iterate without a live database. Set allow_dev_fallback=false in any shared or production environment.

001_schema.sql — Core tables

The foundation migration creates the database, character roster, and server registry, and seeds one test account plus three game server entries.

accounts

Stores one row per registered player.
ColumnTypeNotes
account_idBIGINT UNSIGNEDAuto-increment surrogate key
account_nameVARCHAR(64)Unique login name; 4–64 characters enforced by the AuthServer
nicknameVARCHAR(32)Display name; defaults to account_name when omitted at registration
password_hashVARCHAR(255)PBKDF2-SHA256 hash produced by the AuthServer
created_atTIMESTAMPRow insertion time, set by the database

game_servers

Registry of game server instances the AuthServer exposes via GET /servers. The maintenance flag causes POST /auth/select-server to return HTTP 409.
ColumnTypeNotes
server_idINT UNSIGNEDManual primary key matching Config::GameServerId in the C++ binary
nameVARCHAR(64)Human-readable server name shown in the client lobby
ipVARCHAR(64)Publicly reachable IP or hostname of the game server
portINT UNSIGNEDTCP port the game server listens on
current_usersINT UNSIGNEDLive player count (updated by the game server)
max_usersINT UNSIGNEDCapacity ceiling displayed to clients
maintenanceTINYINT(1)1 = server is in maintenance; 0 = accepting connections

characters

One row per (account, server) pair. A player gets exactly one character per game server, created automatically by EnsureDefaultCharacterAsync during server selection.
ColumnTypeNotes
character_idBIGINT UNSIGNEDAuto-increment surrogate key
account_idBIGINT UNSIGNEDFK → accounts.account_id (CASCADE DELETE)
server_idINT UNSIGNEDFK → game_servers.server_id (CASCADE DELETE)
nameVARCHAR(32)Character display name
levelINT UNSIGNEDCurrent level, default 1
x, y, zFLOATLast known world position in Unreal units
current_hpINTCurrent hit points persisted by the bucket-save system
state_versionBIGINT UNSIGNEDMonotonically increasing counter used for optimistic concurrency on character-state writes
state_updated_atTIMESTAMPAutomatically updated by MariaDB on every row change

002_inventory.sql — Inventory tables

character_inventories

Header record for each character’s bag. The revision column is an optimistic-concurrency counter: every time any item in the inventory changes, the server increments revision atomically. Clients attach the last-known revision to mutating requests; the server rejects requests that arrive with a stale revision.
ColumnTypeNotes
character_idBIGINT UNSIGNED1-to-1 FK → characters.character_id
capacityINT UNSIGNEDMaximum number of slots; default 40
revisionBIGINT UNSIGNEDIncremented on every inventory change for optimistic locking
updated_atTIMESTAMPAuto-updated by MariaDB

item_instances

One row per item stack occupying a slot. The composite unique key (character_id, container_type, slot_index) guarantees no two items can occupy the same slot in the same container.
ColumnTypeNotes
item_instance_idBIGINT UNSIGNEDSurrogate key
character_idBIGINT UNSIGNEDOwner character
template_idINT UNSIGNEDFK → item_templates.template_id
container_typeTINYINT UNSIGNEDBag type identifier (e.g., 1 = main bag)
slot_indexINT UNSIGNEDZero-based slot position within the container
quantityINT UNSIGNEDStack size; must be > 0 (enforced by CHECK constraint)
durabilityINT UNSIGNEDCurrent durability value; 0 for non-degradable items
bind_flagsINT UNSIGNEDBit mask for bind-on-equip / bind-on-pickup state
versionBIGINT UNSIGNEDPer-instance change counter

inventory_operations

Append-only audit log. Each client request carries a client_request_id (16-byte UUID); the unique key on (character_id, client_request_id) makes operations idempotent — a duplicate submission returns the stored result instead of executing twice.
ColumnTypeNotes
operation_idBIGINT UNSIGNEDAuto-increment surrogate
client_request_idBINARY(16)UUID supplied by the client for idempotency
operation_typeVARCHAR(32)Verb string, e.g., "add", "remove", "move"
reason_codeVARCHAR(64)Source of the change, e.g., "quest_reward", "shop_purchase"
item_instance_idBIGINT UNSIGNEDNullable reference to the affected item row
quantity_deltaBIGINTSigned quantity change (+add / −remove)

003_item_templates.sql — Item definitions

USE game;

CREATE TABLE IF NOT EXISTS item_templates (
  template_id INT UNSIGNED NOT NULL PRIMARY KEY,
  name        VARCHAR(100) NOT NULL,
  max_stack   INT UNSIGNED NOT NULL DEFAULT 1,
  usable      TINYINT(1)   NOT NULL DEFAULT 0,
  CONSTRAINT chk_item_templates_max_stack CHECK (max_stack > 0)
);
ColumnTypeNotes
template_idINT UNSIGNEDDesigner-assigned item type ID; referenced by item_instances.template_id
nameVARCHAR(100)Display name
max_stackINT UNSIGNEDMaximum units per inventory stack; must be ≥ 1
usableTINYINT(1)1 if the item can be consumed/activated by the client

004_item_effects.sql — Effect columns

This migration extends item_templates with two columns that describe the outcome when a usable item is consumed.
USE game;

ALTER TABLE item_templates
  ADD COLUMN IF NOT EXISTS effect_type  TINYINT UNSIGNED NOT NULL DEFAULT 0,
  ADD COLUMN IF NOT EXISTS effect_value INT              NOT NULL DEFAULT 0;
ColumnTypeNotes
effect_typeTINYINT UNSIGNEDNumeric code for the effect category (e.g., 1 = restore HP)
effect_valueINTMagnitude of the effect (e.g., 30 = restore 30 HP)

005_character_state.sql — State columns

This migration adds three columns to characters that track live combat state between server restarts. The columns are already present in 001_schema.sql for fresh deployments; this file exists to bring older schemas forward safely via ADD COLUMN IF NOT EXISTS.
USE game;

ALTER TABLE characters
  ADD COLUMN IF NOT EXISTS current_hp       INT             NOT NULL DEFAULT 100 AFTER z,
  ADD COLUMN IF NOT EXISTS state_version    BIGINT UNSIGNED NOT NULL DEFAULT 0   AFTER current_hp,
  ADD COLUMN IF NOT EXISTS state_updated_at TIMESTAMP       NOT NULL
    DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP   AFTER state_version;
state_version is a monotonically increasing integer incremented by the C++ GameServer’s bucket-save system every time a dirty character row is flushed. Batch writes use this value for optimistic concurrency: a flush is aborted if state_version in the database is higher than the value the server cached when it last read the row.

Build docs developers (and LLMs) love