Introduce room assignment logic based on POD_NAME and TOTAL_REPLICAS, enable selective handling for game.join and score.submit events, and update environment configurations.
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 2m28s
All checks were successful
Dynamic Branch Deploy / build-and-deploy (push) Successful in 2m28s
This commit is contained in:
@@ -21,11 +21,22 @@ var (
|
||||
playerSessions = make(map[string]*server.Room)
|
||||
mu sync.RWMutex
|
||||
globalWorld *game.World
|
||||
serverID string // Eindeutige Server-ID für diesen Pod
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Println("🚀 Escape From Teacher SERVER startet...")
|
||||
|
||||
// 0. Server-ID generieren (Hostname oder zufällig)
|
||||
serverID = os.Getenv("HOSTNAME")
|
||||
if serverID == "" {
|
||||
serverID = os.Getenv("POD_NAME")
|
||||
}
|
||||
if serverID == "" {
|
||||
serverID = "server-" + time.Now().Format("150405")
|
||||
}
|
||||
log.Printf("🆔 Server-ID: %s", serverID)
|
||||
|
||||
// 1. WELT & ASSETS LADEN
|
||||
globalWorld = game.NewWorld()
|
||||
loadServerAssets(globalWorld)
|
||||
@@ -100,10 +111,8 @@ func main() {
|
||||
}
|
||||
log.Printf("✅ Verbunden mit NATS: %s", natsURL)
|
||||
|
||||
// 3. HANDLER: GAME JOIN (mit Queue Group für Load Balancing)
|
||||
sub, err := ec.QueueSubscribe("game.join", "game-servers", func(req *game.JoinRequest) {
|
||||
log.Printf("📥 JOIN empfangen: Name=%s, RoomID=%s", req.Name, req.RoomID)
|
||||
|
||||
// 3. HANDLER: GAME JOIN (broadcast - alle Pods hören, aber nur zuständiger erstellt)
|
||||
sub, err := ec.Subscribe("game.join", func(req *game.JoinRequest) {
|
||||
playerID := req.Name
|
||||
if playerID == "" {
|
||||
playerID = "Unknown"
|
||||
@@ -114,13 +123,21 @@ func main() {
|
||||
roomID = "lobby"
|
||||
}
|
||||
|
||||
log.Printf("📥 JOIN empfangen: Name=%s, RoomID=%s", req.Name, roomID)
|
||||
|
||||
// Prüfe ob dieser Pod für den Raum zuständig ist
|
||||
if !isResponsibleForRoom(roomID) {
|
||||
log.Printf("⏭️ Überspringe JOIN - nicht zuständig für Raum '%s'", roomID)
|
||||
return
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
// Raum finden oder erstellen
|
||||
room, exists := rooms[roomID]
|
||||
if !exists {
|
||||
log.Printf("🆕 Erstelle neuen Raum: '%s'", roomID)
|
||||
log.Printf("🆕 Erstelle neuen Raum: '%s' (zuständiger Pod)", roomID)
|
||||
room = server.NewRoom(roomID, nc, globalWorld)
|
||||
rooms[roomID] = room
|
||||
|
||||
@@ -170,8 +187,8 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
// 6. HANDLER: SCORE SUBMISSION
|
||||
_, _ = ec.Subscribe("score.submit", func(submission *game.ScoreSubmission) {
|
||||
// 6. HANDLER: SCORE SUBMISSION (Queue Group - nur ein Pod speichert)
|
||||
_, _ = ec.QueueSubscribe("score.submit", "score-handlers", func(submission *game.ScoreSubmission) {
|
||||
// Verwende Team-Name wenn vorhanden (Coop-Mode), sonst Player-Name (Solo-Mode)
|
||||
displayName := submission.PlayerName
|
||||
if submission.TeamName != "" {
|
||||
@@ -234,6 +251,44 @@ func getEnv(key, defaultValue string) string {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// isResponsibleForRoom prüft ob dieser Pod für den Raum zuständig ist
|
||||
func isResponsibleForRoom(roomID string) bool {
|
||||
// Wenn nur 1 Replica läuft, sind wir immer zuständig
|
||||
totalReplicas := getEnv("TOTAL_REPLICAS", "1")
|
||||
if totalReplicas == "1" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Hash-basierte Zuweisung: RoomID → Pod
|
||||
// Einfacher Ansatz: erster Buchstabe von RoomID
|
||||
// A-M → Pod 0, N-Z → Pod 1
|
||||
if len(roomID) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
firstChar := roomID[0]
|
||||
|
||||
// Für 2 Replicas: A-M und N-Z splitten
|
||||
if totalReplicas == "2" {
|
||||
// Pod Namen sind meist: escape-game-0, escape-game-1, etc.
|
||||
if firstChar <= 'M' || firstChar <= 'm' {
|
||||
return serverID[len(serverID)-1] == '0' || !hasDigitSuffix()
|
||||
}
|
||||
return serverID[len(serverID)-1] == '1' || hasDigitSuffix()
|
||||
}
|
||||
|
||||
// Fallback: immer zuständig
|
||||
return true
|
||||
}
|
||||
|
||||
func hasDigitSuffix() bool {
|
||||
if len(serverID) == 0 {
|
||||
return false
|
||||
}
|
||||
lastChar := serverID[len(serverID)-1]
|
||||
return lastChar >= '0' && lastChar <= '9'
|
||||
}
|
||||
|
||||
func loadServerAssets(w *game.World) {
|
||||
assetDir := "./cmd/client/web/assets"
|
||||
chunkDir := filepath.Join(assetDir, "chunks")
|
||||
|
||||
Reference in New Issue
Block a user