summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorElizabeth (Lizzy) Hunt <elizabeth.hunt@simponic.xyz>2023-08-26 17:57:05 -0600
committerGitHub <noreply@github.com>2023-08-26 17:57:05 -0600
commit8a4ab8d79b5ce1dabb431168398b5d5111fe326c (patch)
treee60767dc5295edf379cf421e20171dc418e548b7 /client
parentc6e9baa0009f7cce0f6ff156a3957ef04a8cb684 (diff)
parent6ce6946a4401d2ee6fa5cb747fab7d4c658a63c8 (diff)
downloadjumpstorm-8a4ab8d79b5ce1dabb431168398b5d5111fe326c.tar.gz
jumpstorm-8a4ab8d79b5ce1dabb431168398b5d5111fe326c.zip
Merge pull request #1 from Simponic/network
Network
Diffstat (limited to 'client')
-rw-r--r--client/.eslintrc.js6
-rw-r--r--client/index.html2
-rw-r--r--client/public/css/colors.css2
-rw-r--r--client/public/css/style.css10
-rw-r--r--client/public/css/tf.css2
-rw-r--r--client/public/css/theme.css2
-rw-r--r--client/src/JumpStorm.ts168
-rw-r--r--client/src/components/GameCanvas.svelte18
-rw-r--r--client/src/components/LeaderBoard.svelte2
-rw-r--r--client/src/main.ts4
-rw-r--r--client/src/routes/Home.svelte3
-rw-r--r--client/svelte.config.js6
-rw-r--r--client/tsconfig.json5
-rw-r--r--client/vite.config.ts23
14 files changed, 193 insertions, 60 deletions
diff --git a/client/.eslintrc.js b/client/.eslintrc.js
index f200fbf..a9b1e2d 100644
--- a/client/.eslintrc.js
+++ b/client/.eslintrc.js
@@ -1,11 +1,11 @@
module.exports = {
extends: [
// add more generic rule sets here, such as:
- "eslint:recommended",
- "plugin:svelte/recommended",
+ 'eslint:recommended',
+ 'plugin:svelte/recommended'
],
rules: {
// override/add rules settings here, such as:
// 'svelte/rule-name': 'error'
- },
+ }
};
diff --git a/client/index.html b/client/index.html
index 00b94e7..892a3af 100644
--- a/client/index.html
+++ b/client/index.html
@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
diff --git a/client/public/css/colors.css b/client/public/css/colors.css
index 067ddcd..6108028 100644
--- a/client/public/css/colors.css
+++ b/client/public/css/colors.css
@@ -10,7 +10,7 @@
--orange: #af3a03;
}
-[data-theme="dark"] {
+[data-theme='dark'] {
--bg: #282828;
--text: #f9f5d7;
--red: #fb4934;
diff --git a/client/public/css/style.css b/client/public/css/style.css
index cdfef76..4dfe605 100644
--- a/client/public/css/style.css
+++ b/client/public/css/style.css
@@ -1,15 +1,15 @@
-@import url("./theme.css");
-@import url("./tf.css");
+@import url('./theme.css');
+@import url('./tf.css');
@font-face {
- font-family: "scientifica";
- src: url("/fonts/scientifica.ttf");
+ font-family: 'scientifica';
+ src: url('/fonts/scientifica.ttf');
}
* {
padding: 0;
margin: 0;
- font-family: "scientifica", monospace;
+ font-family: 'scientifica', monospace;
transition: background 0.2s ease-in-out;
font-smooth: never;
}
diff --git a/client/public/css/tf.css b/client/public/css/tf.css
index c1acd72..855fe0d 100644
--- a/client/public/css/tf.css
+++ b/client/public/css/tf.css
@@ -17,7 +17,7 @@
rgba(162, 254, 254, 1) 100%
);
- content: "";
+ content: '';
width: 100%;
height: 100%;
top: 0;
diff --git a/client/public/css/theme.css b/client/public/css/theme.css
index c65b2a8..eeb15ee 100644
--- a/client/public/css/theme.css
+++ b/client/public/css/theme.css
@@ -1,4 +1,4 @@
-@import url("./colors.css");
+@import url('./colors.css');
.primary {
color: var(--aqua);
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">
diff --git a/client/svelte.config.js b/client/svelte.config.js
index b0683fd..db735be 100644
--- a/client/svelte.config.js
+++ b/client/svelte.config.js
@@ -1,7 +1,7 @@
-import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
export default {
// Consult https://svelte.dev/docs#compile-time-svelte-preprocess
// for more information about preprocessors
- preprocess: vitePreprocess(),
-}
+ preprocess: vitePreprocess()
+};
diff --git a/client/tsconfig.json b/client/tsconfig.json
index 781d1b3..fadebb0 100644
--- a/client/tsconfig.json
+++ b/client/tsconfig.json
@@ -1,5 +1,5 @@
{
- "extends": "@tsconfig/svelte/tsconfig.json",
+ "extends": ["@tsconfig/svelte/tsconfig.json", "../tsconfig.engine.json"],
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
@@ -24,8 +24,5 @@
"src/**/*.js",
"src/**/*.svelte"
],
- "paths": {
- "@engine/*": ["../engine/*"]
- },
"references": [{ "path": "./tsconfig.node.json" }]
}
diff --git a/client/vite.config.ts b/client/vite.config.ts
index 0307338..6f0e1d0 100644
--- a/client/vite.config.ts
+++ b/client/vite.config.ts
@@ -1,13 +1,24 @@
-import { defineConfig } from "vite";
-import { svelte } from "@sveltejs/vite-plugin-svelte";
-import { fileURLToPath, URL } from "node:url";
+import { defineConfig } from 'vite';
+import { svelte } from '@sveltejs/vite-plugin-svelte';
+import { fileURLToPath, URL } from 'node:url';
// https://vitejs.dev/config/
export default defineConfig({
+ server: {
+ host: '0.0.0.0',
+ proxy: {
+ '/api': {
+ target: 'http://10.0.0.237:8080',
+ ws: true,
+ rewrite: (path) => path.replace(/^\/api/, '')
+ }
+ }
+ },
+ cors: true,
plugins: [svelte()],
resolve: {
alias: {
- "@engine": fileURLToPath(new URL("../engine", import.meta.url)),
- },
- },
+ '@engine': fileURLToPath(new URL('../engine', import.meta.url))
+ }
+ }
});