diff options
Diffstat (limited to 'server.js')
-rwxr-xr-x | server.js | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/server.js b/server.js new file mode 100755 index 0000000..81df97c --- /dev/null +++ b/server.js @@ -0,0 +1,134 @@ +#!/usr/bin/env node +const http = require("http"); +const express = require("express"); +const socketio = require("socket.io") + +const PORT = 8080; + +const app = express(); +const server = http.Server(app); +const io = socketio(server); + +// gameid -> {pl: [socket], started: Bool} +const games = new Map(); + +function genId() { + for (let i = 0; i < 10; i++) { + // 2176782336 == 36^6 + const id = ("000000" + (2176782336 * Math.random() | 0).toString(36)).slice(-6); + if (!games.has(id)) return id; + } + return ""; +} + +function validId(id) { + return /^[0-9a-z]{6}$/.test(id); +} + +app.get("/", (req, res) => { + const gameid = genId(); + if (gameid == "") { + res.sendStatus(500); + return; + } + res.redirect("/game/" + gameid); +}); + +app.param("gameid", (req, res, next, gameid) => { + if (!validId(gameid)) { + res.sendStatus(404); + } else { + next(); + } +}); + +app.get("/game/:gameid", (req, res) => { + res.sendFile(__dirname + "/game.html"); +}); + +app.get("/game.css", (req, res) => res.sendFile(__dirname + "/game.css")); +app.get("/game.js", (req, res) => res.sendFile(__dirname + "/game.js")); + +io.on("connection", (conn) => { + let gameid, gameobj; + conn.on("open", (id) => { + console.log("open " + id); + if (!validId(id)) { + console.log(" invalid"); + conn.emit("redirect", "/"); + conn.disconnect(true); + return; + } + gameobj = games.get(id); + if (gameobj != undefined) { + if (gameobj.pl.length == 1 && !gameobj.started) { + console.log(" serve"); + gameid = id; + gameobj.pl.push(conn); + gameobj.pl[0].emit("status", "Get ready..."); + gameobj.pl[1].emit("status", "Get ready..."); + gameobj.pl[0].emit("serve", "left", 0.5, 0.5); + gameobj.pl[1].emit("serve", "right", 0.5, 0.5); + gameobj.started = true; + setTimeout(() => { + if (!gameobj || gameobj.pl.length != 2) return; + gameobj.pl[0].emit("status", ""); + gameobj.pl[1].emit("status", ""); + gameobj.pl[0].emit("startBall"); + gameobj.pl[1].emit("start"); + }, 2000); + } else { + console.log(" full"); + gameobj = undefined; + conn.emit("status", "Game full! Opening new game..."); + setTimeout(() => { + conn.emit("redirect", "/"); + conn.disconnect(true); + }, 2000); + } + } else { + console.log(" new"); + gameid = id; + gameobj = {pl: [conn], started: false}; + games.set(gameid, gameobj); + conn.emit("status", "Waiting for other player..."); + } + }); + + conn.on("disconnect", () => { + if (gameobj == undefined) return; + + console.log("stop " + gameid); + + const newpl = []; + for (const p of gameobj.pl) { + if (p != conn) { + p.emit("stop"); + p.emit("status", "Other player left."); + setTimeout(() => { + p.emit("redirect", "/"); + p.disconnect(true); + }, 2000); + newpl.push(p); + } + } + + if (newpl.length == 0) { + console.log(" delete"); + games.delete(gameid); + } else { + gameobj.pl = newpl; + } + }); + + conn.on("padvec", (pos, vel) => { + if (!gameobj) return; + for (const p of gameobj.pl) { + if (p != conn) { + p.emit("padvec", pos, vel); + } + } + }); +}); + +server.listen(PORT, () => console.log("Listening on port " + PORT)); |