diff options
author | Elizabeth (Lizzy) Hunt <elizabeth.hunt@simponic.xyz> | 2023-08-26 17:57:05 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-26 17:57:05 -0600 |
commit | 8a4ab8d79b5ce1dabb431168398b5d5111fe326c (patch) | |
tree | e60767dc5295edf379cf421e20171dc418e548b7 /client/src | |
parent | c6e9baa0009f7cce0f6ff156a3957ef04a8cb684 (diff) | |
parent | 6ce6946a4401d2ee6fa5cb747fab7d4c658a63c8 (diff) | |
download | jumpstorm-8a4ab8d79b5ce1dabb431168398b5d5111fe326c.tar.gz jumpstorm-8a4ab8d79b5ce1dabb431168398b5d5111fe326c.zip |
Merge pull request #1 from Simponic/network
Network
Diffstat (limited to 'client/src')
-rw-r--r-- | client/src/JumpStorm.ts | 168 | ||||
-rw-r--r-- | client/src/components/GameCanvas.svelte | 18 | ||||
-rw-r--r-- | client/src/components/LeaderBoard.svelte | 2 | ||||
-rw-r--r-- | client/src/main.ts | 4 | ||||
-rw-r--r-- | client/src/routes/Home.svelte | 3 |
5 files changed, 160 insertions, 35 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); } } diff --git a/client/src/components/GameCanvas.svelte b/client/src/components/GameCanvas.svelte index ae8c1b0..ea7dd15 100644 --- a/client/src/components/GameCanvas.svelte +++ b/client/src/components/GameCanvas.svelte @@ -1,24 +1,26 @@ <script lang="ts"> import { onMount } from "svelte"; import { loadAssets } from "@engine/config"; + import { Game } from "@engine/Game"; import { JumpStorm } from "../JumpStorm"; - + let canvas: HTMLCanvasElement; let ctx: CanvasRenderingContext2D; export let width: number; export let height: number; - let jumpStorm: JumpStorm; - - onMount(() => { + onMount(async () => { ctx = canvas.getContext("2d"); ctx.imageSmoothingEnabled = false; - loadAssets().then(() => { - jumpStorm = new JumpStorm(ctx); - jumpStorm.play(); - }); + await loadAssets(); + + const game = new Game(); + const jumpStorm = new JumpStorm(game); + + await jumpStorm.init(ctx, "http", "ws", document.location.host + "/api"); + jumpStorm.play(); }); </script> diff --git a/client/src/components/LeaderBoard.svelte b/client/src/components/LeaderBoard.svelte index 8343c56..2f3e411 100644 --- a/client/src/components/LeaderBoard.svelte +++ b/client/src/components/LeaderBoard.svelte @@ -3,7 +3,7 @@ const MAX_ENTRIES = 8; - export let entries: { name: string, score: number }[] = []; + export let entries: { name: string; score: number }[] = []; </script> <div class="leaderboard"> diff --git a/client/src/main.ts b/client/src/main.ts index 5332616..aa7431f 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -1,7 +1,7 @@ -import App from "./App.svelte"; +import App from './App.svelte'; const app = new App({ - target: document.getElementById("app"), + target: document.getElementById('app') }); export default app; diff --git a/client/src/routes/Home.svelte b/client/src/routes/Home.svelte index 9ada10e..71ad324 100644 --- a/client/src/routes/Home.svelte +++ b/client/src/routes/Home.svelte @@ -3,10 +3,9 @@ import LeaderBoard from "../components/LeaderBoard.svelte"; import { Miscellaneous } from "@engine/config"; - + let width: number = Miscellaneous.WIDTH; let height: number = Miscellaneous.HEIGHT; - </script> <div class="centered-game"> |