revert conversion of join to XHR call

This commit is contained in:
AlecM33
2022-01-21 01:33:49 -05:00
parent 422bffd95b
commit 4e4aee3fe8
3 changed files with 113 additions and 144 deletions

View File

@@ -12,26 +12,6 @@ import { XHRUtility } from '../modules/XHRUtility.js';
const game = () => {
injectNavbar();
const socket = io('/in-game');
const timerWorker = new Worker(new URL('../modules/Timer.js', import.meta.url));
const gameTimerManager = new GameTimerManager(stateBucket, socket);
const gameStateRenderer = new GameStateRenderer(stateBucket, socket);
socket.on('disconnect', () => {
toast('Disconnected. Attempting reconnect...', 'error', true, false);
});
socket.on('connect', () => {
if (!stateBucket.joinRequestInFlight) {
prepareGamePage(
stateBucket,
stateBucket.accessCode,
gameTimerManager,
gameStateRenderer,
timerWorker,
socket,
UserUtility.validateAnonUserSignature(stateBucket.environment)
);
}
});
XHRUtility.xhr(
'/api/games/environment',
'GET',
@@ -40,81 +20,74 @@ const game = () => {
)
.then((res) => {
stateBucket.environment = res.content;
joinGame(res, gameTimerManager, gameStateRenderer, socket, timerWorker);
const socket = io('/in-game');
const timerWorker = new Worker(new URL('../modules/Timer.js', import.meta.url));
const gameTimerManager = new GameTimerManager(stateBucket, socket);
const gameStateRenderer = new GameStateRenderer(stateBucket, socket);
socket.on('connect', () => {
syncWithGame(
stateBucket,
gameTimerManager,
gameStateRenderer,
timerWorker,
socket,
UserUtility.validateAnonUserSignature(res.content)
);
});
socket.on('disconnect', () => {
toast('Disconnected. Attempting reconnect...', 'error', true, false);
});
setClientSocketHandlers(stateBucket, gameStateRenderer, socket, timerWorker, gameTimerManager);
}).catch((res) => {
toast(res.content, 'error', true);
});
};
function joinGame (environmentResponse, gameTimerManager, gameStateRenderer, socket, timerWorker) {
let cookie = UserUtility.validateAnonUserSignature(environmentResponse.content);
function syncWithGame (stateBucket, gameTimerManager, gameStateRenderer, timerWorker, socket, cookie) {
const splitUrl = window.location.href.split('/game/');
const accessCode = splitUrl[1];
if (/^[a-zA-Z0-9]+$/.test(accessCode) && accessCode.length === globals.ACCESS_CODE_LENGTH) {
XHRUtility.xhr(
'/api/games/' + accessCode + '/players',
'PATCH',
null,
JSON.stringify({ cookie: cookie })
)
.then((res) => {
UserUtility.setAnonymousUserId(res.content, environmentResponse.content);
stateBucket.accessCode = accessCode;
stateBucket.joinRequestInFlight = false;
cookie = res.content;
setClientSocketHandlers(stateBucket, gameStateRenderer, socket, timerWorker, gameTimerManager);
prepareGamePage(stateBucket, accessCode, gameTimerManager, gameStateRenderer, timerWorker, socket, cookie);
}).catch((res) => {
if (res.status === 404) {
window.location = '/not-found?reason=' + encodeURIComponent('game-not-found');
} else if (res.status >= 500) {
toast(
'The server is experiencing problems. Please try again later',
'error',
true
);
}
});
socket.emit(globals.COMMANDS.FETCH_GAME_STATE, accessCode, cookie, function (gameState) {
cookie = gameState.client.cookie;
UserUtility.setAnonymousUserId(cookie, stateBucket.environment);
stateBucket.currentGameState = gameState;
document.querySelector('.spinner-container')?.remove();
document.querySelector('.spinner-background')?.remove();
document.getElementById('game-content').innerHTML = templates.INITIAL_GAME_DOM;
toast('You are connected.', 'success', true, true, 2);
processGameState(stateBucket.currentGameState, cookie, socket, gameStateRenderer, gameTimerManager, timerWorker);
if (!gameState.client.hasEnteredName) {
document.getElementById('prompt').innerHTML = templates.NAME_CHANGE_MODAL;
document.getElementById('change-name-form').onsubmit = (e) => {
e.preventDefault();
const name = document.getElementById('player-new-name').value;
if (validateName(name)) {
socket.emit(globals.COMMANDS.CHANGE_NAME, gameState.accessCode, {
name: name,
personId: gameState.client.id
}, (result) => {
switch (result) {
case 'taken':
toast('This name is already taken.', 'error', true, true, 8);
break;
case 'changed':
ModalManager.dispelModal('change-name-modal', 'change-name-modal-background');
toast('Name set.', 'success', true, true, 5);
propagateNameChange(stateBucket.currentGameState, name, stateBucket.currentGameState.client.id);
processGameState(stateBucket.currentGameState, cookie, socket, gameStateRenderer, gameTimerManager, timerWorker);
}
});
} else {
toast('Name must be between 1 and 30 characters.', 'error', true, true, 8);
}
};
}
});
} else {
window.location = '/not-found?reason=' + encodeURIComponent('invalid-access-code');
}
}
function prepareGamePage (stateBucket, accessCode, gameTimerManager, gameStateRenderer, timerWorker, socket, cookie) {
socket.emit(globals.COMMANDS.FETCH_GAME_STATE, accessCode, cookie, function (gameState) {
stateBucket.currentGameState = gameState;
document.querySelector('.spinner-container')?.remove();
document.querySelector('.spinner-background')?.remove();
document.getElementById('game-content').innerHTML = templates.INITIAL_GAME_DOM;
toast('You are connected.', 'success', true, true, 2);
processGameState(stateBucket.currentGameState, cookie, socket, gameStateRenderer, gameTimerManager, timerWorker);
if (!gameState.client.hasEnteredName) {
document.getElementById('prompt').innerHTML = templates.NAME_CHANGE_MODAL;
document.getElementById('change-name-form').onsubmit = (e) => {
e.preventDefault();
const name = document.getElementById('player-new-name').value;
if (validateName(name)) {
socket.emit(globals.COMMANDS.CHANGE_NAME, gameState.accessCode, {
name: name,
personId: gameState.client.id
}, (result) => {
switch (result) {
case 'taken':
toast('This name is already taken.', 'error', true, true, 8);
break;
case 'changed':
ModalManager.dispelModal('change-name-modal', 'change-name-modal-background');
toast('Name set.', 'success', true, true, 5);
propagateNameChange(stateBucket.currentGameState, name, stateBucket.currentGameState.client.id);
processGameState(stateBucket.currentGameState, cookie, socket, gameStateRenderer, gameTimerManager, timerWorker);
}
});
} else {
toast('Name must be between 1 and 30 characters.', 'error', true, true, 8);
}
};
}
});
}
function processGameState (currentGameState, userId, socket, gameStateRenderer, gameTimerManager, timerWorker, refreshPrompt = true) {
displayClientInfo(currentGameState.client.name, currentGameState.client.userType);
if (refreshPrompt) {

View File

@@ -19,7 +19,7 @@ const apiLimiter = rateLimit({
const corsOptions = process.env.NODE_ENV.trim() === 'development'
? {
origin: '*',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
optionsSuccessStatus: 200
}
: {
origin: 'https://playwerewolf.uk.r.appspot.com',
@@ -27,7 +27,7 @@ const corsOptions = process.env.NODE_ENV.trim() === 'development'
};
router.use(cors(corsOptions));
router.options('/:code/players', cors(corsOptions)); // enable pre-flight request for DELETE
//router.options('/:code/players', cors(corsOptions));
if (process.env.NODE_ENV.trim() === 'production') { // in prod, limit clients to creating 5 games per 10 minutes.
router.use('/create', apiLimiter);
@@ -65,21 +65,21 @@ router.get('/:code/availability', function (req, res) {
});
});
router.patch('/:code/players', function (req, res) {
if (
req.body === null
|| req.body.cookie === null
|| (typeof req.body.cookie !== 'string' && req.body.cookie !== false)
|| (req.body.cookie.length !== globals.USER_SIGNATURE_LENGTH && req.body.cookie !== false)
) {
res.status(400).send();
}
gameManager.joinGame(req.body.cookie, req.params.code).then((data) => {
res.status(200).send(data);
}).catch((code) => {
res.status(code).send();
});
});
// router.patch('/:code/players', function (req, res) {
// if (
// req.body === null
// || req.body.cookie === null
// || (typeof req.body.cookie !== 'string' && req.body.cookie !== false)
// || (req.body.cookie.length !== globals.USER_SIGNATURE_LENGTH && req.body.cookie !== false)
// ) {
// res.status(400).send();
// }
// gameManager.joinGame(req.body.cookie, req.params.code).then((data) => {
// res.status(200).send(data);
// }).catch((code) => {
// res.status(code).send();
// });
// });
router.get('/environment', function (req, res) {
res.status(200).send(gameManager.environment);

View File

@@ -14,9 +14,9 @@ class GameManager {
}
addGameSocketHandlers = (namespace, socket) => {
socket.on(globals.CLIENT_COMMANDS.FETCH_GAME_STATE, (accessCode, personId, ackFn) => {
socket.on(globals.CLIENT_COMMANDS.FETCH_GAME_STATE, async (accessCode, personId, ackFn) => {
this.logger.trace('request for game state for accessCode: ' + accessCode + ' from socket: ' + socket.id + ' with cookie: ' + personId);
this.handleRequestForGameState(
await this.handleRequestForGameState(
this.namespace,
this.logger,
this.activeGameRunner,
@@ -253,59 +253,55 @@ class GameManager {
}
};
joinGame = (cookie, accessCode) => {
const game = this.activeGameRunner.activeGames[accessCode];
if (game) {
const person = findPersonByField(game, 'cookie', cookie);
if (person) {
return Promise.resolve(person.cookie);
} else {
const unassignedPerson = game.moderator.assigned === false
? game.moderator
: game.people.find((person) => person.assigned === false);
if (unassignedPerson) {
this.logger.trace('request from client to join game. Assigning: ' + unassignedPerson.name);
unassignedPerson.assigned = true;
game.isFull = isGameFull(game);
this.namespace.in(game.accessCode).emit(
globals.EVENTS.PLAYER_JOINED,
GameStateCurator.mapPerson(unassignedPerson),
game.isFull
);
return Promise.resolve(unassignedPerson.cookie);
} else { // if the game is full, make them a spectator.
const spectator = new Person(
createRandomId(),
createRandomId(),
UsernameGenerator.generate(),
globals.USER_TYPES.SPECTATOR
);
this.logger.trace('new spectator: ' + spectator.name);
game.spectators.push(spectator);
return Promise.resolve(spectator.cookie);
}
}
} else {
return Promise.reject(404);
joinGame = (game) => {
const unassignedPerson = game.moderator.assigned === false
? game.moderator
: game.people.find((person) => person.assigned === false);
if (unassignedPerson) {
this.logger.trace('request from client to join game. Assigning: ' + unassignedPerson.name);
unassignedPerson.assigned = true;
game.isFull = isGameFull(game);
this.namespace.in(game.accessCode).emit(
globals.EVENTS.PLAYER_JOINED,
GameStateCurator.mapPerson(unassignedPerson),
game.isFull
);
return unassignedPerson;
} else { // if the game is full, make them a spectator.
const spectator = new Person(
createRandomId(),
createRandomId(),
UsernameGenerator.generate(),
globals.USER_TYPES.SPECTATOR
);
this.logger.trace('new spectator: ' + spectator.name);
game.spectators.push(spectator);
return spectator;
}
};
handleRequestForGameState = (namespace, logger, gameRunner, accessCode, personCookie, ackFn, socket) => {
handleRequestForGameState = async (namespace, logger, gameRunner, accessCode, personCookie, ackFn, clientSocket) => {
const game = gameRunner.activeGames[accessCode];
if (game) {
const matchingPerson = findPersonByField(game, 'cookie', personCookie);
if (matchingPerson) {
if (matchingPerson.socketId === socket.id) {
if (matchingPerson.socketId === clientSocket.id) {
logger.trace('matching person found with an established connection to the room: ' + matchingPerson.name);
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, matchingPerson, gameRunner, socket, logger));
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, matchingPerson, gameRunner, clientSocket, logger));
} else {
logger.trace('matching person found with a new connection to the room: ' + matchingPerson.name);
socket.join(accessCode);
matchingPerson.socketId = socket.id;
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, matchingPerson, gameRunner, socket, logger));
clientSocket.join(accessCode);
matchingPerson.socketId = clientSocket.id;
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, matchingPerson, gameRunner, clientSocket, logger));
}
} else {
rejectClientRequestForGameState(ackFn);
const namespaceSockets = await namespace.in(accessCode).fetchSockets();
if (!namespaceSockets.find((namespaceSocket) => namespaceSocket.id === clientSocket.id)) {
let newlyAssignedPerson = this.joinGame(game);
clientSocket.join(accessCode);
newlyAssignedPerson.socketId = clientSocket.id;
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, newlyAssignedPerson, gameRunner, clientSocket, logger));
}
}
} else {
rejectClientRequestForGameState(ackFn);