diff options
Diffstat (limited to 'client/src/JumpStorm.ts')
-rw-r--r-- | client/src/JumpStorm.ts | 168 |
1 files changed, 146 insertions, 22 deletions
diff --git a/client/src/JumpStorm.ts b/client/src/JumpStorm.ts index bd48483..6f9e24f 100644 --- a/client/src/JumpStorm.ts +++ b/client/src/JumpStorm.ts @@ -1,5 +1,6 @@ -import { Floor, Player } from "@engine/entities"; -import { Game } from "@engine/Game"; +import { Game } from '@engine/Game'; +import { Entity } from '@engine/entities'; +import { Grid } from '@engine/structures'; import { WallBounds, FacingDirection, @@ -7,28 +8,141 @@ import { Physics, Input, Collision, -} from "@engine/systems"; + 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'; -export class JumpStorm { +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) => + this.game.addEntity( + Entity.from(addBody.entityName, addBody.id, addBody.args) + ) + ); + 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 }) => this.game.getEntity(id)?.setFrom(args) + ); + break; + default: + break; + } + } +} + +class ClientSocketMessageQueueProvider implements MessageQueueProvider { private socket: WebSocket; + private messages: Message[]; + + constructor(socket: WebSocket) { + this.socket = socket; + this.messages = []; - constructor(ctx: CanvasRenderingContext2D) { - this.game = new Game(); - this.socket = new WebSocket("ws://localhost:8080"); + 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 = []; + } + } +} + +export class JumpStorm { + private game: Game; + private clientId: string; + + constructor(game: Game) { + this.game = game; + } + + public async init( + ctx: CanvasRenderingContext2D, + httpMethod: string, + wsMethod: string, + host: string + ) { + this.clientId = await this.getAssignedCookie( + `${httpMethod}://${host}/assign` + ); + const socket = new WebSocket(`${wsMethod}://${host}/game`); + const clientSocketMessageQueueProvider = + new ClientSocketMessageQueueProvider(socket); + const clientSocketMessagePublisher = new ClientSocketMessagePublisher( + socket + ); + const clientMessageProcessor = new ClientMessageProcessor(this.game); + + const inputSystem = new Input(this.clientId, clientSocketMessagePublisher); + this.addWindowEventListenersToInputSystem(inputSystem); + + const grid = new Grid(); [ - this.createInputSystem(), + new NetworkUpdate( + clientSocketMessageQueueProvider, + clientSocketMessagePublisher, + clientMessageProcessor + ), + inputSystem, new FacingDirection(), new Physics(), - new Collision(), - new WallBounds(ctx.canvas.width), - new Render(ctx), + new Collision(grid), + new WallBounds(), + new Render(ctx) ].forEach((system) => this.game.addSystem(system)); - - [new Floor(160), new Player()].forEach((entity) => - this.game.addEntity(entity), - ); } public play() { @@ -41,16 +155,26 @@ export class JumpStorm { requestAnimationFrame(loop); } - private createInputSystem(): Input { - const inputSystem = new Input(); - - window.addEventListener("keydown", (e) => { + private addWindowEventListenersToInputSystem(input: Input) { + window.addEventListener('keydown', (e) => { if (!e.repeat) { - inputSystem.keyPressed(e.key); + input.keyPressed(e.key.toLowerCase()); } }); - window.addEventListener("keyup", (e) => inputSystem.keyReleased(e.key)); - return inputSystem; + window.addEventListener('keyup', (e) => + input.keyReleased(e.key.toLowerCase()) + ); + } + + private async getAssignedCookie(endpoint: string): Promise<string> { + return fetch(endpoint) + .then((resp) => { + if (resp.ok) { + return resp.text(); + } + throw resp; + }) + .then((cookie) => cookie); } } |