various refactors

This commit is contained in:
AlecM33
2023-08-13 17:51:41 -04:00
parent 29431565b4
commit 0b7dd9f4d7
34 changed files with 1097 additions and 1164 deletions

View File

@@ -1,7 +1,6 @@
const globals = require('../config/globals');
const GameStateCurator = require('./GameStateCurator');
const GameCreationRequest = require('../model/GameCreationRequest');
const EVENT_IDS = globals.EVENT_IDS;
const { EVENT_IDS, STATUS, USER_TYPES, GAME_PROCESS_COMMANDS, REDIS_CHANNELS } = require('../config/globals');
const Events = [
{
@@ -12,7 +11,7 @@ const Events = [
},
communicate: async (game, socketArgs, vars) => {
vars.gameManager.namespace.in(game.accessCode).emit(
globals.EVENTS.PLAYER_JOINED,
EVENT_IDS.PLAYER_JOINED,
GameStateCurator.mapPerson(socketArgs),
game.isStartable
);
@@ -87,7 +86,7 @@ const Events = [
},
communicate: async (game, socketArgs, vars) => {
vars.gameManager.namespace.in(game.accessCode).emit(
globals.EVENT_IDS.ADD_SPECTATOR,
EVENT_IDS.ADD_SPECTATOR,
GameStateCurator.mapPerson(socketArgs)
);
}
@@ -117,7 +116,7 @@ const Events = [
communicate: async (game, socketArgs, vars) => {
const matchingPerson = vars.gameManager.findPersonByField(game, 'id', socketArgs.personId);
if (matchingPerson && vars.gameManager.namespace.sockets.get(matchingPerson.socketId)) {
vars.gameManager.namespace.to(matchingPerson.socketId).emit(globals.EVENTS.SYNC_GAME_STATE);
vars.gameManager.namespace.to(matchingPerson.socketId).emit(EVENT_IDS.SYNC_GAME_STATE);
}
}
},
@@ -125,7 +124,7 @@ const Events = [
id: EVENT_IDS.START_GAME,
stateChange: async (game, socketArgs, vars) => {
if (game.isStartable) {
game.status = globals.STATUS.IN_PROGRESS;
game.status = STATUS.IN_PROGRESS;
vars.gameManager.deal(game);
if (game.hasTimer) {
game.timerParams.paused = true;
@@ -137,7 +136,7 @@ const Events = [
if (vars.ackFn) {
vars.ackFn();
}
vars.gameManager.namespace.in(game.accessCode).emit(globals.EVENT_IDS.START_GAME);
vars.gameManager.namespace.in(game.accessCode).emit(EVENT_IDS.START_GAME);
}
},
{
@@ -145,9 +144,9 @@ const Events = [
stateChange: async (game, socketArgs, vars) => {
const person = game.people.find((person) => person.id === socketArgs.personId);
if (person && !person.out) {
person.userType = person.userType === globals.USER_TYPES.BOT
? globals.USER_TYPES.KILLED_BOT
: globals.USER_TYPES.KILLED_PLAYER;
person.userType = person.userType === USER_TYPES.BOT
? USER_TYPES.KILLED_BOT
: USER_TYPES.KILLED_PLAYER;
person.out = true;
person.killed = true;
}
@@ -155,7 +154,7 @@ const Events = [
communicate: async (game, socketArgs, vars) => {
const person = game.people.find((person) => person.id === socketArgs.personId);
if (person) {
vars.gameManager.namespace.in(game.accessCode).emit(globals.EVENT_IDS.KILL_PLAYER, person);
vars.gameManager.namespace.in(game.accessCode).emit(EVENT_IDS.KILL_PLAYER, person);
}
}
},
@@ -171,7 +170,7 @@ const Events = [
const person = game.people.find((person) => person.id === socketArgs.personId);
if (person) {
vars.gameManager.namespace.in(game.accessCode).emit(
globals.EVENT_IDS.REVEAL_PLAYER,
EVENT_IDS.REVEAL_PLAYER,
{
id: person.id,
gameRole: person.gameRole,
@@ -184,7 +183,7 @@ const Events = [
{
id: EVENT_IDS.END_GAME,
stateChange: async (game, socketArgs, vars) => {
game.status = globals.STATUS.ENDED;
game.status = STATUS.ENDED;
if (game.hasTimer && vars.timerManager.timerThreads[game.accessCode]) {
vars.logger.trace('KILLING TIMER PROCESS FOR ENDED GAME ' + game.accessCode);
vars.timerManager.timerThreads[game.accessCode].kill();
@@ -195,7 +194,7 @@ const Events = [
},
communicate: async (game, socketArgs, vars) => {
vars.gameManager.namespace.in(game.accessCode)
.emit(globals.EVENT_IDS.END_GAME, GameStateCurator.mapPeopleForModerator(game.people));
.emit(EVENT_IDS.END_GAME, GameStateCurator.mapPeopleForModerator(game.people));
if (vars.ackFn) {
vars.ackFn();
}
@@ -208,14 +207,14 @@ const Events = [
const toTransferTo = vars.gameManager.findPersonByField(game, 'id', socketArgs.personId);
if (currentModerator) {
if (currentModerator.gameRole) {
currentModerator.userType = globals.USER_TYPES.KILLED_PLAYER;
currentModerator.userType = USER_TYPES.KILLED_PLAYER;
} else {
currentModerator.userType = globals.USER_TYPES.SPECTATOR;
currentModerator.userType = USER_TYPES.SPECTATOR;
}
game.previousModeratorId = currentModerator.id;
}
if (toTransferTo) {
toTransferTo.userType = globals.USER_TYPES.MODERATOR;
toTransferTo.userType = USER_TYPES.MODERATOR;
game.currentModeratorId = toTransferTo.id;
}
},
@@ -223,7 +222,7 @@ const Events = [
if (vars.ackFn) {
vars.ackFn();
}
vars.gameManager.namespace.to(game.accessCode).emit(globals.EVENT_IDS.SYNC_GAME_STATE);
vars.gameManager.namespace.to(game.accessCode).emit(EVENT_IDS.SYNC_GAME_STATE);
}
},
{
@@ -233,10 +232,10 @@ const Events = [
const toTransferTo = vars.gameManager.findPersonByField(game, 'id', socketArgs.personId);
if (currentModerator && toTransferTo) {
if (currentModerator.id !== toTransferTo.id) {
currentModerator.userType = globals.USER_TYPES.PLAYER;
currentModerator.userType = USER_TYPES.PLAYER;
}
toTransferTo.userType = globals.USER_TYPES.MODERATOR;
toTransferTo.userType = USER_TYPES.MODERATOR;
toTransferTo.out = true;
toTransferTo.killed = true;
game.previousModeratorId = currentModerator.id;
@@ -247,14 +246,14 @@ const Events = [
const moderator = vars.gameManager.findPersonByField(game, 'id', game.currentModeratorId);
const moderatorSocket = vars.gameManager.namespace.sockets.get(moderator?.socketId);
if (moderator && moderatorSocket) {
vars.gameManager.namespace.to(moderator.socketId).emit(globals.EVENTS.SYNC_GAME_STATE);
moderatorSocket.to(game.accessCode).emit(globals.EVENT_IDS.KILL_PLAYER, moderator);
vars.gameManager.namespace.to(moderator.socketId).emit(EVENT_IDS.SYNC_GAME_STATE);
moderatorSocket.to(game.accessCode).emit(EVENT_IDS.KILL_PLAYER, moderator);
} else {
vars.gameManager.namespace.in(game.accessCode).emit(globals.EVENT_IDS.KILL_PLAYER, moderator);
vars.gameManager.namespace.in(game.accessCode).emit(EVENT_IDS.KILL_PLAYER, moderator);
}
const previousModerator = vars.gameManager.findPersonByField(game, 'id', game.previousModeratorId);
if (previousModerator && previousModerator.id !== moderator.id && vars.gameManager.namespace.sockets.get(previousModerator.socketId)) {
vars.gameManager.namespace.to(previousModerator.socketId).emit(globals.EVENTS.SYNC_GAME_STATE);
vars.gameManager.namespace.to(previousModerator.socketId).emit(EVENT_IDS.SYNC_GAME_STATE);
}
}
},
@@ -274,7 +273,7 @@ const Events = [
if (vars.ackFn) {
vars.ackFn();
}
vars.gameManager.namespace.in(game.accessCode).emit(globals.EVENT_IDS.RESTART_GAME);
vars.gameManager.namespace.in(game.accessCode).emit(EVENT_IDS.RESTART_GAME);
}
},
{
@@ -294,7 +293,7 @@ const Events = [
const socket = vars.gameManager.namespace.sockets.get(vars.requestingSocketId);
if (socket) {
vars.gameManager.namespace.to(socket.id).emit(
globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING,
GAME_PROCESS_COMMANDS.GET_TIME_REMAINING,
game.timerParams.timeRemaining,
game.timerParams.paused
);
@@ -302,10 +301,10 @@ const Events = [
}
} else { // we need to consult another container for the timer data
await vars.eventManager.publisher?.publish(
globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM,
REDIS_CHANNELS.ACTIVE_GAME_STREAM,
vars.eventManager.createMessageToPublish(
game.accessCode,
globals.EVENT_IDS.SOURCE_TIMER_EVENT,
EVENT_IDS.SOURCE_TIMER_EVENT,
vars.instanceId,
JSON.stringify({ socketId: vars.requestingSocketId, timerEventSubtype: vars.timerEventSubtype })
)
@@ -330,7 +329,7 @@ const Events = [
});
} else {
await vars.eventManager.publisher.publish(
globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM,
REDIS_CHANNELS.ACTIVE_GAME_STREAM,
vars.eventManager.createMessageToPublish(
game.accessCode,
socketArgs.timerEventSubtype,
@@ -353,7 +352,7 @@ const Events = [
game.timerParams.timeRemaining = 0;
},
communicate: async (game, socketArgs, vars) => {
vars.gameManager.namespace.in(game.accessCode).emit(globals.GAME_PROCESS_COMMANDS.END_TIMER);
vars.gameManager.namespace.in(game.accessCode).emit(GAME_PROCESS_COMMANDS.END_TIMER);
}
},
{
@@ -363,7 +362,7 @@ const Events = [
game.timerParams.timeRemaining = socketArgs.timeRemaining;
},
communicate: async (game, socketArgs, vars) => {
vars.gameManager.namespace.in(game.accessCode).emit(globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER, socketArgs.timeRemaining);
vars.gameManager.namespace.in(game.accessCode).emit(GAME_PROCESS_COMMANDS.PAUSE_TIMER, socketArgs.timeRemaining);
}
},
{
@@ -373,7 +372,7 @@ const Events = [
game.timerParams.timeRemaining = socketArgs.timeRemaining;
},
communicate: async (game, socketArgs, vars) => {
vars.gameManager.namespace.in(game.accessCode).emit(globals.GAME_PROCESS_COMMANDS.RESUME_TIMER, socketArgs.timeRemaining);
vars.gameManager.namespace.in(game.accessCode).emit(GAME_PROCESS_COMMANDS.RESUME_TIMER, socketArgs.timeRemaining);
}
},
{
@@ -382,7 +381,7 @@ const Events = [
communicate: async (game, socketArgs, vars) => {
const socket = vars.gameManager.namespace.sockets.get(socketArgs.socketId);
if (socket) {
vars.gameManager.namespace.to(socket.id).emit(globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING, socketArgs.timeRemaining, game.timerParams.paused);
vars.gameManager.namespace.to(socket.id).emit(GAME_PROCESS_COMMANDS.GET_TIME_REMAINING, socketArgs.timeRemaining, game.timerParams.paused);
}
}
}

View File

@@ -1,4 +1,4 @@
const globals = require('../config/globals.js');
const { GAME_PROCESS_COMMANDS, PRIMITIVES } = require('../config/globals');
const ServerTimer = require('./ServerTimer.js');
let timer;
@@ -7,43 +7,43 @@ let timer;
process.on('message', (msg) => {
const logger = require('./Logger')(msg.logLevel);
switch (msg.command) {
case globals.GAME_PROCESS_COMMANDS.START_TIMER:
case GAME_PROCESS_COMMANDS.START_TIMER:
logger.trace('CHILD PROCESS ' + msg.accessCode + ': START TIMER');
timer = new ServerTimer(
msg.hours,
msg.minutes,
globals.CLOCK_TICK_INTERVAL_MILLIS,
PRIMITIVES.CLOCK_TICK_INTERVAL_MILLIS,
logger
);
timer.runTimer().then(() => {
logger.debug('Timer finished for ' + msg.accessCode);
process.send({ command: globals.GAME_PROCESS_COMMANDS.END_TIMER });
process.send({ command: GAME_PROCESS_COMMANDS.END_TIMER });
process.exit(0);
});
break;
case globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER:
case GAME_PROCESS_COMMANDS.PAUSE_TIMER:
timer.stopTimer();
logger.trace('CHILD PROCESS ' + msg.accessCode + ': PAUSE TIMER');
process.send({ command: globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER, timeRemaining: timer.currentTimeInMillis });
process.send({ command: GAME_PROCESS_COMMANDS.PAUSE_TIMER, timeRemaining: timer.currentTimeInMillis });
break;
case globals.GAME_PROCESS_COMMANDS.RESUME_TIMER:
case GAME_PROCESS_COMMANDS.RESUME_TIMER:
timer.resumeTimer().then(() => {
logger.debug('Timer finished for ' + msg.accessCode);
process.send({ command: globals.GAME_PROCESS_COMMANDS.END_TIMER });
process.send({ command: GAME_PROCESS_COMMANDS.END_TIMER });
process.exit(0);
});
logger.trace('CHILD PROCESS ' + msg.accessCode + ': RESUME TIMER');
process.send({ command: globals.GAME_PROCESS_COMMANDS.RESUME_TIMER, timeRemaining: timer.currentTimeInMillis });
process.send({ command: GAME_PROCESS_COMMANDS.RESUME_TIMER, timeRemaining: timer.currentTimeInMillis });
break;
case globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING:
case GAME_PROCESS_COMMANDS.GET_TIME_REMAINING:
logger.trace('CHILD PROCESS ' + msg.accessCode + ': GET TIME REMAINING');
process.send({
command: globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING,
command: GAME_PROCESS_COMMANDS.GET_TIME_REMAINING,
timeRemaining: timer.currentTimeInMillis,
socketId: msg.socketId
});

View File

@@ -1,4 +1,4 @@
const globals = require('../config/globals');
const { USER_TYPES, STATUS } = require('../config/globals');
/* The purpose of this component is to only return the game state information that is necessary. For example, we only
want to return player role information to moderators. This avoids any possibility of a player having access to
@@ -12,7 +12,7 @@ const GameStateCurator = {
mapPeopleForModerator: (people) => {
return people
.filter((person) => {
return person.assigned === true || (person.userType === globals.USER_TYPES.SPECTATOR || person.userType === globals.USER_TYPES.MODERATOR);
return person.assigned === true || (person.userType === USER_TYPES.SPECTATOR || person.userType === USER_TYPES.MODERATOR);
})
.map((person) => ({
name: person.name,
@@ -45,7 +45,7 @@ const GameStateCurator = {
};
function getGameStateBasedOnPermissions (game, person) {
const client = game.status === globals.STATUS.LOBBY // people won't be able to know their role until past the lobby stage.
const client = game.status === STATUS.LOBBY // people won't be able to know their role until past the lobby stage.
? { name: person.name, hasEnteredName: person.hasEnteredName, id: person.id, cookie: person.cookie, userType: person.userType }
: {
name: person.name,
@@ -61,7 +61,7 @@ function getGameStateBasedOnPermissions (game, person) {
killed: person.killed
};
switch (person.userType) {
case globals.USER_TYPES.MODERATOR:
case USER_TYPES.MODERATOR:
return {
accessCode: game.accessCode,
status: game.status,
@@ -73,10 +73,10 @@ function getGameStateBasedOnPermissions (game, person) {
timerParams: game.timerParams,
isStartable: game.isStartable
};
case globals.USER_TYPES.TEMPORARY_MODERATOR:
case globals.USER_TYPES.SPECTATOR:
case globals.USER_TYPES.PLAYER:
case globals.USER_TYPES.KILLED_PLAYER:
case USER_TYPES.TEMPORARY_MODERATOR:
case USER_TYPES.SPECTATOR:
case USER_TYPES.PLAYER:
case USER_TYPES.KILLED_PLAYER:
return {
accessCode: game.accessCode,
status: game.status,
@@ -86,7 +86,7 @@ function getGameStateBasedOnPermissions (game, person) {
gameSize: game.gameSize,
people: game.people
.filter((person) => {
return person.assigned === true || person.userType === globals.USER_TYPES.SPECTATOR;
return person.assigned === true || person.userType === USER_TYPES.SPECTATOR;
})
.map((filteredPerson) => GameStateCurator.mapPerson(filteredPerson)),
timerParams: game.timerParams,

View File

@@ -1,6 +1,6 @@
const globals = require('../config/globals');
const { LOG_LEVEL } = require('../config/globals');
module.exports = function (logLevel = globals.LOG_LEVEL.INFO) {
module.exports = function (logLevel = LOG_LEVEL.INFO) {
return {
logLevel: logLevel,
info (message = '') {
@@ -10,7 +10,7 @@ module.exports = function (logLevel = globals.LOG_LEVEL.INFO) {
error (message = '') {
if (
logLevel === globals.LOG_LEVEL.INFO
logLevel === LOG_LEVEL.INFO
) { return; }
const now = new Date();
console.error('ERROR ', now.toGMTString(), ': ', message);
@@ -18,25 +18,25 @@ module.exports = function (logLevel = globals.LOG_LEVEL.INFO) {
warn (message = '') {
if (
logLevel === globals.LOG_LEVEL.INFO
|| logLevel === globals.LOG_LEVEL.ERROR
logLevel === LOG_LEVEL.INFO
|| logLevel === LOG_LEVEL.ERROR
) return;
const now = new Date();
console.error('WARN ', now.toGMTString(), ': ', message);
},
debug (message = '') {
if (logLevel === globals.LOG_LEVEL.INFO || logLevel === globals.LOG_LEVEL.ERROR || logLevel === globals.LOG_LEVEL.WARN) return;
if (logLevel === LOG_LEVEL.INFO || logLevel === LOG_LEVEL.ERROR || logLevel === LOG_LEVEL.WARN) return;
const now = new Date();
console.debug('DEBUG ', now.toGMTString(), ': ', message);
},
trace (message = '') {
if (
logLevel === globals.LOG_LEVEL.INFO
|| logLevel === globals.LOG_LEVEL.WARN
|| logLevel === globals.LOG_LEVEL.DEBUG
|| logLevel === globals.LOG_LEVEL.ERROR
logLevel === LOG_LEVEL.INFO
|| logLevel === LOG_LEVEL.WARN
|| logLevel === LOG_LEVEL.DEBUG
|| logLevel === LOG_LEVEL.ERROR
) return;
const now = new Date();

View File

@@ -1,4 +1,4 @@
const LOG_LEVEL = require('../config/globals').LOG_LEVEL;
const { LOG_LEVEL, ENVIRONMENTS } = require('../config/globals');
const http = require('http');
const https = require('https');
const path = require('path');
@@ -7,7 +7,6 @@ const crypto = require('crypto');
const EventManager = require('./singletons/EventManager.js');
const GameManager = require('./singletons/GameManager.js');
const TimerManager = require('./singletons/TimerManager.js');
const { ENVIRONMENT } = require('../config/globals.js');
const rateLimit = require('express-rate-limit').default;
const ServerBootstrapper = {
@@ -17,8 +16,8 @@ const ServerBootstrapper = {
timerManager: new TimerManager(logger, instanceId),
eventManager: new EventManager(logger, instanceId),
gameManager: process.env.NODE_ENV.trim() === 'development'
? new GameManager(logger, ENVIRONMENT.LOCAL, instanceId)
: new GameManager(logger, ENVIRONMENT.PRODUCTION, instanceId)
? new GameManager(logger, ENVIRONMENTS.LOCAL, instanceId)
: new GameManager(logger, ENVIRONMENTS.PRODUCTION, instanceId)
};
},
@@ -114,7 +113,7 @@ const ServerBootstrapper = {
});
// API endpoints
app.use('/api/games', standardRateLimit, require('../api/GamesAPI'));
app.use('/api/games', standardRateLimit, require('../api/RoomsAPI'));
app.use('/api/admin', (req, res, next) => {
if (isAuthorized(req)) {
next();

View File

@@ -1,7 +1,7 @@
const globals = require('../../config/globals');
const { RateLimiterMemory } = require('rate-limiter-flexible');
const redis = require('redis');
const Events = require('../Events');
const { EVENT_IDS, REDIS_CHANNELS, PRIMITIVES, SOCKET_EVENTS, TIMER_EVENTS, SYNCABLE_EVENTS } = require('../../config/globals');
class EventManager {
constructor (logger, instanceId) {
@@ -20,7 +20,7 @@ class EventManager {
}
broadcast = (message) => {
this.io?.emit(globals.EVENTS.BROADCAST, message);
this.io?.emit(EVENT_IDS.BROADCAST, message);
};
createRedisPublisher = async () => {
@@ -53,7 +53,7 @@ class EventManager {
throw new Error('UNABLE TO CONNECT TO REDIS because: ' + e);
}
await this.subscriber.subscribe(globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM, async (message) => {
await this.subscriber.subscribe(REDIS_CHANNELS.ACTIVE_GAME_STREAM, async (message) => {
this.logger.debug('MESSAGE: ' + message);
let messageComponents, args;
try {
@@ -64,7 +64,7 @@ class EventManager {
}
args = JSON.parse(
message.slice(
message.indexOf(messageComponents[messageComponents.length - 1]) + (globals.INSTANCE_ID_LENGTH + 1)
message.indexOf(messageComponents[messageComponents.length - 1]) + (PRIMITIVES.INSTANCE_ID_LENGTH + 1)
)
);
} catch (e) {
@@ -133,12 +133,12 @@ class EventManager {
};
registerSocketHandler = (namespace, socket, gameManager) => {
socket.on(globals.SOCKET_EVENTS.IN_GAME_MESSAGE, async (eventId, accessCode, args = null, ackFn = null) => {
socket.on(SOCKET_EVENTS.IN_GAME_MESSAGE, async (eventId, accessCode, args = null, ackFn = null) => {
const game = await gameManager.getActiveGame(accessCode);
if (game) {
if (globals.TIMER_EVENTS().includes(eventId)) {
if (TIMER_EVENTS().includes(eventId)) {
await this.handleEventById(
globals.EVENT_IDS.TIMER_EVENT,
EVENT_IDS.TIMER_EVENT,
null,
game,
socket.id,
@@ -160,10 +160,10 @@ class EventManager {
handleAndSyncSocketEvent = async (eventId, game, socket, socketArgs, ackFn) => {
await this.handleEventById(eventId, null, game, socket?.id, game.accessCode, socketArgs, ackFn, false);
/* This server should publish events initiated by a connected socket to Redis for consumption by other instances. */
if (globals.SYNCABLE_EVENTS().includes(eventId)) {
if (SYNCABLE_EVENTS().includes(eventId)) {
await this.gameManager.refreshGame(game);
await this.publisher?.publish(
globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM,
REDIS_CHANNELS.ACTIVE_GAME_STREAM,
this.createMessageToPublish(game.accessCode, eventId, this.instanceId, JSON.stringify(socketArgs))
);
}
@@ -194,7 +194,7 @@ class EventManager {
timerEventSubtype: timerEventSubtype
};
if (event) {
if (!syncOnly || eventId === globals.EVENT_IDS.RESTART_GAME) {
if (!syncOnly || eventId === EVENT_IDS.RESTART_GAME) {
await event.stateChange(game, socketArgs, additionalVars);
}
await event.communicate(game, socketArgs, additionalVars);

View File

@@ -1,4 +1,12 @@
const globals = require('../../config/globals');
const {
STATUS,
PRIMITIVES,
ERROR_MESSAGES,
GAME_PROCESS_COMMANDS,
USER_TYPES,
EVENT_IDS,
REDIS_CHANNELS
} = require('../../config/globals');
const Game = require('../../model/Game');
const Person = require('../../model/Person');
const GameStateCurator = require('../GameStateCurator');
@@ -62,9 +70,9 @@ class GameManager {
gameParams.hasDedicatedModerator,
gameParams.isTestGame
);
const newAccessCode = await this.generateAccessCode(globals.ACCESS_CODE_CHAR_POOL);
const newAccessCode = await this.generateAccessCode(PRIMITIVES.ACCESS_CODE_CHAR_POOL);
if (newAccessCode === null) {
return Promise.reject(globals.ERROR_MESSAGE.NO_UNIQUE_ACCESS_CODE);
return Promise.reject(ERROR_MESSAGES.NO_UNIQUE_ACCESS_CODE);
}
const moderator = initializeModerator(req.moderatorName, req.hasDedicatedModerator);
moderator.assigned = true;
@@ -75,7 +83,7 @@ class GameManager {
}
const newGame = new Game(
newAccessCode,
globals.STATUS.LOBBY,
STATUS.LOBBY,
null,
req.deck,
req.hasTimer,
@@ -88,7 +96,7 @@ class GameManager {
);
newGame.people = initializePeopleForGame(req.deck, moderator, this.shuffle, req.isTestGame, newGame.gameSize);
await this.eventManager.publisher.set(newAccessCode, JSON.stringify(newGame), {
EX: globals.STALE_GAME_SECONDS
EX: PRIMITIVES.STALE_GAME_SECONDS
});
return Promise.resolve({ accessCode: newAccessCode, cookie: moderator.cookie, environment: this.environment });
}).catch((message) => {
@@ -103,7 +111,7 @@ class GameManager {
if (thread && !thread.killed) {
this.logger.debug('Timer thread found for game ' + game.accessCode);
thread.send({
command: globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER,
command: GAME_PROCESS_COMMANDS.PAUSE_TIMER,
accessCode: game.accessCode,
logLevel: this.logger.logLevel
});
@@ -115,7 +123,7 @@ class GameManager {
if (thread && !thread.killed) {
this.logger.debug('Timer thread found for game ' + game.accessCode);
thread.send({
command: globals.GAME_PROCESS_COMMANDS.RESUME_TIMER,
command: GAME_PROCESS_COMMANDS.RESUME_TIMER,
accessCode: game.accessCode,
logLevel: this.logger.logLevel
});
@@ -127,14 +135,14 @@ class GameManager {
const thread = this.timerManager.timerThreads[game.accessCode];
if (thread && (!thread.killed && thread.exitCode === null)) {
thread.send({
command: globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING,
command: GAME_PROCESS_COMMANDS.GET_TIME_REMAINING,
accessCode: game.accessCode,
socketId: socketId,
logLevel: this.logger.logLevel
});
} else if (thread) {
if (game.timerParams && game.timerParams.timeRemaining === 0) {
this.namespace.to(socketId).emit(globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING, game.timerParams.timeRemaining, game.timerParams.paused);
this.namespace.to(socketId).emit(GAME_PROCESS_COMMANDS.GET_TIME_REMAINING, game.timerParams.timeRemaining, game.timerParams.paused);
}
}
}
@@ -154,9 +162,9 @@ class GameManager {
let codeDigits, accessCode;
let attempts = 0;
while (!accessCode || ((await this.eventManager.publisher.keys('*')).includes(accessCode)
&& attempts < globals.ACCESS_CODE_GENERATION_ATTEMPTS)) {
&& attempts < PRIMITIVES.ACCESS_CODE_GENERATION_ATTEMPTS)) {
codeDigits = [];
let iterations = globals.ACCESS_CODE_LENGTH;
let iterations = PRIMITIVES.ACCESS_CODE_LENGTH;
while (iterations > 0) {
iterations --;
codeDigits.push(charPool[getRandomInt(charCount)]);
@@ -178,7 +186,7 @@ class GameManager {
return Promise.reject({ status: 400, reason: 'This name is taken.' });
}
if (joinAsSpectator
&& game.people.filter(person => person.userType === globals.USER_TYPES.SPECTATOR).length === globals.MAX_SPECTATORS
&& game.people.filter(person => person.userType === USER_TYPES.SPECTATOR).length === PRIMITIVES.MAX_SPECTATORS
) {
return Promise.reject({ status: 400, reason: 'There are too many people already spectating.' });
} else if (joinAsSpectator || this.isGameStartable(game)) {
@@ -196,7 +204,7 @@ class GameManager {
createRandomId(),
createRandomId(),
name,
globals.USER_TYPES.PLAYER,
USER_TYPES.PLAYER,
null,
null,
null,
@@ -208,15 +216,15 @@ class GameManager {
game.isStartable = this.isGameStartable(game);
await this.refreshGame(game);
this.namespace.in(game.accessCode).emit(
globals.EVENTS.PLAYER_JOINED,
EVENT_IDS.PLAYER_JOINED,
GameStateCurator.mapPerson(moderator || newPlayer),
game.isStartable
);
await this.eventManager.publisher?.publish(
globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM,
REDIS_CHANNELS.ACTIVE_GAME_STREAM,
this.eventManager.createMessageToPublish(
game.accessCode,
globals.EVENT_IDS.PLAYER_JOINED,
EVENT_IDS.PLAYER_JOINED,
this.instanceId,
JSON.stringify(moderator || newPlayer)
)
@@ -237,7 +245,7 @@ class GameManager {
return cards;
}
restartGame = async (game, namespace, status = globals.STATUS.IN_PROGRESS) => {
restartGame = async (game, namespace) => {
// kill any outstanding timer threads
const subProcess = this.timerManager.timerThreads[game.accessCode];
if (subProcess) {
@@ -250,16 +258,16 @@ class GameManager {
}
for (let i = 0; i < game.people.length; i ++) {
if (game.people[i].userType === globals.USER_TYPES.KILLED_PLAYER) {
game.people[i].userType = globals.USER_TYPES.PLAYER;
if (game.people[i].userType === USER_TYPES.KILLED_PLAYER) {
game.people[i].userType = USER_TYPES.PLAYER;
game.people[i].out = false;
}
if (game.people[i].userType === globals.USER_TYPES.KILLED_BOT) {
game.people[i].userType = globals.USER_TYPES.BOT;
if (game.people[i].userType === USER_TYPES.KILLED_BOT) {
game.people[i].userType = USER_TYPES.BOT;
game.people[i].out = false;
}
if (game.people[i].gameRole && game.people[i].id === game.currentModeratorId && game.people[i].userType === globals.USER_TYPES.MODERATOR) {
game.people[i].userType = globals.USER_TYPES.TEMPORARY_MODERATOR;
if (game.people[i].gameRole && game.people[i].id === game.currentModeratorId && game.people[i].userType === USER_TYPES.MODERATOR) {
game.people[i].userType = USER_TYPES.TEMPORARY_MODERATOR;
game.people[i].out = false;
}
game.people[i].revealed = false;
@@ -270,19 +278,19 @@ class GameManager {
game.people[i].customRole = null;
}
game.status = globals.STATUS.LOBBY;
game.status = STATUS.LOBBY;
await this.refreshGame(game);
await this.eventManager.publisher?.publish(
globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM,
REDIS_CHANNELS.ACTIVE_GAME_STREAM,
this.eventManager.createMessageToPublish(
game.accessCode,
globals.EVENT_IDS.RESTART_GAME,
EVENT_IDS.RESTART_GAME,
this.instanceId,
'{}'
)
);
namespace.in(game.accessCode).emit(globals.EVENT_IDS.RESTART_GAME);
namespace.in(game.accessCode).emit(EVENT_IDS.RESTART_GAME);
};
/*
@@ -305,9 +313,9 @@ class GameManager {
deal = (game) => {
const cards = this.prepareDeck(game.deck);
let i = 0;
for (const person of game.people.filter(person => person.userType === globals.USER_TYPES.PLAYER
|| person.userType === globals.USER_TYPES.TEMPORARY_MODERATOR
|| person.userType === globals.USER_TYPES.BOT)
for (const person of game.people.filter(person => person.userType === USER_TYPES.PLAYER
|| person.userType === USER_TYPES.TEMPORARY_MODERATOR
|| person.userType === USER_TYPES.BOT)
) {
person.gameRole = cards[i].role;
person.customRole = cards[i].custom;
@@ -318,9 +326,9 @@ class GameManager {
}
isGameStartable = (game) => {
return game.people.filter(person => person.userType === globals.USER_TYPES.PLAYER
|| person.userType === globals.USER_TYPES.TEMPORARY_MODERATOR
|| person.userType === globals.USER_TYPES.BOT).length === game.gameSize;
return game.people.filter(person => person.userType === USER_TYPES.PLAYER
|| person.userType === USER_TYPES.TEMPORARY_MODERATOR
|| person.userType === USER_TYPES.BOT).length === game.gameSize;
}
findPersonByField = (game, fieldName, value) => {
@@ -334,8 +342,8 @@ function getRandomInt (max) {
function initializeModerator (name, hasDedicatedModerator) {
const userType = hasDedicatedModerator
? globals.USER_TYPES.MODERATOR
: globals.USER_TYPES.TEMPORARY_MODERATOR;
? USER_TYPES.MODERATOR
: USER_TYPES.TEMPORARY_MODERATOR;
return new Person(createRandomId(), createRandomId(), name, userType);
}
@@ -343,7 +351,7 @@ function initializePeopleForGame (uniqueRoles, moderator, shuffle, isTestGame, g
const people = [];
if (isTestGame) {
let j = 0;
const number = moderator.userType === globals.USER_TYPES.TEMPORARY_MODERATOR
const number = moderator.userType === USER_TYPES.TEMPORARY_MODERATOR
? gameSize - 1
: gameSize;
while (j < number) {
@@ -351,7 +359,7 @@ function initializePeopleForGame (uniqueRoles, moderator, shuffle, isTestGame, g
createRandomId(),
createRandomId(),
UsernameGenerator.generate(),
globals.USER_TYPES.BOT,
USER_TYPES.BOT,
null,
null,
null,
@@ -369,8 +377,8 @@ function initializePeopleForGame (uniqueRoles, moderator, shuffle, isTestGame, g
function createRandomId () {
let id = '';
for (let i = 0; i < globals.INSTANCE_ID_LENGTH; i ++) {
id += globals.INSTANCE_ID_CHAR_POOL[Math.floor(Math.random() * globals.INSTANCE_ID_CHAR_POOL.length)];
for (let i = 0; i < PRIMITIVES.INSTANCE_ID_LENGTH; i ++) {
id += PRIMITIVES.INSTANCE_ID_CHAR_POOL[Math.floor(Math.random() * PRIMITIVES.INSTANCE_ID_CHAR_POOL.length)];
}
return id;
}
@@ -385,21 +393,21 @@ async function addSpectator (game, name, logger, namespace, eventManager, instan
createRandomId(),
createRandomId(),
name,
globals.USER_TYPES.SPECTATOR
USER_TYPES.SPECTATOR
);
spectator.assigned = true;
logger.trace('new spectator: ' + spectator.name);
game.people.push(spectator);
await refreshGame(game);
namespace.in(game.accessCode).emit(
globals.EVENT_IDS.ADD_SPECTATOR,
EVENT_IDS.ADD_SPECTATOR,
GameStateCurator.mapPerson(spectator)
);
await eventManager.publisher.publish(
globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM,
REDIS_CHANNELS.ACTIVE_GAME_STREAM,
eventManager.createMessageToPublish(
game.accessCode,
globals.EVENT_IDS.ADD_SPECTATOR,
EVENT_IDS.ADD_SPECTATOR,
instanceId,
JSON.stringify(GameStateCurator.mapPerson(spectator))
)

View File

@@ -1,6 +1,6 @@
const { fork } = require('child_process');
const path = require('path');
const globals = require('../../config/globals');
const { REDIS_CHANNELS, GAME_PROCESS_COMMANDS } = require('../../config/globals');
class TimerManager {
constructor (logger, instanceId) {
@@ -25,7 +25,7 @@ class TimerManager {
await eventManager.handleEventById(msg.command, null, game, msg.socketId, game.accessCode, msg, null, false);
await gameManager.refreshGame(game);
await eventManager.publisher.publish(
globals.REDIS_CHANNELS.ACTIVE_GAME_STREAM,
REDIS_CHANNELS.ACTIVE_GAME_STREAM,
eventManager.createMessageToPublish(game.accessCode, msg.command, this.instanceId, JSON.stringify(msg))
);
});
@@ -34,7 +34,7 @@ class TimerManager {
this.logger.debug('Game timer thread ' + gameProcess.pid + ' exiting with code ' + code + ' - game ' + game.accessCode);
});
gameProcess.send({
command: globals.GAME_PROCESS_COMMANDS.START_TIMER,
command: GAME_PROCESS_COMMANDS.START_TIMER,
accessCode: game.accessCode,
logLevel: this.logger.logLevel,
hours: game.timerParams.hours,