mirror of
https://github.com/AlecM33/Werewolf.git
synced 2025-12-26 15:57:50 +01:00
refactor of networking when first reaching game page
This commit is contained in:
@@ -9,7 +9,6 @@ export const globals = {
|
|||||||
ACCESS_CODE_CHAR_POOL: 'abcdefghijklmnopqrstuvwxyz0123456789',
|
ACCESS_CODE_CHAR_POOL: 'abcdefghijklmnopqrstuvwxyz0123456789',
|
||||||
COMMANDS: {
|
COMMANDS: {
|
||||||
FETCH_GAME_STATE: 'fetchGameState',
|
FETCH_GAME_STATE: 'fetchGameState',
|
||||||
GET_ENVIRONMENT: 'getEnvironment',
|
|
||||||
START_GAME: 'startGame',
|
START_GAME: 'startGame',
|
||||||
PAUSE_TIMER: 'pauseTimer',
|
PAUSE_TIMER: 'pauseTimer',
|
||||||
RESUME_TIMER: 'resumeTimer',
|
RESUME_TIMER: 'resumeTimer',
|
||||||
@@ -18,8 +17,7 @@ export const globals = {
|
|||||||
REVEAL_PLAYER: 'revealPlayer',
|
REVEAL_PLAYER: 'revealPlayer',
|
||||||
TRANSFER_MODERATOR: 'transferModerator',
|
TRANSFER_MODERATOR: 'transferModerator',
|
||||||
CHANGE_NAME: 'changeName',
|
CHANGE_NAME: 'changeName',
|
||||||
END_GAME: 'endGame',
|
END_GAME: 'endGame'
|
||||||
FETCH_IN_PROGRESS_STATE: 'fetchInitialInProgressState'
|
|
||||||
},
|
},
|
||||||
STATUS: {
|
STATUS: {
|
||||||
LOBBY: 'lobby',
|
LOBBY: 'lobby',
|
||||||
|
|||||||
@@ -105,6 +105,10 @@ export class GameCreationStepManager {
|
|||||||
window.location = ('/game/' + res.content);
|
window.location = ('/game/' + res.content);
|
||||||
}
|
}
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
|
let button = document.getElementById("create-game");
|
||||||
|
button.innerText = "Create Game";
|
||||||
|
button.classList.remove('submitted');
|
||||||
|
button.addEventListener('click', this.steps["4"].forwardHandler);
|
||||||
if (e.status === 429) {
|
if (e.status === 429) {
|
||||||
toast('You\'ve sent this request too many times.', 'error', true, true, 6);
|
toast('You\'ve sent this request too many times.', 'error', true, true, 6);
|
||||||
}
|
}
|
||||||
@@ -395,6 +399,9 @@ function showButtons (back, forward, forwardHandler, backHandler, builtGame = nu
|
|||||||
createButton.setAttribute('id', 'create-game');
|
createButton.setAttribute('id', 'create-game');
|
||||||
createButton.classList.add('app-button');
|
createButton.classList.add('app-button');
|
||||||
createButton.addEventListener('click', () => {
|
createButton.addEventListener('click', () => {
|
||||||
|
createButton.removeEventListener('click', forwardHandler);
|
||||||
|
createButton.classList.add('submitted');
|
||||||
|
createButton.innerText = 'Creating...'
|
||||||
forwardHandler(
|
forwardHandler(
|
||||||
builtGame.deck.filter((card) => card.quantity > 0),
|
builtGame.deck.filter((card) => card.quantity > 0),
|
||||||
builtGame.hasTimer,
|
builtGame.hasTimer,
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ function renderPotentialMods (gameState, group, transferModHandlers, socket) {
|
|||||||
if ((member.out || member.userType === globals.USER_TYPES.SPECTATOR) && !(member.id === gameState.client.id)) {
|
if ((member.out || member.userType === globals.USER_TYPES.SPECTATOR) && !(member.id === gameState.client.id)) {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
container.classList.add('potential-moderator');
|
container.classList.add('potential-moderator');
|
||||||
container.setAttribute("tabindex", "0");
|
container.setAttribute('tabindex', '0');
|
||||||
container.dataset.pointer = member.id;
|
container.dataset.pointer = member.id;
|
||||||
container.innerText = member.name;
|
container.innerText = member.name;
|
||||||
transferModHandlers[member.id] = (e) => {
|
transferModHandlers[member.id] = (e) => {
|
||||||
|
|||||||
@@ -8,82 +8,105 @@ import { ModalManager } from '../modules/ModalManager.js';
|
|||||||
import { stateBucket } from '../modules/StateBucket.js';
|
import { stateBucket } from '../modules/StateBucket.js';
|
||||||
import { io } from 'socket.io-client';
|
import { io } from 'socket.io-client';
|
||||||
import { injectNavbar } from '../modules/Navbar.js';
|
import { injectNavbar } from '../modules/Navbar.js';
|
||||||
|
import { XHRUtility } from '../modules/XHRUtility.js';
|
||||||
|
|
||||||
const game = () => {
|
const game = () => {
|
||||||
injectNavbar();
|
injectNavbar();
|
||||||
const timerWorker = new Worker(new URL('../modules/Timer.js', import.meta.url));
|
XHRUtility.xhr(
|
||||||
const socket = io('/in-game');
|
'/api/games/environment',
|
||||||
socket.on('disconnect', () => {
|
'GET',
|
||||||
toast('Disconnected. Attempting reconnect...', 'error', true, false);
|
null,
|
||||||
});
|
null
|
||||||
socket.on('connect', () => {
|
)
|
||||||
console.log('connect event fired');
|
.then((res) => {
|
||||||
socket.emit(globals.COMMANDS.GET_ENVIRONMENT, function (returnedEnvironment) {
|
joinGame(res);
|
||||||
prepareGamePage(returnedEnvironment, socket, timerWorker);
|
}).catch((res) => {
|
||||||
|
toast(res.content, 'error', true);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function prepareGamePage (environment, socket, timerWorker) {
|
function joinGame (environmentResponse) {
|
||||||
let userId = UserUtility.validateAnonUserSignature(environment);
|
let cookie = UserUtility.validateAnonUserSignature(environmentResponse.content);
|
||||||
const splitUrl = window.location.href.split('/game/');
|
const splitUrl = window.location.href.split('/game/');
|
||||||
const accessCode = splitUrl[1];
|
const accessCode = splitUrl[1];
|
||||||
if (/^[a-zA-Z0-9]+$/.test(accessCode) && accessCode.length === globals.ACCESS_CODE_LENGTH) {
|
if (/^[a-zA-Z0-9]+$/.test(accessCode) && accessCode.length === globals.ACCESS_CODE_LENGTH) {
|
||||||
socket.emit(globals.COMMANDS.FETCH_GAME_STATE, accessCode, userId, function (gameState) {
|
XHRUtility.xhr(
|
||||||
stateBucket.currentGameState = gameState;
|
'/api/games/' + accessCode + '/players',
|
||||||
document.querySelector('.spinner-container')?.remove();
|
'PATCH',
|
||||||
document.querySelector('.spinner-background')?.remove();
|
null,
|
||||||
|
JSON.stringify({ cookie: cookie })
|
||||||
if (gameState === null) {
|
)
|
||||||
window.location = '/not-found?reason=' + encodeURIComponent('game-not-found');
|
.then((res) => {
|
||||||
} else {
|
cookie = res.content;
|
||||||
document.getElementById('game-content').innerHTML = templates.INITIAL_GAME_DOM;
|
UserUtility.setAnonymousUserId(res.content, environmentResponse.content);
|
||||||
toast('You are connected.', 'success', true, true, 2);
|
const timerWorker = new Worker(new URL('../modules/Timer.js', import.meta.url));
|
||||||
userId = gameState.client.cookie;
|
const socket = io('/in-game');
|
||||||
UserUtility.setAnonymousUserId(userId, environment);
|
const gameTimerManager = new GameTimerManager(stateBucket, socket);
|
||||||
const gameStateRenderer = new GameStateRenderer(stateBucket, socket);
|
const gameStateRenderer = new GameStateRenderer(stateBucket, socket);
|
||||||
let gameTimerManager;
|
socket.on('disconnect', () => {
|
||||||
if (stateBucket.currentGameState.timerParams) {
|
toast('Disconnected. Attempting reconnect...', 'error', true, false);
|
||||||
gameTimerManager = new GameTimerManager(stateBucket, socket);
|
});
|
||||||
|
socket.on('connect', () => {
|
||||||
|
prepareGamePage(
|
||||||
|
environmentResponse.content,
|
||||||
|
socket,
|
||||||
|
timerWorker,
|
||||||
|
cookie,
|
||||||
|
accessCode,
|
||||||
|
gameStateRenderer,
|
||||||
|
gameTimerManager
|
||||||
|
);
|
||||||
|
});
|
||||||
|
setClientSocketHandlers(stateBucket, gameStateRenderer, socket, timerWorker, gameTimerManager);
|
||||||
|
}).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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
initializeGame(stateBucket, socket, timerWorker, userId, gameStateRenderer, gameTimerManager);
|
});
|
||||||
|
|
||||||
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, userId, 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 initializeGame (stateBucket, socket, timerWorker, userId, gameStateRenderer, gameTimerManager) {
|
function prepareGamePage (environment, socket, timerWorker, cookie, accessCode, gameStateRenderer, gameTimerManager) {
|
||||||
setClientSocketHandlers(stateBucket, gameStateRenderer, socket, timerWorker, gameTimerManager);
|
socket.emit(globals.COMMANDS.FETCH_GAME_STATE, accessCode, cookie, function (gameState) {
|
||||||
processGameState(stateBucket.currentGameState, userId, socket, gameStateRenderer, gameTimerManager, timerWorker);
|
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) {
|
function processGameState (currentGameState, userId, socket, gameStateRenderer, gameTimerManager, timerWorker, refreshPrompt = true) {
|
||||||
@@ -163,79 +186,72 @@ function displayClientInfo (name, userType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setClientSocketHandlers (stateBucket, gameStateRenderer, socket, timerWorker, gameTimerManager) {
|
function setClientSocketHandlers (stateBucket, gameStateRenderer, socket, timerWorker, gameTimerManager) {
|
||||||
if (!socket.hasListeners(globals.EVENTS.PLAYER_JOINED)) {
|
socket.on(globals.EVENTS.PLAYER_JOINED, (player, gameIsFull) => {
|
||||||
socket.on(globals.EVENTS.PLAYER_JOINED, (player, gameIsFull) => {
|
toast(player.name + ' joined!', 'success', false, true, 3);
|
||||||
toast(player.name + ' joined!', 'success', false, true, 3);
|
stateBucket.currentGameState.people.push(player);
|
||||||
stateBucket.currentGameState.people.push(player);
|
stateBucket.currentGameState.isFull = gameIsFull;
|
||||||
stateBucket.currentGameState.isFull = gameIsFull;
|
gameStateRenderer.renderLobbyPlayers();
|
||||||
|
if (
|
||||||
|
gameIsFull
|
||||||
|
&& (
|
||||||
|
stateBucket.currentGameState.client.userType === globals.USER_TYPES.MODERATOR
|
||||||
|
|| stateBucket.currentGameState.client.userType === globals.USER_TYPES.TEMPORARY_MODERATOR
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
displayStartGamePromptForModerators(stateBucket.currentGameState, gameStateRenderer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on(globals.EVENTS.PLAYER_LEFT, (player) => {
|
||||||
|
removeStartGameFunctionalityIfPresent(gameStateRenderer);
|
||||||
|
toast(player.name + ' has left!', 'error', false, true, 3);
|
||||||
|
const index = stateBucket.currentGameState.people.findIndex(person => person.id === player.id);
|
||||||
|
if (index >= 0) {
|
||||||
|
stateBucket.currentGameState.people.splice(
|
||||||
|
index,
|
||||||
|
1
|
||||||
|
);
|
||||||
gameStateRenderer.renderLobbyPlayers();
|
gameStateRenderer.renderLobbyPlayers();
|
||||||
if (
|
}
|
||||||
gameIsFull
|
});
|
||||||
&& (
|
|
||||||
stateBucket.currentGameState.client.userType === globals.USER_TYPES.MODERATOR
|
|
||||||
|| stateBucket.currentGameState.client.userType === globals.USER_TYPES.TEMPORARY_MODERATOR
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
displayStartGamePromptForModerators(stateBucket.currentGameState, gameStateRenderer);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!socket.hasListeners(globals.EVENTS.PLAYER_LEFT)) {
|
socket.on(globals.EVENTS.START_GAME, () => {
|
||||||
socket.on(globals.EVENTS.PLAYER_LEFT, (player) => {
|
socket.emit(
|
||||||
removeStartGameFunctionalityIfPresent(gameStateRenderer);
|
globals.COMMANDS.FETCH_GAME_STATE,
|
||||||
toast(player.name + ' has left!', 'error', false, true, 3);
|
stateBucket.currentGameState.accessCode,
|
||||||
const index = stateBucket.currentGameState.people.findIndex(person => person.id === player.id);
|
stateBucket.currentGameState.client.cookie,
|
||||||
if (index >= 0) {
|
function (gameState) {
|
||||||
stateBucket.currentGameState.people.splice(
|
stateBucket.currentGameState = gameState;
|
||||||
index,
|
processGameState(
|
||||||
1
|
stateBucket.currentGameState,
|
||||||
|
gameState.client.cookie,
|
||||||
|
socket,
|
||||||
|
gameStateRenderer,
|
||||||
|
gameTimerManager,
|
||||||
|
timerWorker
|
||||||
);
|
);
|
||||||
gameStateRenderer.renderLobbyPlayers();
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
if (!socket.hasListeners(globals.EVENTS.START_GAME)) {
|
socket.on(globals.EVENTS.SYNC_GAME_STATE, () => {
|
||||||
socket.on(globals.EVENTS.START_GAME, () => {
|
socket.emit(
|
||||||
socket.emit(
|
globals.COMMANDS.FETCH_GAME_STATE,
|
||||||
globals.COMMANDS.FETCH_IN_PROGRESS_STATE,
|
stateBucket.currentGameState.accessCode,
|
||||||
stateBucket.currentGameState.accessCode,
|
stateBucket.currentGameState.client.cookie,
|
||||||
stateBucket.currentGameState.client.cookie,
|
function (gameState) {
|
||||||
function (gameState) {
|
stateBucket.currentGameState = gameState;
|
||||||
stateBucket.currentGameState = gameState;
|
processGameState(
|
||||||
processGameState(
|
stateBucket.currentGameState,
|
||||||
stateBucket.currentGameState,
|
gameState.client.cookie,
|
||||||
gameState.client.cookie,
|
socket,
|
||||||
socket,
|
gameStateRenderer,
|
||||||
gameStateRenderer,
|
gameTimerManager,
|
||||||
gameTimerManager,
|
timerWorker
|
||||||
timerWorker
|
);
|
||||||
);
|
}
|
||||||
}
|
);
|
||||||
);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!socket.hasListeners(globals.EVENTS.SYNC_GAME_STATE)) {
|
|
||||||
socket.on(globals.EVENTS.SYNC_GAME_STATE, () => {
|
|
||||||
socket.emit(
|
|
||||||
globals.COMMANDS.FETCH_IN_PROGRESS_STATE,
|
|
||||||
stateBucket.currentGameState.accessCode,
|
|
||||||
stateBucket.currentGameState.client.cookie,
|
|
||||||
function (gameState) {
|
|
||||||
stateBucket.currentGameState = gameState;
|
|
||||||
processGameState(
|
|
||||||
stateBucket.currentGameState,
|
|
||||||
gameState.client.cookie,
|
|
||||||
socket,
|
|
||||||
gameStateRenderer,
|
|
||||||
gameTimerManager,
|
|
||||||
timerWorker
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timerWorker && gameTimerManager) {
|
if (timerWorker && gameTimerManager) {
|
||||||
gameTimerManager.attachTimerSocketListeners(socket, timerWorker, gameStateRenderer);
|
gameTimerManager.attachTimerSocketListeners(socket, timerWorker, gameStateRenderer);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ function roomCodeIsValid (code) {
|
|||||||
|
|
||||||
function attemptToJoinGame (code) {
|
function attemptToJoinGame (code) {
|
||||||
XHRUtility.xhr(
|
XHRUtility.xhr(
|
||||||
'/api/games/availability/' + code.toLowerCase().trim(),
|
'/api/games/' + code.toLowerCase().trim() + 'availability',
|
||||||
'GET',
|
'GET',
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ th, thead, tr, tt, u, ul, var {
|
|||||||
border: 0;
|
border: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
@font-face {
|
|
||||||
font-family: 'signika-negative';
|
|
||||||
src: url("../webfonts/Diavlo_LIGHT_II_37.woff2") format("woff2");
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'signika-negative';
|
font-family: 'signika-negative';
|
||||||
@@ -164,6 +160,11 @@ button {
|
|||||||
border: 2px solid #8a1c1c !important;
|
border: 2px solid #8a1c1c !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.submitted {
|
||||||
|
filter: opacity(0.5);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|||||||
@@ -1,68 +1,68 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>Create A Game</title>
|
<title>Not Found</title>
|
||||||
<meta name="description" content="This resource was not found.">
|
<meta name="description" content="This resource was not found.">
|
||||||
<meta property="og:title" content="Not Found">
|
<meta property="og:title" content="Not Found">
|
||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
<meta property="og:url" content="https://playwerewolf.uk.r.appspot.com/not-found">
|
<meta property="og:url" content="https://playwerewolf.uk.r.appspot.com/not-found">
|
||||||
<meta property="og:description" content="The page you are looking for could not be found.">
|
<meta property="og:description" content="The page you are looking for could not be found.">
|
||||||
<meta property="og:image" content="image.png">
|
<meta property="og:image" content="image.png">
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.ico">
|
||||||
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
||||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||||
<link rel="stylesheet" href="/styles/GLOBAL.css">
|
<link rel="stylesheet" href="/styles/GLOBAL.css">
|
||||||
<link rel="stylesheet" href="/styles/create.css">
|
<link rel="stylesheet" href="/styles/create.css">
|
||||||
<link rel="stylesheet" href="/styles/modal.css">
|
<link rel="stylesheet" href="/styles/modal.css">
|
||||||
<link rel="stylesheet" href="/styles/hamburgers.css">
|
<link rel="stylesheet" href="/styles/hamburgers.css">
|
||||||
</head>
|
<style>
|
||||||
<body>
|
|
||||||
<div id="mobile-menu-background-overlay"></div>
|
|
||||||
<div id="navbar"></div>
|
|
||||||
<span>
|
|
||||||
<h1>404</h1>
|
|
||||||
<h3>The game or other resource that you are looking for could not be found, or you don't have permission to access it.
|
|
||||||
If this error is unexpected, the application may have restarted.</h3>
|
|
||||||
</span>
|
|
||||||
<style>
|
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
max-width: 40em;
|
max-width: 40em;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
#not-found-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media(min-width: 701px) {
|
@media(min-width: 701px) {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 75px;
|
font-size: 75px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media(max-width: 700px) {
|
@media(max-width: 700px) {
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 40px;
|
font-size: 40px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script src="/dist/notFound-bundle.js"></script>
|
</head>
|
||||||
</body>
|
<body>
|
||||||
|
<div id="mobile-menu-background-overlay"></div>
|
||||||
|
<div id="navbar"></div>
|
||||||
|
<div id="not-found-container">
|
||||||
|
<h1>404</h1>
|
||||||
|
<h3>The game or other resource that you are looking for could not be found, or you don't have permission to access it.
|
||||||
|
If this error is unexpected, the application may have restarted.</h3>
|
||||||
|
</div>
|
||||||
|
<script src="/dist/notFound-bundle.js"></script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -16,8 +16,7 @@
|
|||||||
<link rel="stylesheet" href="/styles/game.css">
|
<link rel="stylesheet" href="/styles/game.css">
|
||||||
<link rel="stylesheet" href="/styles/modal.css">
|
<link rel="stylesheet" href="/styles/modal.css">
|
||||||
<link rel="stylesheet" href="/styles/hamburgers.css">
|
<link rel="stylesheet" href="/styles/hamburgers.css">
|
||||||
<link rel="preload" as="font" href="/webfonts/SignikaNegative-Light.woff2" crossorigin/>
|
<link rel="preload" href="/webfonts/SignikaNegative-Light.woff2" as="font" type="font/woff2" crossorigin>
|
||||||
<link rel="preload" as="font" href="/webfonts/Diavlo_LIGHT_II_37.woff2" crossorigin/>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="prompt"></div>
|
<div id="prompt"></div>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"bundle": "webpack --config client/webpack/webpack-prod.config.js",
|
"bundle": "webpack --config client/webpack/webpack-prod.config.js",
|
||||||
"prestart": "npm run bundle",
|
"prestart": "npm run bundle",
|
||||||
|
"gcp-build": "webpack --config client/webpack/webpack-prod.config.js",
|
||||||
"build:dev": "webpack --watch --config client/webpack/webpack-dev.config.js --mode=development",
|
"build:dev": "webpack --watch --config client/webpack/webpack-dev.config.js --mode=development",
|
||||||
"start:dev": "NODE_ENV=development nodemon server/main.js",
|
"start:dev": "NODE_ENV=development nodemon server/main.js",
|
||||||
"start:dev:no-hot-reload": "NODE_ENV=development && node server/main.js",
|
"start:dev:no-hot-reload": "NODE_ENV=development && node server/main.js",
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ router.post('/create', function (req, res) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/availability/:code', function (req, res) {
|
router.get('/:code/availability', function (req, res) {
|
||||||
const joinGamePromise = gameManager.joinGame(req.params.code);
|
const availabilityPromise = gameManager.checkAvailability(req.params.code);
|
||||||
joinGamePromise.then((result) => {
|
availabilityPromise.then((result) => {
|
||||||
if (result === 404) {
|
if (result === 404) {
|
||||||
res.status(404).send();
|
res.status(404).send();
|
||||||
} else if (result instanceof Error) {
|
} else if (result instanceof Error) {
|
||||||
@@ -51,4 +51,26 @@ router.get('/availability/:code', function (req, res) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.patch('/:code/players', function (req, res) {
|
||||||
|
console.log(typeof req.body.cookie);
|
||||||
|
console.log(req.body.cookie);
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ const globals = {
|
|||||||
STALE_GAME_HOURS: 12,
|
STALE_GAME_HOURS: 12,
|
||||||
CLIENT_COMMANDS: {
|
CLIENT_COMMANDS: {
|
||||||
FETCH_GAME_STATE: 'fetchGameState',
|
FETCH_GAME_STATE: 'fetchGameState',
|
||||||
GET_ENVIRONMENT: 'getEnvironment',
|
|
||||||
START_GAME: 'startGame',
|
START_GAME: 'startGame',
|
||||||
PAUSE_TIMER: 'pauseTimer',
|
PAUSE_TIMER: 'pauseTimer',
|
||||||
RESUME_TIMER: 'resumeTimer',
|
RESUME_TIMER: 'resumeTimer',
|
||||||
@@ -14,8 +13,7 @@ const globals = {
|
|||||||
REVEAL_PLAYER: 'revealPlayer',
|
REVEAL_PLAYER: 'revealPlayer',
|
||||||
TRANSFER_MODERATOR: 'transferModerator',
|
TRANSFER_MODERATOR: 'transferModerator',
|
||||||
CHANGE_NAME: 'changeName',
|
CHANGE_NAME: 'changeName',
|
||||||
END_GAME: 'endGame',
|
END_GAME: 'endGame'
|
||||||
FETCH_IN_PROGRESS_STATE: 'fetchInitialInProgressState'
|
|
||||||
},
|
},
|
||||||
MESSAGES: {
|
MESSAGES: {
|
||||||
ENTER_NAME: 'Client must enter name.'
|
ENTER_NAME: 'Client must enter name.'
|
||||||
|
|||||||
@@ -24,14 +24,6 @@ app.set('port', args.port);
|
|||||||
|
|
||||||
const inGameSocketServer = ServerBootstrapper.createSocketServer(main, app, args.port);
|
const inGameSocketServer = ServerBootstrapper.createSocketServer(main, app, args.port);
|
||||||
|
|
||||||
inGameSocketServer.on('connection', function (socket) {
|
|
||||||
socket.on('disconnecting', (reason) => {
|
|
||||||
logger.trace('client socket disconnecting because: ' + reason);
|
|
||||||
gameManager.removeClientFromLobbyIfApplicable(socket);
|
|
||||||
});
|
|
||||||
gameManager.addGameSocketHandlers(inGameSocketServer, socket);
|
|
||||||
});
|
|
||||||
|
|
||||||
let gameManager;
|
let gameManager;
|
||||||
|
|
||||||
/* Instantiate the singleton game manager */
|
/* Instantiate the singleton game manager */
|
||||||
@@ -41,6 +33,16 @@ if (process.env.NODE_ENV.trim() === 'development') {
|
|||||||
gameManager = new GameManager(logger, globals.ENVIRONMENT.PRODUCTION).getInstance();
|
gameManager = new GameManager(logger, globals.ENVIRONMENT.PRODUCTION).getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gameManager.namespace = inGameSocketServer;
|
||||||
|
|
||||||
|
inGameSocketServer.on('connection', function (socket) {
|
||||||
|
socket.on('disconnecting', (reason) => {
|
||||||
|
logger.trace('client socket disconnecting because: ' + reason);
|
||||||
|
gameManager.removeClientFromLobbyIfApplicable(socket);
|
||||||
|
});
|
||||||
|
gameManager.addGameSocketHandlers(inGameSocketServer, socket);
|
||||||
|
});
|
||||||
|
|
||||||
/* api endpoints */
|
/* api endpoints */
|
||||||
const games = require('./api/GamesAPI');
|
const games = require('./api/GamesAPI');
|
||||||
app.use('/api/games', games);
|
app.use('/api/games', games);
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ class GameManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addGameSocketHandlers = (namespace, socket) => {
|
addGameSocketHandlers = (namespace, socket) => {
|
||||||
this.namespace = namespace;
|
|
||||||
socket.on(globals.CLIENT_COMMANDS.FETCH_GAME_STATE, (accessCode, personId, ackFn) => {
|
socket.on(globals.CLIENT_COMMANDS.FETCH_GAME_STATE, (accessCode, personId, ackFn) => {
|
||||||
this.logger.trace('request for game state for accessCode: ' + accessCode + ' from socket: ' + socket.id + ' with cookie: ' + personId);
|
this.logger.trace('request for game state for accessCode: ' + accessCode + ' from socket: ' + socket.id + ' with cookie: ' + personId);
|
||||||
this.handleRequestForGameState(
|
this.handleRequestForGameState(
|
||||||
@@ -28,27 +27,6 @@ class GameManager {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
/* this event handler will call handleRequestForGameState() with the 'handleNoMatch' arg as false - only
|
|
||||||
connections that match a participant in the game at that time will have the game state sent to them.
|
|
||||||
*/
|
|
||||||
socket.on(globals.CLIENT_COMMANDS.FETCH_IN_PROGRESS_STATE, (accessCode, personId, ackFn) => {
|
|
||||||
this.logger.trace('request for game state for accessCode ' + accessCode + ', person ' + personId);
|
|
||||||
this.handleRequestForGameState(
|
|
||||||
this.namespace,
|
|
||||||
this.logger,
|
|
||||||
this.activeGameRunner,
|
|
||||||
accessCode,
|
|
||||||
personId,
|
|
||||||
ackFn,
|
|
||||||
socket,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on(globals.CLIENT_COMMANDS.GET_ENVIRONMENT, (ackFn) => {
|
|
||||||
ackFn(this.environment);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on(globals.CLIENT_COMMANDS.START_GAME, (accessCode) => {
|
socket.on(globals.CLIENT_COMMANDS.START_GAME, (accessCode) => {
|
||||||
const game = this.activeGameRunner.activeGames[accessCode];
|
const game = this.activeGameRunner.activeGames[accessCode];
|
||||||
if (game && game.isFull) {
|
if (game && game.isFull) {
|
||||||
@@ -152,7 +130,7 @@ class GameManager {
|
|||||||
socket.on(globals.CLIENT_COMMANDS.CHANGE_NAME, (accessCode, data, ackFn) => {
|
socket.on(globals.CLIENT_COMMANDS.CHANGE_NAME, (accessCode, data, ackFn) => {
|
||||||
const game = this.activeGameRunner.activeGames[accessCode];
|
const game = this.activeGameRunner.activeGames[accessCode];
|
||||||
if (game) {
|
if (game) {
|
||||||
const person = findPersonById(game, data.personId);
|
const person = findPersonByField(game, 'id', data.personId);
|
||||||
if (person) {
|
if (person) {
|
||||||
if (!isNameTaken(game, data.name)) {
|
if (!isNameTaken(game, data.name)) {
|
||||||
ackFn('changed');
|
ackFn('changed');
|
||||||
@@ -207,7 +185,7 @@ class GameManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
joinGame = (code) => {
|
checkAvailability = (code) => {
|
||||||
const game = this.activeGameRunner.activeGames[code];
|
const game = this.activeGameRunner.activeGames[code];
|
||||||
if (game) {
|
if (game) {
|
||||||
const unassignedPerson = game.people.find((person) => person.assigned === false);
|
const unassignedPerson = game.people.find((person) => person.assigned === false);
|
||||||
@@ -275,16 +253,47 @@ class GameManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRequestForGameState = (namespace, logger, gameRunner, accessCode, personCookie, ackFn, socket, handleNoMatch = true) => {
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleRequestForGameState = (namespace, logger, gameRunner, accessCode, personCookie, ackFn, socket) => {
|
||||||
const game = gameRunner.activeGames[accessCode];
|
const game = gameRunner.activeGames[accessCode];
|
||||||
if (game) {
|
if (game) {
|
||||||
let matchingPerson = game.people.find((person) => person.cookie === personCookie);
|
const matchingPerson = findPersonByField(game, 'cookie', personCookie);
|
||||||
if (!matchingPerson) {
|
|
||||||
matchingPerson = game.spectators.find((spectator) => spectator.cookie === personCookie);
|
|
||||||
}
|
|
||||||
if (!matchingPerson && game.moderator.cookie === personCookie) {
|
|
||||||
matchingPerson = game.moderator;
|
|
||||||
}
|
|
||||||
if (matchingPerson) {
|
if (matchingPerson) {
|
||||||
if (matchingPerson.socketId === socket.id) {
|
if (matchingPerson.socketId === socket.id) {
|
||||||
logger.trace('matching person found with an established connection to the room: ' + matchingPerson.name);
|
logger.trace('matching person found with an established connection to the room: ' + matchingPerson.name);
|
||||||
@@ -295,8 +304,8 @@ class GameManager {
|
|||||||
matchingPerson.socketId = socket.id;
|
matchingPerson.socketId = socket.id;
|
||||||
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, matchingPerson, gameRunner, socket, logger));
|
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, matchingPerson, gameRunner, socket, logger));
|
||||||
}
|
}
|
||||||
} else if (handleNoMatch) {
|
} else {
|
||||||
this.handleRequestFromNonMatchingPerson(game, socket, gameRunner, ackFn, logger);
|
rejectClientRequestForGameState(ackFn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rejectClientRequestForGameState(ackFn);
|
rejectClientRequestForGameState(ackFn);
|
||||||
@@ -304,43 +313,6 @@ class GameManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRequestFromNonMatchingPerson = (game, socket, gameRunner, ackFn, logger) => {
|
|
||||||
const personWithMatchingSocketId = findPersonWithMatchingSocketId(game, socket.id);
|
|
||||||
if (personWithMatchingSocketId) {
|
|
||||||
logger.trace('matching person found whose cookie got cleared after establishing a connection to the room: ' + personWithMatchingSocketId.name);
|
|
||||||
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, personWithMatchingSocketId, gameRunner, socket, logger));
|
|
||||||
} else {
|
|
||||||
const unassignedPerson = game.moderator.assigned === false
|
|
||||||
? game.moderator
|
|
||||||
: game.people.find((person) => person.assigned === false);
|
|
||||||
if (unassignedPerson) {
|
|
||||||
logger.trace('completely new person with a first connection to the room: ' + unassignedPerson.name);
|
|
||||||
unassignedPerson.assigned = true;
|
|
||||||
unassignedPerson.socketId = socket.id;
|
|
||||||
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, unassignedPerson, gameRunner, socket, logger));
|
|
||||||
const isFull = isGameFull(game);
|
|
||||||
game.isFull = isFull;
|
|
||||||
socket.to(game.accessCode).emit(
|
|
||||||
globals.EVENTS.PLAYER_JOINED,
|
|
||||||
GameStateCurator.mapPerson(unassignedPerson),
|
|
||||||
isFull
|
|
||||||
);
|
|
||||||
} else { // if the game is full, make them a spectator.
|
|
||||||
const spectator = new Person(
|
|
||||||
createRandomId(),
|
|
||||||
createRandomId(),
|
|
||||||
UsernameGenerator.generate(),
|
|
||||||
globals.USER_TYPES.SPECTATOR
|
|
||||||
);
|
|
||||||
spectator.socketId = socket.id;
|
|
||||||
logger.trace('new spectator: ' + spectator.name);
|
|
||||||
game.spectators.push(spectator);
|
|
||||||
ackFn(GameStateCurator.getGameStateFromPerspectiveOfPerson(game, spectator, gameRunner, socket, logger));
|
|
||||||
}
|
|
||||||
socket.join(game.accessCode);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
removeClientFromLobbyIfApplicable (socket) {
|
removeClientFromLobbyIfApplicable (socket) {
|
||||||
socket.rooms.forEach((room) => {
|
socket.rooms.forEach((room) => {
|
||||||
if (this.activeGameRunner.activeGames[room]) {
|
if (this.activeGameRunner.activeGames[room]) {
|
||||||
@@ -442,17 +414,6 @@ function rejectClientRequestForGameState (acknowledgementFunction) {
|
|||||||
return acknowledgementFunction(null);
|
return acknowledgementFunction(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPersonWithMatchingSocketId (game, socketId) {
|
|
||||||
let person = game.people.find((person) => person.socketId === socketId);
|
|
||||||
if (!person) {
|
|
||||||
person = game.spectators.find((spectator) => spectator.socketId === socketId);
|
|
||||||
}
|
|
||||||
if (!person && game.moderator.socketId === socketId) {
|
|
||||||
person = game.moderator;
|
|
||||||
}
|
|
||||||
return person;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findPlayerBySocketId (people, socketId) {
|
function findPlayerBySocketId (people, socketId) {
|
||||||
return people.find((person) => person.socketId === socketId && person.userType === globals.USER_TYPES.PLAYER);
|
return people.find((person) => person.socketId === socketId && person.userType === globals.USER_TYPES.PLAYER);
|
||||||
}
|
}
|
||||||
@@ -461,16 +422,16 @@ function isGameFull (game) {
|
|||||||
return game.moderator.assigned === true && !game.people.find((person) => person.assigned === false);
|
return game.moderator.assigned === true && !game.people.find((person) => person.assigned === false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPersonById (game, id) {
|
function findPersonByField (game, fieldName, value) {
|
||||||
let person;
|
let person;
|
||||||
if (id === game.moderator.id) {
|
if (value === game.moderator[fieldName]) {
|
||||||
person = game.moderator;
|
person = game.moderator;
|
||||||
}
|
}
|
||||||
if (!person) {
|
if (!person) {
|
||||||
person = game.people.find((person) => person.id === id);
|
person = game.people.find((person) => person[fieldName] === value);
|
||||||
}
|
}
|
||||||
if (!person) {
|
if (!person) {
|
||||||
person = game.spectators.find((spectator) => spectator.id === id);
|
person = game.spectators.find((spectator) => spectator[fieldName] === value);
|
||||||
}
|
}
|
||||||
return person;
|
return person;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,15 +65,11 @@ const ServerBootstrapper = {
|
|||||||
let io;
|
let io;
|
||||||
if (process.env.NODE_ENV.trim() === 'development') {
|
if (process.env.NODE_ENV.trim() === 'development') {
|
||||||
io = require('socket.io')(main, {
|
io = require('socket.io')(main, {
|
||||||
cors: { origin: 'http://localhost:' + port },
|
cors: { origin: 'http://localhost:' + port }
|
||||||
pingTimeout: 5000,
|
|
||||||
pingInterval: 5000
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
io = require('socket.io')(main, {
|
io = require('socket.io')(main, {
|
||||||
cors: { origin: 'https://playwerewolf.uk.r.appspot.com' },
|
cors: { origin: 'https://playwerewolf.uk.r.appspot.com' }
|
||||||
pingTimeout: 5000,
|
|
||||||
pingInterval: 5000
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user