game server internals
Guide for game server internals
Game Server Internals: The GameState Architecture
Context: This document details the internal architecture of the Rust Game Server (loh-backend), specifically focusing on theGameStatestruct which serves as the central "God Object" for managing the world.
1. Core Concept: GameState vs GameServer
Contrary to typical patterns where a
GameServer struct manages everything, our architecture uses GameState as the central synchronization point.- Definition:
crates/logic-core/src/game_state.rs - Role: Thread-safe container for all runtime data (Players, NPCs, World, Economy).
- Concurrency: Uses
DashMapfor high-concurrency read/write access to players and entities without global locking.
2. The GameState Struct
The
GameState struct is shared across all Axum handlers, WebSocket connections, and background tasks (Tick Loop, Persistence).pub struct GameState {
// --- 1. Entity Storage (Concurrent) ---
pub players: DashMap<Uuid, Player>,
pub npcs: DashMap<u32, Npc>,
// --- 2. Infrastructure ---
pub db_pool: PgPool, // Direct SQLx access
pub redis: Option<ConnectionManager>, // Pub/Sub & Caching
pub zone_manager: RwLock<Option<ZoneManager>>, // Multi-zone orchestration
// --- 3. Communication ---
// Broadcast channel for global/area events (Chat, Combat log)
pub broadcast_tx: broadcast::Sender<BroadcastMessage>,
// Registry of active WebSocket sessions
pub sessions: DashMap<Uuid, Session>,
// Direct channels to individual player actors
pub player_channels: DashMap<Uuid, UnboundedSender<Arc<GamePacket>>>,
// --- 4. Sub-Systems (Managers) ---
// These generic managers handle specific logic domains
pub matching_engine: Arc<RwLock<MatchingEngine>>, // Grand Exchange
pub chat_manager: Arc<ChatManager>, // Public Chat
pub party_manager: Arc<PartyManager>, // Groups/Raids
pub loot_manager: Arc<LootManager>, // Drop distribution
// --- 5. Integrity & Analytics ---
pub heuristics_engine: Arc<HeuristicsEngine>, // Anti-Cheat
pub analytics: Mutex<AnalyticsProcessor>, // Event logging
pub xp_rate_limiter: Arc<XPRateLimiter>, // Anti-Bot
}3. Initialization Flow (main.rs)
The server boots up in
crates/api-game/src/main.rs.- Config Load: Reads
.envandConfigstruct. - Infrastructure Connect: Connects to Postgres (SQLx), Redis, and RabbitMQ (Lapin).
- Zone Manager: Initializes
ZoneManagerto handle multi-server grid logic (e.g., this server is "Grid 2,2"). - State Hydration:
- Creates
GameStatewith empty maps. - Hydrates
MatchingEngine(Market Data) from DB.
- Creates
- Task Spawning:
- Tick Loop: Runs
start_tick_loop(game_state)(Game Logic). - Heartbeat: Reports load to Zone Manager.
- Persistence: Write-behind task saving dirty players every 30s.
- Metrics: Logs DB pool stats.
- Tick Loop: Runs
- Server Start: Binds Axum
Routerto TCP port.
4. The Tick Loop
The specific game logic runs in a separate async task (defined in
tick_engine.rs but orchestrated via GameState::process_tick).- Frequency: 600ms (0.6s) standard tick.
- Operations:
- Regen: HP/Special Attack regeneration (every N ticks).
- Prayer: Drains prayer points if active.
- Combat: Processes all pending combat interactions.
- Status Effects: Applies Poison/Venom damage.
5. Persistence Strategy (Write-Behind)
We do not save to the database on every action.
- Dirty Flag: When a player gains XP or changes items,
player.dirty = trueis set in memory. - Batch Save: A background task runs every 30s.
- Execution: It scans
playersfordirty: true, collects them, and executesUPDATEqueries. - Shutdown: On
SIGINT/SIGTERM, a forced flush occurs to ensure no data loss.
6. Access Patterns
- Handlers: API handlers (
handlers/) accessstateviaState<Arc<AppState>>. - WebSockets: The persistent WebSocket task holds an
Arc<GameState>and modifies it directly on incoming packets.