package main import ( "context" "flag" "os" "os/signal" "syscall" "a301_game_server/config" "a301_game_server/internal/db" "a301_game_server/internal/game" "a301_game_server/internal/network" "a301_game_server/pkg/logger" ) func main() { configPath := flag.String("config", "config/config.yaml", "path to configuration file") flag.Parse() cfg, err := config.Load(*configPath) if err != nil { panic("failed to load config: " + err.Error()) } if err := logger.Init(cfg.Log.Level); err != nil { panic("failed to init logger: " + err.Error()) } defer logger.Sync() ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Connect to PostgreSQL. dbPool, err := db.NewPool(ctx, &cfg.Database) if err != nil { logger.Fatal("failed to connect to database", "error", err) } defer dbPool.Close() // Run migrations. if err := dbPool.RunMigrations(ctx); err != nil { logger.Fatal("failed to run migrations", "error", err) } // Create game server. gs := game.NewGameServer(cfg, dbPool) gs.Start() defer gs.Stop() // Create and start network server. srv := network.NewServer(cfg, gs) // Graceful shutdown on SIGINT/SIGTERM. sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) go func() { sig := <-sigCh logger.Info("received signal, shutting down", "signal", sig) cancel() }() logger.Info("game server starting", "address", cfg.Server.Address(), "tickRate", cfg.World.TickRate, "aoiEnabled", cfg.World.AOI.Enabled, ) if err := srv.Start(ctx); err != nil { logger.Fatal("server error", "error", err) } logger.Info("server shutdown complete") }