diff --git a/client/src/JumpStorm.ts b/client/src/JumpStorm.ts
index 1beeb0d..ca95ed8 100644
--- a/client/src/JumpStorm.ts
+++ b/client/src/JumpStorm.ts
@@ -1,5 +1,4 @@
import { Game } from '@engine/Game';
-import { Entity } from '@engine/entities';
import { Grid } from '@engine/structures';
import {
WallBounds,
@@ -8,128 +7,13 @@ import {
Physics,
Input,
Collision,
- NetworkUpdate,
- SystemNames
+ NetworkUpdate
} from '@engine/systems';
import {
- type MessageQueueProvider,
- type MessagePublisher,
- type MessageProcessor,
- type Message,
- type EntityAddBody,
- MessageType,
- type EntityUpdateBody
-} from '@engine/network';
-import { stringify, parse } from '@engine/utils';
-import { ComponentNames, Control, NetworkUpdateable } from '@engine/components';
-
-class ClientMessageProcessor implements MessageProcessor {
- private game: Game;
-
- constructor(game: Game) {
- this.game = game;
- }
-
- public process(message: Message) {
- switch (message.type) {
- case MessageType.NEW_ENTITIES:
- const entityAdditions = message.body as unknown as EntityAddBody[];
- entityAdditions.forEach((addBody) => {
- const entity = Entity.from(
- addBody.entityName,
- addBody.id,
- addBody.args
- );
- if (entity.hasComponent(ComponentNames.Control)) {
- const clientId = this.game.getSystem(
- SystemNames.Input
- ).clientId;
- const control = entity.getComponent(
- ComponentNames.Control
- );
-
- if (control.controllableBy === clientId) {
- entity.addComponent(new NetworkUpdateable());
- }
- }
-
- this.game.addEntity(entity);
- });
- break;
- case MessageType.REMOVE_ENTITIES:
- const ids = message.body as unknown as string[];
- ids.forEach((id) => this.game.removeEntity(id));
- break;
- case MessageType.UPDATE_ENTITIES:
- const entityUpdates = message.body as unknown as EntityUpdateBody[];
- entityUpdates.forEach(({ id, args }) => {
- const entity = this.game.getEntity(id);
- if (!entity) return;
- if (entity && entity.hasComponent(ComponentNames.Control)) {
- const clientId = this.game.getSystem(
- SystemNames.Input
- ).clientId;
- const control = entity.getComponent(
- ComponentNames.Control
- );
-
- // don't listen to entities which we control
- if (control.controllableBy == clientId) return;
- }
- entity.setFrom(args);
- });
- break;
- default:
- break;
- }
- }
-}
-
-class ClientSocketMessageQueueProvider implements MessageQueueProvider {
- private socket: WebSocket;
- private messages: Message[];
-
- constructor(socket: WebSocket) {
- this.socket = socket;
- this.messages = [];
-
- this.socket.addEventListener('message', (e) => {
- const messages = parse(e.data);
- this.messages = this.messages.concat(messages);
- });
- }
-
- public getNewMessages() {
- return this.messages;
- }
-
- public clearMessages() {
- this.messages = [];
- }
-}
-
-class ClientSocketMessagePublisher implements MessagePublisher {
- private socket: WebSocket;
- private messages: Message[];
-
- constructor(socket: WebSocket) {
- this.socket = socket;
- this.messages = [];
- }
-
- public addMessage(message: Message) {
- this.messages.push(message);
- }
-
- public publish() {
- if (this.socket.readyState == WebSocket.OPEN) {
- this.messages.forEach((message: Message) =>
- this.socket.send(stringify(message))
- );
- this.messages = [];
- }
- }
-}
+ ClientMessageProcessor,
+ ClientSocketMessagePublisher,
+ ClientSocketMessageQueueProvider
+} from './network';
export class JumpStorm {
private game: Game;
@@ -148,6 +32,7 @@ export class JumpStorm {
this.clientId = await this.getAssignedCookie(
`${httpMethod}://${host}/assign`
);
+
const socket = new WebSocket(`${wsMethod}://${host}/game`);
const clientSocketMessageQueueProvider =
new ClientSocketMessageQueueProvider(socket);
@@ -159,8 +44,6 @@ export class JumpStorm {
const inputSystem = new Input(this.clientId, clientSocketMessagePublisher);
this.addWindowEventListenersToInputSystem(inputSystem);
- const grid = new Grid();
-
[
new Physics(),
new NetworkUpdate(
@@ -170,7 +53,7 @@ export class JumpStorm {
),
inputSystem,
new FacingDirection(),
- new Collision(grid),
+ new Collision(new Grid()),
new WallBounds(),
new Render(ctx)
].forEach((system) => this.game.addSystem(system));
diff --git a/client/src/network/MessageProcessor.ts b/client/src/network/MessageProcessor.ts
new file mode 100644
index 0000000..539937a
--- /dev/null
+++ b/client/src/network/MessageProcessor.ts
@@ -0,0 +1,74 @@
+import type { Game } from '@engine/Game';
+import { ComponentNames, Control, NetworkUpdateable } from '@engine/components';
+import { Entity } from '@engine/entities';
+import {
+ MessageType,
+ type Message,
+ type EntityAddBody,
+ type EntityUpdateBody,
+ type MessageProcessor
+} from '@engine/network';
+import { Input, SystemNames } from '@engine/systems';
+
+export class ClientMessageProcessor implements MessageProcessor {
+ private game: Game;
+
+ constructor(game: Game) {
+ this.game = game;
+ }
+
+ public process(message: Message) {
+ switch (message.type) {
+ case MessageType.NEW_ENTITIES:
+ const entityAdditions = message.body as unknown as EntityAddBody[];
+ entityAdditions.forEach((addBody) => {
+ const entity = Entity.from(
+ addBody.entityName,
+ addBody.id,
+ addBody.args
+ );
+ if (entity.hasComponent(ComponentNames.Control)) {
+ const clientId = this.game.getSystem(
+ SystemNames.Input
+ ).clientId;
+ const control = entity.getComponent(
+ ComponentNames.Control
+ );
+
+ if (control.controllableBy === clientId) {
+ entity.addComponent(new NetworkUpdateable());
+ }
+ }
+
+ this.game.addEntity(entity);
+ });
+ break;
+ case MessageType.REMOVE_ENTITIES:
+ const ids = message.body as unknown as string[];
+ ids.forEach((id) => this.game.removeEntity(id));
+ break;
+ case MessageType.UPDATE_ENTITIES:
+ const entityUpdates = message.body as unknown as EntityUpdateBody[];
+ entityUpdates.forEach(({ id, args }) => {
+ const entity = this.game.getEntity(id);
+ if (!entity) return;
+
+ if (entity && entity.hasComponent(ComponentNames.Control)) {
+ const clientId = this.game.getSystem(
+ SystemNames.Input
+ ).clientId;
+ const control = entity.getComponent(
+ ComponentNames.Control
+ );
+
+ // don't listen to entities which we control
+ if (control.controllableBy === clientId) return;
+ }
+ entity.setFrom(args);
+ });
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/client/src/network/MessagePublisher.ts b/client/src/network/MessagePublisher.ts
new file mode 100644
index 0000000..de105c5
--- /dev/null
+++ b/client/src/network/MessagePublisher.ts
@@ -0,0 +1,25 @@
+import type { Message, MessagePublisher } from '@engine/network';
+import { stringify } from '@engine/utils';
+
+export class ClientSocketMessagePublisher implements MessagePublisher {
+ private socket: WebSocket;
+ private messages: Message[];
+
+ constructor(socket: WebSocket) {
+ this.socket = socket;
+ this.messages = [];
+ }
+
+ public addMessage(message: Message) {
+ this.messages.push(message);
+ }
+
+ public publish() {
+ if (this.socket.readyState == WebSocket.OPEN) {
+ this.messages.forEach((message: Message) =>
+ this.socket.send(stringify(message))
+ );
+ this.messages = [];
+ }
+ }
+}
diff --git a/client/src/network/MessageQueueReceiver.ts b/client/src/network/MessageQueueReceiver.ts
new file mode 100644
index 0000000..46ca5cc
--- /dev/null
+++ b/client/src/network/MessageQueueReceiver.ts
@@ -0,0 +1,25 @@
+import type { Message, MessageQueueProvider } from '@engine/network';
+import { parse } from '@engine/utils';
+
+export class ClientSocketMessageQueueProvider implements MessageQueueProvider {
+ private socket: WebSocket;
+ private messages: Message[];
+
+ constructor(socket: WebSocket) {
+ this.socket = socket;
+ this.messages = [];
+
+ this.socket.addEventListener('message', (e) => {
+ const messages = parse(e.data);
+ this.messages = this.messages.concat(messages);
+ });
+ }
+
+ public getNewMessages() {
+ return this.messages;
+ }
+
+ public clearMessages() {
+ this.messages = [];
+ }
+}
diff --git a/client/src/network/index.ts b/client/src/network/index.ts
new file mode 100644
index 0000000..1f4d1a4
--- /dev/null
+++ b/client/src/network/index.ts
@@ -0,0 +1,3 @@
+export * from './MessageProcessor';
+export * from './MessagePublisher';
+export * from './MessageQueueReceiver';
diff --git a/engine/entities/Player.ts b/engine/entities/Player.ts
index abe3bb5..2786b8a 100644
--- a/engine/entities/Player.ts
+++ b/engine/entities/Player.ts
@@ -92,7 +92,7 @@ export class Player extends Entity {
const distance = Math.sqrt(
Math.pow(center.y - myCenter.y, 2) + Math.pow(center.x - myCenter.x, 2)
);
- const clientServerPredictionCenterThreshold = 20;
+ const clientServerPredictionCenterThreshold = 15;
if (distance < clientServerPredictionCenterThreshold) center = myCenter;
[
diff --git a/server/src/server.ts b/server/src/server.ts
index f28c80f..251fd89 100644
--- a/server/src/server.ts
+++ b/server/src/server.ts
@@ -38,7 +38,7 @@ export class GameServer {
public serve() {
if (!this.server)
this.server = Bun.serve({
- host: Constants.HOST,
+ hostname: Constants.HOST,
port: Constants.SERVER_PORT,
fetch: (req, srv) => this.fetchHandler(req, srv),
websocket: {