Skip to content

Commit

Permalink
refactor(web): correct players actions handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Neosoulink committed Nov 14, 2024
1 parent 5002d84 commit 61bd95d
Show file tree
Hide file tree
Showing 26 changed files with 357 additions and 204 deletions.
4 changes: 1 addition & 3 deletions apps/api/nest-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@
"$schema": "https://json.schemastore.org/nest-cli",
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"plugins": ["@nestjs/graphql"]
}
"compilerOptions": {}
}
4 changes: 2 additions & 2 deletions apps/api/src/players/gateways/players.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class PlayersGateway

const newPlayer: PlayerEntity = {
id: player.id,
position: { x: 0, y: 0, z: 0 },
rotation: { w: 0, x: 0, y: 0, z: 0 },
color: "b",
isOpponent: false,
connectedAt: new Date()
};

Expand Down
110 changes: 60 additions & 50 deletions apps/web/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,69 @@
import { useEffect } from "react";
import { register, RegisterModule } from "@quick-threejs/reactive";
import GUI from "three/examples/jsm/libs/lil-gui.module.min.js";
import { Move } from "chess.js";

import { useSocket } from "./hooks/use-socket.hook";

const location = new URL(
"./core/main.worker.ts",
import.meta.url
) as unknown as string;
const enableDebug = !!import.meta.env?.DEV;

const onReady = async (app: RegisterModule) => {
const gui = app.gui() as GUI | undefined;
gui?.close();

const aiWorker = await app.workerPool().run({
payload: {
path: new URL(
"./core/ai.worker.ts",
import.meta.url
) as unknown as string,
subject: {}
}
});

aiWorker.thread?.movePerformed$()?.subscribe((payload: Move) => {
console.log("AI move performed...", payload);
app.worker()?.postMessage?.({
type: "piece_moved",
payload
});
});
};
import { useEffect, useMemo } from "react";

import { merge } from "rxjs";
import { useActions, useAi, useGame, useSocket } from "./shared/hooks";
import { PlayerModel } from "./shared/models";

export const App = () => {
const { socket, currentPlayer, playersList } = useSocket();
const { setup: setupGame, app } = useGame();
const { setup: setupActions, movePiece: movePieceAction } = useActions();
const { setup: setupAI, worker: aiWorker, player: opponentPlayer } = useAi();
const { socket } = useSocket();

// TODO: Players color should be defined by the user.
const currentPlayer = useMemo(() => new PlayerModel(), []);

// Setting up the game.
useEffect(() => {
register({
location,
enableDebug,
axesSizes: 5,
gridSizes: 10,
withMiniCamera: true,
onReady: async (app) => {
await onReady(app);
socket.connect();
}
});
}, [socket]);
if (!app) setupGame();

return () => {
app?.dispose();
};
}, [app, setupGame]);

// Setting up the game actions.
useEffect(() => {
if (app) setupActions(app);

return () => {};
}, [app, setupActions]);

// Setting up the AI player.
useEffect(() => {
console.log(currentPlayer, playersList);
}, [currentPlayer, playersList]);
if (app && !aiWorker) setupAI(app);

return () => {
aiWorker?.worker?.terminate?.();
};
}, [app, setupAI, aiWorker]);

// Setting up the socket player.
useEffect(() => {
if (app && !socket.connected) socket.connect();

return () => {
socket.disconnect();
};
}, [app, socket]);

// Setting up the socket player.
useEffect(() => {
const playersActionsSubscription = merge(
currentPlayer.pieceMoved$$,
opponentPlayer.pieceMoved$$
).subscribe((move) => {
movePieceAction(move);
});

return () => {
playersActionsSubscription.unsubscribe();
};
}, [
currentPlayer.pieceMoved$$,
movePieceAction,
opponentPlayer.pieceMoved$$
]);

return <div />;
};
Empty file.
File renamed without changes.
18 changes: 0 additions & 18 deletions apps/web/src/core/core.module.ts

This file was deleted.

17 changes: 17 additions & 0 deletions apps/web/src/core/game/game.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { inject, singleton } from "tsyringe";
import { Module } from "@quick-threejs/reactive";

import { PlayersModule } from "./players/players.module";

@singleton()
export class GameModule implements Module {
constructor(@inject(PlayersModule) public readonly players: PlayersModule) {}

public init(...props: any[]): void {
this.players.init(...props);
}

public dispose(): void {
this.players.dispose();
}
}
26 changes: 26 additions & 0 deletions apps/web/src/core/game/game.worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import "reflect-metadata";

