diff options
Diffstat (limited to 'backend/src/websocket')
| -rw-r--r-- | backend/src/websocket/coop.ts | 142 | ||||
| -rw-r--r-- | backend/src/websocket/game.ts | 97 | ||||
| -rw-r--r-- | backend/src/websocket/websocket-router.ts | 18 |
3 files changed, 160 insertions, 97 deletions
diff --git a/backend/src/websocket/coop.ts b/backend/src/websocket/coop.ts new file mode 100644 index 0000000..ce8bfa0 --- /dev/null +++ b/backend/src/websocket/coop.ts @@ -0,0 +1,142 @@ +import { + addSessionClient, + createNewSession, + getSession, + setSessionState, +} from "../config/coop-session-store.js"; +import { WebSocketServer } from "ws"; +import { v4 as uuidv4 } from "uuid"; +import { IncomingMessage } from "http"; +import { CoopWebSocket } from "../model/websocket.js"; +import { parse } from "url"; +import { + ClientJoinedCoopSessionMessage, + CoopSessionCreatedMessage, + CoopSessionMessage, + CoopSessionMoveMessage, + CoopSessionMoveTimeoutMessage, + CoopSessionStateChangeMessage, +} from "../model/actions/coop.js"; + +export const wss = new WebSocketServer({ noServer: true }); + +const sendMessageToClient = ( + client: CoopWebSocket, + message: CoopSessionMessage +) => { + if (client.readyState === client.OPEN) { + client.send(JSON.stringify(message)); + console.log( + `Sent message to client ${client.clientId}: ${JSON.stringify(message)}}` + ); + } +}; + +wss.on("connection", (ws: CoopWebSocket, req: IncomingMessage) => { + ws.clientId = uuidv4(); + + const url = parse(req.url!, true); + + if (url.query.action === "create") { + const session = createNewSession(ws); + sendMessageToClient(ws, <CoopSessionCreatedMessage>{ + type: "create", + payload: { + sessionId: session.id, + }, + }); + ws.sessionId = session.id; + } else if (url.query.action === "join") { + const session = getSession(url.query.sessionId as string); + if (!session) { + ws.close(); + return; + } + + addSessionClient(url.query.sessionId as string, ws); + + sendMessageToClient(session.host, <ClientJoinedCoopSessionMessage>{ + type: "join", + payload: { + numberOfClients: session.clients.length, + }, + }); + sendMessageToClient(ws, <CoopSessionStateChangeMessage>{ + type: "state", + payload: { + state: session.state, + }, + }); + + ws.sessionId = session.id; + } else { + ws.close(); + return; + } + + ws.on("message", (message) => { + console.log(`Received message from client ${ws.clientId}: ${message}`); + let data: any; + try { + data = JSON.parse(message.toString()); + } catch (e) { + return; + } + + const session = getSession(ws.sessionId); + if (!session) { + return; + } + + const type = data.type as string; + const payload = data.payload as any; + + if (!type || !payload) { + return; + } + + if (type === "move") { + if (Date.now() - ws.nextMoveTimestamp < 0) { + return; + } + + sendMessageToClient(session.host, <CoopSessionMoveMessage>{ + type: "move", + payload: { + move: payload.move, + }, + }); + + ws.nextMoveTimestamp = Date.now() + 1000; + + sendMessageToClient(ws, <CoopSessionMoveTimeoutMessage>{ + type: "timeout", + payload: { + timeoutUntil: ws.nextMoveTimestamp, + }, + }); + } else if (type === "start") { + session.state = "playing"; + + [session.host, ...session.clients].forEach((client) => { + sendMessageToClient(client, <CoopSessionStateChangeMessage>{ + type: "state", + payload: { + state: "playing", + }, + }); + }); + } else if (type === "end") { + session.state = "finished"; + + [session.host, ...session.clients].forEach((client) => { + sendMessageToClient(client, <CoopSessionStateChangeMessage>{ + type: "state", + payload: { + state: "finished", + }, + }); + }); + } + }); +}); diff --git a/backend/src/websocket/game.ts b/backend/src/websocket/game.ts deleted file mode 100644 index c37b1c5..0000000 --- a/backend/src/websocket/game.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Server } from "http"; -import { addSessionClient, getSession, setSessionHost, setSessionState } 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; - } - - setSessionState(data.sessionId, "playing"); - - sendToClient(session.host!, { - action: "state", - state: "playing", - }); - - broadcastToClients(session.clients, { - action: "state", - state: "playing", - }); - } - }); - }); - - return wss; -}; - -export default createWebsocketServer; diff --git a/backend/src/websocket/websocket-router.ts b/backend/src/websocket/websocket-router.ts new file mode 100644 index 0000000..0b11985 --- /dev/null +++ b/backend/src/websocket/websocket-router.ts @@ -0,0 +1,18 @@ +import { Server } from "http"; +import { wss as gameServer } from "./coop.js"; + +export const createWebsocketServer = (server: Server) => { + + server.on("upgrade", (req, socket, head) => { + if (req.url?.startsWith("/coop")) { + gameServer.handleUpgrade(req, socket, head, (ws) => { + gameServer.emit("connection", ws, req); + }); + } else { + socket.destroy(); + } + }); + +}; + +export default createWebsocketServer; |
