aboutsummaryrefslogtreecommitdiff
path: root/server.js
diff options
context:
space:
mode:
Diffstat (limited to 'server.js')
-rwxr-xr-xserver.js134
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));