Private
Public Access
1
0

Integrate direct WebSocket-based leaderboard functionality for real-time updates and requests. Refactor related client-side logic to utilize this new connection.

This commit is contained in:
Sebastian Unterschütz
2026-01-04 02:26:23 +01:00
parent 41d15c60d3
commit ce51a2ba4f
11 changed files with 192 additions and 39 deletions

View File

@@ -190,6 +190,17 @@ func (g *Game) connectForLeaderboard() {
return
}
// Temporäre Daten für Leaderboard-Verbindung
if g.playerName == "" {
g.playerName = "LeaderboardViewer"
}
if g.roomID == "" {
g.roomID = "leaderboard_only"
}
if g.gameMode == "" {
g.gameMode = "solo"
}
// Neue Verbindung aufbauen
g.connectToServer()
@@ -200,6 +211,13 @@ func (g *Game) connectForLeaderboard() {
// requestLeaderboard fordert das Leaderboard an
func (g *Game) requestLeaderboard() {
// Verbindung aufbauen falls nicht vorhanden
if g.wsConn == nil || !g.wsConn.connected {
log.Println("📡 Keine Verbindung für Leaderboard, stelle Verbindung her...")
go g.connectForLeaderboard()
return
}
mode := "solo"
if g.gameMode == "coop" {
mode = "coop"

View File

@@ -0,0 +1,9 @@
//go:build !wasm
// +build !wasm
package main
// notifyGameStarted ist ein Stub für native Builds
func (g *Game) notifyGameStarted() {
// Native hat kein JavaScript-Interface
}

View File

@@ -0,0 +1,17 @@
//go:build js && wasm
// +build js,wasm
package main
import (
"log"
"syscall/js"
)
// notifyGameStarted benachrichtigt JavaScript dass das Spiel startet
func (g *Game) notifyGameStarted() {
if startFunc := js.Global().Get("onGameStarted"); !startFunc.IsUndefined() {
startFunc.Invoke()
log.Println("🎮 Game Started - Benachrichtigung an JavaScript gesendet")
}
}

View File

@@ -0,0 +1,9 @@
//go:build !wasm
// +build !wasm
package main
// sendLobbyUpdateToJS ist ein Stub für native Builds (kein HTML-Interface)
func (g *Game) sendLobbyUpdateToJS() {
// Native hat kein HTML-Overlay, nichts zu tun
}

9
cmd/client/lobby_wasm.go Normal file
View File

@@ -0,0 +1,9 @@
//go:build js && wasm
// +build js,wasm
package main
// sendLobbyUpdateToJS sendet Lobby-Updates an das HTML-Interface
func (g *Game) sendLobbyUpdateToJS() {
g.sendLobbyPlayersToJS()
}

View File

@@ -367,7 +367,10 @@ func (g *Game) updateLobby() {
// Spiel wurde gestartet?
if g.gameState.Status == "COUNTDOWN" || g.gameState.Status == "RUNNING" {
g.appState = StateGame
if g.appState != StateGame {
g.appState = StateGame
g.notifyGameStarted() // Benachrichtige JavaScript dass Spiel startet
}
}
}

View File

@@ -3,6 +3,83 @@ let wasmReady = false;
let gameStarted = false;
let audioMuted = false;
// WebSocket for Leaderboard (direct JS connection)
let leaderboardWS = null;
let leaderboardSessionID = 'lb_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
function connectLeaderboardWebSocket() {
if (leaderboardWS && leaderboardWS.readyState === WebSocket.OPEN) {
return; // Already connected
}
const wsURL = 'ws://localhost:8080/ws';
leaderboardWS = new WebSocket(wsURL);
leaderboardWS.onopen = () => {
console.log('📡 Leaderboard WebSocket connected with session:', leaderboardSessionID);
// Send JOIN message to register session
const joinMsg = JSON.stringify({
type: 'join',
payload: {
name: leaderboardSessionID,
room_id: 'leaderboard_viewer',
game_mode: 'solo',
is_host: false,
team_name: ''
}
});
leaderboardWS.send(joinMsg);
console.log('📝 Registered leaderboard session:', leaderboardSessionID);
};
leaderboardWS.onmessage = (event) => {
try {
const msg = JSON.parse(event.data);
if (msg.type === 'leaderboard_response') {
console.log('📊 Received leaderboard:', msg.payload?.entries?.length || 0, 'entries');
updateLeaderboard(msg.payload?.entries || []);
}
} catch (e) {
console.error('Failed to parse WebSocket message:', e);
}
};
leaderboardWS.onerror = (error) => {
console.error('❌ Leaderboard WebSocket error:', error);
};
leaderboardWS.onclose = () => {
console.log('📡 Leaderboard WebSocket closed');
leaderboardWS = null;
};
}
function requestLeaderboardDirect() {
connectLeaderboardWebSocket();
// Wait for connection then request
const checkAndRequest = setInterval(() => {
if (leaderboardWS && leaderboardWS.readyState === WebSocket.OPEN) {
clearInterval(checkAndRequest);
const msg = JSON.stringify({
type: 'leaderboard_request',
payload: {
mode: 'solo',
limit: 10
}
});
leaderboardWS.send(msg);
console.log('📤 Requesting leaderboard via WebSocket (session:', leaderboardSessionID + ')');
}
}, 100);
// Timeout after 3 seconds
setTimeout(() => clearInterval(checkAndRequest), 3000);
}
// Initialize WASM
async function initWASM() {
const go = new Go();
@@ -17,11 +94,9 @@ async function initWASM() {
console.log('✅ WASM loaded successfully');
// Load initial leaderboard
// Load initial leaderboard via direct WebSocket
setTimeout(() => {
if (window.requestLeaderboard) {
window.requestLeaderboard();
}
requestLeaderboardDirect();
}, 500);
} catch (err) {
console.error('❌ Failed to load WASM:', err);
@@ -187,23 +262,13 @@ function joinRoom() {
// Lobby Functions
function startGameFromLobby() {
// Host startet das Spiel
hideAllScreens();
document.getElementById('menu').style.display = 'none';
gameStarted = true;
// Canvas sichtbar machen
const canvas = document.querySelector('canvas');
if (canvas) {
canvas.classList.add('game-active');
}
// Host startet das Spiel - Lobby bleibt sichtbar bis Server COUNTDOWN/RUNNING sendet
// Signal an WASM senden dass Spiel starten soll
if (window.startGameFromLobby_WASM) {
window.startGameFromLobby_WASM();
}
console.log('🎮 Host started game from lobby');
console.log('🎮 Host requested game start - waiting for server...');
}
function leaveLobby() {
@@ -230,14 +295,12 @@ function loadLeaderboard() {
const list = document.getElementById('leaderboardList');
list.innerHTML = '<div style="text-align:center; padding:20px;">Lädt Leaderboard...</div>';
// Request leaderboard from WASM
if (window.requestLeaderboard) {
window.requestLeaderboard();
}
// Request leaderboard via direct WebSocket
requestLeaderboardDirect();
// Fallback timeout
setTimeout(() => {
if (list.innerHTML.includes('Lädt')) {
if (list && list.innerHTML.includes('Lädt')) {
list.innerHTML = '<div style="text-align:center; padding:20px; color:#888;">Keine Daten verfügbar</div>';
}
}, 3000);
@@ -370,19 +433,32 @@ function showGameOver(score) {
localStorage.setItem('escape_local_highscore', score);
}
// Request leaderboard
if (window.requestLeaderboard) {
window.requestLeaderboard();
}
// Request leaderboard via direct WebSocket
requestLeaderboardDirect();
console.log('💀 Game Over! Score:', score);
}
// Called by WASM when game actually starts
function onGameStarted() {
console.log('🎮 Game Started - Making canvas visible');
hideAllScreens();
document.getElementById('menu').style.display = 'none';
gameStarted = true;
// Canvas sichtbar machen
const canvas = document.querySelector('canvas');
if (canvas) {
canvas.classList.add('game-active');
}
}
// Export functions for WASM to call
window.showMenu = showMenu;
window.hideMenu = hideMenu;
window.updateLeaderboard = updateLeaderboard;
window.showGameOver = showGameOver;
window.onGameStarted = onGameStarted;
// Initialize on load
initWASM();

View File

@@ -5,19 +5,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>Escape From Teacher</title>
<link rel="stylesheet" href="style.css">
<style>
/* DEBUG: Force menu visibility */
#menu {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background: rgba(0, 0, 0, 0.95) !important;
z-index: 10000 !important;
display: flex !important;
}
</style>
</head>
<body>

Binary file not shown.

BIN
cmd/client/web/pc-trash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<style>
body { margin: 0; padding: 0; background: red; }
.test-menu {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.9);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 48px;
}
</style>
</head>
<body>
<div class="test-menu">TEST - SIEHST DU MICH?</div>
</body>
</html>