Skip to content

The Game Loop

TalesMUD runs multiple concurrent goroutines to manage game state. Understanding the update cycles helps you reason about when scripts fire and how frequently game state changes.

Each WebSocket connection spawns four goroutines:

GoroutinePurpose
Message ReceiverReads incoming WebSocket messages from the client
Game LoopProcesses commands and events for this connection
Broadcast HandlerListens for room/global broadcasts and forwards to client
Timeout HandlerDisconnects idle sessions after a configurable period

Independent of player connections, the game engine runs periodic update ticks:

CycleIntervalWhat It Does
Room Updates10 secondsFires room.update events, runs room tick scripts
NPC Updates10 secondsUpdates NPC AI state, handles idle behavior
Spawner Updates5 secondsChecks spawners, spawns NPCs if below max count
Combat Updates2 secondsResolves pending combat rounds, applies status effects

The game loop processes two categories of input:

Commands typed by players:

  1. Client sends message over WebSocket
  2. Receiver goroutine reads it
  3. Message queued to the game loop
  4. CommandProcessor dispatches to appropriate handler
  5. Handler executes game logic, produces output messages
  6. Output routed to appropriate audience

Events from the server itself (NPC deaths, spawns, combat ticks):

  1. Event generated by update cycle or another handler
  2. Queued as a synthetic message
  3. Processed by game loop in same pipeline as player commands

The combat update runs every 2 seconds. When a combat instance is active:

  1. Check for disconnected players (auto-flee)
  2. Apply status effect ticks (DoT damage, HoT healing)
  3. Reduce cooldowns by 1 round for each combatant
  4. Auto-attack: each combatant attacks their target
  5. Check for defeat conditions (HP ≤ 0)
  6. If combat ends: distribute XP and loot, send resolution messages
  7. Update character state in the database

Every 5 seconds, each room’s spawners are checked:

  1. Count current NPC instances in the room for this template
  2. If count < maxCount AND last_spawn + respawn_time has elapsed
  3. Create a new NPC instance (with a unique instance ID)
  4. Place the NPC in the room
  5. Notify players in the room

WebSocket writes are protected by a mutex. All game state mutations go through the service layer which handles SQLite transactions. The Lua VM pool ensures safe concurrent script execution (each script gets its own VM state from the pool).