//go:build js && wasm // +build js,wasm package main import ( "log" "syscall/js" ) // notifyWasmReady signalisiert JavaScript dass WASM vollständig geladen ist func (g *Game) notifyWasmReady() { if readyFunc := js.Global().Get("onWasmReady"); !readyFunc.IsUndefined() { readyFunc.Invoke() log.Println("✅ WASM Ready-Signal an JavaScript gesendet") } } // setupJavaScriptBridge registriert JavaScript-Funktionen für HTML-Menü Interaktion func (g *Game) setupJavaScriptBridge() { // startGame(mode, playerName, roomID, teamName, isHost) startGameFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { if len(args) < 2 { log.Println("❌ startGame: Nicht genug Argumente") return nil } mode := args[0].String() // "solo" oder "coop" playerName := args[1].String() // Spielername // Spieler-Daten setzen g.playerName = playerName g.gameMode = mode g.savePlayerName(playerName) if mode == "solo" { // Solo Mode - Jetzt standardmäßig OFFLINE g.isHost = true g.startOfflineGame() log.Printf("🎮 Solo-Spiel OFFLINE gestartet: %s", playerName) return nil } else if mode == "coop" && len(args) >= 5 { // Co-op Mode - in die Lobby roomID := args[2].String() teamName := args[3].String() isHost := args[4].Bool() g.roomID = roomID g.teamName = teamName g.isHost = isHost g.appState = StateLobby log.Printf("🎮 Co-op-Lobby erstellt: %s (Room: %s, Team: %s, Host: %v)", playerName, roomID, teamName, isHost) } // Verbindung starten go g.connectAndStart() return nil }) // requestLeaderboard() requestLeaderboardFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { log.Println("📊 Leaderboard angefordert") go g.requestLeaderboard() return nil }) // setMusicVolume(volume) setMusicVolumeFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { if len(args) > 0 { volume := args[0].Float() g.audio.SetMusicVolume(volume) log.Printf("🎵 Musik-Lautstärke: %.0f%%", volume*100) } return nil }) // setSFXVolume(volume) setSFXVolumeFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { if len(args) > 0 { volume := args[0].Float() g.audio.SetSFXVolume(volume) log.Printf("🔊 SFX-Lautstärke: %.0f%%", volume*100) } return nil }) // startGameFromLobby_WASM() - Host startet Spiel aus HTML Lobby startGameFromLobbyFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { log.Println("🎮 Host startet Spiel aus HTML Lobby") go g.sendStartRequest() return nil }) // setTeamName_WASM(teamName) - Host setzt Team-Namen setTeamNameFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { if len(args) > 0 { teamName := args[0].String() g.teamName = teamName log.Printf("🏷️ Team-Name gesetzt: '%s'", teamName) go g.sendSetTeamNameInput(teamName) } return nil }) // Im globalen Scope registrieren js.Global().Set("startGame", startGameFunc) js.Global().Set("requestLeaderboard", requestLeaderboardFunc) js.Global().Set("setMusicVolume", setMusicVolumeFunc) js.Global().Set("setSFXVolume", setSFXVolumeFunc) js.Global().Set("startGameFromLobby_WASM", startGameFromLobbyFunc) js.Global().Set("setTeamName_WASM", setTeamNameFunc) log.Println("✅ JavaScript Bridge registriert") log.Printf("🔍 window.startGame defined: %v", !js.Global().Get("startGame").IsUndefined()) log.Printf("🔍 window.startGameFromLobby_WASM defined: %v", !js.Global().Get("startGameFromLobby_WASM").IsUndefined()) } // Leaderboard an JavaScript senden func (g *Game) sendLeaderboardToJS() { g.leaderboardMutex.Lock() entries := make([]interface{}, len(g.leaderboard)) for i, entry := range g.leaderboard { entries[i] = map[string]interface{}{ "player_name": entry.PlayerName, "score": entry.Score, "player_code": entry.PlayerCode, } } g.leaderboardMutex.Unlock() // JavaScript-Funktion aufrufen if updateFunc := js.Global().Get("updateLeaderboard"); !updateFunc.IsUndefined() { jsEntries := js.ValueOf(entries) updateFunc.Invoke(jsEntries) log.Printf("📤 Leaderboard an JavaScript gesendet: %d Einträge", len(entries)) } } // Game Over Screen an JavaScript senden func (g *Game) sendGameOverToJS(score int) { if gameOverFunc := js.Global().Get("showGameOver"); !gameOverFunc.IsUndefined() { gameOverFunc.Invoke(score) log.Printf("💀 Game Over an JavaScript gesendet: Score=%d", score) } } // Lobby Player List an JavaScript senden func (g *Game) sendLobbyPlayersToJS() { g.stateMutex.Lock() players := make([]interface{}, 0, len(g.gameState.Players)) hostID := g.gameState.HostID teamName := g.gameState.TeamName for id, p := range g.gameState.Players { name := p.Name if name == "" { name = id } isHost := (id == hostID) players = append(players, map[string]interface{}{ "name": name, "is_host": isHost, }) } g.stateMutex.Unlock() // JavaScript-Funktion aufrufen if updateFunc := js.Global().Get("updateLobbyPlayers"); !updateFunc.IsUndefined() { jsPlayers := js.ValueOf(players) updateFunc.Invoke(jsPlayers) log.Printf("👥 Lobby-Spieler an JavaScript gesendet: %d Spieler", len(players)) } // Team-Name an JavaScript senden if updateTeamFunc := js.Global().Get("updateLobbyTeamName"); !updateTeamFunc.IsUndefined() { myID := g.getMyPlayerID() isHost := (myID == hostID) updateTeamFunc.Invoke(teamName, isHost) log.Printf("🏷️ Team-Name an JavaScript gesendet: '%s' (isHost: %v)", teamName, isHost) } }