WebSocket seems to be working
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
0bc96d5121
commit
0e91755c72
@ -150,6 +150,11 @@
|
||||
clip-path: polygon(25% 0%,75% 0%,100% 50%,75% 100%,25% 100%,0% 50%);
|
||||
}
|
||||
|
||||
div[disabled] .Option {
|
||||
cursor: pointer;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.Option {
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
|
@ -502,6 +502,18 @@ const Board = ({ table, game }) => {
|
||||
return (game && game.turn && Array.isArray(game.turn.actions) && game.turn.actions.indexOf(action) !== -1);
|
||||
};
|
||||
|
||||
const canRoad = (canAction('place-road')
|
||||
&& game.turn.color === game.color
|
||||
&& (game.state === 'initial-placement' || game.state === 'normal'));
|
||||
|
||||
const canCorner = ((canAction('place-settlement') || canAction('place-city'))
|
||||
&& game.turn.color === game.color
|
||||
&& (game.state === 'initial-placement' || game.state === 'normal'));
|
||||
|
||||
const canPip = (canAction('place-robber')
|
||||
&& game.turn.color === game.color
|
||||
&& (game.state === 'initial-placement' || game.state === 'normal'));
|
||||
|
||||
return (
|
||||
<div className="Board">
|
||||
<div className="BoardBox">
|
||||
@ -512,13 +524,13 @@ const Board = ({ table, game }) => {
|
||||
<div className="Tiles" disabled>
|
||||
{ tiles }
|
||||
</div>
|
||||
<div className="Pips" disabled={!canAction('place-robber') || game.turn.color !== game.color || (game.state !== 'initial-placement' && game.state !== 'normal')}>
|
||||
<div className="Pips" disabled={!canPip}>
|
||||
{ pips }
|
||||
</div>
|
||||
<div className="Corners" disabled={!canAction('place-settlement') || game.turn.color !== game.color || (game.state !== 'initial-placement' && game.state !== 'normal')}>
|
||||
<div className="Corners" disabled={!canCorner}>
|
||||
{ corners }
|
||||
</div>
|
||||
<div className="Roads" disabled={!canAction('place-road') || game.turn.color !== game.color || (game.state !== 'initial-placement' && game.state !== 'normal')}>
|
||||
<div className="Roads" disabled={!canRoad}>
|
||||
{ roads }
|
||||
</div>
|
||||
</> }
|
||||
|
@ -403,7 +403,7 @@ const Action = ({ table }) => {
|
||||
<StartButton table={table}/>
|
||||
<Button disabled={game.color ? false : true} onClick={newTableClick}>New table</Button>
|
||||
<Button disabled={game.color ? true : false} onClick={() => {table.setState({ pickName: true})}}>Change name</Button> </> }
|
||||
{ game.state === 'normal' && <>
|
||||
{ !inLobby && <>
|
||||
<Button disabled={robberActions || !isTurn || hasRolled} onClick={rollClick}>Roll Dice</Button>
|
||||
<Button disabled={robberActions || !isTurn || !hasRolled || !haveResources} onClick={tradeClick}>Trade</Button>
|
||||
<Button disabled={robberActions || !isTurn || !hasRolled || !haveResources} onClick={buildClicked}>Build</Button>
|
||||
@ -430,7 +430,8 @@ const PlayerName = ({table}) => {
|
||||
if (name !== table.game.name) {
|
||||
table.setPlayerName(name);
|
||||
} else {
|
||||
table.setState({ pickName: false, error: "" });
|
||||
table.setError("");
|
||||
table.setState({ pickName: false });
|
||||
}
|
||||
}
|
||||
|
||||
@ -604,10 +605,10 @@ class Table extends React.Component {
|
||||
const error = (game.status !== 'success') ? game.status : undefined;
|
||||
this.updateGame(game);
|
||||
this.updateMessage();
|
||||
this.setState({ error: error });
|
||||
this.setError(error);
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
this.setState({error: error.message});
|
||||
this.setError(error.message);
|
||||
}).then(() => {
|
||||
this.setState({ loading: this.state.loading - 1 });
|
||||
});
|
||||
@ -640,7 +641,7 @@ class Table extends React.Component {
|
||||
shuffleTable() {
|
||||
return this.sendAction('shuffle')
|
||||
.then(() => {
|
||||
this.setState({ error: "Table shuffled!" });
|
||||
this.setError("Table shuffled!");
|
||||
});
|
||||
}
|
||||
|
||||
@ -676,6 +677,19 @@ class Table extends React.Component {
|
||||
return this.sendAction('roll');
|
||||
}
|
||||
|
||||
setError(error) {
|
||||
if (!error) {
|
||||
return;
|
||||
}
|
||||
if (this.errorTimeout) {
|
||||
clearTimeout(this.errorTimeout);
|
||||
}
|
||||
setTimeout(() => this.setState({error: undefined}), 3000);
|
||||
if (this.state.error !== error) {
|
||||
this.setState({ error });
|
||||
}
|
||||
}
|
||||
|
||||
setGameState(state) {
|
||||
if (this.loadTimer) {
|
||||
window.clearTimeout(this.loadTimer);
|
||||
@ -702,9 +716,9 @@ class Table extends React.Component {
|
||||
this.updateMessage();
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
this.setState({error: error.message});
|
||||
this.setError(error.message);
|
||||
}).then(() => {
|
||||
this.setState({ loading: this.state.loading + 1 });
|
||||
this.setState({ loading: this.state.loading - 1 });
|
||||
return this.game.state;
|
||||
});
|
||||
}
|
||||
@ -865,7 +879,7 @@ class Table extends React.Component {
|
||||
try {
|
||||
data = JSON.parse(event.data);
|
||||
} catch (error) {
|
||||
this.setState({ error });
|
||||
this.setError(error);
|
||||
return;
|
||||
}
|
||||
let update;
|
||||
@ -875,7 +889,16 @@ class Table extends React.Component {
|
||||
const error = (update.status !== 'success') ? update.status : undefined;
|
||||
this.updateGame(update);
|
||||
this.updateMessage();
|
||||
this.setState({ error });
|
||||
this.setError(error);
|
||||
break;
|
||||
case 'ping':
|
||||
if (this.keepAlive) {
|
||||
clearTimeout(this.keepAlive);
|
||||
}
|
||||
this.keepAlive = setTimeout(() => {
|
||||
console.error(`No server ping for 5 seconds!`);
|
||||
}, 5000);
|
||||
this.ws.send(JSON.stringify({ type: 'pong', timestamp: data.ping }));
|
||||
break;
|
||||
default:
|
||||
console.log(`Unknown event type: ${data.type}`);
|
||||
@ -925,7 +948,7 @@ class Table extends React.Component {
|
||||
|
||||
error = `Unable to find game ${this.id}. Starting new game.`
|
||||
console.log(error);
|
||||
this.setState({ error: error });
|
||||
this.setError(error);
|
||||
|
||||
params.url = `${base}/api/v1/games/${this.id}`;
|
||||
params.method = "POST";
|
||||
@ -951,7 +974,7 @@ class Table extends React.Component {
|
||||
this.setState({ error: "" });
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
this.setState({error: error.message});
|
||||
this.setError(error.message);
|
||||
}).then(() => {
|
||||
this.setState({ loading: this.state.loading - 1 });
|
||||
});
|
||||
@ -961,10 +984,16 @@ class Table extends React.Component {
|
||||
if (this.loadTimer) {
|
||||
clearTimeout(this.loadTimer);
|
||||
}
|
||||
if (this.keepAlive) {
|
||||
clearTimeout(this.keepAlive);
|
||||
}
|
||||
if (this.updateSizeTimer) {
|
||||
clearTimeout(this.updateSizeTimer);
|
||||
this.updateSizeTimer = 0;
|
||||
}
|
||||
if (this.errorTimeout) {
|
||||
clearTimeout(this.errorTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
cardClicked(card) {
|
||||
@ -1098,7 +1127,7 @@ class Table extends React.Component {
|
||||
(!game.player || !game.player.mustDiscard) && <WaitingForPlayer table={this}/>
|
||||
}
|
||||
|
||||
{ this.state.error && <Paper className="Error"><div>{this.state.error}</div></Paper> }
|
||||
{ this.state.error && <Paper onClick={() => this.setState({ error: undefined })} className="Error"><div>{this.state.error}</div></Paper> }
|
||||
|
||||
</div>
|
||||
);
|
||||
|
@ -115,7 +115,6 @@ app.use(basePath, function(req, res, next) {
|
||||
/* Everything below here requires a successful authentication */
|
||||
app.use(basePath, express.static(frontendPath, { index: false }));
|
||||
|
||||
app.set('ws', ws);
|
||||
app.use(`${basePath}api/v1/games`, require("./routes/games"));
|
||||
|
||||
/* Declare the "catch all" index route last; the final route is a 404 dynamic router */
|
||||
@ -127,10 +126,9 @@ app.use(basePath, index);
|
||||
app.set("port", serverConfig.port);
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
server.close(() => {
|
||||
console.log("Gracefully shutting down from SIGINT (Ctrl-C)");
|
||||
process.exit(1);
|
||||
});
|
||||
console.log("Gracefully shutting down from SIGINT (Ctrl-C) in 2 seconds");
|
||||
setTimeout(() => process.exit(-1), 2000);
|
||||
server.close(() => process.exit(1));
|
||||
});
|
||||
|
||||
require("./db/games").then(function(db) {
|
||||
|
@ -8,6 +8,7 @@ const express = require("express"),
|
||||
accessSync = fs.accessSync,
|
||||
randomWords = require("random-words");
|
||||
|
||||
const session = require("express-session");
|
||||
const layout = require('./layout.js');
|
||||
|
||||
const MAX_SETTLEMENTS = 5;
|
||||
@ -2489,20 +2490,59 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
||||
return sendGame(req, res, game, error);
|
||||
})
|
||||
|
||||
const ping = (session) => {
|
||||
session.ping = Date.now();
|
||||
session.ws.send(JSON.stringify({ type: 'ping', ping: session.ping }));
|
||||
if (session.keepAlive) {
|
||||
clearTimeout(session.keepAlive);
|
||||
}
|
||||
session.keepAlive = setTimeout(() => { ping(session); }, 2500);
|
||||
}
|
||||
|
||||
router.ws("/ws/:id", (ws, req) => {
|
||||
const { id } = req.params;
|
||||
ws.on('message', (msg) => {
|
||||
console.log(msg);
|
||||
});
|
||||
if (id in games) {
|
||||
const game = games[id];
|
||||
|
||||
console.log(`WebSocket connect from game ${id}`);
|
||||
|
||||
let game;
|
||||
if (!(id in games)) {
|
||||
game = createGame(id);
|
||||
} else {
|
||||
game = games[id];
|
||||
}
|
||||
|
||||
const session = getSession(game, req.session);
|
||||
if (session) {
|
||||
console.log(`WebSocket connected for ${session.name}`);
|
||||
console.log(`WebSocket connected for ${session.name ? session.name : "Unnamed"}`);
|
||||
session.ws = ws;
|
||||
if (session.keepAlive) {
|
||||
clearTimeout(session.keepAlive);
|
||||
}
|
||||
session.keepAlive = setTimeout(() => { ping(session); }, 2500);
|
||||
} else {
|
||||
console.log(`No session found for WebSocket with id ${id}`);
|
||||
}
|
||||
|
||||
ws.on('error', (event) => {
|
||||
console.error(`WebSocket error: `, event.message);
|
||||
});
|
||||
|
||||
ws.on('open', (event) => {
|
||||
console.log(`WebSocket open: `, event.message);
|
||||
});
|
||||
|
||||
ws.on('message', (message) => {
|
||||
try {
|
||||
const data = JSON.parse(message);
|
||||
switch (data.type) {
|
||||
case 'pong':
|
||||
console.log(`Latency for ${session.name ? session.name : 'Unammed'} is ${Date.now() - data.timestamp}`);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.get("/:id", async (req, res/*, next*/) => {
|
||||
@ -2658,6 +2698,9 @@ const sendGame = async (req, res, game, error) => {
|
||||
if (reduced.ws) {
|
||||
delete reduced.ws;
|
||||
}
|
||||
if (reduced.keepAlive) {
|
||||
delete reduced.keepAlive;
|
||||
}
|
||||
reducedGame.sessions[id] = reduced;
|
||||
|
||||
/* Do not send session-id as those are secrets */
|
||||
@ -2704,6 +2747,7 @@ const sendGame = async (req, res, game, error) => {
|
||||
});
|
||||
|
||||
if (useWS) {
|
||||
if (!error) {
|
||||
if (!target.ws) {
|
||||
console.error(`No WebSocket connection to ${target.name}`);
|
||||
} else {
|
||||
@ -2713,8 +2757,9 @@ const sendGame = async (req, res, game, error) => {
|
||||
update: playerGame
|
||||
}));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`Returning update to ${target.name}`);
|
||||
console.log(`Returning update to ${target.name ? target.name : 'Unnamed'}`);
|
||||
res.status(200).send(playerGame);
|
||||
}
|
||||
}
|
||||
@ -2726,7 +2771,8 @@ const resetGame = (game) => {
|
||||
Object.assign(game, {
|
||||
startTime: Date.now(),
|
||||
state: 'lobby',
|
||||
turn: 0,
|
||||
turns: 0,
|
||||
turn: {},
|
||||
sheep: 19,
|
||||
ore: 19,
|
||||
wool: 19,
|
||||
@ -2738,7 +2784,6 @@ const resetGame = (game) => {
|
||||
},
|
||||
developmentCards: [],
|
||||
chat: [],
|
||||
turn: {},
|
||||
pipOrder: game.pipOrder,
|
||||
borderOrder: game.borderOrder,
|
||||
tileOrder: game.tileOrder,
|
||||
|
Loading…
x
Reference in New Issue
Block a user