@@ -62,7 +65,7 @@ export async function loadArena() {
initArenaModes();
}
-/* ── Styles ────────────────────────────────────────────────────────────────── */
+/* ── Styles ─────────────────────────────────────────────────────────────────── */
function injectArenaStyles() {
if (document.getElementById("arena-popup-styles")) return;
@@ -105,8 +108,19 @@ function injectArenaStyles() {
text-decoration: underline;
animation: none;
}
- #arena-queue-status .qs-cancel:hover {
+ #arena-queue-status .qs-cancel:hover { color: #e74c3c; }
+
+ /* ── 2v2 Fehlermeldung ── */
+ #arena-2v2-error {
+ padding: 10px 14px;
+ border-radius: 8px;
+ background: rgba(231,76,60,0.12);
+ border: 1px solid rgba(231,76,60,0.4);
color: #e74c3c;
+ font-family: "Cinzel", serif;
+ font-size: 12px;
+ text-align: center;
+ margin-bottom: 8px;
}
/* ── Backdrop ── */
@@ -152,21 +166,6 @@ function injectArenaStyles() {
align-items: center;
gap: 10px;
}
- #arena-popup-titlebar .ap-dots {
- display: flex;
- gap: 7px;
- }
- #arena-popup-titlebar .ap-dot {
- width: 13px;
- height: 13px;
- border-radius: 50%;
- cursor: pointer;
- transition: filter 0.15s;
- }
- #arena-popup-titlebar .ap-dot:hover { filter: brightness(1.3); }
- #arena-popup-titlebar .ap-dot.close { background: #e74c3c; border: 1px solid rgba(0,0,0,0.25); }
- #arena-popup-titlebar .ap-dot.min { background: #f1c40f; border: 1px solid rgba(0,0,0,0.25); }
- #arena-popup-titlebar .ap-dot.expand { background: #2ecc71; border: 1px solid rgba(0,0,0,0.25); }
#arena-popup-titlebar .ap-title {
font-family: "Cinzel", serif;
font-size: 13px;
@@ -381,13 +380,12 @@ function injectArenaStyles() {
document.head.appendChild(style);
}
-/* ── Socket-Referenz holen ─────────────────────────────────────────────────── */
+/* ── Socket-Referenz holen ──────────────────────────────────────────────────── */
function getSocket() {
- // Wird von der Haupt-App als window._socket bereitgestellt
return window._socket || null;
}
-/* ── Klick-Handler initialisieren ─────────────────────────────────────────── */
+/* ── Klick-Handler initialisieren ──────────────────────────────────────────── */
function initArenaModes() {
document.querySelectorAll(".arena-mode-card").forEach((card) => {
card.addEventListener("click", () => {
@@ -406,31 +404,40 @@ function initArenaModes() {
/* ══════════════════════════════════════════════════════════
2v2 LOBBY
══════════════════════════════════════════════════════════ */
-let my2v2TeamId = null;
-let myArenaData = null;
+let my2v2TeamId = null;
+let myArenaData = null;
async function open2v2Lobby() {
const socket = getSocket();
- if (!socket) { showArenaError("Keine Verbindung zum Server."); return; }
+
+ // Screen ZUERST wechseln – so sind Fehlermeldungen sichtbar
+ document.getElementById("arena-mode-screen").style.display = "none";
+ document.getElementById("arena-2v2-screen").style.display = "flex";
+
+ if (!socket) {
+ console.error("[2v2] Kein Socket – window._socket:", window._socket);
+ show2v2Error("Keine Verbindung zum Server. Bitte Seite neu laden.");
+ return;
+ }
// Spielerdaten laden
if (!myArenaData) {
try {
+ console.log("[2v2] Lade Spielerdaten…");
const res = await fetch("/arena/me");
- if (!res.ok) throw new Error(res.status);
+ if (!res.ok) throw new Error("HTTP " + res.status);
myArenaData = await res.json();
- } catch {
- showArenaError("Spielerdaten konnten nicht geladen werden.");
+ console.log("[2v2] Spielerdaten:", myArenaData);
+ } catch (err) {
+ console.error("[2v2] Spielerdaten Fehler:", err);
+ show2v2Error("Spielerdaten konnten nicht geladen werden. (Eingeloggt?)");
return;
}
}
- // Screen wechseln
- document.getElementById("arena-mode-screen").style.display = "none";
- document.getElementById("arena-2v2-screen").style.display = "flex";
-
// Lobbyliste anfordern
socket.emit("get_2v2_lobbies");
+ console.log("[2v2] get_2v2_lobbies gesendet");
// Zurück-Button
document.getElementById("arena-2v2-back").onclick = () => {
@@ -442,6 +449,7 @@ async function open2v2Lobby() {
// Team erstellen
document.getElementById("arena-create-team-btn").onclick = () => {
+ console.log("[2v2] Team erstellen geklickt – sende create_2v2_team mit:", myArenaData);
socket.emit("create_2v2_team", myArenaData);
};
@@ -454,12 +462,17 @@ async function open2v2Lobby() {
socket.off("match_found_2v2");
socket.off("2v2_error");
- socket.on("2v2_lobbies", (list) => render2v2LobbyList(list, socket));
+ socket.on("2v2_lobbies", (list) => {
+ console.log("[2v2] Lobbies empfangen:", list);
+ render2v2LobbyList(list, socket);
+ });
socket.on("2v2_team_joined", (data) => {
+ console.log("[2v2] Team joined:", data);
my2v2TeamId = data.teamId;
document.getElementById("arena-team-panel").style.display = "block";
document.getElementById("arena-lobby-section").style.display = "none";
+ hide2v2Error();
});
socket.on("2v2_team_update", (data) => render2v2TeamPanel(data, socket));
@@ -467,7 +480,6 @@ async function open2v2Lobby() {
socket.on("2v2_partner_left", (data) => {
const status = document.getElementById("arena-team-status");
if (status) status.innerHTML = `
⚠️ ${data.name} hat das Team verlassen.`;
- // Bereit-Button zurücksetzen
render2v2TeamPanel({ teamId: my2v2TeamId, players: [{ name: myArenaData.name, level: myArenaData.level, ready: false }], count: 1 }, socket);
});
@@ -496,8 +508,8 @@ async function open2v2Lobby() {
});
socket.on("2v2_error", (data) => {
- const status = document.getElementById("arena-team-status");
- if (status) { status.innerHTML = `
❌ ${data.message}`; }
+ console.warn("[2v2] Fehler vom Server:", data.message);
+ show2v2Error(data.message);
});
}
@@ -527,9 +539,9 @@ function render2v2LobbyList(list, socket) {
}
function render2v2TeamPanel(data, socket) {
- const playersEl = document.getElementById("arena-team-players");
- const actionsEl = document.getElementById("arena-team-actions");
- const statusEl = document.getElementById("arena-team-status");
+ const playersEl = document.getElementById("arena-team-players");
+ const actionsEl = document.getElementById("arena-team-actions");
+ const statusEl = document.getElementById("arena-team-status");
if (!playersEl || !actionsEl) return;
playersEl.innerHTML = data.players.map(p => `
@@ -544,7 +556,7 @@ function render2v2TeamPanel(data, socket) {
actionsEl.innerHTML = `
Warte auf Partner…
`;
if (statusEl) statusEl.innerHTML = "";
} else {
- const myEntry = data.players.find(p => p.name === myArenaData?.name);
+ const myEntry = data.players.find(p => p.name === myArenaData?.name);
const iAmReady = myEntry?.ready;
actionsEl.innerHTML = iAmReady
? `
`
@@ -572,7 +584,21 @@ function leave2v2Team(socket) {
socket.off("2v2_error");
}
-/* ── 1v1: Hauptlogik ───────────────────────────────────────────────────────── */
+/* ── 2v2 Fehlermeldung ──────────────────────────────────────────────────────── */
+function show2v2Error(msg) {
+ const el = document.getElementById("arena-2v2-error");
+ if (!el) return;
+ el.textContent = "❌ " + msg;
+ el.style.display = "block";
+ setTimeout(() => { el.style.display = "none"; }, 4000);
+}
+
+function hide2v2Error() {
+ const el = document.getElementById("arena-2v2-error");
+ if (el) el.style.display = "none";
+}
+
+/* ── 1v1: Hauptlogik ────────────────────────────────────────────────────────── */
async function handle1v1Click(card) {
const socket = getSocket();
if (!socket) {
@@ -580,30 +606,25 @@ async function handle1v1Click(card) {
return;
}
- // Bereits in Suche?
if (card.classList.contains("searching")) return;
- // Spielerdaten laden
let me;
try {
const res = await fetch("/arena/me");
if (!res.ok) throw new Error("Status " + res.status);
me = await res.json();
} catch (err) {
- console.error("[1v1] Spielerdaten konnten nicht geladen werden:", err);
+ console.error("[1v1] Spielerdaten Fehler:", err);
showArenaError("Spielerdaten konnten nicht geladen werden. (Eingeloggt?)");
return;
}
- // UI: Suche läuft
setCardSearching(card, true);
showQueueStatus(me.level);
- // Sicherstellen, dass keine alten Listener hängen
socket.off("match_found");
socket.off("queue_status");
- // Queue-Status empfangen
socket.on("queue_status", (data) => {
if (data.status === "waiting") {
showQueueStatus(me.level, data.poolSize);
@@ -613,7 +634,6 @@ async function handle1v1Click(card) {
}
});
- // Match gefunden
socket.once("match_found", (data) => {
socket.off("queue_status");
setCardSearching(card, false);
@@ -628,15 +648,14 @@ async function handle1v1Click(card) {
});
});
- // Matchmaking starten
socket.emit("join_1v1", {
- id: me.id,
- name: me.name,
+ id: me.id,
+ name: me.name,
level: me.level,
});
}
-/* ── Queue abbrechen ───────────────────────────────────────────────────────── */
+/* ── Queue abbrechen ────────────────────────────────────────────────────────── */
function cancelQueue(card) {
const socket = getSocket();
if (socket) {
@@ -648,9 +667,8 @@ function cancelQueue(card) {
hideQueueStatus();
}
-/* ── Match-Found Splash ────────────────────────────────────────────────────── */
+/* ── Match-Found Splash ─────────────────────────────────────────────────────── */
function showMatchFoundOverlay(myName, opponentName, onDone) {
- // Verhindert doppeltes Öffnen
if (document.getElementById("match-found-overlay")) return;
const overlay = document.createElement("div");
@@ -662,22 +680,19 @@ function showMatchFoundOverlay(myName, opponentName, onDone) {
`;
document.body.appendChild(overlay);
- // Ladebalken animieren
requestAnimationFrame(() => {
const bar = document.getElementById("mfBar");
if (bar) bar.style.width = "100%";
});
- // Nach 1.6s zum Spielfeld
setTimeout(() => {
overlay.remove();
onDone();
}, 1600);
}
-/* ── Popup öffnen ──────────────────────────────────────────────────────────── */
+/* ── Popup öffnen ───────────────────────────────────────────────────────────── */
function openArenaPopup(src, opponentName, matchId) {
- // Vorhandenen Popup schließen (falls mehrfach)
document.getElementById("arena-backdrop")?.remove();
document.getElementById("arena-popup")?.remove();
@@ -688,8 +703,8 @@ function openArenaPopup(src, opponentName, matchId) {
popup.id = "arena-popup";
const title = opponentName
- ? `⚔️ 1v1 · vs ${opponentName}`
- : "⚔️ Arena · 1v1";
+ ? `⚔️ Arena · vs ${opponentName}`
+ : "⚔️ Arena";
popup.innerHTML = `