-
-
-
+
+ RAUM: ...
- ...
-
+
+
+ WOLF & + SCHAFE
+ +Offene Räume:
+Suche Räume...
+
+
+
diff --git a/server.js b/server.js
index 472a27b..253daf6 100644
--- a/server.js
+++ b/server.js
@@ -14,82 +14,99 @@ const board_sheep = { 0: [1, 2, 3], 1: [2, 4, 5], 2: [1, 3, 5], 3: [2, 5, 6], 4:
const rooms = {};
-function broadcast(roomId) {
- const room = rooms[roomId];
- if (!room) return;
- room.players.forEach(p => {
- if (p.ws && p.ws.readyState === WebSocket.OPEN) {
- p.ws.send(JSON.stringify({ type: "state", game: room.game, yourRole: p.role }));
+function getRoomList() {
+ return Object.keys(rooms).map(id => ({
+ id,
+ players: rooms[id].players.length,
+ turn: rooms[id].game.turn
+ }));
+}
+
+function broadcastRoomList() {
+ const list = JSON.stringify({ type: "room_list", rooms: getRoomList() });
+ wss.clients.forEach(client => {
+ if (client.readyState === WebSocket.OPEN && !client.roomId) {
+ client.send(list);
}
});
}
-// Heartbeat: Check if clients are still alive every 30s
-const interval = setInterval(() => {
- wss.clients.forEach(ws => {
- if (ws.isAlive === false) return ws.terminate();
- ws.isAlive = false;
- ws.ping();
- });
-}, 30000);
-
wss.on("connection", (ws, req) => {
const urlParams = new URLSearchParams(req.url.split('?')[1]);
let roomId = urlParams.get("room");
let sessionId = urlParams.get("sessionId");
- ws.isAlive = true;
- ws.on('pong', () => ws.isAlive = true);
+ if (!roomId || roomId === "null") {
+ ws.send(JSON.stringify({ type: "room_list", rooms: getRoomList() }));
+ return;
+ }
- if (!roomId || !rooms[roomId]) {
- if (!roomId || roomId === "null") roomId = randomBytes(3).toString("hex");
+ if (!rooms[roomId]) {
rooms[roomId] = {
- game: { wolf: 5, sheep: [0, 1, 3], turn: "sheep", moveCount: 0, winner: null },
- players: [],
- nextFirstRole: "sheep"
+ game: { wolf: 5, sheep: [0, 1, 3], turn: "sheep", moveCount: 0, winner: null, lastMove: null },
+ players: [], nextFirstRole: "sheep"
};
}
const room = rooms[roomId];
- let player = room.players.find(p => p.sessionId === sessionId);
+ ws.roomId = roomId;
+ let player = room.players.find(p => p.sessionId === sessionId);
if (!player && room.players.length >= 2) {
ws.send(JSON.stringify({ type: "full" }));
- ws.close();
return;
}
if (player) {
+ if (player.timeout) clearTimeout(player.timeout);
player.ws = ws;
} else {
const role = room.players.length === 0 ? room.nextFirstRole : (room.nextFirstRole === "sheep" ? "wolf" : "sheep");
- player = { ws, role, sessionId };
+ player = { ws, role, sessionId, timeout: null };
room.players.push(player);
}
ws.send(JSON.stringify({ type: "init", role: player.role, roomId }));
- broadcast(roomId);
+ broadcastRoomList();
+ broadcastState(roomId);
ws.on("message", msg => {
let data = JSON.parse(msg);
if (data.type === "restart") {
room.players.forEach(p => p.role = (p.role === "wolf" ? "sheep" : "wolf"));
room.nextFirstRole = room.nextFirstRole === "sheep" ? "wolf" : "sheep";
- room.game = { wolf: 5, sheep: [0, 1, 3], turn: "sheep", moveCount: 0, winner: null };
- broadcast(roomId);
- } else if (data.type === "leave") {
- room.players = room.players.filter(p => p.sessionId !== sessionId);
- if (room.players.length === 0) delete rooms[roomId];
+ room.game = { wolf: 5, sheep: [0, 1, 3], turn: "sheep", moveCount: 0, winner: null, lastMove: null };
+ broadcastState(roomId);
} else if (data.from !== undefined && data.to !== undefined) {
handleMove(roomId, player.role, data);
}
});
ws.on("close", () => {
- // We keep the player in the room for a while to allow reconnects
+ if (player) {
+ player.timeout = setTimeout(() => {
+ room.players = room.players.filter(p => p.sessionId !== sessionId);
+ if (room.players.length === 0) {
+ delete rooms[roomId];
+ }
+ broadcastRoomList();
+ broadcastState(roomId);
+ }, 1000);
+ }
});
});
+function broadcastState(roomId) {
+ const room = rooms[roomId];
+ if (!room) return;
+ const online = room.players.filter(p => p.ws?.readyState === WebSocket.OPEN).length;
+ room.players.forEach(p => {
+ if (p.ws?.readyState === WebSocket.OPEN) {
+ p.ws.send(JSON.stringify({ type: "state", game: room.game, yourRole: p.role, onlineCount: online }));
+ }
+ });
+}
+
function handleMove(roomId, role, { from, to }) {
const room = rooms[roomId];
if (!room || room.game.winner || room.game.turn !== role) return;
@@ -101,18 +118,17 @@ function handleMove(roomId, role, { from, to }) {
else { game.sheep[game.sheep.indexOf(from)] = to; game.turn = "wolf"; }
game.moveCount++;
+ game.lastMove = { from, to, role };
game.winner = checkWinConditions(game);
- broadcast(roomId);
+ broadcastState(roomId);
}
function checkWinConditions(game) {
if (game.wolf === 0) return "wolf";
if (game.moveCount >= 40) return "wolf";
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)));
if (!canWolfMove) return "sheep";
- if (!canSheepMove && game.turn === "sheep") return "wolf";
return null;
}
-server.listen(3030, () => console.log("Server running on port 3030"));
\ No newline at end of file
+server.listen(3030, () => console.log("Server running on 3030"));
\ No newline at end of file
+
-
-
+ RAUM: ...
- Verbinde...
+ ...
-
-
-
+
+
+ ...
+
+
+
+
+
+
+ WARTEN AUF GEGNER...
+ Link kopieren und Freund einladen!
+
+
+