213 lines
5.6 KiB
Go
213 lines
5.6 KiB
Go
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("================================================================================")
|
|
} |