vmfg
This commit is contained in:
parent
fea1b776e5
commit
fea2a99b62
@ -1,7 +1,7 @@
|
|||||||
/* ============================================================
|
/* ============================================================
|
||||||
sockets/arena.js
|
sockets/arena.js
|
||||||
1v1 Matchmaking + 2v2 Team-Lobby + 4v4 Team-Lobby
|
1v1 Matchmaking + 2v2 Team-Lobby + 4v4 Team-Lobby
|
||||||
inkl. Kick-Funktion für Team-Leader
|
inkl. Kick-Funktion für Team-Leader wurde getestet
|
||||||
============================================================ */
|
============================================================ */
|
||||||
|
|
||||||
const waitingPool = new Map();
|
const waitingPool = new Map();
|
||||||
@ -23,9 +23,15 @@ function generateId() {
|
|||||||
/* ═══════════════════════════════════════════════════════════
|
/* ═══════════════════════════════════════════════════════════
|
||||||
HELPER: Generisch für 2v2 UND 4v4
|
HELPER: Generisch für 2v2 UND 4v4
|
||||||
═══════════════════════════════════════════════════════════ */
|
═══════════════════════════════════════════════════════════ */
|
||||||
function getTeamMap(mode) { return mode === "4v4" ? teams4v4 : teams2v2; }
|
function getTeamMap(mode) {
|
||||||
function getReadyMap(mode) { return mode === "4v4" ? readyTeams4v4 : readyTeams2v2; }
|
return mode === "4v4" ? teams4v4 : teams2v2;
|
||||||
function getMaxPlayers(mode) { return mode === "4v4" ? 4 : 2; }
|
}
|
||||||
|
function getReadyMap(mode) {
|
||||||
|
return mode === "4v4" ? readyTeams4v4 : readyTeams2v2;
|
||||||
|
}
|
||||||
|
function getMaxPlayers(mode) {
|
||||||
|
return mode === "4v4" ? 4 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
function broadcastLobbies(io, mode) {
|
function broadcastLobbies(io, mode) {
|
||||||
const teams = getTeamMap(mode);
|
const teams = getTeamMap(mode);
|
||||||
@ -51,7 +57,7 @@ function broadcastTeamStatus(io, teamId, mode) {
|
|||||||
const data = {
|
const data = {
|
||||||
teamId,
|
teamId,
|
||||||
leaderId: team.leaderId, // ← Leader-SocketId mitschicken
|
leaderId: team.leaderId, // ← Leader-SocketId mitschicken
|
||||||
players: team.players.map(p => ({
|
players: team.players.map((p) => ({
|
||||||
socketId: p.socketId, // ← für Kick-Button im Frontend
|
socketId: p.socketId, // ← für Kick-Button im Frontend
|
||||||
name: p.player.name,
|
name: p.player.name,
|
||||||
level: p.player.level,
|
level: p.player.level,
|
||||||
@ -80,15 +86,20 @@ function tryMatchmaking_nvn(io, mode) {
|
|||||||
|
|
||||||
const matchId = `${mode}_${generateId()}`;
|
const matchId = `${mode}_${generateId()}`;
|
||||||
const allPlayers = [
|
const allPlayers = [
|
||||||
...team1.players.map(p => ({ team: 1, ...p })),
|
...team1.players.map((p) => ({ team: 1, ...p })),
|
||||||
...team2.players.map(p => ({ team: 2, ...p })),
|
...team2.players.map((p) => ({ team: 2, ...p })),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const p of allPlayers) {
|
for (const p of allPlayers) {
|
||||||
const opponents = allPlayers.filter(x => x.team !== p.team).map(x => x.player.name);
|
const opponents = allPlayers
|
||||||
const teammates = allPlayers.filter(x => x.team === p.team && x.socketId !== p.socketId).map(x => x.player.name);
|
.filter((x) => x.team !== p.team)
|
||||||
|
.map((x) => x.player.name);
|
||||||
|
const teammates = allPlayers
|
||||||
|
.filter((x) => x.team === p.team && x.socketId !== p.socketId)
|
||||||
|
.map((x) => x.player.name);
|
||||||
const teamRef = p.team === 1 ? team1 : team2;
|
const teamRef = p.team === 1 ? team1 : team2;
|
||||||
const slotIndex = teamRef.players.findIndex(x => x.socketId === p.socketId) + 1;
|
const slotIndex =
|
||||||
|
teamRef.players.findIndex((x) => x.socketId === p.socketId) + 1;
|
||||||
|
|
||||||
io.to(p.socketId).emit(`match_found_${mode}`, {
|
io.to(p.socketId).emit(`match_found_${mode}`, {
|
||||||
matchId,
|
matchId,
|
||||||
@ -100,8 +111,8 @@ function tryMatchmaking_nvn(io, mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`[${mode}] Match: Team1(${team1.players.map(p => p.player.name)})` +
|
`[${mode}] Match: Team1(${team1.players.map((p) => p.player.name)})` +
|
||||||
` vs Team2(${team2.players.map(p => p.player.name)}) | ${matchId}`
|
` vs Team2(${team2.players.map((p) => p.player.name)}) | ${matchId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +121,7 @@ function leaveAllTeams_nvn(socketId, io, mode) {
|
|||||||
const ready = getReadyMap(mode);
|
const ready = getReadyMap(mode);
|
||||||
|
|
||||||
for (const [teamId, team] of teams) {
|
for (const [teamId, team] of teams) {
|
||||||
const idx = team.players.findIndex(p => p.socketId === socketId);
|
const idx = team.players.findIndex((p) => p.socketId === socketId);
|
||||||
if (idx === -1) continue;
|
if (idx === -1) continue;
|
||||||
|
|
||||||
const playerName = team.players[idx].player.name;
|
const playerName = team.players[idx].player.name;
|
||||||
@ -125,7 +136,9 @@ function leaveAllTeams_nvn(socketId, io, mode) {
|
|||||||
// Falls Leader das Team verlässt → nächsten Spieler zum Leader machen
|
// Falls Leader das Team verlässt → nächsten Spieler zum Leader machen
|
||||||
if (team.leaderId === socketId) {
|
if (team.leaderId === socketId) {
|
||||||
team.leaderId = team.players[0].socketId;
|
team.leaderId = team.players[0].socketId;
|
||||||
console.log(`[${mode}] Neuer Leader in Team ${teamId}: ${team.players[0].player.name}`);
|
console.log(
|
||||||
|
`[${mode}] Neuer Leader in Team ${teamId}: ${team.players[0].player.name}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
broadcastTeamStatus(io, teamId, mode);
|
broadcastTeamStatus(io, teamId, mode);
|
||||||
for (const p of team.players) {
|
for (const p of team.players) {
|
||||||
@ -150,10 +163,20 @@ function tryMatchmaking(io, newSocketId) {
|
|||||||
waitingPool.delete(id);
|
waitingPool.delete(id);
|
||||||
|
|
||||||
const matchId = `match_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
const matchId = `match_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
||||||
challenger.socket.emit("match_found", { matchId, opponent: entry.player, mySlot: "player1" });
|
challenger.socket.emit("match_found", {
|
||||||
entry.socket.emit("match_found", { matchId, opponent: challenger.player, mySlot: "player2" });
|
matchId,
|
||||||
|
opponent: entry.player,
|
||||||
|
mySlot: "player1",
|
||||||
|
});
|
||||||
|
entry.socket.emit("match_found", {
|
||||||
|
matchId,
|
||||||
|
opponent: challenger.player,
|
||||||
|
mySlot: "player2",
|
||||||
|
});
|
||||||
|
|
||||||
console.log(`[1v1] ${challenger.player.name} vs ${entry.player.name} | ${matchId}`);
|
console.log(
|
||||||
|
`[1v1] ${challenger.player.name} vs ${entry.player.name} | ${matchId}`,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +197,10 @@ function startReadyTimer(io, matchId) {
|
|||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
io._arenaTimers.delete(matchId);
|
io._arenaTimers.delete(matchId);
|
||||||
console.log(`[1v1] Match ${matchId} abgebrochen – Zeit abgelaufen.`);
|
console.log(`[1v1] Match ${matchId} abgebrochen – Zeit abgelaufen.`);
|
||||||
io.to("arena_" + matchId).emit("match_cancelled", { reason: "timeout", message: "Zeit abgelaufen." });
|
io.to("arena_" + matchId).emit("match_cancelled", {
|
||||||
|
reason: "timeout",
|
||||||
|
message: "Zeit abgelaufen.",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
@ -218,7 +244,11 @@ function registerTeamModeHandlers(io, socket, mode) {
|
|||||||
socket.on(`create_${mode}_team`, (playerData) => {
|
socket.on(`create_${mode}_team`, (playerData) => {
|
||||||
leaveAllTeams_nvn(socket.id, io, mode);
|
leaveAllTeams_nvn(socket.id, io, mode);
|
||||||
|
|
||||||
const player = { id: playerData.id, name: playerData.name, level: Number(playerData.level) || 1 };
|
const player = {
|
||||||
|
id: playerData.id,
|
||||||
|
name: playerData.name,
|
||||||
|
level: Number(playerData.level) || 1,
|
||||||
|
};
|
||||||
const teamId = `team_${mode}_${generateId()}`;
|
const teamId = `team_${mode}_${generateId()}`;
|
||||||
|
|
||||||
getTeamMap(mode).set(teamId, {
|
getTeamMap(mode).set(teamId, {
|
||||||
@ -239,13 +269,23 @@ function registerTeamModeHandlers(io, socket, mode) {
|
|||||||
const { teamId, playerData } = data;
|
const { teamId, playerData } = data;
|
||||||
const team = getTeamMap(mode).get(teamId);
|
const team = getTeamMap(mode).get(teamId);
|
||||||
|
|
||||||
if (!team) return socket.emit(`${mode}_error`, { message: "Team nicht mehr verfügbar." });
|
if (!team)
|
||||||
if (team.players.length >= max) return socket.emit(`${mode}_error`, { message: "Team ist bereits voll." });
|
return socket.emit(`${mode}_error`, {
|
||||||
if (team.players.find(p => p.socketId===socket.id)) return;
|
message: "Team nicht mehr verfügbar.",
|
||||||
|
});
|
||||||
|
if (team.players.length >= max)
|
||||||
|
return socket.emit(`${mode}_error`, {
|
||||||
|
message: "Team ist bereits voll.",
|
||||||
|
});
|
||||||
|
if (team.players.find((p) => p.socketId === socket.id)) return;
|
||||||
|
|
||||||
leaveAllTeams_nvn(socket.id, io, mode);
|
leaveAllTeams_nvn(socket.id, io, mode);
|
||||||
|
|
||||||
const player = { id: playerData.id, name: playerData.name, level: Number(playerData.level) || 1 };
|
const player = {
|
||||||
|
id: playerData.id,
|
||||||
|
name: playerData.name,
|
||||||
|
level: Number(playerData.level) || 1,
|
||||||
|
};
|
||||||
team.players.push({ socketId: socket.id, player });
|
team.players.push({ socketId: socket.id, player });
|
||||||
|
|
||||||
socket.emit(`${mode}_team_joined`, { teamId, isLeader: false });
|
socket.emit(`${mode}_team_joined`, { teamId, isLeader: false });
|
||||||
@ -268,13 +308,15 @@ function registerTeamModeHandlers(io, socket, mode) {
|
|||||||
|
|
||||||
// Nur der Leader darf kicken
|
// Nur der Leader darf kicken
|
||||||
if (team.leaderId !== socket.id) {
|
if (team.leaderId !== socket.id) {
|
||||||
return socket.emit(`${mode}_error`, { message: "Nur der Team-Leader kann Spieler entfernen." });
|
return socket.emit(`${mode}_error`, {
|
||||||
|
message: "Nur der Team-Leader kann Spieler entfernen.",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sich selbst kicken nicht erlaubt
|
// Sich selbst kicken nicht erlaubt
|
||||||
if (targetSocketId === socket.id) return;
|
if (targetSocketId === socket.id) return;
|
||||||
|
|
||||||
const idx = team.players.findIndex(p => p.socketId === targetSocketId);
|
const idx = team.players.findIndex((p) => p.socketId === targetSocketId);
|
||||||
if (idx === -1) return;
|
if (idx === -1) return;
|
||||||
|
|
||||||
const kickedName = team.players[idx].player.name;
|
const kickedName = team.players[idx].player.name;
|
||||||
@ -300,12 +342,16 @@ function registerTeamModeHandlers(io, socket, mode) {
|
|||||||
|
|
||||||
team.ready.add(socket.id);
|
team.ready.add(socket.id);
|
||||||
broadcastTeamStatus(io, teamId, mode);
|
broadcastTeamStatus(io, teamId, mode);
|
||||||
console.log(`[${mode}] Bereit in Team ${teamId}: ${team.ready.size}/${max}`);
|
console.log(
|
||||||
|
`[${mode}] Bereit in Team ${teamId}: ${team.ready.size}/${max}`,
|
||||||
|
);
|
||||||
|
|
||||||
if (team.ready.size >= max) {
|
if (team.ready.size >= max) {
|
||||||
getReadyMap(mode).set(teamId, team);
|
getReadyMap(mode).set(teamId, team);
|
||||||
for (const p of team.players) {
|
for (const p of team.players) {
|
||||||
io.to(p.socketId).emit(`${mode}_searching`, { message: "Suche nach Gegnerteam…" });
|
io.to(p.socketId).emit(`${mode}_searching`, {
|
||||||
|
message: "Suche nach Gegnerteam…",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
console.log(`[${mode}] Team ${teamId} sucht Gegner.`);
|
console.log(`[${mode}] Team ${teamId} sucht Gegner.`);
|
||||||
tryMatchmaking_nvn(io, mode);
|
tryMatchmaking_nvn(io, mode);
|
||||||
@ -317,54 +363,71 @@ function registerTeamModeHandlers(io, socket, mode) {
|
|||||||
HAUPT-HANDLER
|
HAUPT-HANDLER
|
||||||
═══════════════════════════════════════════════════════════ */
|
═══════════════════════════════════════════════════════════ */
|
||||||
function registerArenaHandlers(io, socket) {
|
function registerArenaHandlers(io, socket) {
|
||||||
|
|
||||||
/* ── 1v1 ── */
|
/* ── 1v1 ── */
|
||||||
socket.on("join_1v1", (playerData) => {
|
socket.on("join_1v1", (playerData) => {
|
||||||
if (waitingPool.has(socket.id)) return;
|
if (waitingPool.has(socket.id)) return;
|
||||||
const player = { id: playerData.id, name: playerData.name, level: Number(playerData.level) || 1 };
|
const player = {
|
||||||
|
id: playerData.id,
|
||||||
|
name: playerData.name,
|
||||||
|
level: Number(playerData.level) || 1,
|
||||||
|
};
|
||||||
waitingPool.set(socket.id, { socket, player });
|
waitingPool.set(socket.id, { socket, player });
|
||||||
socket.emit("queue_status", { status: "waiting", poolSize: waitingPool.size });
|
socket.emit("queue_status", {
|
||||||
console.log(`[1v1] ${player.name} (Lvl ${player.level}) im Pool. Größe: ${waitingPool.size}`);
|
status: "waiting",
|
||||||
|
poolSize: waitingPool.size,
|
||||||
|
});
|
||||||
|
console.log(
|
||||||
|
`[1v1] ${player.name} (Lvl ${player.level}) im Pool. Größe: ${waitingPool.size}`,
|
||||||
|
);
|
||||||
tryMatchmaking(io, socket.id);
|
tryMatchmaking(io, socket.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("leave_1v1", () => {
|
socket.on("leave_1v1", () => {
|
||||||
if (waitingPool.delete(socket.id)) socket.emit("queue_status", { status: "left" });
|
if (waitingPool.delete(socket.id))
|
||||||
|
socket.emit("queue_status", { status: "left" });
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("arena_join", (data) => {
|
socket.on("arena_join", (data) => {
|
||||||
const { matchId, slot, playerName } = data;
|
const { matchId, slot, playerName } = data;
|
||||||
console.log(`[1v1] arena_join empfangen: matchId=${matchId}, slot=${slot}, name=${playerName}, socketId=${socket.id}`);
|
console.log(
|
||||||
|
`[1v1] arena_join empfangen: matchId=${matchId}, slot=${slot}, name=${playerName}, socketId=${socket.id}`,
|
||||||
|
);
|
||||||
if (!matchId || !slot) {
|
if (!matchId || !slot) {
|
||||||
console.warn(`[1v1] arena_join abgewiesen – matchId oder slot fehlt`);
|
console.warn(`[1v1] arena_join abgewiesen – matchId oder slot fehlt`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!io._arenaRooms) io._arenaRooms = new Map();
|
if (!io._arenaRooms) io._arenaRooms = new Map();
|
||||||
if (!io._arenaRooms.has(matchId)) io._arenaRooms.set(matchId, { sockets: {}, names: {} });
|
if (!io._arenaRooms.has(matchId))
|
||||||
|
io._arenaRooms.set(matchId, { sockets: {}, names: {} });
|
||||||
|
|
||||||
const room = io._arenaRooms.get(matchId);
|
const room = io._arenaRooms.get(matchId);
|
||||||
room.sockets[slot] = socket.id;
|
room.sockets[slot] = socket.id;
|
||||||
|
|
||||||
// Name aus socket.user (Objekt) oder vom Client mitgesendet
|
// Name aus socket.user (Objekt) oder vom Client mitgesendet
|
||||||
const u = socket.user;
|
const u = socket.user;
|
||||||
room.names[slot] = (u && (u.ingame_name || u.username || u.name))
|
room.names[slot] =
|
||||||
|| playerName
|
(u && (u.ingame_name || u.username || u.name)) || playerName || "Spieler";
|
||||||
|| "Spieler";
|
|
||||||
|
|
||||||
socket.join("arena_" + matchId);
|
socket.join("arena_" + matchId);
|
||||||
|
|
||||||
const otherSlot = slot === "player1" ? "player2" : "player1";
|
const otherSlot = slot === "player1" ? "player2" : "player1";
|
||||||
if (room.sockets[otherSlot]) {
|
if (room.sockets[otherSlot]) {
|
||||||
console.log(`[1v1] Beide Spieler da → arena_ready senden | Match ${matchId}`);
|
console.log(
|
||||||
|
`[1v1] Beide Spieler da → arena_ready senden | Match ${matchId}`,
|
||||||
|
);
|
||||||
io.to("arena_" + matchId).emit("arena_ready", {
|
io.to("arena_" + matchId).emit("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",
|
||||||
});
|
});
|
||||||
startReadyTimer(io, matchId);
|
startReadyTimer(io, matchId);
|
||||||
} else {
|
} else {
|
||||||
console.log(`[1v1] Erster Spieler joined, warte auf zweiten | Match ${matchId}`);
|
console.log(
|
||||||
socket.to("arena_" + matchId).emit("arena_opponent_joined", { name: room.names[slot], slot });
|
`[1v1] Erster Spieler joined, warte auf zweiten | Match ${matchId}`,
|
||||||
|
);
|
||||||
|
socket
|
||||||
|
.to("arena_" + matchId)
|
||||||
|
.emit("arena_opponent_joined", { name: room.names[slot], slot });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -375,8 +438,14 @@ function registerArenaHandlers(io, socket) {
|
|||||||
if (!io._arenaReady.has(matchId)) io._arenaReady.set(matchId, new Set());
|
if (!io._arenaReady.has(matchId)) io._arenaReady.set(matchId, new Set());
|
||||||
const readySet = io._arenaReady.get(matchId);
|
const readySet = io._arenaReady.get(matchId);
|
||||||
readySet.add(slot);
|
readySet.add(slot);
|
||||||
io.to("arena_" + matchId).emit("ready_status", { readyCount: readySet.size, readySlots: Array.from(readySet) });
|
io.to("arena_" + matchId).emit("ready_status", {
|
||||||
if (readySet.size >= 2) { stopReadyTimer(io, matchId); io._arenaReady.delete(matchId); }
|
readyCount: readySet.size,
|
||||||
|
readySlots: Array.from(readySet),
|
||||||
|
});
|
||||||
|
if (readySet.size >= 2) {
|
||||||
|
stopReadyTimer(io, matchId);
|
||||||
|
io._arenaReady.delete(matchId);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("player_surrender", (data) => {
|
socket.on("player_surrender", (data) => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user