From a917d0d2aa2b455aa02a15e409278158a8b48b17 Mon Sep 17 00:00:00 2001 From: Simon Oberzier Date: Mon, 9 Feb 2026 22:13:02 +0100 Subject: [PATCH] Persistant rooms --- public/index.html | 48 ++++++++++++++++++++------------- server.js | 69 +++++++++++++++++++---------------------------- 2 files changed, 57 insertions(+), 60 deletions(-) diff --git a/public/index.html b/public/index.html index ecffeeb..8cfb09b 100644 --- a/public/index.html +++ b/public/index.html @@ -75,6 +75,14 @@ button:hover { background: #34495e; } + + #exitBtn { + background: #e74c3c; + } + + #exitBtn:hover { + background: #c0392b; + } @@ -86,8 +94,16 @@
+ diff --git a/server.js b/server.js index 13e34c8..02329b7 100644 --- a/server.js +++ b/server.js @@ -9,16 +9,15 @@ app.use(express.static("public")); const server = http.createServer(app); const wss = new WebSocket.Server({ server }); -// Movement logic: Wolf can move anywhere, Sheep only forward const board_wolf = { - 0:[1,2,3], 1:[0,2,4,5], 2:[0,1,3,5], 3:[0,2,5,6], 4:[1,5,7], - 5:[1,2,3,4,6,7,8,9], 6:[3,5,9], 7:[4,5,8,10], 8:[5,7,9,10], - 9:[5,6,8,10], 10:[7,8,9] + 0: [1, 2, 3], 1: [0, 2, 4, 5], 2: [0, 1, 3, 5], 3: [0, 2, 5, 6], 4: [1, 5, 7], + 5: [1, 2, 3, 4, 6, 7, 8, 9], 6: [3, 5, 9], 7: [4, 5, 8, 10], 8: [5, 7, 9, 10], + 9: [5, 6, 8, 10], 10: [7, 8, 9] }; const board_sheep = { - 0:[1,2,3], 1:[2,4,5], 2:[1,3,5], 3:[2,5,6], 4:[5,7], - 5:[4,6,7,8,9], 6:[5,9], 7:[8,10], 8:[7,9,10], 9:[8,10], 10:[] + 0: [1, 2, 3], 1: [2, 4, 5], 2: [1, 3, 5], 3: [2, 5, 6], 4: [5, 7], + 5: [4, 6, 7, 8, 9], 6: [5, 9], 7: [8, 10], 8: [7, 9, 10], 9: [8, 10], 10: [] }; const rooms = {}; @@ -28,39 +27,27 @@ function broadcast(roomId) { if (!room) return; const msg = JSON.stringify({ type: "state", game: room.game }); room.players.forEach(p => { - if (p.ws.readyState === WebSocket.OPEN) p.ws.send(msg); + if (p.ws && p.ws.readyState === WebSocket.OPEN) p.ws.send(msg); }); } function checkWinConditions(game) { - // 1. Wolf reaches node 0 if (game.wolf === 0) return "wolf"; - - // 2. Turn limit (40 moves) if (game.moveCount >= 40) return "wolf"; - // Mobility Check helpers - const canWolfMove = board_wolf[game.wolf].some(to => - !game.sheep.includes(to) - ); - - const canSheepMove = game.sheep.some(from => + const canWolfMove = board_wolf[game.wolf].some(to => !game.sheep.includes(to)); + const canSheepMove = game.sheep.some(from => board_sheep[from].some(to => to !== game.wolf && !game.sheep.includes(to)) ); - // 3. Wolf trapped if (!canWolfMove) return "sheep"; - - // 4. Sheep cannot move if (!canSheepMove && game.turn === "sheep") return "wolf"; - return null; } function handleMove(roomId, role, { from, to }) { const room = rooms[roomId]; if (!room || room.game.winner) return; - const game = room.game; if (game.turn !== role) return; @@ -78,20 +65,16 @@ function handleMove(roomId, role, { from, to }) { game.sheep[i] = to; game.turn = "wolf"; } - game.moveCount++; game.winner = checkWinConditions(game); broadcast(roomId); } wss.on("connection", (ws, req) => { - ws.isAlive = true; - ws.on("pong", () => ws.isAlive = true); - const urlParams = new URLSearchParams(req.url.split('?')[1]); let roomId = urlParams.get("room"); + let sessionId = urlParams.get("sessionId"); - // Room creation/joining logic if (!roomId || !rooms[roomId]) { if (!roomId) roomId = randomBytes(3).toString("hex"); rooms[roomId] = { @@ -101,16 +84,23 @@ wss.on("connection", (ws, req) => { } const room = rooms[roomId]; - if (room.players.length >= 2) { + let player = room.players.find(p => p.sessionId === sessionId); + + if (!player && room.players.length >= 2) { ws.send(JSON.stringify({ type: "full" })); ws.close(); return; } - const role = room.players.length === 0 ? "sheep" : "wolf"; - room.players.push({ ws, role }); + if (player) { + player.ws = ws; // Re-attach new socket to existing session + } else { + const role = room.players.length === 0 ? "sheep" : "wolf"; + player = { ws, role, sessionId }; + room.players.push(player); + } - ws.send(JSON.stringify({ type: "role", role, roomId })); + ws.send(JSON.stringify({ type: "role", role: player.role, roomId })); broadcast(roomId); ws.on("message", msg => { @@ -120,23 +110,18 @@ wss.on("connection", (ws, req) => { if (data.type === "restart") { room.game = { wolf: 5, sheep: [0, 1, 3], turn: "sheep", moveCount: 0, winner: null }; broadcast(roomId); - return; + } else if (data.type === "leave") { + room.players = room.players.filter(p => p.sessionId !== sessionId); + if (room.players.length === 0) delete rooms[roomId]; + ws.close(); + } else { + handleMove(roomId, player.role, data); } - handleMove(roomId, role, data); }); ws.on("close", () => { - room.players = room.players.filter(p => p.ws !== ws); - if (room.players.length === 0) delete rooms[roomId]; + // We don't remove the player here so they can reconnect on refresh }); }); -setInterval(() => { - wss.clients.forEach(ws => { - if (!ws.isAlive) return ws.terminate(); - ws.isAlive = false; - ws.ping(); - }); -}, 30000); - server.listen(3030, () => console.log("Server läuft auf Port 3030")); \ No newline at end of file