mirror of
https://github.com/AlecM33/Werewolf.git
synced 2025-12-26 07:47:50 +01:00
various refactors
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user