- { isSelf &&
- { mic && }
- { !mic && }
-
}
-
- { mute &&
}
- { !mute &&
}
+ return
+
+ { isSelf &&
+ { mic && }
+ { !mic && }
+
}
+
+ { mute && }
+ { !mute && }
+
- );
+ ;
};
-export { MediaControl, MediaAgent };
+export { MediaControl, MediaAgent, MediaContext };
diff --git a/client/src/Table.css b/client/src/Table.css
index 80ad591..53274bc 100755
--- a/client/src/Table.css
+++ b/client/src/Table.css
@@ -294,6 +294,11 @@
background-color: rgba(255, 255, 0, 0.5);
}
+.Players .PlayerEntry > *:last-child {
+ display: flex;
+ flex-grow: 1;
+}
+
.Players .PlayerToggle {
min-width: 5em;
diff --git a/client/src/Table.js b/client/src/Table.js
index 8954f21..0cf3bd6 100755
--- a/client/src/Table.js
+++ b/client/src/Table.js
@@ -19,7 +19,7 @@ import 'moment-timezone';
import Activities from './Activities.js';
import Placard from './Placard.js';
import PlayersStatus from './PlayersStatus.js';
-import { MediaAgent, MediaControl } from './MediaControl.js';
+import { MediaAgent, MediaControl, MediaContext } from './MediaControl.js';
import { base, assetsPath, getPlayerName, gamesPath } from './Common.js';
/* Start of withRouter polyfill */
@@ -57,39 +57,37 @@ const Development = ({table, type, card, onClick}) => {
);
};
-const StartButton = ({ table }) => {
+const StartButton = ({ table, game }) => {
const startClick = (event) => {
- table.setGameState("game-order").then((state) => {
- table.game.state = state;
- });
+ table.setGameState("game-order");
};
return (
-
+
);
};
-const GameOrder = ({table}) => {
+const GameOrder = ({table, game}) => {
const rollClick = (event) => {
table.throwDice();
}
- if (!table.game) {
+ if (!game) {
return (<>>);
}
let players = [], hasRolled = true;
- for (let color in table.game.players) {
- const item = table.game.players[color],
- name = getPlayerName(table.game.sessions, color);
+ for (let color in game.players) {
+ const item = game.players[color],
+ name = getPlayerName(game.sessions, color);
if (!name) {
continue;
}
if (!item.orderRoll) {
item.orderRoll = 0;
}
- if (color === table.game.color) {
+ if (color === game.color) {
hasRolled = item.orderRoll !== 0;
}
players.push({ name: name, color: color, ...item });
@@ -116,7 +114,7 @@ const GameOrder = ({table}) => {
return (
- { table.game &&
+ { game &&
Game Order
{ players }
@@ -127,19 +125,19 @@ const GameOrder = ({table}) => {
);
};
-const SelectPlayer = ({table, players}) => {
+const SelectPlayer = ({table, game, players}) => {
const playerClick = (event) => {
table.stealResource(event.currentTarget.getAttribute('data-color'));
}
- if (!table.game) {
+ if (!game.id) {
return (<>>);
}
let list = players.map(color => {
let item = {
color: color,
- name: getPlayerName(table.game.sessions, color)
+ name: getPlayerName(game.sessions, color)
};
return
{
return (
- { table.game &&
+ { game &&
Select Player to Steal From
{ list }
@@ -162,7 +160,7 @@ const SelectPlayer = ({table, players}) => {
);
};
-const Action = ({ table }) => {
+const Action = ({ table, game }) => {
const buildClicked = (event) => {
table.buildClicked(event);
};
@@ -197,13 +195,12 @@ const Action = ({ table }) => {
table.setSelected("");
}
*/
- if (!table.game) {
- console.log("Why no game?");
+ if (!game.id) {
+ console.log("Why no game id?");
return (
);
}
- const game = table.game,
- inLobby = game.state === 'lobby',
+ const inLobby = game.state === 'lobby',
inGame = game.state === 'normal',
player = game ? game.player : undefined,
hasRolled = (game && game.turn && game.turn.roll) ? true : false,
@@ -216,7 +213,7 @@ const Action = ({ table }) => {
return (
{ inLobby && <>
-
+
> }
{ !inLobby && <>
@@ -235,15 +232,15 @@ const Action = ({ table }) => {
);
}
-const PlayerName = ({table}) => {
- const [name, setName] = useState((table && table.game && table.game.name) ? table.game.name : "");
+const PlayerName = ({table, game}) => {
+ const [name, setName] = useState(game.name ? game.name : "");
const nameChange = (event) => {
setName(event.target.value);
}
const sendName = () => {
- if (name !== table.game.name) {
+ if (name !== game.name) {
table.setPlayerName(name);
} else {
table.setError("");
@@ -273,35 +270,36 @@ const PlayerName = ({table}) => {
/* This needs to take in a mechanism to declare the
* player's active item in the game */
-const Players = ({ table }) => {
+const Players = ({ table, game }) => {
const toggleSelected = (key) => {
- table.setSelected(table.game.color === key ? "" : key);
+ table.setSelected(game.color === key ? "" : key);
}
const players = [];
- if (!table.game) {
+ if (!game.id) {
return (<>>);
}
- for (let color in table.game.players) {
- const item = table.game.players[color], inLobby = table.game.state === 'lobby';
+
+ for (let color in game.players) {
+ const item = game.players[color], inLobby = game.state === 'lobby';
if (!inLobby && item.status === 'Not active') {
continue;
}
- let name = getPlayerName(table.game.sessions, color),
- selectable = table.game.state === 'lobby' && (item.status === 'Not active' || table.game.color === color);
- if (!name) {
- name = "Available";
- }
+ let name = getPlayerName(game.sessions, color),
+ selectable = game.state === 'lobby' && (item.status === 'Not active' || game.color === color);
players.push((
{ inLobby && selectable && toggleSelected(color) }}
key={`player-${color}`}>
-
{name}
-
+ {name ? name : 'Available' }
+ { name &&
+
+ }
+ { !name && }
));
}
@@ -321,20 +319,15 @@ class Table extends React.Component {
constructor(props) {
super(props);
this.state = {
- total: 0,
- wood: 0,
- sheep: 0,
- brick: 0,
- stone: 0,
- wheat: 0,
- game: null,
message: "",
error: "",
signature: "",
buildActive: false,
cardActive: undefined,
loading: 0,
- noNetwork: false
+ noNetwork: false,
+ ws: undefined,
+ peers: {}
};
this.componentDidMount = this.componentDidMount.bind(this);
this.throwDice = this.throwDice.bind(this);
@@ -359,25 +352,19 @@ class Table extends React.Component {
this.selectResources = this.selectResources.bind(this);
this.buildItem = this.buildItem.bind(this);
- this.mouse = { x: 0, y: 0 };
- this.radius = 0.317;
-
this.loadTimer = null;
-
- this.game = null;
- this.pips = [];
- this.tiles = [];
- this.borders = [];
- this.tabletop = null;
- this.closest = {
- info: {},
- tile: null,
- road: null,
- tradeToken: null,
- settlement: null
- };
-
+ this.peers = {};
this.id = (props.router && props.router.params.id) ? props.router.params.id : 0;
+ this.setPeers = this.setPeers.bind(this);
+ }
+
+ setPeers(update) {
+ for (let key in this.peers) {
+ if (!(key in update)) {
+ delete this.peers[key];
+ }
+ }
+ this.setState({ peers: Object.assign({}, this.peers, update)});
}
closeCard() {
@@ -396,7 +383,7 @@ class Table extends React.Component {
this.setState({ loading: this.state.loading + 1 });
- return window.fetch(`${base}/api/v1/games/${this.state.game.id}/${action}/${value}`, {
+ return window.fetch(`${base}/api/v1/games/${this.state.id}/${action}/${value}`, {
method: "PUT",
cache: 'no-cache',
credentials: 'same-origin',
@@ -509,7 +496,7 @@ class Table extends React.Component {
}
this.setState({ loading: this.state.loading + 1 });
- return window.fetch(`${base}/api/v1/games/${this.state.game.id}/state/${state}`, {
+ return window.fetch(`${base}/api/v1/games/${this.state.id}/state/${state}`, {
method: "PUT",
cache: 'no-cache',
credentials: 'same-origin',
@@ -531,7 +518,7 @@ class Table extends React.Component {
this.setError(error.message);
}).then(() => {
this.setState({ loading: this.state.loading - 1 });
- return this.game.state;
+ return this.state.state;
});
}
@@ -584,38 +571,43 @@ class Table extends React.Component {
}
console.log("Update Game", game);
- this.setState( { game } );
- this.setState(this.state);
- this.game = game;
+ /* Only update fields that are changing */
+ for (let key in game) {
+ if (game[key] === this.state[key]) {
+ delete game[key];
+ }
+ }
+ console.log(`Updating: `, { ...game });
+ this.setState( { ...game } );
}
updateMessage() {
- const player = (this.game && this.game.color) ? this.game.players[this.game.color] : undefined,
- name = this.game ? this.game.name : "";
+ const player = (this.state.id && this.state.color) ? this.state.players[this.state.color] : undefined,
+ name = this.state ? this.state.name : "";
let message = <>>;
if (this.state.pickName || !name) {
message = <>{message}Enter the name you would like to be known by, then press ENTER or select SET.>;
} else {
- switch (this.game && this.game.state) {
+ switch (this.state.state) {
case 'lobby':
message = <>{message}You are in the lobby as {name}.>;
- if (!this.game.color) {
+ if (!this.state.color) {
message = <>{message}You select one of the Available colors below.>;
} else {
- message = <>{message}You have selected .>;
+ message = <>{message}You have selected .>;
}
message = <>{message}You can chat with other players below.>;
- if (this.game.active < 2) {
- message = <>{message}Once there are two or more players, you can select .>;
+ if (this.state.active < 2) {
+ message = <>{message}Once there are two or more players, you can select .>;
} else {
- message = <>{message}There are enough players to start the game. Select when ready.>;
+ message = <>{message}There are enough players to start the game. Select when ready.>;
}
break;
case 'game-order':
if (!player) {
message = <>{message}You are an observer in this game as {name}.>;
- message = <>{message}You can chat with other players below as {this.game.name}, but cannot play unless players go back to the Lobby.>;
+ message = <>{message}You can chat with other players below as {this.state.name}, but cannot play unless players go back to the Lobby.>;
} else {
if (!player.order) {
message = <>{message}You need to roll for game order. Click Roll Dice below.>;
@@ -638,33 +630,33 @@ class Table extends React.Component {
message = <>{message}The game is in a wonky state. Sorry :(>;
break;
case 'normal':
- if (this.game && this.game.turn) {
- if (this.game.turn.roll === 7) {
+ if (this.state.turn) {
+ if (this.state.turn.roll === 7) {
message = <>{message}Robber was rolled!>;
let move = true;
- for (let color in this.game.players) {
+ for (let color in this.state.players) {
let name = '';
- for (let i = 0; i < this.game.sessions.length; i++) {
- if (this.game.sessions[i].color === color) {
- name = this.game.sessions[i].name;
+ for (let i = 0; i < this.state.sessions.length; i++) {
+ if (this.state.sessions[i].color === color) {
+ name = this.state.sessions[i].name;
}
}
- const discard = this.game.players[color].mustDiscard;
+ const discard = this.state.players[color].mustDiscard;
if (discard) {
move = false;
message = <>{message} {name} needs to discard {discard} resources.>;
}
}
- if (move && (this.game.turn && !this.game.turn.placedRobber)) {
- message = <>{message} {this.game.turn.name} needs to move the robber.>
+ if (move && (this.state.turn && !this.state.turn.placedRobber)) {
+ message = <>{message} {this.state.turn.name} needs to move the robber.>
}
} else {
- message = <>It is {this.game.turn.name}'s turn.>;
+ message = <>It is {this.state.turn.name}'s turn.>;
}
}
break;
default:
- message = <>{message}Game state is: {this.game.state}>;
+ message = <>{message}Game state is: {this.state.state}>;
break;
}
}
@@ -679,7 +671,7 @@ class Table extends React.Component {
delete this.ws;
}
} else {
- console.log(`${this.game.name} Resetting keep-alive. Last ping: ${(Date.now() - this.lastPing) / 1000}`);
+// console.log(`${this.game.name} Resetting keep-alive. Last ping: ${(Date.now() - this.lastPing) / 1000}`);
}
if (this.keepAlive) {
@@ -690,7 +682,7 @@ class Table extends React.Component {
}
this.keepAlive = setTimeout(() => {
- console.log(`${this.game.name} No ping after 10 seconds. Last ping: ${(Date.now() - this.lastPing) / 1000}`);
+ console.log(`${this.state.name} No ping after 10 seconds. Last ping: ${(Date.now() - this.lastPing) / 1000}`);
this.setState({ noNetwork: true });
if (this.ws) {
this.ws.close();
@@ -707,7 +699,7 @@ class Table extends React.Component {
}
connectWebSocket() {
- if (!this.game) {
+ if (!this.state.id) {
console.log(`Cannot initiate websocket connection while no game is set.`);
this.resetKeepAlive(true);
return;
@@ -721,11 +713,12 @@ class Table extends React.Component {
} else {
new_uri = "ws";
}
- new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${this.game.id}/`;
+ new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${this.state.id}/`;
console.log(`Attempting WebSocket connection to ${new_uri}`);
this.ws = new WebSocket(new_uri);
- this.lastPing = this.game.timestamp;
+ this.setState({ ws: this.ws });
+ this.lastPing = this.state.timestamp;
this.ws.addEventListener('message', (event) => {
this.resetKeepAlive();
@@ -758,18 +751,18 @@ class Table extends React.Component {
this.ws.addEventListener('error', (event) => {
this.setState({ error: event.message });
- console.error(`${this.game.name} WebSocket error: ${(Date.now() - this.game.lastPing) / 1000}`);
+ console.error(`${this.state.name} WebSocket error: ${(Date.now() - this.state.lastPing) / 1000}`);
this.resetKeepAlive(true);
});
this.ws.addEventListener('close', (event) => {
- console.log(`${this.game.name} WebSocket close: ${(Date.now() - this.game.lastPing) / 1000}`);
+ console.log(`${this.state.name} WebSocket close: ${(Date.now() - this.state.lastPing) / 1000}`);
this.setState({ error: event.message });
this.resetKeepAlive(true);
});
this.ws.addEventListener('open', (event) => {
- console.log(`${this.game.name} WebSocket open: Sending game-update request: ${(Date.now() - this.lastPing) / 1000}`);
+ console.log(`${this.state.name} WebSocket open: Sending game-update request: ${(Date.now() - this.lastPing) / 1000}`);
this.ws.send(JSON.stringify({ type: 'game-update' }));
this.resetKeepAlive();
});
@@ -877,15 +870,11 @@ class Table extends React.Component {
}
cardClicked(card) {
- const game = this.state.game;
- if (!game) {
- return;
- }
this.setState({cardActive: card });
}
render() {
- const game = this.state.game,
+ const game = this.state,
player = game ? game.player : undefined,
isTurn = (game && game.turn && game.turn.color === game.color) ? true : false,
showMessage = (game && (game.state === 'lobby' || !game.name));
@@ -928,26 +917,30 @@ class Table extends React.Component {
development = <>/>;
}
- if (!this.game) {
+ if (!this.state.id) {
return <>>;
}
return (<>
-
+
+
+
{ this.state.loading > 0 &&
}
{ this.state.noNetwork &&
}
- { this.game &&
}
+
-
+
{ player !== undefined && <>
-
+
+ table={this}
+ game={this.state}
+ color={this.state.color}/>
@@ -984,11 +977,11 @@ class Table extends React.Component {
{ game &&
{ showMessage &&
{ this.state.message } }
- {(this.state.pickName || !game.name) &&
}
+ {(this.state.pickName || !game.name) && }
{(!this.state.pickName && game.name) && <>
-
-
-
+
+
+
> }
}
@@ -1020,7 +1013,7 @@ class Table extends React.Component {
game.turn &&
isTurn &&
game.turn.actions && game.turn.actions.indexOf('steal-resource') !== -1 &&
-
+
}
{ this.state.error && this.setState({ error: undefined })} className="Error">{this.state.error}
}
diff --git a/server/routes/games.js b/server/routes/games.js
index c928717..68f3012 100755
--- a/server/routes/games.js
+++ b/server/routes/games.js
@@ -92,7 +92,9 @@ const staticData = {
[ undefined, "stone", undefined ]
]
};
+
const games = {};
+const audio = {};
const processTies = (players) => {
players.sort((A, B) => {
@@ -470,7 +472,7 @@ const getSession = (game, session) => {
}
if (!session.player_id) {
- session.player_id = crypto.randomBytes(32).toString('hex');
+ session.player_id = crypto.randomBytes(16).toString('hex');
}
const id = session.player_id;
@@ -782,6 +784,8 @@ const setPlayerName = (game, session, name) => {
if (session.color) {
return `You cannot change your name while you have a color selected.`;
}
+ const id = game.id;
+
let rejoin = false;
/* Check to ensure name is not already in use */
if (game && name) for (let key in game.sessions) {
@@ -811,22 +815,33 @@ const setPlayerName = (game, session, name) => {
const old = session.name;
let message;
- session.name = name;
-
- if (name) {
- if (!old) {
- message = `A new player has entered the lobby as ${name}.`;
- } else {
- if (rejoin) {
- message = `${name} has rejoined the game! Welcome back, ${name}.`;
- } else {
- message = `${old} has changed their name to ${name}.`;
- }
- }
- } else {
+ if (!name) {
return `You can not set your name to nothing!`;
}
-
+
+ if (!old) {
+ message = `A new player has entered the lobby as ${name}.`;
+ session.name = name;
+ } else {
+ if (rejoin) {
+ message = `${name} has rejoined the game! Welcome back, ${name}.`;
+ session.name = name;
+ if (session.ws && id in audio) {
+ part(audio[id], session, game.id);
+ }
+ } else {
+ message = `${old} has changed their name to ${name}.`;
+ if (session.ws && id in audio) {
+ part(audio[id], session, game.id);
+ }
+ session.name = name;
+ }
+ }
+
+ if (session.ws) {
+ join(audio[id], session, game.id);
+ }
+
addChatMessage(game, null, message);
return undefined;
}
@@ -2719,28 +2734,59 @@ const resetDisconnectCheck = (game, req) => {
//req.disconnectCheck = setTimeout(() => { wsInactive(game, req) }, 20000);
}
-const channels = {},
- sockets = {};
+const join = (peers, session, id) => {
+ const ws = session.ws;
-const part = (ws, channel) => {
- console.log(`[${ws.id}] part `);
-
- if (!(channel in ws.channels)) {
- console.log(`[${ws.id}] ERROR: not in `, channel);
+ if (!session.name) {
+ console.error(`${id}:${session.id} - join - No name set yet. Audio not available.`);
return;
}
- delete ws.channels[channel];
- delete channels[channel][id];
+ console.log(`${id} - join - ${session.name}`);
+
+ if (session.name in peers) {
+ console.log(`${id}:${session.name} - Already joined to Audio.`);
+ return;
+ }
- for (id in channels[channel]) {
- channels[channel][id].send(JSON.stringify({
+ for (let peer in peers) {
+ peers[peer].send(JSON.stringify({
+ type: 'addPeer',
+ data: { 'peer_id': peer, 'should_create_offer': false }
+ }));
+
+ ws.send(JSON.stringify({
+ type: 'addPeer',
+ data: {'peer_id': peer, 'should_create_offer': true}
+ }));
+ }
+
+ /* Add this user as a peer connected to this WebSocket */
+ peers[session.name] = ws;
+};
+
+const part = (peers, session, id) => {
+ const ws = session.ws;
+
+ console.log(`${id}:${session.name} - Audio part.`);
+
+ if (!(session.name in peers)) {
+ console.log(`${id}:${session.name} - Does not exist in game audio.`);
+ return;
+ }
+
+ delete peers[session.name];
+
+ /* Remove this peer from all other peers, and remove each
+ * peer from this peer */
+ for (let peer in peers) {
+ peers[peer].send(JSON.stringify({
type: 'removePeer',
- data: {'peer_id': id}
+ data: {'peer_id': peer}
}));
ws.send(JSON.stringify({
type: 'removePeer',
- data: {'peer_id': id}
+ data: {'peer_id': peer}
}));
}
};
@@ -2749,12 +2795,13 @@ router.ws("/ws/:id", async (ws, req) => {
const { id } = req.params;
ws.id = req.session.player_id;
- ws.channels = {},
- sockets[ws.id] = ws;
-
-
- console.log(`Connection for ${ws.id}`);
+ if (!(id in audio)) {
+ audio[id] = {}; /* List of peer sockets using session.name as index. */
+ console.log(`${id} - New Game Audio`);
+ } else {
+ console.log(`${id} - Already has Audio`);
+ }
/* Setup WebSocket event handlers prior to performing any async calls or
* we may miss the first messages from clients */
@@ -2782,93 +2829,88 @@ router.ws("/ws/:id", async (ws, req) => {
const game = await loadGame(id);
if (game) {
const session = getSession(game, req.session);
- console.log(`WebSocket closed for ${session.name}`);
if (session && session.ws) {
+ /* Cleanup any voice channels */
+ if (id in audio) {
+ part(audio[id], session, id);
+ }
session.ws.close();
session.ws = undefined;
+ console.log(`WebSocket closed for ${session.name}`);
}
}
- /* Cleanup any voice channels */
- for (let channel in ws.channels) {
- part(channel);
- }
- console.log(`[${ws.id}] disconnected`);
- delete sockets[ws.id];
+
+ console.log(`${id}:${ws.id} - closed connection`);
});
ws.on('message', async (message) => {
const data = JSON.parse(message);
+ const game = await loadGame(id);
+ if (!game) {
+ console.error(`Unable to load/create new game for WS request.`);
+ return;
+ }
+ const session = getSession(game, req.session);
+ if (!session) {
+ console.error(`Unable to obtain session.`);
+ return;
+ }
+
+ if (!session.ws) {
+ session.ws = ws;
+ }
switch (data.type) {
- case 'join': {
- const { channel, userdata } = data.config;
- console.log(`[${ws.id}] join `, channel);
-
- if (channel in ws.channels) {
- console.log(`[${ws.id}] ERROR: already joined `, channel);
- return;
- }
-
- if (!(channel in channels)) {
- channels[channel] = {};
- }
-
- for (let id in channels[channel]) {
- channels[channel][id].send(JSON.stringify({
- type: 'addPeer',
- data: { 'peer_id': id, 'should_create_offer': false }
- }));
- ws.send(JSON.stringify({
- type: 'addPeer',
- data: {'peer_id': id, 'should_create_offer': true}
- }));
- }
-
- channels[channel][ws.id] = ws;
- ws.channels[channel] = channel;
- } break;
- case 'part':
- part(ws, data.part);
+ case 'join':
+ join(audio[id], session, id);
break;
+
+ case 'part':
+ part(audio[id], session, id);
+ break;
+
case 'relayICECandidate': {
+ if (!(id in audio)) {
+ console.error(`${id} - relayICECandidate - Does not have Audio`);
+ return;
+ }
+
const { peer_id, ice_candidate } = data.config;
- console.log(`[${ws.id}] relaying ICE candidate to [${peer_id}] `, ice_candidate);
+ console.log(`${id} - relayICECandidate ${session.name} to ${peer_id}`,
+ ice_candidate);
- if (peer_id in sockets) {
- sockets[peer_id].send(JSON.stringify({
+ if (peer_id in audio[id]) {
+ audio[id][peer_id].send(JSON.stringify({
type: 'iceCandidate',
- data: {'peer_id': ws.id, 'ice_candidate': ice_candidate }
+ data: {'peer_id': session.name, 'ice_candidate': ice_candidate }
}));
}
} break;
+
case 'relaySessionDescription': {
+ if (!(id in audio)) {
+ console.error(`${id} - relaySessionDescription - Does not have Audio`);
+ return;
+ }
const { peer_id, session_description } = data.config;
- console.log(`[${ws.id}] relaying session description to [${peer_id}] `, session_description);
- if (peer_id in sockets) {
- sockets[peer_id].send(JSON.stringify({
+ console.log(`${id} - relaySessionDescription ${session.name} to ${peer_id}`,
+ session_description);
+ if (peer_id in audio[id]) {
+ audio[id][peer_id].send(JSON.stringify({
type: 'sessionDescription',
- data: {'peer_id': ws.id, 'session_description': session_description }
+ data: {'peer_id': session.name, 'session_description': session_description }
}));
}
} break;
- case 'pong': {
- const game = await loadGame(id);
- if (!game) {
- console.error(`Unable to load/create new game for WS request.`);
- return;
- }
+
+ case 'pong':
resetDisconnectCheck(game, req);
- } break;
- case 'game-update': {
- const game = await loadGame(id);
- if (!game) {
- console.error(`Unable to load/create new game for WS request.`);
- return;
- }
+ break;
+ case 'game-update':
console.log(`Player ${session.name ? session.name : 'Unnamed'} requested a game update.`);
resetDisconnectCheck(game, req);
sendGame(req, undefined, game, undefined, ws);
- } break;
+ break;
}
});
@@ -3284,7 +3326,7 @@ const createGame = (id) => {
addChatMessage(game, null, `New game created with Beginner's Layout: ${game.id}`);
games[game.id] = game;
-
+ audio[game.id] = {};
return game;
};