EQ2Go World Server
The EQ2Go World Server is the main game server component that handles client connections, zone management, and game logic. This implementation is converted from the C++ EQ2EMu WorldServer while leveraging modern Go patterns.
Architecture Overview
The world server consists of several key components:
Core Components
- World: Main server instance managing all subsystems
- ZoneList: Zone management with instance support
- ClientList: Connected player management
- Database: SQLite-based data persistence
- CommandManager: Integrated command system
- RuleManager: Server configuration rules
Key Features
- Multi-Zone Support: Manages multiple zone instances
- Client Management: Handles player connections and state
- Command Integration: Full admin and player command support
- Database Integration: SQLite with automatic schema creation
- Configuration Management: JSON-based configuration with CLI overrides
- Graceful Shutdown: Clean shutdown with proper resource cleanup
- Thread-Safe Operations: All components use proper synchronization
Server Components
World Server (world.go
)
The main World struct coordinates all server operations:
type World struct {
db *database.Database
commandManager *commands.CommandManager
rulesManager *rules.RuleManager
zones *ZoneList
clients *ClientList
config *WorldConfig
worldTime *WorldTime
stats *ServerStatistics
}
Key Methods:
NewWorld()
: Creates a new world server instanceStart()
: Starts all server subsystemsStop()
: Gracefully shuts down the serverProcess()
: Main server processing loop
Zone Management (zone_list.go
)
Manages all active zones and their instances:
Features:
- Zone instance management
- Population tracking
- Health monitoring
- Automatic cleanup
- Load balancing
Zone Properties:
- ID, Name, Instance ID
- Level requirements
- Population limits
- Safe locations
- Processing state
Client Management (client_list.go
)
Handles all connected players:
Features:
- Connection tracking
- Linkdead detection
- Admin level management
- Zone transitions
- Command integration
Client State:
- Account/Character information
- Connection details
- Zone assignment
- AFK/Anonymous flags
- Group/Guild membership
Database Integration (database.go
)
SQLite-based persistence with automatic schema creation:
Tables:
- Rules: Server configuration rules
- Accounts: Player accounts
- Characters: Character data
- Zones: Zone definitions
- Server Stats: Performance metrics
- Merchants: NPC merchant data
Configuration System
JSON-based configuration with CLI overrides:
{
"listen_addr": "0.0.0.0",
"listen_port": 9000,
"max_clients": 1000,
"web_port": 8080,
"database_type": "sqlite",
"database_path": "eq2.db",
"database_host": "localhost",
"database_port": 3306,
"database_name": "eq2emu",
"database_user": "eq2",
"database_pass": "password",
"server_name": "EQ2Go World Server",
"xp_rate": 1.0,
"ts_xp_rate": 1.0
}
For MySQL/MariaDB configuration:
{
"database_type": "mysql",
"database_host": "localhost",
"database_port": 3306,
"database_name": "eq2emu",
"database_user": "eq2",
"database_pass": "password"
}
For SQLite configuration (default):
{
"database_type": "sqlite",
"database_path": "eq2.db"
}
Usage
Basic Startup
# Use default configuration
./world_server
# Override specific settings
./world_server -listen-port 9001 -xp-rate 2.0 -name "My EQ2 Server"
# Use custom config file
./world_server -config custom_config.json
Command Line Options
-config
: Configuration file path-listen-addr
: Override listen address-listen-port
: Override listen port-web-port
: Override web interface port-db
: Override database path-log-level
: Override log level-name
: Override server name-xp-rate
: Override XP rate multiplier-version
: Show version information
Configuration File
On first run, a default configuration file is created automatically. The configuration includes:
Network Settings:
- Listen address and port
- Maximum client connections
- Web interface settings
Database Settings:
- Database file path
- Connection pool settings
Game Settings:
- XP/TS XP/Coin/Loot rate multipliers
- Server name and MOTD
- Login server connection details
Integration Points
Command System Integration
The world server fully integrates with the command system:
// Client implements commands.ClientInterface
func (c *Client) GetPlayer() *entity.Entity
func (c *Client) SendMessage(channel int, color int, message string)
func (c *Client) GetAdminLevel() int
// Zone implements commands.ZoneInterface through ZoneAdapter
func (za *ZoneAdapter) GetID() int32
func (za *ZoneAdapter) SendZoneMessage(channel int, color int, message string)
Database Integration
All server data is persisted to SQLite:
// Load server configuration
func (d *Database) LoadRules() (map[string]map[string]string, error)
// Zone management
func (d *Database) GetZones() ([]map[string]any, error)
// Character persistence (planned)
func (d *Database) SaveCharacter(character *Character) error
Rules System Integration
Integrates with the existing rules package:
// Rules manager provides server configuration
rulesManager := rules.NewRuleManager()
// Access server rules
maxLevel := rulesManager.GetInt32(rules.CategoryServer, rules.TypeMaxLevel)
xpRate := rulesManager.GetFloat32(rules.CategoryServer, rules.TypeXPMultiplier)
Server Statistics
The world server tracks comprehensive statistics:
- Connection counts (current, total, peak)
- Zone statistics (active zones, instances)
- Performance metrics (CPU, memory usage)
- Character statistics (total accounts, average level)
Time System
Implements EverQuest II's accelerated time system:
- 3 real seconds = 1 game minute
- 72 real minutes = 1 game day
- Broadcasts time updates to all zones
- Supports custom starting year/date
Lifecycle Management
Startup Sequence
- Load/create configuration file
- Initialize database connection
- Load server data from database
- Initialize command and rules managers
- Start background processing threads
- Begin accepting client connections
Shutdown Sequence
- Stop accepting new connections
- Disconnect all clients gracefully
- Shutdown all zones
- Save server state
- Close database connections
- Clean up resources
Thread Safety
All components use proper Go synchronization:
sync.RWMutex
for read-heavy operationssync.Mutex
for exclusive accesscontext.Context
for cancellationsync.WaitGroup
for graceful shutdown
Future Integration Points
The world server is designed for easy integration with:
Network Layer (UDP Package)
// TODO: Integrate UDP connection handling
func (w *World) handleClientConnection(conn *udp.Connection) {
client := &Client{
Connection: conn,
// ...
}
w.clients.Add(client)
}
Game Systems
// TODO: Integrate additional game systems
w.spellManager = spells.NewManager()
w.questManager = quests.NewManager()
w.itemManager = items.NewManager()
Zone Loading
// TODO: Implement zone loading from database
func (zl *ZoneList) LoadZone(zoneID int32) (*ZoneServer, error) {
// Load zone data from database
// Initialize NPCs, spawns, objects
// Start zone processing
}
Error Handling
Comprehensive error handling throughout:
- Database connection errors
- Configuration validation
- Resource cleanup on errors
- Graceful degradation
- Detailed error logging
Performance Considerations
- Efficient concurrent data structures
- Connection pooling for database
- Batched time updates
- Lazy loading of game data
- Memory pool reuse (planned)
Testing
The world server can be tested in isolation:
# Run server with test configuration
./world_server -config test_config.json -db test.db
# Test with different rates
./world_server -xp-rate 10.0 -name "Test Server"
Monitoring
Built-in monitoring capabilities:
- Server statistics tracking
- Zone health monitoring
- Client connection monitoring
- Performance metrics collection
- Automatic dead zone cleanup
Conclusion
The EQ2Go World Server provides a solid foundation for the EverQuest II server emulator. It maintains compatibility with the original protocol while leveraging modern Go patterns for improved reliability, performance, and maintainability. The modular design allows for easy extension and integration with additional game systems as they are implemented.