some name change stuff

This commit is contained in:
Alec
2021-12-20 00:28:40 -05:00
parent 133d3a6a03
commit 82ca096600
16 changed files with 534 additions and 125 deletions

View File

@@ -22,27 +22,27 @@ class ActiveGameRunner {
//game.status = globals.STATUS.ENDED;
game.timerParams.paused = false;
game.timerParams.timeRemaining = 0;
this.logger.debug('PARENT: END GAME');
this.logger.trace('PARENT: END GAME');
namespace.in(game.accessCode).emit(globals.GAME_PROCESS_COMMANDS.END_GAME, game.accessCode);
break;
case globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER:
game.timerParams.paused = true;
this.logger.trace(msg);
game.timerParams.timeRemaining = msg.timeRemaining;
this.logger.debug('PARENT: PAUSE TIMER');
this.logger.trace('PARENT: PAUSE TIMER');
namespace.in(game.accessCode).emit(globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER, game.timerParams.timeRemaining);
break;
case globals.GAME_PROCESS_COMMANDS.RESUME_TIMER:
game.timerParams.paused = false;
this.logger.trace(msg);
game.timerParams.timeRemaining = msg.timeRemaining;
this.logger.debug('PARENT: RESUME TIMER');
this.logger.trace('PARENT: RESUME TIMER');
namespace.in(game.accessCode).emit(globals.GAME_PROCESS_COMMANDS.RESUME_TIMER, game.timerParams.timeRemaining);
break;
case globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING:
this.logger.trace(msg);
game.timerParams.timeRemaining = msg.timeRemaining;
this.logger.debug('PARENT: GET TIME REMAINING');
this.logger.trace('PARENT: GET TIME REMAINING');
namespace.to(msg.socketId).emit(globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING, game.timerParams.timeRemaining, game.timerParams.paused);
break;
}

View File

