Skip to content

Commit

Permalink
refactor: improve events payloads
Browse files Browse the repository at this point in the history
  • Loading branch information
Neosoulink committed Nov 24, 2024
1 parent fbcd778 commit 948287e
Show file tree
Hide file tree
Showing 21 changed files with 134 additions and 147 deletions.
24 changes: 13 additions & 11 deletions apps/api/src/players/gateways/players.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {
OnGatewayDisconnect,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
type WsResponse
WebSocketServer
} from "@nestjs/websockets";
import { Server, Socket } from "socket.io";

Expand All @@ -15,9 +14,10 @@ import {
SOCKET_ROOM_CREATED_TOKEN,
SOCKET_JOINED_ROOM_TOKEN,
SOCKET_PERFORM_MOVE_TOKEN,
SOCKET_MOVE_PERFORMED_TOKEN
SOCKET_MOVE_PERFORMED_TOKEN,
type GameUpdatedPayload
} from "@chess-d/shared";
import { Move } from "chess.js";
import { validateFen } from "chess.js";

@WebSocketGateway({
cors: {
Expand Down Expand Up @@ -71,14 +71,16 @@ export class PlayersGateway
}

@SubscribeMessage(SOCKET_PERFORM_MOVE_TOKEN)
handlePerformMove(@ConnectedSocket() socket: Socket, @MessageBody() payload) {
handleMove(
@ConnectedSocket() socket: Socket,
@MessageBody() payload: GameUpdatedPayload
): void {
console.log("Move performed by", socket.id, payload);

this.playersService.handleMove(socket, payload.move);

this.server
.in(socket.data?.roomID)
.except(socket.id)
.emit(SOCKET_MOVE_PERFORMED_TOKEN, payload);
if (this.playersService.handleMove(socket, payload.move))
this.server
.in(socket.data?.roomID)
.except(socket.id)
.emit(SOCKET_MOVE_PERFORMED_TOKEN, payload);
}
}
16 changes: 8 additions & 8 deletions apps/api/src/players/services/players.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import {
PlayerEntity
} from "@chess-d/shared";
import { randomUUID, UUID } from "crypto";
import { validateFen, type Move } from "chess.js";
import type { Socket } from "socket.io";
import { Move } from "chess.js";

@Injectable()
export class PlayersService {
Expand All @@ -30,10 +30,8 @@ export class PlayersService {
if (
typeof queryRoomID === "string" &&
!Array.isArray(this.rooms[queryRoomID]?.players)
) {
const err = new Error("Invalid room ID.");
return err;
}
)
return new Error("Invalid room ID.");

const player: PlayerEntity = {
id: socket.id,
Expand All @@ -43,7 +41,8 @@ export class PlayersService {
};

if (typeof queryRoomID === "string") {
if (this.rooms[queryRoomID]?.players?.length !== 1) return null;
if (this.rooms[queryRoomID]?.players?.length !== 1)
return new Error("Unable to join a room without a player or full.");

player.color = getOppositeColorSide(
this.rooms[queryRoomID].players[0].color
Expand Down Expand Up @@ -88,8 +87,9 @@ export class PlayersService {
return { roomID, room, player };
}

handleMove(socket: Socket, move: Move) {
if (!move) return null;
handleMove(socket: Socket, move?: Move): string | null {
if (typeof move?.after !== "string" || !validateFen(move.after))
return null;

const roomID = socket.data?.roomID;
this.rooms[roomID].fen = move.after;
Expand Down
19 changes: 11 additions & 8 deletions apps/web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export const App = () => {
setup: setupGame,
app,
movePiece,
dispose: disposeApp,
gameUpdatedCallbackRegister
} = useGame();
const {
Expand Down Expand Up @@ -41,8 +40,8 @@ export const App = () => {
useEffect(() => {
if (app && !socket.connected) {
socket.connect();
socket.on("disconnect", (r, d) => {
console.log("disconnect ==>", r, d);
socket.on("disconnect", (reason, description) => {
console.log("disconnect ==>", reason, description);
});
}

Expand All @@ -69,14 +68,18 @@ export const App = () => {

useEffect(() => {
gameUpdatedCallbackRegister((payload) => {
opponentPlayer?.notify$$?.next({
fen: payload?.fen,
turn: payload?.turn
});
console.log("Game updated", payload);
opponentPlayer?.notify$$?.next(payload);
currentPlayer?.notify$$?.next(payload);

socket?.emit(SOCKET_PERFORM_MOVE_TOKEN, payload);
});
}, [opponentPlayer?.notify$$, gameUpdatedCallbackRegister, socket]);
}, [
currentPlayer?.notify$$,
opponentPlayer?.notify$$,
gameUpdatedCallbackRegister,
socket
]);

return <div />;
};
10 changes: 4 additions & 6 deletions apps/web/src/core/ai/ai.controller.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { singleton } from "tsyringe";
import { filter, fromEvent, Subject } from "rxjs";
import { RegisterLifecycleState } from "@quick-threejs/reactive";
import type { Move } from "chess.js";
import type { RegisterLifecycleState } from "@quick-threejs/reactive";

import { MessageEventPayload, MoveLike } from "../../shared/types";
import { AI_WILL_PERFORM_MOVE_TOKEN } from "../../shared/tokens";
import type { MessageEventPayload } from "../../shared/types";

@singleton()
export class AiController {
public readonly lifecycle$$ = new Subject<RegisterLifecycleState>();
public readonly movePerformed$$ = new Subject<
MessageEventPayload<MoveLike>
>();

public readonly movePerformed$$ = new Subject<MessageEventPayload<Move>>();
public readonly willPerformMove$ = fromEvent<
MessageEvent<MessageEventPayload<{ fen: string }>>
>(self, "message").pipe(
Expand Down
7 changes: 1 addition & 6 deletions apps/web/src/core/ai/ai.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ export class AiService {
return console.warn("AI received invalid FEN string");

this.game.load(fen);
console.log(
"AI received FEN string",
fen,
this.game.fen(),
this.game.turn()
);
console.log("AI received FEN string", this.game.fen(), this.game.turn());

return this.ai?.getMove(this.game.turn());
};
Expand Down
23 changes: 8 additions & 15 deletions apps/web/src/core/game/engine/engine.controller.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
import { inject, singleton } from "tsyringe";
import { map, Observable } from "rxjs";
import { Chess, Move } from "chess.js";
import { Chess } from "chess.js";
import {
CoreModule as ChessboardModule,
PieceNotificationPayload
} from "@chess-d/chessboard";
import {
coordToSquare,
ObservablePayload,
squareToCoord
} from "@chess-d/shared";
import { coordToSquare, squareToCoord } from "@chess-d/shared";

import { EngineNotificationPayload } from "../../../shared/interfaces";
import {
EngineNotificationPayload,
EnginePieceMovedNotificationPayload
} from "../../../shared/types";

@singleton()
export class EngineController {
public readonly pieceSelected$?: Observable<EngineNotificationPayload>;
public readonly pieceMoved$?: Observable<
EngineNotificationPayload & {
nextMoveIndex: number;
nextMove?: Move;
} & ObservablePayload<
ChessboardModule["pieces"]["controller"]["pieceMoved$$"]
>
>;
public readonly pieceMoved$?: Observable<EnginePieceMovedNotificationPayload>;

constructor(
@inject(Chess) private readonly game: Chess,
Expand All @@ -48,6 +40,7 @@ export class EngineController {
return {
...payload,
...enginePayload,
endCoord,
possibleCoords,
possibleMoves,
nextMoveIndex,
Expand Down
17 changes: 1 addition & 16 deletions apps/web/src/core/game/engine/engine.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { inject, singleton } from "tsyringe";
import { Subscription } from "rxjs";
import { Color } from "chess.js";
import { Module } from "@quick-threejs/reactive";

import { EngineService } from "./engine.service";
import { EngineController } from "./engine.controller";
import { GAME_UPDATED_TOKEN } from "../../../shared/tokens";
import { MessageEventPayload, MoveLike } from "../../../shared/types";

@singleton()
export class EngineModule implements Module {
Expand All @@ -24,19 +21,7 @@ export class EngineModule implements Module {
),
this.controller.pieceMoved$?.subscribe((payload) => {
this.service.handlePieceMoved(payload);

self.postMessage({
token: GAME_UPDATED_TOKEN,
value: {
fen: this.service.getFen(),
turn: this.service.getTurn(),
move: payload.nextMove
}
} satisfies MessageEventPayload<{
turn: Color;
fen: string;
move?: MoveLike;
}>);
this.service.handlePieceMovedSuccessfully(payload);
})
);
}
Expand Down
30 changes: 20 additions & 10 deletions apps/web/src/core/game/engine/engine.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
PieceType
} from "@chess-d/shared";

import { EngineGameUpdatedMessageEventPayload } from "../../../shared/types";
import { GAME_UPDATED_TOKEN } from "../../../shared/tokens";
import { EngineController } from "./engine.controller";

@singleton()
Expand All @@ -20,12 +22,12 @@ export class EngineService {
@inject(ChessboardModule) private readonly chessboard: ChessboardModule
) {}

public getTurn() {
return this.game.turn();
}
public handlePieceSelected(
payload: ObservablePayload<EngineController["pieceSelected$"]>
) {
const { possibleCoords } = payload;

public getFen() {
return this.game.fen();
this.chessboard.board.component.setMarkers(possibleCoords);
}

public handlePieceMoved(
Expand Down Expand Up @@ -84,21 +86,29 @@ export class EngineService {
}

this.chessboard.pieces.component.movePieceByCoord(piece, endCoord);
this.game.move(nextMove);

if (nextMove.promotion && piece.type === PieceType.pawn) {
this.chessboard.pieces.component.promotePiece(
piece as MatrixPieceModel<PieceType.pawn, (typeof piece)["color"]>,
nextMove.promotion as PieceType
);
}

this.game.move(nextMove);
}

public handlePieceSelected(
payload: ObservablePayload<EngineController["pieceSelected$"]>
public handlePieceMovedSuccessfully(
payload: ObservablePayload<EngineController["pieceMoved$"]>
) {
const { possibleCoords } = payload;
const messagePayload: EngineGameUpdatedMessageEventPayload = {
token: GAME_UPDATED_TOKEN,
value: {
fen: this.game.fen(),
turn: this.game.turn(),
move: payload.nextMove
}
};

this.chessboard.board.component.setMarkers(possibleCoords);
self.postMessage(messagePayload);
}
}
7 changes: 4 additions & 3 deletions apps/web/src/core/game/pieces/pieces.controller.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { singleton } from "tsyringe";
import { Move } from "chess.js";
import { filter, fromEvent, Subject } from "rxjs";

import { MessageEventPayload, MoveLike } from "../../../shared/types";
import { MessageEventPayload } from "../../../shared/types";
import { PIECE_WILL_MOVE_TOKEN } from "../../../shared/tokens";

@singleton()
export class PiecesController {
public readonly playerMovedPiece$$ = new Subject<MoveLike>();
public readonly playerMovedPiece$$ = new Subject<Move>();

public readonly pieceWillMove$ = fromEvent<
MessageEvent<MessageEventPayload<MoveLike>>
MessageEvent<MessageEventPayload<Move>>
>(self, "message").pipe(
filter((payload) => payload.data.token === PIECE_WILL_MOVE_TOKEN)
);
Expand Down
6 changes: 1 addition & 5 deletions apps/web/src/core/game/pieces/pieces.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { inject, singleton } from "tsyringe";
import { Subscription } from "rxjs";
import { Module } from "@quick-threejs/reactive";

import { PIECE_WILL_MOVE_TOKEN } from "../../../shared/tokens";
import { PiecesService } from "./pieces.service";
import { PiecesController } from "./pieces.controller";

Expand All @@ -23,10 +22,7 @@ export class PiecesModule implements Module {
this.controller.pieceWillMove$.subscribe((payload) => {
const move = payload.data.value;

console.log("move", move);

if (payload.data?.token === PIECE_WILL_MOVE_TOKEN && move?.to)
this.controller.playerMovedPiece$$.next(move);
if (move?.to) this.controller.playerMovedPiece$$.next(move);
})
);
}
Expand Down
5 changes: 2 additions & 3 deletions apps/web/src/core/game/pieces/pieces.service.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { CoreModule as ChessCoreModule } from "@chess-d/chessboard";
import { ColorSide, PieceType, squareToCoord } from "@chess-d/shared";
import { Move } from "chess.js";
import { inject, singleton } from "tsyringe";

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

@singleton()
export class PiecesService {
constructor(
@inject(ChessCoreModule) private readonly chessboard: ChessCoreModule
) {}

handlePlayerMovedPiece(move: MoveLike) {
handlePlayerMovedPiece(move: Move) {
const piece = this.chessboard.pieces.component.getPieceByCoord(
move.piece as PieceType,
move.color as ColorSide,
Expand Down
Loading

0 comments on commit 948287e

Please sign in to comment.