This commit is contained in:
cay 2026-04-08 19:13:50 +01:00
parent 5940dfb01a
commit 3fd04e2211

View File

@ -35,6 +35,9 @@ export async function loadArena() {
<div class="arena-title" style="margin:0;"> 2v2 Team-Lobby</div>
</div>
<!-- Fehlermeldung auf dem 2v2-Screen -->
<div id="arena-2v2-error" style="display:none;"></div>
<!-- Team-Panel (erscheint nach Beitritt) -->
<div id="arena-team-panel" style="display:none;">
<div class="arena-team-box">
@ -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 = `<span style="color:#e74c3c;">⚠️ ${data.name} hat das Team verlassen.</span>`;
// 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 = `<span style="color:#e74c3c;">❌ ${data.message}</span>`; }
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 = `<div class="arena-waiting-partner">Warte auf Partner…</div>`;
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
? `<button class="arena-btn-ready active" disabled>✅ Du bist bereit</button>`
@ -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 &nbsp;·&nbsp; vs ${opponentName}`
: "⚔️ Arena &nbsp;·&nbsp; 1v1";
? `⚔️ Arena &nbsp;·&nbsp; vs ${opponentName}`
: "⚔️ Arena";
popup.innerHTML = `
<div id="arena-popup-titlebar">
@ -703,23 +718,21 @@ function openArenaPopup(src, opponentName, matchId) {
document.body.appendChild(backdrop);
document.body.appendChild(popup);
// Backdrop-Klick deaktiviert Fenster nur über Aufgeben/Spielende schließbar
}
/* ── UI Hilfsfunktionen ────────────────────────────────────────────────────── */
/* ── UI Hilfsfunktionen ────────────────────────────────────────────────────── */
function setCardSearching(card, searching) {
const label = card.querySelector(".arena-mode-label");
const desc = card.querySelector(".arena-mode-desc");
const desc = card.querySelector(".arena-mode-desc");
if (searching) {
card.classList.add("searching");
label.textContent = "⏳ Suche…";
desc.textContent = "Warte auf passenden Gegner…";
desc.textContent = "Warte auf passenden Gegner…";
} else {
card.classList.remove("searching");
label.textContent = "1v1";
desc.textContent = "Einzelkampf Beweis deine Stärke im Duell";
desc.textContent = "Einzelkampf Beweis deine Stärke im Duell";
}
}
@ -727,9 +740,8 @@ function showQueueStatus(myLevel, poolSize) {
const box = document.getElementById("arena-queue-status");
if (!box) return;
const range = 5;
const min = Math.max(1, myLevel - range);
const max = myLevel + range;
const min = Math.max(1, myLevel - 5);
const max = myLevel + 5;
const pool = poolSize ? ` · ${poolSize} Spieler im Pool` : "";
box.style.display = "block";
@ -739,7 +751,6 @@ function showQueueStatus(myLevel, poolSize) {
<span class="qs-cancel" id="qs-cancel-btn">Suche abbrechen</span>
`;
// Cancel-Button Card-Referenz über data-attribute
document.getElementById("qs-cancel-btn")?.addEventListener("click", () => {
const card = document.querySelector(".arena-mode-card[data-mode='1v1']");
if (card) cancelQueue(card);
@ -754,15 +765,15 @@ function hideQueueStatus() {
function showArenaError(msg) {
const box = document.getElementById("arena-queue-status");
if (!box) return;
box.style.display = "block";
box.style.animation = "none";
box.style.display = "block";
box.style.animation = "none";
box.style.borderColor = "rgba(231,76,60,0.5)";
box.style.color = "#e74c3c";
box.textContent = "❌ " + msg;
box.style.color = "#e74c3c";
box.textContent = "❌ " + msg;
setTimeout(() => {
box.style.display = "none";
box.style.animation = "";
box.style.display = "none";
box.style.animation = "";
box.style.borderColor = "";
box.style.color = "";
box.style.color = "";
}, 3000);
}