The Game Loop
The Game Loop
Section titled “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.
Goroutines per Player Connection
Section titled “Goroutines per Player Connection”Each WebSocket connection spawns four goroutines:
| Goroutine | Purpose |
|---|---|
| Message Receiver | Reads incoming WebSocket messages from the client |
| Game Loop | Processes commands and events for this connection |
| Broadcast Handler | Listens for room/global broadcasts and forwards to client |
| Timeout Handler | Disconnects idle sessions after a configurable period |
Server-Wide Update Cycles
Section titled “Server-Wide Update Cycles”Independent of player connections, the game engine runs periodic update ticks:
| Cycle | Interval | What It Does |
|---|---|---|
| Room Updates | 10 seconds | Fires room.update events, runs room tick scripts |
| NPC Updates | 10 seconds | Updates NPC AI state, handles idle behavior |
| Spawner Updates | 5 seconds | Checks spawners, spawns NPCs if below max count |
| Combat Updates | 2 seconds | Resolves pending combat rounds, applies status effects |
Message Processing
Section titled “Message Processing”The game loop processes two categories of input:
Player Messages
Section titled “Player Messages”Commands typed by players:
- Client sends message over WebSocket
- Receiver goroutine reads it
- Message queued to the game loop
- CommandProcessor dispatches to appropriate handler
- Handler executes game logic, produces output messages
- Output routed to appropriate audience
System Events
Section titled “System Events”Events from the server itself (NPC deaths, spawns, combat ticks):
- Event generated by update cycle or another handler
- Queued as a synthetic message
- Processed by game loop in same pipeline as player commands
Combat Loop Detail
Section titled “Combat Loop Detail”The combat update runs every 2 seconds. When a combat instance is active:
- Check for disconnected players (auto-flee)
- Apply status effect ticks (DoT damage, HoT healing)
- Reduce cooldowns by 1 round for each combatant
- Auto-attack: each combatant attacks their target
- Check for defeat conditions (HP ≤ 0)
- If combat ends: distribute XP and loot, send resolution messages
- Update character state in the database
Spawner Cycle
Section titled “Spawner Cycle”Every 5 seconds, each room’s spawners are checked:
- Count current NPC instances in the room for this template
- If count < maxCount AND last_spawn + respawn_time has elapsed
- Create a new NPC instance (with a unique instance ID)
- Place the NPC in the room
- Notify players in the room
Thread Safety
Section titled “Thread Safety”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).
Next Steps
Section titled “Next Steps”- Combat System — How combat rounds resolve
- Message System — How messages reach players
- Scripting Event Hooks — Reacting to game events