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 the GameState struct 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 DashMap for 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.
  1. Config Load: Reads .env and Config struct.
  2. Infrastructure Connect: Connects to Postgres (SQLx), Redis, and RabbitMQ (Lapin).
  3. Zone Manager: Initializes ZoneManager to handle multi-server grid logic (e.g., this server is "Grid 2,2").
  4. State Hydration:
    • Creates GameState with empty maps.
    • Hydrates MatchingEngine (Market Data) from DB.
  5. 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.
  6. Server Start: Binds Axum Router to 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:
    1. Regen: HP/Special Attack regeneration (every N ticks).
    2. Prayer: Drains prayer points if active.
    3. Combat: Processes all pending combat interactions.
    4. Status Effects: Applies Poison/Venom damage.

5. Persistence Strategy (Write-Behind)

We do not save to the database on every action.
  1. Dirty Flag: When a player gains XP or changes items, player.dirty = true is set in memory.
  2. Batch Save: A background task runs every 30s.
  3. Execution: It scans players for dirty: true, collects them, and executes UPDATE queries.
  4. Shutdown: On SIGINT/SIGTERM, a forced flush occurs to ensure no data loss.

6. Access Patterns

  • Handlers: API handlers (handlers/) access state via State<Arc<AppState>>.
  • WebSockets: The persistent WebSocket task holds an Arc<GameState> and modifies it directly on incoming packets.