This commit is contained in:
cay 2026-04-12 11:06:46 +01:00
parent afc744f0ee
commit f470f39461
2 changed files with 39 additions and 31 deletions

View File

@ -458,6 +458,7 @@ function registerArenaHandlers(io, socket) {
emitToMatch(io, matchId, "arena_ready", { emitToMatch(io, matchId, "arena_ready", {
player1: room.names["player1"] || "Spieler 1", player1: room.names["player1"] || "Spieler 1",
player2: room.names["player2"] || "Spieler 2", player2: room.names["player2"] || "Spieler 2",
boardSync: room.boardCards || [],
}); });
startReadyTimer(io, matchId); startReadyTimer(io, matchId);
} else { } else {
@ -498,10 +499,16 @@ function registerArenaHandlers(io, socket) {
if (!matchId || !slot) return; if (!matchId || !slot) return;
const nextSlot = slot === "player1" ? "player2" : "player1"; const nextSlot = slot === "player1" ? "player2" : "player1";
// Direkt an beide Spieler senden kein Room-Broadcast nötig // Board-State mitschicken → beide Clients können Board synchronisieren
emitToMatch(io, matchId, "turn_change", { activeSlot: nextSlot }); const room = io._arenaRooms?.get(matchId);
const boardCards = room?.boardCards || [];
console.log(`[1v1] Zug: ${slot}${nextSlot} | Match ${matchId}`); emitToMatch(io, matchId, "turn_change", {
activeSlot: nextSlot,
boardSync: boardCards,
});
console.log(`[1v1] Zug: ${slot}${nextSlot} | boardCards=${boardCards.length} | Match ${matchId}`);
}); });
/* ── Karte gespielt → direkt an Gegner senden ── */ /* ── Karte gespielt → direkt an Gegner senden ── */
@ -531,8 +538,8 @@ function registerArenaHandlers(io, socket) {
io._turnInit.add(matchId); io._turnInit.add(matchId);
emitToMatch(io, matchId, "turn_change", { activeSlot: starterSlot }); emitToMatch(io, matchId, "turn_change", { activeSlot: starterSlot });
console.log(`[1v1] Startzug: ${starterSlot} | Match ${matchId}`); console.log(`[1v1] Startzug: ${starterSlot} | Match ${matchId}`);
// Cleanup nach 10s // Cleanup nach 60s (lang genug damit doppelte end_turn_init geblockt bleiben)
setTimeout(() => io._turnInit?.delete(matchId), 10000); setTimeout(() => io._turnInit?.delete(matchId), 60000);
}); });
/* ── 2v2 & 4v4 ── */ /* ── 2v2 & 4v4 ── */

View File

@ -840,6 +840,8 @@
console.log("[Arena] arena_ready:", data); console.log("[Arena] arena_ready:", data);
clearTimeout(readyFallbackTimer); clearTimeout(readyFallbackTimer);
document.getElementById("connecting-overlay")?.remove(); document.getElementById("connecting-overlay")?.remove();
// Board sync falls Karten bereits gespielt wurden
if (data.boardSync) applyBoardSync(data.boardSync);
// Gegner-Name: URL-Parameter hat Vorrang (aus match_found, 100% korrekt) // Gegner-Name: URL-Parameter hat Vorrang (aus match_found, 100% korrekt)
// Server-Daten nur als Fallback wenn URL-Name fehlt // Server-Daten nur als Fallback wenn URL-Name fehlt
const oppName = amIPlayer1 ? data.player2 : data.player1; const oppName = amIPlayer1 ? data.player2 : data.player1;
@ -863,35 +865,36 @@
if (lockOverlay) lockOverlay.style.display = "flex"; if (lockOverlay) lockOverlay.style.display = "flex";
}); });
/* ── Board-Sync bei Reconnect ──────────────────────────── */ /* ── Board synchronisieren (aus boardSync Array) ───────── */
socket.on("board_sync", (data) => { function applyBoardSync(cards) {
if (!data.cards) return; if (!cards || !cards.length) return;
data.cards.forEach((cardData) => { cards.forEach((cardData) => {
const slotEl = document.getElementById(cardData.boardSlot); const slotEl = document.getElementById(cardData.boardSlot);
if (!slotEl || boardState[cardData.boardSlot]) return; // bereits gesetzt if (!slotEl || boardState[cardData.boardSlot]) return;
boardState[cardData.boardSlot] = cardData.card; boardState[cardData.boardSlot] = cardData.card;
renderCardOnBoard(slotEl, cardData.card); renderCardOnBoard(slotEl, cardData.card);
}); });
console.log("[1v1] Board sync:", data.cards.length, "Karten geladen"); console.log("[1v1] Board sync:", cards.length, "Karten");
}
/* ── Board-Sync bei Reconnect ──────────────────────────── */
socket.on("board_sync", (data) => {
if (data.cards) applyBoardSync(data.cards);
}); });
/* ── Server: Zugwechsel ──────────────────────────────── */ /* ── Server: Zugwechsel ──────────────────────────────── */
let lastTurnChangeTs = 0; let lastTurnChangeActive = null;
socket.on("turn_change", (data) => { socket.on("turn_change", (data) => {
// Duplikat-Schutz: identisches Event innerhalb 500ms ignorieren // Board synchronisieren falls mitgeliefert
const now = Date.now(); if (data.boardSync) applyBoardSync(data.boardSync);
if (now - lastTurnChangeTs < 200) return;
lastTurnChangeTs = now;
const nowMyTurn = data.activeSlot === mySlot; const nowMyTurn = data.activeSlot === mySlot;
console.log(
"[1v1] turn_change:", // Duplikat-Schutz: gleiche Zustandsänderung nicht doppelt anwenden
data.activeSlot, if (data.activeSlot === lastTurnChangeActive && nowMyTurn === isMyTurn) return;
"| ich bin:", lastTurnChangeActive = data.activeSlot;
mySlot,
"| meinZug:", console.log("[1v1] turn_change:", data.activeSlot, "| ich:", mySlot, "| meinZug:", nowMyTurn);
nowMyTurn,
);
setTurnState(nowMyTurn); setTurnState(nowMyTurn);
}); });
@ -992,15 +995,13 @@
document.getElementById("board-lock-overlay")?.remove(); document.getElementById("board-lock-overlay")?.remove();
// Festlegen ob ich der linke Spieler bin // Festlegen ob ich der linke Spieler bin
// flip=false: player1=links, flip=true: player1=rechts
amILeftPlayer = flip ? mySlot === "player2" : mySlot === "player1"; amILeftPlayer = flip ? mySlot === "player2" : mySlot === "player1";
// Linker Spieler beginnt // Startspieler NUR vom Server bestimmen lassen kein lokales setTurnState!
setTurnState(amILeftPlayer); // Nur der erste Spieler sendet end_turn_init, Server entscheidet wer beginnt
socket.emit("end_turn_init", { const starterSlot = flip ? "player2" : "player1";
matchId, socket.emit("end_turn_init", { matchId, starterSlot });
starterSlot: flip ? "player2" : "player1", // turn_change vom Server setzt dann den korrekten Zustand für beide Spieler
});
} }
}); });