Skip to content

Commit

Permalink
🎮 Add ingame frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
ferdodo committed Dec 14, 2024
1 parent 93195df commit 5bff6c8
Show file tree
Hide file tree
Showing 28 changed files with 1,597 additions and 37 deletions.
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
VITE_BACK_DOMAIN=localhost
VITE_WEBSOCKET_PORT=28035
VITE_WEBSOCKET_PROTOCOL=ws
2 changes: 1 addition & 1 deletion back/entities/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Game {
@Property()
playerHealths: Record<PublicKey, Health>;

@Property()
@Property({ nullable: true })
combats?: Combat[];

@Property()
Expand Down
25 changes: 25 additions & 0 deletions back/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,31 @@ Promise.resolve().then(async () => {
//await benchMarkDataMapper(dataMapper);
//await benchmarkSignVerify();
const backContext = await createBackContext(orm, db);

backContext.connections$.subscribe({
next: (connection) => {
console.log("Connection established");

connection.messages$.subscribe({
next: (message) => {
console.log("Message received", Object.keys(message).pop());
},
error: (error) => {
console.error("Message error", error);
},
complete: () => {
console.log("Message stream closed");
},
});
},
error: (error) => {
console.error("Connection error", error);
},
complete: () => {
console.log("Connection closed");
},
});

startServer(backContext);
console.log("Server started");
});
6 changes: 1 addition & 5 deletions back/types/mongo-deserialized.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
interface WithoutObjectId {
_id: undefined;
}

export type MongoDeserialized<T> = T & WithoutObjectId;
export type MongoDeserialized<T> = Omit<T, "_id">;
3 changes: 2 additions & 1 deletion back/utils/create-back-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { Db } from "mongodb";
import { createRoundTimer } from "core/utils/create-round-timer";
import { sign } from "./sign.js";
import { createKeyPair } from "./create-key-pair.js";
import { verify } from "./verify.js";

export async function createBackContext(
orm: MikroORM,
Expand All @@ -16,7 +17,7 @@ export async function createBackContext(

return {
connections$: createWsServer(),
isValidSignature: () => Promise.resolve(true),
isValidSignature: (signed) => verify(signed),
serverPublicKey,
signMessage: (message) => sign(serverPublicKey, serverPrivateKey, message),
lateMatchmakingTimer: (source) => source.pipe(debounceTime(10000)),
Expand Down
5 changes: 3 additions & 2 deletions back/utils/create-data-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import type { Db } from "mongodb";
import type { MikroORM } from "@mikro-orm/core";
import type { Game } from "core/types/game";
import type { Queuer } from "core/types/queuer";
import type { MongoSerialized } from "../types/mongo-serialized.js";

export function createDataMapper(orm: MikroORM, db: Db): DataMapper {
const gameCollection = db.collection<Game>("game");
const queuerCollection = db.collection<Queuer>("queuer");
const gameCollection = db.collection<MongoSerialized<Game>>("game");
const queuerCollection = db.collection<MongoSerialized<Queuer>>("queuer");

return {
readGame: (playsig) => readGame(orm, playsig),
Expand Down
4 changes: 2 additions & 2 deletions back/utils/create-ws-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { uid } from "uid";
import type { Server } from "node:https";

export function createWsServer<I, O>(): Observable<Connection<I, O>> {
return new Observable<Connection<I, O>>((connexionSubscriber) => {
const wss = createWebSocketServer();
const wss = createWebSocketServer();

return new Observable<Connection<I, O>>((connexionSubscriber) => {
wss.on("connection", (ws) => {
const messages$ = new Observable<I>((messageSubscriber) => {
ws.on("message", async function message(data) {
Expand Down
11 changes: 6 additions & 5 deletions back/utils/mongo-deserialize.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import type { MongoDeserialized } from "../types/mongo-deserialized.js";
import type { MongoSerialized } from "../types/mongo-serialized.js";

export function mongoDeserialize<T>(data: T): MongoDeserialized<T> {
return {
...data,
_id: undefined,
};
export function mongoDeserialize<T>({
_id,
...data
}: MongoSerialized<T>): MongoDeserialized<T> {
return { ...data };
}
3 changes: 2 additions & 1 deletion back/utils/observe-created-game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { Observable, share } from "rxjs";
import type { Game } from "core/types/game";
import type { MongoDeserialized } from "../types/mongo-deserialized.js";
import { mongoDeserialize } from "./mongo-deserialize.js";
import type { MongoSerialized } from "../types/mongo-serialized.js";

export function observeCreatedGame(
gameCollection: Collection<Game>,
gameCollection: Collection<MongoSerialized<Game>>,
): Observable<MongoDeserialized<Game>> {
return new Observable<MongoDeserialized<Game>>((subscriber) => {
const changeStream = gameCollection.watch([
Expand Down
3 changes: 2 additions & 1 deletion back/utils/observe-game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import type { Game } from "core/types/game";
import type { Playsig } from "core/types/playsig";
import { mongoDeserialize } from "./mongo-deserialize.js";
import type { MongoDeserialized } from "../types/mongo-deserialized.js";
import type { MongoSerialized } from "../types/mongo-serialized.js";

export function observeGame(
gameCollection: Collection<Game>,
gameCollection: Collection<MongoSerialized<Game>>,
playsig: Playsig,
): Observable<MongoDeserialized<Game>> {
return new Observable<MongoDeserialized<Game>>((subscriber) => {
Expand Down
3 changes: 2 additions & 1 deletion back/utils/observe-queuers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import { Observable, share } from "rxjs";
import type { MikroORM } from "@mikro-orm/core";
import { mongoDeserialize } from "./mongo-deserialize.js";
import type { MongoDeserialized } from "../types/mongo-deserialized.js";
import type { MongoSerialized } from "../types/mongo-serialized.js";

export function observeQueuers(
orm: MikroORM,
queuerCollection: Collection<Queuer>,
queuerCollection: Collection<MongoSerialized<Queuer>>,
): Observable<MongoDeserialized<Queuer>[]> {
const em = orm.em.fork();
const queuerRepository = em.getRepository(QueuerEntity);
Expand Down
4 changes: 3 additions & 1 deletion back/utils/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ export async function verify<T>(payload: T & Signed): Promise<boolean> {

const payloadBuffer: Buffer = Buffer.from(payloadSerialised, "utf8");

return subtle.verify(
const result = subtle.verify(
ecdsaParams,
publicCryptoKey,
signatureBuffer,
payloadBuffer,
);

return result;
}
73 changes: 72 additions & 1 deletion compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ services:
NODE_1: mongo-config-server-node1
NODE_2: mongo-config-server-node2
IS_REPLICA_SET_INITIATOR: true
volumes:
- mongo-config-server-node0-data:/data/db
- mongo-config-server-node0-config:/data/configdb

mongo-config-server-node1:
build: mongo-config-server
Expand All @@ -74,6 +77,9 @@ services:
NODE_0: mongo-config-server-node0
NODE_1: mongo-config-server-node1
NODE_2: mongo-config-server-node2
volumes:
- mongo-config-server-node1-data:/data/db
- mongo-config-server-node1-config:/data/configdb

mongo-config-server-node2:
build: mongo-config-server
Expand All @@ -84,6 +90,9 @@ services:
NODE_0: mongo-config-server-node0
NODE_1: mongo-config-server-node1
NODE_2: mongo-config-server-node2
volumes:
- mongo-config-server-node2-data:/data/db
- mongo-config-server-node2-config:/data/configdb

mongo-shard0-node0:
build: mongo-shard
Expand All @@ -94,6 +103,9 @@ services:
NODE_0: mongo-shard0-node0
NODE_1: mongo-shard0-node1
IS_REPLICA_SET_INITIATOR: true
volumes:
- mongo-shard0-node0-data:/data/db
- mongo-shard0-node0-config:/data/configdb

mongo-shard0-node1:
build: mongo-shard
Expand All @@ -103,6 +115,9 @@ services:
REPLICASET: shard0rs
NODE_0: mongo-shard0-node0
NODE_1: mongo-shard0-node1
volumes:
- mongo-shard0-node1-data:/data/db
- mongo-shard0-node1-config:/data/configdb

mongo-shard1-node0:
build: mongo-shard
Expand All @@ -113,6 +128,9 @@ services:
NODE_0: mongo-shard1-node0
NODE_1: mongo-shard1-node1
IS_REPLICA_SET_INITIATOR: true
volumes:
- mongo-shard1-node0-data:/data/db
- mongo-shard1-node0-config:/data/configdb

mongo-shard1-node1:
build: mongo-shard
Expand All @@ -122,6 +140,9 @@ services:
REPLICASET: shard1rs
NODE_0: mongo-shard1-node0
NODE_1: mongo-shard1-node1
volumes:
- mongo-shard1-node1-data:/data/db
- mongo-shard1-node1-config:/data/configdb

mongo-router-node0:
build: mongo-router
Expand Down Expand Up @@ -152,6 +173,11 @@ services:
- mongo-shard0-node1
- mongo-shard1-node0
- mongo-shard1-node1
volumes:
- mongo-router-node0-data:/data/db
- mongo-router-node0-config:/data/configdb
ports:
- "27017:27017"

mongo-router-node1:
build: mongo-router
Expand Down Expand Up @@ -181,15 +207,60 @@ services:
- mongo-shard0-node1
- mongo-shard1-node0
- mongo-shard1-node1
volumes:
- mongo-router-node1-data:/data/db
- mongo-router-node1-config:/data/configdb
ports:
- "27018:27017"

back:
build: back
environment:
MONGODB_USERNAME: user
MONGODB_PASSWORD: example
MONGODB_DATABASE: autochess
VITE_WEBSOCKET_PROTOCOL: ws
VITE_WEBSOCKET_PROTOCOL: ${VITE_WEBSOCKET_PROTOCOL}
ports:
- ${VITE_WEBSOCKET_PORT}:3000
depends_on:
- core
- mongo-router-node0
- mongo-router-node1

ingame:
build:
context: ingame
args:
- VITE_WEBSOCKET_PROTOCOL=${VITE_WEBSOCKET_PROTOCOL}
- VITE_WEBSOCKET_PORT=${VITE_WEBSOCKET_PORT}
- VITE_BACK_DOMAIN=${VITE_BACK_DOMAIN}
environment:
VITE_WEBSOCKET_PROTOCOL: ${VITE_WEBSOCKET_PROTOCOL}
VITE_WEBSOCKET_PORT: ${VITE_WEBSOCKET_PORT}
VITE_BACK_DOMAIN: ${VITE_BACK_DOMAIN}
ports:
- 53015:53015
depends_on:
- back
- core
- interface

volumes:
mongo-config-server-node0-data:
mongo-config-server-node0-config:
mongo-config-server-node1-data:
mongo-config-server-node1-config:
mongo-config-server-node2-data:
mongo-config-server-node2-config:
mongo-shard0-node0-data:
mongo-shard0-node0-config:
mongo-shard0-node1-data:
mongo-shard0-node1-config:
mongo-shard1-node0-data:
mongo-shard1-node0-config:
mongo-shard1-node1-data:
mongo-shard1-node1-config:
mongo-router-node0-data:
mongo-router-node0-config:
mongo-router-node1-data:
mongo-router-node1-config:
3 changes: 2 additions & 1 deletion core/automations/as-new-player-connect.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createRandomPublicKey } from "../mocks/create-random-public-key.js";
import type { FrontContext } from "../types/front-context.js";
import type { TestContext } from "../types/test-context.js";

Expand All @@ -8,7 +9,7 @@ export function asNewPlayerConnect(testContext: TestContext) {
const numberToLetter = (n: number) =>
n >= 1 && n <= 26 ? String.fromCharCode(n + 64) : n;

const publicKey = `${playersCount}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`;
const publicKey = createRandomPublicKey();

const frontContext: FrontContext = {
connection,
Expand Down
11 changes: 11 additions & 0 deletions core/mocks/create-random-public-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function createRandomPublicKey(): string {
let publicKey = "";

while (publicKey.length < 240) {
publicKey += Math.random()
.toString(16)
.slice(2, 2 + 60);
}

return publicKey.slice(0, 240);
}
4 changes: 2 additions & 2 deletions core/types/playsig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export const playsigSchema = {
description:
"Unique identifier for a game. Also a digest that " +
"can be computed from from it's public keys.",
minLength: 132,
maxLength: 132,
minLength: 8,
maxLength: 64,
pattern: "^[0-9a-fA-F]+$",
} as const;

Expand Down
4 changes: 2 additions & 2 deletions core/types/public-key.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export const publicKeySchema = {
title: "Public Key",
description: "A public key in hexadecimal format.",
type: "string",
minLength: 66,
maxLength: 66,
minLength: 240,
maxLength: 240,
pattern: "^[a-fA-F0-9]+$",
} as const;

Expand Down
7 changes: 5 additions & 2 deletions core/utils/create-playsig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import type { Queuer } from "../types/queuer.js";
import type { Playsig } from "../types/playsig.js";

export function createPlaysig(players: Queuer[]): Playsig {
const sortedPublicKeys = players.map((player) => player.publicKey).sort();
return sortedPublicKeys.slice(0, 8).join("");
const sortedPublicKeys = players
.map((player) => player.publicKey.slice(0, 8))
.sort();

return sortedPublicKeys.join("");
}
7 changes: 3 additions & 4 deletions core/utils/create-test-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Subject, withLatestFrom, map, tap, share } from "rxjs";
import type { Queuer } from "../types/queuer.js";
import type { Observable } from "rxjs";
import type { Game } from "../types/game.js";
import { createRandomPublicKey } from "../mocks/create-random-public-key.js";

export function createTestContext(): TestContext {
const dataMapper = createDataMapperMock();
Expand All @@ -16,12 +17,10 @@ export function createTestContext(): TestContext {
const backContext: BackContext = {
connections$: connectionMockFactory.createServer(),
isValidSignature: () => Promise.resolve(true),
serverPublicKey:
"ddddddddddcccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
serverPublicKey: createRandomPublicKey(),
signMessage: async (message) => ({
...message,
publicKey:
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
publicKey: createRandomPublicKey(),
signature: "ccccccccccc",
issuedAt: new Date().toISOString(),
expiresAt: new Date(Date.now() + 60000).toISOString(),
Expand Down
Loading

0 comments on commit 5bff6c8

Please sign in to comment.