aboutsummaryrefslogtreecommitdiffstats
path: root/backend/src
diff options
context:
space:
mode:
Diffstat (limited to 'backend/src')
-rw-r--r--backend/src/app.ts22
-rw-r--r--backend/src/config/session-store.ts77
-rw-r--r--backend/src/router.ts8
-rw-r--r--backend/src/routes/session.route.ts7
-rw-r--r--backend/src/websocket/game.ts95
5 files changed, 209 insertions, 0 deletions
diff --git a/backend/src/app.ts b/backend/src/app.ts
new file mode 100644
index 0000000..41b8821
--- /dev/null
+++ b/backend/src/app.ts
@@ -0,0 +1,22 @@
+import express from 'express';
+import router from './router.js';
+import cors from 'cors';
+import createWebsocketServer from './websocket/game.js';
+import { WebSocketServer } from 'ws';
+
+const app = express();
+
+app.use(express.json());
+app.use(express.urlencoded({ extended : true}))
+
+app.use(cors());
+
+app.use('/', router);
+
+const port = parseInt(process.env.PORT || "3000");
+
+const server = app.listen(port, () => {
+ console.log(`Server listening on port ${port}`);
+});
+
+const websocketServer: WebSocketServer = createWebsocketServer(server); \ No newline at end of file
diff --git a/backend/src/config/session-store.ts b/backend/src/config/session-store.ts
new file mode 100644
index 0000000..283031b
--- /dev/null
+++ b/backend/src/config/session-store.ts
@@ -0,0 +1,77 @@
+export type Session = {
+ id: string;
+ state: string;
+ host?: string;
+ clients: string[];
+};
+
+const sessions: { [key: string]: Session } = {};
+
+function makeid(length) {
+ let result = '';
+ const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ const charactersLength = characters.length;
+ let counter = 0;
+ while (counter < length) {
+ result += characters.charAt(Math.floor(Math.random() * charactersLength));
+ counter += 1;
+ }
+ return result;
+}
+
+
+export const createNewSession = (): Session => {
+ const id = makeid(10);
+ const session = {
+ id,
+ state: "waiting",
+ host: undefined,
+ clients: [],
+ };
+ sessions[id] = session;
+ return session;
+};
+
+export const setSessionState = (id: string, state: string): void => {
+ if (!sessions[id]) {
+ return;
+ }
+
+ sessions[id].state = state;
+};
+
+export const setSessionHost = (id: string, clientId: string): void => {
+ if (!sessions[id]) {
+ return;
+ }
+
+ sessions[id].host = clientId;
+};
+
+export const addSessionClient = (id: string, clientId: string): void => {
+ if (!sessions[id]) {
+ return;
+ }
+
+ sessions[id]?.clients.push(clientId);
+};
+
+export const cleanupSession = (id: string): void => {
+ if (!sessions[id]) {
+ return;
+ }
+
+// if (sessions[id].host) {
+// sessions[id].host!.close();
+// }
+//
+// sessions[id].clients.forEach((client) => {
+// client.close();
+// });
+
+ delete sessions[id];
+}
+
+export const getSession = (id: string): Session => {
+ return sessions[id];
+}; \ No newline at end of file
diff --git a/backend/src/router.ts b/backend/src/router.ts
new file mode 100644
index 0000000..b05ce02
--- /dev/null
+++ b/backend/src/router.ts
@@ -0,0 +1,8 @@
+import express from "express";
+import { createSession } from "./routes/session.route.js";
+
+const router = express.Router();
+
+router.post("/session", createSession);
+
+export default router; \ No newline at end of file
diff --git a/backend/src/routes/session.route.ts b/backend/src/routes/session.route.ts
new file mode 100644
index 0000000..3ac8525
--- /dev/null
+++ b/backend/src/routes/session.route.ts
@@ -0,0 +1,7 @@
+import { createNewSession } from "../config/session-store.js";
+import { Request, Response } from "express";
+
+export function createSession(req: Request, res: Response) {
+ const session = createNewSession();
+ res.status(201).send(session);
+}
diff --git a/backend/src/websocket/game.ts b/backend/src/websocket/game.ts
new file mode 100644
index 0000000..63c537a
--- /dev/null
+++ b/backend/src/websocket/game.ts
@@ -0,0 +1,95 @@
+import { Server } from "http";
+import { addSessionClient, getSession, setSessionHost } from "../config/session-store.js";
+import { WebSocketServer } from "ws";
+import { v4 as uuidv4 } from "uuid";
+
+const wss = new WebSocketServer({ noServer: true });
+
+const sendToClient = (clientId: string, message: any) => {
+ wss.clients.forEach((client: any) => {
+ if (client.clientId === clientId) {
+ client.send(JSON.stringify(message));
+ }
+ });
+};
+
+const broadcastToClients = (clientIds: string[], message: any) => {
+ wss.clients.forEach((client: any) => {
+ if (clientIds.includes(client.clientId)) {
+ client.send(JSON.stringify(message));
+ }
+ });
+};
+
+export const createWebsocketServer = (server: Server): WebSocketServer => {
+ server.on("upgrade", (req, socket, head) => {
+ wss.handleUpgrade(req, socket, head, (ws) => {
+ wss.emit("connection", ws, req);
+ });
+ });
+
+ wss.on("connection", (ws: any) => {
+ ws.clientId = uuidv4();
+
+ ws.on("message", (message) => {
+ console.log("received: %s", message);
+ let data;
+ try {
+ data = JSON.parse(message.toString());
+ } catch (e) {
+ console.log("Invalid JSON");
+ return;
+ }
+
+ if (data.action === "host") {
+ setSessionHost(data.sessionId, ws.clientId);
+ } else if (data.action === "move") {
+ const session = getSession(data.sessionId);
+ if (!session) {
+ return;
+ }
+
+ sendToClient(session.host!, {
+ action: "move",
+ move: data.move,
+ });
+ } else if (data.action === "join") {
+ const session = getSession(data.sessionId);
+ if (!session) {
+ return;
+ }
+
+ addSessionClient(data.sessionId, ws.clientId);
+
+ sendToClient(session.host!, {
+ action: "join",
+ clients: session.clients.length,
+ });
+
+ ws.send(JSON.stringify({
+ action: "state",
+ state: session.state,
+ }));
+ } else if (data.action === "start") {
+ const session = getSession(data.sessionId);
+ if (!session) {
+ return;
+ }
+
+ sendToClient(session.host!, {
+ action: "state",
+ state: "playing",
+ });
+
+ broadcastToClients(session.clients, {
+ action: "state",
+ state: "playing",
+ });
+ }
+ });
+ });
+
+ return wss;
+};
+
+export default createWebsocketServer;