package main import ( "encoding/json" "io/ioutil" "log" "path/filepath" "runtime" "sync" "github.com/nats-io/nats.go" "git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/game" "git.zb-server.de/ZB-Server/EscapeFromTeacher/pkg/server" ) // Globaler Zustand des Servers var ( rooms = make(map[string]*server.Room) playerSessions = make(map[string]*server.Room) mu sync.RWMutex globalWorld *game.World ) func main() { log.Println("πŸš€ Escape From Teacher SERVER startet...") // 1. WELT & ASSETS LADEN globalWorld = game.NewWorld() loadServerAssets(globalWorld) // 2. NATS VERBINDUNG natsURL := "nats://localhost:4222" nc, err := nats.Connect(natsURL) if err != nil { log.Fatal("❌ Konnte nicht zu NATS verbinden: ", err) } defer nc.Close() ec, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER) if err != nil { log.Fatal("❌ JSON Encoder Fehler: ", err) } log.Println("βœ… Verbunden mit NATS unter", natsURL) // 3. HANDLER: GAME JOIN sub, err := ec.Subscribe("game.join", func(req *game.JoinRequest) { log.Printf("πŸ“₯ JOIN empfangen: Name=%s, RoomID=%s", req.Name, req.RoomID) playerID := req.Name if playerID == "" { playerID = "Unknown" } roomID := req.RoomID if roomID == "" { roomID = "lobby" } mu.Lock() defer mu.Unlock() // Raum finden oder erstellen room, exists := rooms[roomID] if !exists { log.Printf("πŸ†• Erstelle neuen Raum: '%s'", roomID) room = server.NewRoom(roomID, nc, globalWorld) rooms[roomID] = room // Starte den Game-Loop (Physik) go room.RunLoop() } // Spieler hinzufΓΌgen (ID, Name) room.AddPlayer(playerID, req.Name) // Session speichern playerSessions[playerID] = room log.Printf("➑️ Spieler '%s' ist Raum '%s' beigetreten.", playerID, roomID) }) if err != nil { log.Fatal("❌ Fehler beim Subscribe auf game.join:", err) } log.Printf("πŸ‘‚ Lausche auf 'game.join'... (Sub Valid: %v)", sub.IsValid()) // TEST: Auch mit Raw-NATS lauschen nc.Subscribe("game.join", func(m *nats.Msg) { log.Printf("πŸ” RAW NATS: Nachricht empfangen auf game.join: %s", string(m.Data)) }) // 4. HANDLER: INPUT _, _ = ec.Subscribe("game.input", func(input *game.ClientInput) { mu.RLock() room, ok := playerSessions[input.PlayerID] mu.RUnlock() if ok { room.HandleInput(*input) } }) log.Println("βœ… Server bereit. Warte auf Spieler...") // Block forever select {} } func loadServerAssets(w *game.World) { assetDir := "./cmd/client/assets" chunkDir := filepath.Join(assetDir, "chunks") // Manifest laden manifestPath := filepath.Join(assetDir, "assets.json") data, err := ioutil.ReadFile(manifestPath) if err == nil { var m game.AssetManifest json.Unmarshal(data, &m) w.Manifest = m log.Printf("πŸ“¦ Manifest geladen: %d Assets", len(m.Assets)) } else { log.Println("⚠️ Manifest nicht gefunden:", manifestPath) } // Chunks laden files, err := ioutil.ReadDir(chunkDir) if err == nil { for _, f := range files { if filepath.Ext(f.Name()) == ".json" { fullPath := filepath.Join(chunkDir, f.Name()) cData, err := ioutil.ReadFile(fullPath) if err == nil { var chunk game.Chunk json.Unmarshal(cData, &chunk) if chunk.ID == "" { chunk.ID = f.Name()[0 : len(f.Name())-5] } w.ChunkLibrary[chunk.ID] = chunk log.Printf("🧩 Chunk geladen: %s", chunk.ID) } } } } else { log.Println("⚠️ Chunk Ordner nicht gefunden:", chunkDir) } }