import { container } from "tsyringe";
import { AppModule } from "@quick-threejs/reactive";
import { launchApp } from "@quick-threejs/reactive/worker";
import { isObject } from "@quick-threejs/utils";
import { CoreModule as ChessboardModule } from "@chess-d/chessboard/dist/core/core.module";
import { setup as setupChessboard } from "@chess-d/chessboard";

import { GameModule } from "./game.module";

launchApp({
onReady: async (app: AppModule) => {
const chessboard = await setupChessboard(app);

if (!isObject(app) || !app.camera)
throw new Error("Unable to retrieve the application context.");

container.register(AppModule, { useValue: app });
container.register(ChessboardModule, { useValue: chessboard });

const game = container.resolve<GameModule>(GameModule);

game.init();
}
});
9 changes: 9 additions & 0 deletions apps/web/src/core/game/players/players.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { singleton } from "tsyringe";
import { Subject } from "rxjs";

import { MoveLike } from "../../../shared/types/chess";

@singleton()
export class PlayersController {
public readonly pieceMoved$$ = new Subject<MoveLike>();
}
33 changes: 33 additions & 0 deletions apps/web/src/core/game/players/players.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { inject, singleton } from "tsyringe";
import { Module } from "@quick-threejs/reactive";

import { PlayersService } from "./players.service";
import { PlayersController } from "./players.controller";
import { MoveLike } from "../../../shared/types/chess";

@singleton()
export class PlayersModule implements Module {
constructor(
@inject(PlayersService) public readonly service: PlayersService,
@inject(PlayersController) public readonly controller: PlayersController
) {}

public init(...props: any[]): void {
self.addEventListener("message", this._onMessage.bind(this));

this.controller.pieceMoved$$.subscribe(
this.service.movePiece.bind(this.service)
);
}

public dispose(): void {
throw new Error("Method not implemented.");
}

private _onMessage(e: MessageEvent<{ type: string; payload: MoveLike }>) {
const move = e.data.payload;

if ((e.data?.type as string) === "piece_moved" && move?.to)
this.controller.pieceMoved$$.next(move);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,17 @@ import {
squareToCoord
} from "@chess-d/chessboard";
import { CoreModule as ChessCoreModule } from "@chess-d/chessboard/dist/core/core.module";
import { Move } from "chess.js";
import { inject, singleton } from "tsyringe";

import { MoveLike } from "../../../shared/types/chess";

@singleton()
export class PlayersService {
constructor(
@inject(ChessCoreModule) private readonly chessboard: ChessCoreModule
) {
console.log("Initialized?");
self.addEventListener(
"message",
(e: MessageEvent<{ type: string; payload: Move }>) => {
const move = e.data.payload as Move;
if ((e.data?.type as string) !== "piece_moved" || !move.to) return;

this.movePiece(move);
}
);
}
) {}

movePiece(move: Move) {
movePiece(move: MoveLike) {
const piece = this.chessboard.piecesModule.component.getPieceByCoord(
move.piece as PieceType,
move.color as ColorVariant,
Expand Down
29 changes: 0 additions & 29 deletions apps/web/src/core/main.worker.ts

This file was deleted.

18 changes: 0 additions & 18 deletions apps/web/src/core/players/players.module.ts

This file was deleted.

27 changes: 0 additions & 27 deletions apps/web/src/models/player.model.ts

This file was deleted.

4 changes: 4 additions & 0 deletions apps/web/src/shared/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from "./use-actions.hook";
export * from "./use-ai.hook";
export * from "./use-game.hook";
export * from "./use-socket.hook";
24 changes: 24 additions & 0 deletions apps/web/src/shared/hooks/use-actions.hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { RegisterModule } from "@quick-threejs/reactive";
import { useCallback, useState } from "react";
import { MoveLike } from "../types";

/** @description Provide actions to control game (chessboard). */
export const useActions = () => {
const [app, setApp] = useState<RegisterModule | undefined>();

const setup = useCallback((app: RegisterModule) => {
setApp(app);
}, []);

const movePiece = (move: MoveLike) => {
app?.worker()?.postMessage?.({
type: "piece_moved",
payload: move
});
};

return {
setup,
movePiece
};
};
Loading

0 comments on commit 61bd95d

Please sign in to comment.