From 8ac678a1d7096e5574baf52976861cb55205a1e3 Mon Sep 17 00:00:00 2001 From: AlecM33 Date: Tue, 27 Dec 2022 15:56:13 -0500 Subject: [PATCH] fix bug with restoring moderator when restarting game --- client/src/config/globals.js | 3 +- client/src/images/play-pause-placeholder.svg | 7 +++++ .../front_end_components/Confirmation.js | 19 +++++++++---- client/src/modules/timer/GameTimerManager.js | 18 ++++++++++-- client/src/styles/confirmation.css | 7 ++++- package.json | 1 + server/modules/ActiveGameRunner.js | 5 ++-- server/modules/GameManager.js | 28 ++++++------------- 8 files changed, 57 insertions(+), 31 deletions(-) create mode 100644 client/src/images/play-pause-placeholder.svg diff --git a/client/src/config/globals.js b/client/src/config/globals.js index 7eb3180..590c9a7 100644 --- a/client/src/config/globals.js +++ b/client/src/config/globals.js @@ -17,7 +17,8 @@ export const globals = { REVEAL_PLAYER: 'revealPlayer', TRANSFER_MODERATOR: 'transferModerator', CHANGE_NAME: 'changeName', - END_GAME: 'endGame' + END_GAME: 'endGame', + END_TIMER: 'endTimer' }, STATUS: { LOBBY: 'lobby', diff --git a/client/src/images/play-pause-placeholder.svg b/client/src/images/play-pause-placeholder.svg new file mode 100644 index 0000000..8186e53 --- /dev/null +++ b/client/src/images/play-pause-placeholder.svg @@ -0,0 +1,7 @@ + + + Layer 1 + + + + diff --git a/client/src/modules/front_end_components/Confirmation.js b/client/src/modules/front_end_components/Confirmation.js index 17cb9da..83e8785 100644 --- a/client/src/modules/front_end_components/Confirmation.js +++ b/client/src/modules/front_end_components/Confirmation.js @@ -1,16 +1,20 @@ import { toast } from './Toast.js'; -export const Confirmation = (message, onYes) => { +export const Confirmation = (message, onYes = null) => { document.querySelector('#confirmation')?.remove(); document.querySelector('#confirmation-background')?.remove(); let confirmation = document.createElement('div'); confirmation.setAttribute('id', 'confirmation'); - confirmation.innerHTML = - `
+ confirmation.innerHTML = onYes + ? `
+
` + : `
+
+
`; confirmation.querySelector('#confirmation-message').innerText = message; @@ -54,8 +58,13 @@ export const Confirmation = (message, onYes) => { }); }; - confirmation.querySelector('#confirmation-cancel-button').addEventListener('click', cancelHandler); - confirmation.querySelector('#confirmation-yes-button').addEventListener('click', confirmHandler); + if (onYes) { + confirmation.querySelector('#confirmation-cancel-button').addEventListener('click', cancelHandler); + confirmation.querySelector('#confirmation-yes-button').addEventListener('click', confirmHandler); + } else { // we are only displaying a message for them to acknowledge, so the yes button should dispel the confirmation + confirmation.querySelector('#confirmation-yes-button').addEventListener('click', cancelHandler); + } + background.addEventListener('click', cancelHandler); document.body.appendChild(background); diff --git a/client/src/modules/timer/GameTimerManager.js b/client/src/modules/timer/GameTimerManager.js index ef43c5a..8e02dd6 100644 --- a/client/src/modules/timer/GameTimerManager.js +++ b/client/src/modules/timer/GameTimerManager.js @@ -1,4 +1,5 @@ import { globals } from '../../config/globals.js'; +import { Confirmation } from '../front_end_components/Confirmation.js'; export class GameTimerManager { constructor (stateBucket, socket) { @@ -88,11 +89,18 @@ export class GameTimerManager { } displayExpiredTime () { - const currentBtn = document.querySelector('#play-pause img'); + const currentBtn = document.querySelector('#timer-container-moderator #play-pause img'); if (currentBtn) { currentBtn.removeEventListener('click', this.pauseListener); currentBtn.removeEventListener('click', this.playListener); - currentBtn.remove(); + currentBtn.classList.add('disabled'); + currentBtn.setAttribute('src', '/images/play-pause-placeholder.svg'); + } else { + document.querySelector('#play-pause-placeholder')?.remove(); + const placeholderBtn = document.createElement('img'); + placeholderBtn.setAttribute('src', '../images/play-pause-placeholder.svg'); + placeholderBtn.classList.add('disabled'); + document.getElementById('play-pause').appendChild(placeholderBtn); } const timer = document.getElementById('game-timer'); @@ -123,6 +131,12 @@ export class GameTimerManager { } }); } + + if (!socket.hasListeners(globals.COMMANDS.END_TIMER)) { + socket.on(globals.COMMANDS.END_TIMER, () => { + Confirmation('The timer has expired!'); + }); + } } swapToPlayButton () { diff --git a/client/src/styles/confirmation.css b/client/src/styles/confirmation.css index 512d035..9bf69a2 100644 --- a/client/src/styles/confirmation.css +++ b/client/src/styles/confirmation.css @@ -34,7 +34,7 @@ margin: 1em 0 2em 0; } -.confirmation-buttons button { +.confirmation-buttons button, .confirmation-buttons-centered button { min-width: 5em; } @@ -43,6 +43,11 @@ justify-content: space-between; } +.confirmation-buttons-centered { + display: flex; + justify-content: center; +} + #confirmation-cancel-button { background-color: #762323 !important; } diff --git a/package.json b/package.json index 928130e..e8f6eab 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "start:dev": "NODE_ENV=development && webpack --config client/webpack/webpack-dev.config.js --mode=development && nodemon index.js", "start:dev:no-hot-reload": "NODE_ENV=development && webpack --config client/webpack/webpack-dev.config.js --mode=development && node index.js", "start:dev:windows": "SET NODE_ENV=development && webpack --config client/webpack/webpack-dev.config.js --mode=development && nodemon index.js", + "start:dev:windows:no-hot-reload:debug": "SET NODE_ENV=development && webpack --config client/webpack/webpack-dev.config.js --mode=development && node --inspect index.js", "start:dev:windows:no-hot-reload": "SET NODE_ENV=development && webpack --config client/webpack/webpack-dev.config.js --mode=development && node index.js", "start": "NODE_ENV=production node index.js -- loglevel=debug", "start:windows": "SET NODE_ENV=production && node index.js -- loglevel=debug port=8080", diff --git a/server/modules/ActiveGameRunner.js b/server/modules/ActiveGameRunner.js index 9837842..fc7c2f7 100644 --- a/server/modules/ActiveGameRunner.js +++ b/server/modules/ActiveGameRunner.js @@ -27,6 +27,7 @@ class ActiveGameRunner { case globals.GAME_PROCESS_COMMANDS.END_TIMER: game.timerParams.paused = false; game.timerParams.timeRemaining = 0; + namespace.in(game.accessCode).emit(globals.GAME_PROCESS_COMMANDS.END_TIMER); this.logger.trace('PARENT: END TIMER'); break; case globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER: @@ -52,8 +53,8 @@ class ActiveGameRunner { } }); - gameProcess.on('exit', () => { - this.logger.debug('Game timer thread ' + gameProcess.pid + ' exiting - game ' + game.accessCode); + gameProcess.on('exit', (code, signal) => { + this.logger.debug('Game timer thread ' + gameProcess.pid + ' exiting with code ' + code + ' - game ' + game.accessCode); }); gameProcess.send({ command: globals.GAME_PROCESS_COMMANDS.START_TIMER, diff --git a/server/modules/GameManager.js b/server/modules/GameManager.js index ef854b4..26ca29f 100644 --- a/server/modules/GameManager.js +++ b/server/modules/GameManager.js @@ -71,7 +71,7 @@ class GameManager { pauseTimer = (game, logger) => { const thread = this.activeGameRunner.timerThreads[game.accessCode]; - if (thread) { + if (thread && !thread.killed) { this.logger.debug('Timer thread found for game ' + game.accessCode); thread.send({ command: globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER, @@ -83,7 +83,7 @@ class GameManager { resumeTimer = (game, logger) => { const thread = this.activeGameRunner.timerThreads[game.accessCode]; - if (thread) { + if (thread && !thread.killed) { this.logger.debug('Timer thread found for game ' + game.accessCode); thread.send({ command: globals.GAME_PROCESS_COMMANDS.RESUME_TIMER, @@ -95,14 +95,14 @@ class GameManager { getTimeRemaining = (game, socket) => { const thread = this.activeGameRunner.timerThreads[game.accessCode]; - if (thread) { + if (thread && (!thread.killed && thread.exitCode === null)) { thread.send({ command: globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING, accessCode: game.accessCode, socketId: socket.id, logLevel: this.logger.logLevel }); - } else { + } else if (thread) { if (game.timerParams && game.timerParams.timeRemaining === 0) { this.namespace.to(socket.id).emit(globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING, game.timerParams.timeRemaining, game.timerParams.paused); } @@ -299,23 +299,11 @@ class GameManager { game.people[i].alignment = cards[i].team; } - /* If the game was originally set up with a TEMP mod and the game has gone far enough to establish - a DEDICATED mod, make the current mod a TEMP mod for the restart. */ - if (!game.hasDedicatedModerator && game.moderator.userType === globals.USER_TYPES.MODERATOR) { - game.moderator.userType = globals.USER_TYPES.TEMPORARY_MODERATOR; - } - - /* If the game was originally set up with a DEDICATED moderator and the current mod is DIFFERENT from that mod - (i.e. they transferred their powers at some point), check if the current mod was once a player (i.e. they have - a game role). If they were once a player, make them a temp mod for the restart. Otherwise, they were a - spectator, and we want to leave them as a dedicated moderator. + /* If there is currently a dedicated mod, and that person was once a player (i.e. they have a game role), make + them a temporary mod for the restarted game. */ - if (game.hasDedicatedModerator && game.moderator.id !== game.originalModeratorId) { - if (game.moderator.gameRole) { - game.moderator.userType = globals.USER_TYPES.TEMPORARY_MODERATOR; - } else { - game.moderator.userType = globals.USER_TYPES.MODERATOR; - } + if (game.moderator.gameRole && game.moderator.userType === globals.USER_TYPES.MODERATOR) { + game.moderator.userType = globals.USER_TYPES.TEMPORARY_MODERATOR; } // start the new game