From dec7b614d895a1b507137e4a96a8999ff63aa179 Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Wed, 23 Aug 2023 19:44:59 -0600 Subject: holy fuck we actually got somewhere --- server/src/server.ts | 162 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 116 insertions(+), 46 deletions(-) (limited to 'server/src/server.ts') diff --git a/server/src/server.ts b/server/src/server.ts index 713d3ed..b3eb1ea 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -1,109 +1,179 @@ import { Game } from "@engine/Game"; -import { Floor, Player } from "@engine/entities"; +import { EntityNames, Player } from "@engine/entities"; +import { WallBounds, Physics, Collision, NetworkUpdate } from "@engine/systems"; import { - WallBounds, - Physics, - Collision, - NetworkUpdate, - MessageQueueProvider, - MessagePublisher, -} from "@engine/systems"; + type MessageQueueProvider, + type MessagePublisher, + MessageType, + type MessageProcessor, + type Message, +} from "@engine/network"; +import { stringify, parse } from "@engine/utils"; import { Grid } from "@engine/structures"; import { Miscellaneous } from "@engine/config"; import { Server } from "bun"; +const SERVER_PORT = 8080; +const SERVER_TICK_RATE = (1 / 100) * 1000; +const GAME_TOPIC = "game"; + +type SessionData = { sessionId: string }; + +interface ServerMessage extends Message { + sessionData: SessionData; +} + class ServerSocketMessageReceiver implements MessageQueueProvider { - private messages: any[]; + private messages: ServerMessage[]; constructor() { this.messages = []; } - addMessage(message: any) { + public addMessage(message: ServerMessage) { this.messages.push(message); } - getNewMessages() { + public getNewMessages() { return this.messages; } - clearMessages() { + public clearMessages() { this.messages = []; } } +class ServerMessageProcessor implements MessageProcessor { + constructor() {} + + public process(_message: ServerMessage) {} +} + class ServerSocketMessagePublisher implements MessagePublisher { - private server: Server; - private messages: any[]; + private server?: Server; + private messages: Message[]; + + constructor(server?: Server) { + if (server) { + this.server = server; + } - constructor(server: Server) { - this.server = server; this.messages = []; } - addMessage(_message: any) {} + public setServer(server: Server) { + this.server = server; + } + + public addMessage(message: Message) { + this.messages.push(message); + } - publish() {} + public publish() { + this.messages.forEach( + (message) => this.server?.publish(GAME_TOPIC, stringify(message)), + ); + + this.messages = []; + } } const game = new Game(); const messageReceiver = new ServerSocketMessageReceiver(); +const messagePublisher = new ServerSocketMessagePublisher(); +const messageProcessor = new ServerMessageProcessor(); +const sessionControllableEntities: Map> = new Map(); -const server = Bun.serve<{ sessionId: string }>({ - port: 8080, - fetch: async (req, server): Promise => { - const sessionId = crypto.randomUUID(); - - server.upgrade(req, { - headers: { - "Set-Cookie": `SessionId=${sessionId}`, - }, - data: { - sessionId, - }, - }); - - return sessionId; +const server = Bun.serve({ + port: SERVER_PORT, + fetch: async (req, server): Promise => { + const url = new URL(req.url); + + const headers = new Headers(); + headers.set("Access-Control-Allow-Origin", "*"); + + if (url.pathname == "/assign") { + const sessionId = crypto.randomUUID(); + headers.set("Set-Cookie", `SessionId=${sessionId};`); + + return new Response(sessionId, { headers }); + } + + const cookie = req.headers.get("cookie"); + if (!cookie) { + return new Response("No session", { headers, status: 401 }); + } + + const sessionId = cookie.split(";").at(0)!.split("SessionId=").at(1); + + if (url.pathname == "/game") { + headers.set( + "Set-Cookie", + `SessionId=${sessionId}; HttpOnly; SameSite=Strict;`, + ); + server.upgrade(req, { + headers, + data: { + sessionId, + }, + }); + + return new Response("upgraded", { headers }); + } + if (url.pathname == "/me") { + return new Response(sessionId, { headers }); + } + + return new Response("Not found", { headers, status: 404 }); }, websocket: { open(ws) { const { sessionId } = ws.data; if (sessionControllableEntities.has(sessionId)) { + // no need to add player return; } - const player = new Player(); + const player = new Player(sessionId); game.addEntity(player); - sessionControllableEntities.set(sessionId, new Set(player.id)); + + messagePublisher.addMessage({ + type: MessageType.NEW_ENTITY, + body: { + entityName: EntityNames.Player, + args: { playerId: sessionId }, + }, + }); + + ws.subscribe(GAME_TOPIC); }, message(ws, message) { - console.log(JSON.parse(message)); - messageReceiver.addMessage(message); + if (typeof message == "string") { + const receivedMessage = parse(message); + receivedMessage.sessionData = ws.data; + + messageReceiver.addMessage(receivedMessage); + } }, - close(ws) {}, + close(_ws) {}, }, }); -const messagePublisher = new ServerSocketMessagePublisher(server); +messagePublisher.setServer(server); [ new Physics(), new Collision(new Grid()), new WallBounds(Miscellaneous.WIDTH), - new NetworkUpdate(messageReceiver, messagePublisher), + new NetworkUpdate(messageReceiver, messagePublisher, messageProcessor), ].forEach((system) => game.addSystem(system)); -[new Floor(160), new Player()].forEach((entity) => game.addEntity(entity)); - game.start(); - setInterval(() => { game.doGameLoop(performance.now()); -}, Miscellaneous.SERVER_TICK_RATE); - -const sessionControllableEntities: Map> = new Map(); +}, SERVER_TICK_RATE); console.log(`Listening on ${server.hostname}:${server.port}`); -- cgit v1.2.3-70-g09d2