package main import ( "encoding/json" "flag" "fmt" "log" "os" "os/signal" "syscall" "eq2emu/internal/world" ) const defaultConfigFile = "world_config.json" var ( configFile = flag.String("config", defaultConfigFile, "Path to configuration file") listenAddr = flag.String("listen-addr", "", "Override listen address") listenPort = flag.Int("listen-port", 0, "Override listen port") webPort = flag.Int("web-port", 0, "Override web interface port") dbPath = flag.String("db", "", "Override database path") logLevel = flag.String("log-level", "", "Override log level (debug, info, warn, error)") serverName = flag.String("name", "", "Override server name") xpRate = flag.Float64("xp-rate", 0, "Override XP rate") showVersion = flag.Bool("version", false, "Show version and exit") ) // Version information (set at build time) var ( Version = "1.0.0-dev" BuildTime = "unknown" GitCommit = "unknown" ) func main() { flag.Parse() if *showVersion { fmt.Printf("EQ2Go World Server\n") fmt.Printf("Version: %s\n", Version) fmt.Printf("Build Time: %s\n", BuildTime) fmt.Printf("Git Commit: %s\n", GitCommit) os.Exit(0) } // Load configuration config, err := loadConfig(*configFile) if err != nil { log.Fatalf("Failed to load configuration: %v", err) } // Apply command-line overrides applyOverrides(config) // Print startup banner printBanner(config) // Create world server worldServer, err := world.NewWorld(config) if err != nil { log.Fatalf("Failed to create world server: %v", err) } // Start world server if err := worldServer.Start(); err != nil { log.Fatalf("Failed to start world server: %v", err) } // Setup signal handlers sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) // Run server in background go worldServer.Process() // Wait for shutdown signal sig := <-sigChan fmt.Printf("\nReceived signal: %v\n", sig) // Graceful shutdown if err := worldServer.Stop(); err != nil { log.Printf("Error during shutdown: %v", err) } } // loadConfig loads the configuration from file func loadConfig(filename string) (*world.WorldConfig, error) { // Check if config file exists if _, err := os.Stat(filename); os.IsNotExist(err) { // Create default configuration config := createDefaultConfig() // Save default configuration if err := saveConfig(filename, config); err != nil { return nil, fmt.Errorf("failed to save default config: %w", err) } fmt.Printf("Created default configuration file: %s\n", filename) return config, nil } // Load existing configuration file, err := os.Open(filename) if err != nil { return nil, fmt.Errorf("failed to open config file: %w", err) } defer file.Close() var config world.WorldConfig decoder := json.NewDecoder(file) if err := decoder.Decode(&config); err != nil { return nil, fmt.Errorf("failed to decode config: %w", err) } return &config, nil } // saveConfig saves the configuration to file func saveConfig(filename string, config *world.WorldConfig) error { file, err := os.Create(filename) if err != nil { return fmt.Errorf("failed to create config file: %w", err) } defer file.Close() encoder := json.NewEncoder(file) encoder.SetIndent("", " ") if err := encoder.Encode(config); err != nil { return fmt.Errorf("failed to encode config: %w", err) } return nil } // createDefaultConfig creates a default configuration func createDefaultConfig() *world.WorldConfig { return &world.WorldConfig{ // Network settings ListenAddr: "0.0.0.0", ListenPort: 9000, MaxClients: 1000, // Web interface settings WebAddr: "0.0.0.0", WebPort: 8080, WebCertFile: "", WebKeyFile: "", WebKeyPassword: "", // Database settings DatabasePath: "world.db", // Server settings ServerName: "EQ2Go World Server", ServerMOTD: "Welcome to EQ2Go!", LogLevel: "info", // Game settings XPRate: 1.0, TSXPRate: 1.0, CoinRate: 1.0, LootRate: 1.0, // Login server settings LoginServerAddr: "127.0.0.1", LoginServerPort: 5999, LoginServerKey: "", } } // applyOverrides applies command-line overrides to the configuration func applyOverrides(config *world.WorldConfig) { if *listenAddr != "" { config.ListenAddr = *listenAddr } if *listenPort > 0 { config.ListenPort = *listenPort } if *webPort > 0 { config.WebPort = *webPort } if *dbPath != "" { config.DatabasePath = *dbPath } if *logLevel != "" { config.LogLevel = *logLevel } if *serverName != "" { config.ServerName = *serverName } if *xpRate > 0 { config.XPRate = float32(*xpRate) } } // printBanner prints the server startup banner func printBanner(config *world.WorldConfig) { fmt.Println("================================================================================") fmt.Println(" EQ2Go World Server") fmt.Println("================================================================================") fmt.Printf("Version: %s\n", Version) fmt.Printf("Server Name: %s\n", config.ServerName) fmt.Printf("Listen Address: %s:%d\n", config.ListenAddr, config.ListenPort) fmt.Printf("Web Interface: %s:%d\n", config.WebAddr, config.WebPort) fmt.Printf("Database: %s\n", config.DatabasePath) fmt.Printf("Log Level: %s\n", config.LogLevel) fmt.Printf("XP Rate: %.1fx\n", config.XPRate) fmt.Printf("TS XP Rate: %.1fx\n", config.TSXPRate) fmt.Printf("Coin Rate: %.1fx\n", config.CoinRate) fmt.Printf("Loot Rate: %.1fx\n", config.LootRate) fmt.Println("================================================================================") }