summaryrefslogtreecommitdiff
path: root/server/src/server.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/server.ts')
-rw-r--r--server/src/server.ts104
1 files changed, 63 insertions, 41 deletions
diff --git a/server/src/server.ts b/server/src/server.ts
index b3eb1ea..c77bfef 100644
--- a/server/src/server.ts
+++ b/server/src/server.ts
@@ -1,21 +1,22 @@
-import { Game } from "@engine/Game";
-import { EntityNames, Player } from "@engine/entities";
-import { WallBounds, Physics, Collision, NetworkUpdate } from "@engine/systems";
+import { Game } from '@engine/Game';
+import { EntityNames, Player } from '@engine/entities';
+import { WallBounds, Physics, Collision, NetworkUpdate } from '@engine/systems';
import {
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";
+ 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";
+const SERVER_TICK_RATE = (1 / 60) * 1000;
+const GAME_TOPIC = 'game';
+const MAX_PLAYERS = 8;
type SessionData = { sessionId: string };
@@ -70,11 +71,11 @@ class ServerSocketMessagePublisher implements MessagePublisher {
}
public publish() {
- this.messages.forEach(
- (message) => this.server?.publish(GAME_TOPIC, stringify(message)),
- );
+ if (this.messages.length) {
+ this.server?.publish(GAME_TOPIC, stringify(this.messages));
- this.messages = [];
+ this.messages = [];
+ }
}
}
@@ -85,81 +86,102 @@ const messagePublisher = new ServerSocketMessagePublisher();
const messageProcessor = new ServerMessageProcessor();
const sessionControllableEntities: Map<string, Set<string>> = new Map();
+const sessions = new Set<string>();
+
const server = Bun.serve<SessionData>({
port: SERVER_PORT,
fetch: async (req, server): Promise<Response> => {
const url = new URL(req.url);
const headers = new Headers();
- headers.set("Access-Control-Allow-Origin", "*");
+ headers.set('Access-Control-Allow-Origin', '*');
+
+ if (url.pathname == '/assign') {
+ if (sessions.size > MAX_PLAYERS)
+ return new Response('too many players', { headers, status: 400 });
- if (url.pathname == "/assign") {
const sessionId = crypto.randomUUID();
- headers.set("Set-Cookie", `SessionId=${sessionId};`);
+ headers.set('Set-Cookie', `SessionId=${sessionId};`);
+
+ sessions.add(sessionId);
return new Response(sessionId, { headers });
}
- const cookie = req.headers.get("cookie");
+ const cookie = req.headers.get('cookie');
if (!cookie) {
- return new Response("No session", { headers, status: 401 });
+ return new Response('No session', { headers, status: 401 });
}
- const sessionId = cookie.split(";").at(0)!.split("SessionId=").at(1);
+ const sessionId = cookie.split(';').at(0)!.split('SessionId=').at(1);
- if (url.pathname == "/game") {
+ if (url.pathname == '/game') {
headers.set(
- "Set-Cookie",
- `SessionId=${sessionId}; HttpOnly; SameSite=Strict;`,
+ 'Set-Cookie',
+ `SessionId=${sessionId}; HttpOnly; SameSite=Strict;`
);
server.upgrade(req, {
headers,
data: {
- sessionId,
- },
+ sessionId
+ }
});
- return new Response("upgraded", { headers });
+ return new Response('upgraded', { headers });
}
- if (url.pathname == "/me") {
+
+ if (url.pathname == '/me') {
return new Response(sessionId, { headers });
}
- return new Response("Not found", { headers, status: 404 });
+ 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(sessionId);
game.addEntity(player);
- sessionControllableEntities.set(sessionId, new Set(player.id));
+ sessionControllableEntities.set(sessionId, new Set([player.id]));
messagePublisher.addMessage({
- type: MessageType.NEW_ENTITY,
- body: {
- entityName: EntityNames.Player,
- args: { playerId: sessionId },
- },
+ type: MessageType.NEW_ENTITIES,
+ body: [
+ {
+ entityName: EntityNames.Player,
+ args: { playerId: sessionId, id: player.id }
+ }
+ ]
});
ws.subscribe(GAME_TOPIC);
},
message(ws, message) {
- if (typeof message == "string") {
+ if (typeof message == 'string') {
const receivedMessage = parse<ServerMessage>(message);
receivedMessage.sessionData = ws.data;
messageReceiver.addMessage(receivedMessage);
}
},
- close(_ws) {},
- },
+ close(ws) {
+ const { sessionId } = ws.data;
+
+ sessions.delete(sessionId);
+
+ const sessionEntities = sessionControllableEntities.get(sessionId);
+ if (!sessionEntities) return;
+
+ messagePublisher.addMessage({
+ type: MessageType.REMOVE_ENTITIES,
+ body: Array.from(sessionEntities)
+ });
+ }
+ }
});
messagePublisher.setServer(server);
@@ -167,8 +189,8 @@ messagePublisher.setServer(server);
[
new Physics(),
new Collision(new Grid()),
- new WallBounds(Miscellaneous.WIDTH),
- new NetworkUpdate(messageReceiver, messagePublisher, messageProcessor),
+ new WallBounds(),
+ new NetworkUpdate(messageReceiver, messagePublisher, messageProcessor)
].forEach((system) => game.addSystem(system));
game.start();