From 82a2724c93fa2629e53a7e163bbea82742173640 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+phoenix-starlight@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:07:51 -0800 Subject: [PATCH 1/3] Do not start game when a user joins and leaves an auto-start room --- app/rooms/commands/preparation-commands.ts | 55 +++++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/app/rooms/commands/preparation-commands.ts b/app/rooms/commands/preparation-commands.ts index 45921aedb..e19884ef6 100644 --- a/app/rooms/commands/preparation-commands.ts +++ b/app/rooms/commands/preparation-commands.ts @@ -23,6 +23,8 @@ import { CloseCodes } from "../../types/enum/CloseCodes" import { getRank } from "../../utils/elo" import { SpecialGameRule } from "../../types/enum/SpecialGameRule" import { UserRecord } from "firebase-admin/lib/auth/user-record" +import { setTimeout } from "node:timers/promises" +import { AbortError } from "node-fetch" export class OnJoinCommand extends Command< PreparationRoom, @@ -606,21 +608,10 @@ export class OnToggleReadyCommand extends Command< // auto start when ranked lobby is full and all ready this.room.state.addMessage({ authorId: "server", - payload: `Lobby is full, starting match...` + payload: "Lobby is full, starting match in 3..." }) - if ( - [GameMode.RANKED, GameMode.SCRIBBLE].includes(this.state.gameMode) - ) { - // open another one - this.room.presence.publish("lobby-full", { - gameMode: this.state.gameMode, - minRank: this.state.minRank, - noElo: this.state.noElo - }) - } - - return [new OnGameStartRequestCommand()] + return new CheckAutoStartRoom() } } catch (error) { logger.error(error) @@ -628,6 +619,44 @@ export class OnToggleReadyCommand extends Command< } } +export class CheckAutoStartRoom extends Command { + async execute() { + const abortOnPlayerLeave = new AbortController() + + this.room.state.users.onRemove(() => abortOnPlayerLeave.abort("User left")) + + try { + await setTimeout(3000, null, { signal: abortOnPlayerLeave.signal }) + + this.room.state.addMessage({ + authorId: "server", + payload: "Starting match..." + }) + + if ([GameMode.RANKED, GameMode.SCRIBBLE].includes(this.state.gameMode)) { + // open another one + this.room.presence.publish("lobby-full", { + gameMode: this.state.gameMode, + minRank: this.state.minRank, + noElo: this.state.noElo + }) + } + + return new OnGameStartRequestCommand() + } catch (error) { + if (error instanceof AbortError) { + this.room.state.addMessage({ + authorId: "server", + avatar: "0070/Sigh", + payload: "Waiting for the room to fill up." + }) + } else { + logger.error(error) + } + } + } +} + export class InitializeBotsCommand extends Command< PreparationRoom, { From 896d1b415783c40dc39e52c5d0b71edd49aed957 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+phoenix-starlight@users.noreply.github.com> Date: Mon, 30 Dec 2024 16:18:48 -0800 Subject: [PATCH 2/3] Change checking mechanism --- app/rooms/commands/preparation-commands.ts | 27 ++++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/app/rooms/commands/preparation-commands.ts b/app/rooms/commands/preparation-commands.ts index e19884ef6..62e6cfc7c 100644 --- a/app/rooms/commands/preparation-commands.ts +++ b/app/rooms/commands/preparation-commands.ts @@ -621,13 +621,14 @@ export class OnToggleReadyCommand extends Command< export class CheckAutoStartRoom extends Command { async execute() { - const abortOnPlayerLeave = new AbortController() + await setTimeout(3000) - this.room.state.users.onRemove(() => abortOnPlayerLeave.abort("User left")) - - try { - await setTimeout(3000, null, { signal: abortOnPlayerLeave.signal }) + const nbExpectedPlayers = + this.room.metadata?.whitelist && this.room.metadata?.whitelist.length > 0 + ? max(MAX_PLAYERS_PER_GAME)(this.room.metadata?.whitelist.length) + : MAX_PLAYERS_PER_GAME + if (this.state.users.size === nbExpectedPlayers) { this.room.state.addMessage({ authorId: "server", payload: "Starting match..." @@ -643,16 +644,12 @@ export class CheckAutoStartRoom extends Command { } return new OnGameStartRequestCommand() - } catch (error) { - if (error instanceof AbortError) { - this.room.state.addMessage({ - authorId: "server", - avatar: "0070/Sigh", - payload: "Waiting for the room to fill up." - }) - } else { - logger.error(error) - } + } else { + this.room.state.addMessage({ + authorId: "server", + avatar: "0070/Sigh", + payload: "Waiting for the room to fill up." + }) } } } From 92d56cfa7ca571a83aa122b6e9491a8a025fc9b0 Mon Sep 17 00:00:00 2001 From: Fury_Phoenix <64714532+phoenix-starlight@users.noreply.github.com> Date: Fri, 3 Jan 2025 10:06:32 -0800 Subject: [PATCH 3/3] Refactor and improve original idea --- app/rooms/commands/preparation-commands.ts | 14 +++++--------- app/rooms/preparation-room.ts | 1 + app/rooms/states/preparation-state.ts | 1 + 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/rooms/commands/preparation-commands.ts b/app/rooms/commands/preparation-commands.ts index 62e6cfc7c..854adbcb7 100644 --- a/app/rooms/commands/preparation-commands.ts +++ b/app/rooms/commands/preparation-commands.ts @@ -621,14 +621,11 @@ export class OnToggleReadyCommand extends Command< export class CheckAutoStartRoom extends Command { async execute() { - await setTimeout(3000) - - const nbExpectedPlayers = - this.room.metadata?.whitelist && this.room.metadata?.whitelist.length > 0 - ? max(MAX_PLAYERS_PER_GAME)(this.room.metadata?.whitelist.length) - : MAX_PLAYERS_PER_GAME + try { + this.state.abortOnPlayerLeave = new AbortController() + const signal = this.state.abortOnPlayerLeave.signal + await setTimeout(3000, null, { signal }) - if (this.state.users.size === nbExpectedPlayers) { this.room.state.addMessage({ authorId: "server", payload: "Starting match..." @@ -644,10 +641,9 @@ export class CheckAutoStartRoom extends Command { } return new OnGameStartRequestCommand() - } else { + } catch (e) { this.room.state.addMessage({ authorId: "server", - avatar: "0070/Sigh", payload: "Waiting for the room to fill up." }) } diff --git a/app/rooms/preparation-room.ts b/app/rooms/preparation-room.ts index 19402ad6b..64b5795dd 100644 --- a/app/rooms/preparation-room.ts +++ b/app/rooms/preparation-room.ts @@ -393,6 +393,7 @@ export default class PreparationRoom extends Room { )*/ } try { + this.state.abortOnPlayerLeave?.abort() if (consented) { throw new Error("consented leave") } diff --git a/app/rooms/states/preparation-state.ts b/app/rooms/states/preparation-state.ts index cb5c58b4c..91f02bb5e 100644 --- a/app/rooms/states/preparation-state.ts +++ b/app/rooms/states/preparation-state.ts @@ -35,6 +35,7 @@ export default class PreparationState @type("boolean") noElo: boolean @type(["string"]) whitelist: string[] @type(["string"]) blacklist: string[] + abortOnPlayerLeave?: AbortController constructor(params: { ownerId?: string