package main import ( "encoding/json" "fmt" "os" ) // Config holds all login server configuration type Config struct { Port int `json:"port"` MaxConnections int `json:"max_connections"` TimeoutSeconds int `json:"timeout_seconds"` EnableCompression bool `json:"enable_compression"` EnableEncryption bool `json:"enable_encryption"` AllowAccountCreation bool `json:"allow_account_creation"` DefaultSubscriptionLevel uint32 `json:"default_subscription_level"` ExpansionFlag uint16 `json:"expansion_flag"` CitiesFlag uint8 `json:"cities_flag"` EnabledRaces uint32 `json:"enabled_races"` SupportedVersions []uint16 `json:"supported_versions"` Database DatabaseConfig `json:"database"` WebServer WebServerConfig `json:"web_server"` WorldServers []WorldServerConfig `json:"world_servers"` } // WebServerConfig holds web server settings type WebServerConfig struct { Enabled bool `json:"enabled"` Address string `json:"address"` Port int `json:"port"` CertFile string `json:"cert_file"` KeyFile string `json:"key_file"` KeyPassword string `json:"key_password"` Username string `json:"username"` Password string `json:"password"` } // WorldServerConfig holds world server connection info type WorldServerConfig struct { ID int32 `json:"id"` Name string `json:"name"` Address string `json:"address"` Port int `json:"port"` SharedKey string `json:"shared_key"` AutoConnect bool `json:"auto_connect"` } // DefaultConfig returns sensible default configuration func DefaultConfig() *Config { return &Config{ Port: 5999, MaxConnections: 1000, TimeoutSeconds: 45, EnableCompression: true, EnableEncryption: true, AllowAccountCreation: false, DefaultSubscriptionLevel: 0xFFFFFFFF, ExpansionFlag: 0x7CFF, CitiesFlag: 0xFF, EnabledRaces: 0xFFFF, SupportedVersions: []uint16{283, 373, 546, 561, 1096, 1208}, Database: DatabaseConfig{ FilePath: "eq2login.db", MaxConnections: 10, BusyTimeout: 5000, }, WebServer: WebServerConfig{ Enabled: true, Address: "0.0.0.0", Port: 8080, }, } } // LoadConfig loads configuration from a JSON file func LoadConfig(filename string) (*Config, error) { // Start with defaults config := DefaultConfig() // Check if config file exists if _, err := os.Stat(filename); os.IsNotExist(err) { // Create default config file if err := SaveConfig(filename, config); err != nil { return nil, fmt.Errorf("failed to create default config: %w", err) } fmt.Printf("Created default configuration file: %s\n", filename) return config, nil } // Read existing config file data, err := os.ReadFile(filename) if err != nil { return nil, fmt.Errorf("failed to read config file: %w", err) } // Parse JSON if err := json.Unmarshal(data, config); err != nil { return nil, fmt.Errorf("failed to parse config JSON: %w", err) } // Validate configuration if err := config.Validate(); err != nil { return nil, fmt.Errorf("invalid configuration: %w", err) } return config, nil } // SaveConfig saves configuration to a JSON file func SaveConfig(filename string, config *Config) error { data, err := json.MarshalIndent(config, "", " ") if err != nil { return fmt.Errorf("failed to marshal config: %w", err) } if err := os.WriteFile(filename, data, 0644); err != nil { return fmt.Errorf("failed to write config file: %w", err) } return nil } // Validate checks if the configuration is valid func (c *Config) Validate() error { if c.Port < 1 || c.Port > 65535 { return fmt.Errorf("invalid port: %d", c.Port) } if c.MaxConnections < 1 { return fmt.Errorf("max_connections must be positive") } if c.TimeoutSeconds < 1 { return fmt.Errorf("timeout_seconds must be positive") } if len(c.SupportedVersions) == 0 { return fmt.Errorf("must specify at least one supported version") } return nil } // IsVersionSupported checks if a client version is supported func (c *Config) IsVersionSupported(version uint16) bool { for _, supported := range c.SupportedVersions { if supported == version { return true } } return false } // GetWorldServerConfig returns configuration for a specific world server func (c *Config) GetWorldServerConfig(id int32) *WorldServerConfig { for i := range c.WorldServers { if c.WorldServers[i].ID == id { return &c.WorldServers[i] } } return nil }