diff --git a/public/scripts/send-ws-messages.js b/public/scripts/send-ws-messages.js index e6e3f81..73f0ed0 100644 --- a/public/scripts/send-ws-messages.js +++ b/public/scripts/send-ws-messages.js @@ -51,5 +51,17 @@ document.addEventListener('htmx:wsConfigSend', function (e) { e.detail.parameters = { type: 'decline_rematch', }; + } else if (e.target.id == 'cancel-takeback-request-button') { + e.detail.parameters = { + type: 'cancel_takeback_request', + }; + } else if (e.target.id == 'cancel-draw-request-button') { + e.detail.parameters = { + type: 'cancel_draw_request', + }; + } else if (e.target.id == 'cancel-rematch-request-button') { + e.detail.parameters = { + type: 'cancel_rematch_request', + }; } }); diff --git a/src/messages.ts b/src/messages.ts index 201a927..5fe19d0 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -11,7 +11,10 @@ export interface Message { | 'request_rematch' | 'accept_rematch' | 'decline_rematch' - | 'redirect_to_game'; + | 'redirect_to_game' + | 'cancel_takeback_request' + | 'cancel_draw_request' + | 'cancel_rematch_request'; } export interface MakeMoveMessage extends Message { @@ -42,3 +45,9 @@ export interface DeclineRematchMessage extends Message {} export interface RedirectToGameMessage extends Message { gameId: string; } + +export interface CancelTakebackRequestMessage extends Message {} + +export interface CancelDrawRequestMessage extends Message {} + +export interface CancelRematchRequestMessage extends Message {} diff --git a/src/web-socket-handler.tsx b/src/web-socket-handler.tsx index 7aabbdb..73fc599 100644 --- a/src/web-socket-handler.tsx +++ b/src/web-socket-handler.tsx @@ -16,6 +16,9 @@ import { AcceptRematchMessage, DeclineRematchMessage, RedirectToGameMessage, + CancelTakebackRequestMessage, + CancelDrawRequestMessage, + CancelRematchRequestMessage, } from './messages'; import { v4 as uuidv4 } from 'uuid'; @@ -150,8 +153,8 @@ class GameServer { if (this.takebackRequesterId) { if (this.takebackRequesterId === conn.id) { buttonsHtml = ( - ); } else { @@ -169,8 +172,8 @@ class GameServer { } else if (this.drawRequesterId) { if (this.drawRequesterId === conn.id) { buttonsHtml = ( - ); } else { @@ -204,8 +207,8 @@ class GameServer { if (this.rematchRequesterId) { if (this.rematchRequesterId === conn.id) { buttonsHtml = ( - ); } else { @@ -304,6 +307,24 @@ class GameServer { this.handleDeclineRematch(conn, message as DeclineRematchMessage); break; } + case 'cancel_takeback_request': { + this.handleCancelTakebackRequest( + conn, + message as CancelTakebackRequestMessage, + ); + break; + } + case 'cancel_draw_request': { + this.handleCancelDrawRequest(conn, message as CancelDrawRequestMessage); + break; + } + case 'cancel_rematch_request': { + this.handleCancelRematchRequest( + conn, + message as CancelRematchRequestMessage, + ); + break; + } } } @@ -592,6 +613,72 @@ class GameServer { this.rematchRequesterId = null; this.broadcastButtons(); } + + private handleCancelTakebackRequest( + conn: PlayerConnection, + message: CancelTakebackRequestMessage, + ): void { + if (this.gomoku.status !== 'playing') { + conn.sendMessage( + 'error', + 'You can only cancel a takeback request in an active game.', + ); + return; + } + + if (this.takebackRequesterId !== conn.id) { + conn.sendMessage( + 'error', + 'You are not the one who requested a takeback.', + ); + return; + } + + this.takebackRequesterId = null; + this.broadcastButtons(); + } + + private handleCancelDrawRequest( + conn: PlayerConnection, + message: CancelDrawRequestMessage, + ): void { + if (this.gomoku.status !== 'playing') { + conn.sendMessage( + 'error', + 'You can only cancel a draw request in an active game.', + ); + return; + } + + if (this.drawRequesterId !== conn.id) { + conn.sendMessage('error', 'You are not the one who requested a draw.'); + return; + } + + this.drawRequesterId = null; + this.broadcastButtons(); + } + + private handleCancelRematchRequest( + conn: PlayerConnection, + message: CancelRematchRequestMessage, + ): void { + if (this.gomoku.status !== 'finished') { + conn.sendMessage( + 'error', + 'You can only cancel a rematch request in a finished game.', + ); + return; + } + + if (this.rematchRequesterId !== conn.id) { + conn.sendMessage('error', 'You are not the one who requested a rematch.'); + return; + } + + this.rematchRequesterId = null; + this.broadcastButtons(); + } } export class WebSocketHandler {