@@ -104,6 +104,10 @@ class GameManager {
this.logger.debug('game ' + accessCode + ': killing player ' + person.name);
person.userType = globals.USER_TYPES.KILLED_PLAYER;
person.out = true;
// temporary moderators will transfer their powers automatically to the first person they kill.
if (game.moderator.userType === globals.USER_TYPES.TEMPORARY_MODERATOR) {
transferModeratorPowers(game, person, namespace, this.logger);
}
namespace.in(accessCode).emit(globals.CLIENT_COMMANDS.KILL_PLAYER, person.id)
}
}
@@ -134,25 +138,26 @@ class GameManager {
if (!person) {
person = game.spectators.find((spectator) => spectator.id === personId)
}
if (person && (person.out || person.userType === globals.USER_TYPES.SPECTATOR)) {
this.logger.debug('game ' + accessCode + ': transferring mod powers to ' + person.name);
if (game.people.includes(game.moderator)) { // the current moderator was at one point a dealt-in player.
game.moderator.userType = globals.USER_TYPES.KILLED_PLAYER; // restore their state from before being made mod.
transferModeratorPowers(game, person, namespace, this.logger);
}
});
socket.on(globals.CLIENT_COMMANDS.CHANGE_NAME, (accessCode, data, ackFn) => {
let game = this.activeGameRunner.activeGames[accessCode];
if (game) {
let person = findPersonById(game, data.personId);
if (person) {
if (!isNameTaken(game, data.name)) {
ackFn("changed");
person.name = data.name.trim();
person.hasEnteredName = true;
socket.to(accessCode).emit(globals.EVENTS.SYNC_GAME_STATE);
} else {
game.moderator.userType = globals.USER_TYPES.SPECTATOR;
if (!game.spectators.includes(game.moderator)) {
game.spectators.push(game.moderator);
}
if (game.spectators.includes(person)) {
game.spectators.splice(game.spectators.indexOf(person), 1);
}
ackFn("taken");
}
person.userType = globals.USER_TYPES.MODERATOR;
game.moderator = person;
namespace.in(accessCode).emit(globals.EVENTS.SYNC_GAME_STATE);
}
}
})
});
}
@@ -216,7 +221,9 @@ function initializeModerator(name, hasDedicatedModerator) {
const userType = hasDedicatedModerator
? globals.USER_TYPES.MODERATOR
: globals.USER_TYPES.TEMPORARY_MODERATOR;
return new Person(createRandomId(), createRandomId(), name, userType)
let moderator = new Person(createRandomId(), createRandomId(), name, userType);
moderator.hasEnteredName = true // they did this when creating the game.
return moderator;
}
function initializePeopleForGame(uniqueCards, moderator) {
@@ -242,7 +249,17 @@ function initializePeopleForGame(uniqueCards, moderator) {
}
while (j < numberOfRoles) {
people.push(new Person(createRandomId(), createRandomId(), UsernameGenerator.generate(), globals.USER_TYPES.PLAYER, cards[j].role, cards[j].description, cards[j].team))
let person = new Person(
createRandomId(),
createRandomId(),
UsernameGenerator.generate(),
globals.USER_TYPES.PLAYER,
cards[j].role,
cards[j].description,
cards[j].team
);
person.hasEnteredName = false;
people.push(person);
j ++;
}
@@ -280,13 +297,33 @@ class Singleton {
}
}
function transferModeratorPowers(game, person, namespace, logger) {
if (person && (person.out || person.userType === globals.USER_TYPES.SPECTATOR)) {
logger.debug('game ' + game.accessCode + ': transferring mod powers to ' + person.name);
if (game.people.includes(game.moderator)) { // the current moderator was at one point a dealt-in player.
game.moderator.userType = globals.USER_TYPES.KILLED_PLAYER; // restore their state from before being made mod.
} else {
game.moderator.userType = globals.USER_TYPES.SPECTATOR;
if (!game.spectators.includes(game.moderator)) {
game.spectators.push(game.moderator);
}
if (game.spectators.includes(person)) {
game.spectators.splice(game.spectators.indexOf(person), 1);
}
}
person.userType = globals.USER_TYPES.MODERATOR;
game.moderator = person;
namespace.in(game.accessCode).emit(globals.EVENTS.SYNC_GAME_STATE);
}
}
/* Since clients are anonymous, we have to rely to some extent on a cookie to identify them. Socket ids
are unique to a client, but they are re-generated if a client disconnects and then reconnects.
Thus, to have the most resilient identification i.e. to let them refresh, navigate away and come back,
get disconnected and reconnect, etc. we should have a combination of the socket id and the cookie. This
will also allow us to reject certain theoretical ways of breaking things, such as copying someone else's
cookie. Though if a client wants to clear their cookie and reset their connection, there's not much we can do.
The best thing in my opinion is to make it hard for clients to _accidentally_ break their experience.
The best thing in my opinion is to make it exceptionally difficult for clients to _accidentally_ break their experience.
*/
function handleRequestForGameState(namespace, logger, gameRunner, accessCode, personCookie, ackFn, socket) {
const game = gameRunner.activeGames[accessCode];
@@ -374,4 +411,19 @@ function isGameFull(game) {
return game.moderator.assigned === true && !game.people.find((person) => person.assigned === false);
}
function findPersonById(game, id) {
let person = game.people.find((person) => person.id === id)
if (!person) {
person = game.spectators.find((spectator) => spectator.id === id)
}
return person;
}
function isNameTaken(game, name) {
let processedName = name.toLowerCase().trim();
return (game.people.find((person) => person.name.toLowerCase().trim() === processedName))
|| (game.moderator.name.toLowerCase().trim() === processedName)
|| (game.spectators.find((spectator) => spectator.name.toLowerCase().trim() === processedName))
}
module.exports = Singleton;

View File

@@ -7,7 +7,7 @@ process.on('message', (msg) => {
const logger = require('./Logger')(msg.logLevel);
switch (msg.command) {
case globals.GAME_PROCESS_COMMANDS.START_TIMER:
logger.debug('CHILD PROCESS ' + msg.accessCode + ': START TIMER');
logger.trace('CHILD PROCESS ' + msg.accessCode + ': START TIMER');
timer = new ServerTimer(
msg.hours,
msg.minutes,
@@ -23,7 +23,7 @@ process.on('message', (msg) => {
break;
case globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER:
timer.stopTimer();
logger.debug('CHILD PROCESS ' + msg.accessCode + ': PAUSE TIMER');
logger.trace('CHILD PROCESS ' + msg.accessCode + ': PAUSE TIMER');
process.send({ command: globals.GAME_PROCESS_COMMANDS.PAUSE_TIMER, timeRemaining: timer.currentTimeInMillis});
break;
@@ -34,13 +34,13 @@ process.on('message', (msg) => {
process.send({ command: globals.GAME_PROCESS_COMMANDS.END_GAME });
process.exit(0);
});
logger.debug('CHILD PROCESS ' + msg.accessCode + ': RESUME TIMER');
logger.trace('CHILD PROCESS ' + msg.accessCode + ': RESUME TIMER');
process.send({ command: globals.GAME_PROCESS_COMMANDS.RESUME_TIMER, timeRemaining: timer.currentTimeInMillis});
break;
case globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING:
logger.debug('CHILD PROCESS ' + msg.accessCode + ': GET TIME REMAINING');
logger.trace('CHILD PROCESS ' + msg.accessCode + ': GET TIME REMAINING');
process.send({
command: globals.GAME_PROCESS_COMMANDS.GET_TIME_REMAINING,
timeRemaining: timer.currentTimeInMillis,

View File

@@ -1,7 +1,8 @@
const globals = 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 information that they shouldn't.
/* 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
information that they shouldn't.
*/
const GameStateCurator = {
getGameStateFromPerspectiveOfPerson: (game, person, gameRunner, socket, logger) => {
@@ -11,9 +12,10 @@ const GameStateCurator = {
function getGameStateBasedOnPermissions(game, person, gameRunner) {
let client = game.status === globals.STATUS.LOBBY // people won't be able to know their role until past the lobby stage.
? { name: person.name, cookie: person.cookie, userType: person.userType }
? { name: person.name, hasEnteredName: person.hasEnteredName, id: person.id, cookie: person.cookie, userType: person.userType }
: {
name: person.name,
hasEnteredName: person.hasEnteredName,
id: person.id,
cookie: person.cookie,
userType: person.userType,