decrease CSP threshold, move client networking to its own folder
This commit is contained in:
parent
ba989bd7f8
commit
d19da30f6d
@ -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<Input>(
|
||||
SystemNames.Input
|
||||
).clientId;
|
||||
const control = entity.getComponent<Control>(
|
||||
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<Input>(
|
||||
SystemNames.Input
|
||||
).clientId;
|
||||
const control = entity.getComponent<Control>(
|
||||
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<Message[]>(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));
|
||||
|
74
client/src/network/MessageProcessor.ts
Normal file
74
client/src/network/MessageProcessor.ts
Normal file
@ -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<Input>(
|
||||
SystemNames.Input
|
||||
).clientId;
|
||||
const control = entity.getComponent<Control>(
|
||||
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<Input>(
|
||||
SystemNames.Input
|
||||
).clientId;
|
||||
const control = entity.getComponent<Control>(
|
||||
ComponentNames.Control
|
||||
);
|
||||
|
||||
// don't listen to entities which we control
|
||||
if (control.controllableBy === clientId) return;
|
||||
}
|
||||
entity.setFrom(args);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
25
client/src/network/MessagePublisher.ts
Normal file
25
client/src/network/MessagePublisher.ts
Normal file
@ -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 = [];
|
||||
}
|
||||
}
|
||||
}
|
25
client/src/network/MessageQueueReceiver.ts
Normal file
25
client/src/network/MessageQueueReceiver.ts
Normal file
@ -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<Message[]>(e.data);
|
||||
this.messages = this.messages.concat(messages);
|
||||
});
|
||||
}
|
||||
|
||||
public getNewMessages() {
|
||||
return this.messages;
|
||||
}
|
||||
|
||||
public clearMessages() {
|
||||
this.messages = [];
|
||||
}
|
||||
}
|
3
client/src/network/index.ts
Normal file
3
client/src/network/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './MessageProcessor';
|
||||
export * from './MessagePublisher';
|
||||
export * from './MessageQueueReceiver';
|
@ -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;
|
||||
|
||||
[
|
||||
|
@ -38,7 +38,7 @@ export class GameServer {
|
||||
public serve() {
|
||||
if (!this.server)
|
||||
this.server = Bun.serve<SessionData>({
|
||||
host: Constants.HOST,
|
||||
hostname: Constants.HOST,
|
||||
port: Constants.SERVER_PORT,
|
||||
fetch: (req, srv) => this.fetchHandler(req, srv),
|
||||
websocket: {
|
||||
|
Loading…
Reference in New Issue
Block a user