Initial commit
This commit is contained in:
134
server.js
Normal file
134
server.js
Normal file
@@ -0,0 +1,134 @@
|
||||
const express = require("express");
|
||||
const http = require("http");
|
||||
const WebSocket = require("ws");
|
||||
const { randomBytes } = require("crypto");
|
||||
|
||||
const app = express();
|
||||
app.use(express.static("public"));
|
||||
|
||||
const server = http.createServer(app);
|
||||
const wss = new WebSocket.Server({ server });
|
||||
|
||||
// Define both movement sets
|
||||
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]
|
||||
};
|
||||
|
||||
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:[]
|
||||
};
|
||||
|
||||
// Rooms: roomId -> { game, players }
|
||||
const rooms = {};
|
||||
|
||||
// Broadcast state to all players in a room
|
||||
function broadcast(roomId) {
|
||||
const room = rooms[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);
|
||||
});
|
||||
}
|
||||
|
||||
// Select the correct allowed moves based on role
|
||||
function handleMove(roomId, role, {from, to}) {
|
||||
const room = rooms[roomId];
|
||||
if(!room) return;
|
||||
|
||||
const game = room.game;
|
||||
if(game.turn !== role) return;
|
||||
|
||||
// Select the correct allowed moves based on role
|
||||
const allowedMoves = (role === "wolf") ? board_wolf[from] : board_sheep[from];
|
||||
|
||||
if(!allowedMoves?.includes(to)) return;
|
||||
if(game.sheep.includes(to) || game.wolf === to) return;
|
||||
|
||||
if(role === "wolf") {
|
||||
if(from !== game.wolf) return;
|
||||
game.wolf = to;
|
||||
game.turn = "sheep";
|
||||
} else {
|
||||
const i = game.sheep.indexOf(from);
|
||||
if(i === -1) return;
|
||||
game.sheep[i] = to;
|
||||
game.turn = "wolf";
|
||||
}
|
||||
broadcast(roomId);
|
||||
}
|
||||
|
||||
// Heartbeat
|
||||
function heartbeat() { this.isAlive = true; }
|
||||
|
||||
wss.on("connection", (ws, req) => { // Added 'req' parameter
|
||||
ws.isAlive = true;
|
||||
ws.on("pong", heartbeat);
|
||||
|
||||
// Use req.url to get the query string
|
||||
const urlParams = new URLSearchParams(req.url.split('?')[1]);
|
||||
let roomId = urlParams.get("room");
|
||||
|
||||
// Logic for creating or joining
|
||||
if (!roomId || !rooms[roomId]) {
|
||||
// If no ID provided, or the provided ID doesn't exist, create a NEW one
|
||||
// UNLESS you want people to be able to create specific room names:
|
||||
if (!roomId) roomId = randomBytes(3).toString("hex");
|
||||
|
||||
if (!rooms[roomId]) {
|
||||
rooms[roomId] = {
|
||||
game: { wolf: 5, sheep: [0, 1, 3], turn: "sheep" },
|
||||
players: []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const room = rooms[roomId];
|
||||
|
||||
// Reject if room full
|
||||
if(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, roomId });
|
||||
|
||||
// Send role + room info
|
||||
ws.send(JSON.stringify({ type:"role", role, roomId }));
|
||||
broadcast(roomId);
|
||||
|
||||
ws.on("message", msg=>{
|
||||
let data;
|
||||
try{ data = JSON.parse(msg); } catch{return;}
|
||||
|
||||
if(data.type==="restart"){
|
||||
room.game = { wolf:5, sheep:[0,1,3], turn:"sheep" };
|
||||
broadcast(roomId);
|
||||
return;
|
||||
}
|
||||
|
||||
handleMove(roomId, role, data);
|
||||
});
|
||||
|
||||
ws.on("close", ()=>{
|
||||
room.players = room.players.filter(p => p.ws !== ws);
|
||||
if(room.players.length === 0) delete rooms[roomId]; // cleanup empty rooms
|
||||
});
|
||||
});
|
||||
|
||||
// Ping-pong to prevent idle disconnect
|
||||
const interval = setInterval(()=>{
|
||||
wss.clients.forEach(ws=>{
|
||||
if(!ws.isAlive) return ws.terminate();
|
||||
ws.isAlive = false;
|
||||
ws.ping();
|
||||
});
|
||||
}, 30000);
|
||||
|
||||
server.on("close", ()=>clearInterval(interval));
|
||||
server.listen(3030, ()=>console.log("Server läuft auf Port 3030"));
|
||||
Reference in New Issue
Block a user