package main import ( "fmt" "log" "os" "os/signal" "strconv" "syscall" "thirdcollapse/internal/combat" "thirdcollapse/internal/game" "thirdcollapse/internal/net" ) func main() { dataDir := os.Getenv("DATA_DIR") if dataDir == "" { dataDir = "data" } port := 4000 if len(os.Args) > 1 { if p, err := strconv.Atoi(os.Args[1]); err == nil && p >= 1 && p <= 65535 { port = p } else { log.Fatalf("invalid port: %s (must be 1-65535)", os.Args[1]) } } g := game.New(dataDir) g.Ticks.Start() defer g.Ticks.Stop() g.Ticks.Subscribe(1, func() bool { g.World.Tick() g.MobStore.Tick() combat.TickCombat() g.RegenTick() g.DisconnectTick() g.WanderTick() return true }) addr := fmt.Sprintf(":%d", port) server, err := net.NewServer(addr) if err != nil { log.Fatalf("failed to start server: %v", err) } g.SetHub(server.Hub()) log.Printf("Third Collapse listening on :%d", port) sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) go func() { <-sigCh log.Println("Shutting down...") g.Ticks.Stop() os.Exit(0) }() if err := server.ListenAndServe(g.HandleSession); err != nil { log.Fatalf("server error: %v", err) } }