Added WebSocket for responses
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
7ec798d0ed
commit
0bc96d5121
@ -530,8 +530,6 @@ class Table extends React.Component {
|
|||||||
};
|
};
|
||||||
this.componentDidMount = this.componentDidMount.bind(this);
|
this.componentDidMount = this.componentDidMount.bind(this);
|
||||||
this.throwDice = this.throwDice.bind(this);
|
this.throwDice = this.throwDice.bind(this);
|
||||||
this.resetGameLoad = this.resetGameLoad.bind(this);
|
|
||||||
this.loadGame = this.loadGame.bind(this);
|
|
||||||
this.rollDice = this.rollDice.bind(this);
|
this.rollDice = this.rollDice.bind(this);
|
||||||
this.setGameState = this.setGameState.bind(this);
|
this.setGameState = this.setGameState.bind(this);
|
||||||
this.shuffleTable = this.shuffleTable.bind(this);
|
this.shuffleTable = this.shuffleTable.bind(this);
|
||||||
@ -612,7 +610,6 @@ class Table extends React.Component {
|
|||||||
this.setState({error: error.message});
|
this.setState({error: error.message});
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.setState({ loading: this.state.loading - 1 });
|
this.setState({ loading: this.state.loading - 1 });
|
||||||
this.resetGameLoad();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,53 +676,6 @@ class Table extends React.Component {
|
|||||||
return this.sendAction('roll');
|
return this.sendAction('roll');
|
||||||
}
|
}
|
||||||
|
|
||||||
loadGame() {
|
|
||||||
if (this.loadTimer) {
|
|
||||||
window.clearTimeout(this.loadTimer);
|
|
||||||
this.loadTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.state.game) {
|
|
||||||
console.error('Attempting to loadGame with no game set');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ loading: this.state.loading + 1 });
|
|
||||||
return window.fetch(`${base}/api/v1/games/${this.state.game.id}`, {
|
|
||||||
method: "GET",
|
|
||||||
cache: 'no-cache',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}
|
|
||||||
}).then((res) => {
|
|
||||||
if (res.status >= 400) {
|
|
||||||
console.log(res);
|
|
||||||
throw new Error(`Server temporarily unreachable.`);
|
|
||||||
}
|
|
||||||
return res.json();
|
|
||||||
}).then((game) => {
|
|
||||||
const error = (game.status !== 'success') ? game.status : undefined;
|
|
||||||
this.updateGame(game);
|
|
||||||
this.updateMessage();
|
|
||||||
this.setState({ error: error });
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
this.setState({error: error.message});
|
|
||||||
}).then(() => {
|
|
||||||
this.setState({ loading: this.state.loading - 1 });
|
|
||||||
this.resetGameLoad();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
resetGameLoad() {
|
|
||||||
if (this.loadTimer) {
|
|
||||||
window.clearTimeout(this.loadTimer);
|
|
||||||
this.loadTimer = 0;
|
|
||||||
}
|
|
||||||
this.loadTimer = window.setTimeout(this.loadGame, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
setGameState(state) {
|
setGameState(state) {
|
||||||
if (this.loadTimer) {
|
if (this.loadTimer) {
|
||||||
window.clearTimeout(this.loadTimer);
|
window.clearTimeout(this.loadTimer);
|
||||||
@ -755,7 +705,6 @@ class Table extends React.Component {
|
|||||||
this.setState({error: error.message});
|
this.setState({error: error.message});
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.setState({ loading: this.state.loading + 1 });
|
this.setState({ loading: this.state.loading + 1 });
|
||||||
this.resetGameLoad();
|
|
||||||
return this.game.state;
|
return this.game.state;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -808,7 +757,7 @@ class Table extends React.Component {
|
|||||||
this.setState( { signature: game.signature });
|
this.setState( { signature: game.signature });
|
||||||
}
|
}
|
||||||
// console.log("Update Game", game);
|
// console.log("Update Game", game);
|
||||||
this.setState( { game: game });
|
this.setState( { game });
|
||||||
this.game = game;
|
this.game = game;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -904,21 +853,44 @@ class Table extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
new_uri = "ws";
|
new_uri = "ws";
|
||||||
}
|
}
|
||||||
new_uri = `${new_uri}://${loc.host}${base}/ws`;
|
new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${this.id}`;
|
||||||
this.ws = new WebSocket(new_uri);
|
this.ws = new WebSocket(new_uri);
|
||||||
|
|
||||||
this.ws.onopen = (event) => {
|
this.ws.onopen = (event) => {
|
||||||
console.log(event);
|
console.log(`WebSocket open:`, event);
|
||||||
//ws.send(JSON.stringify(apiCall));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.ws.onmessage = (event) => {
|
this.ws.onmessage = (event) => {
|
||||||
const json = JSON.parse(event.data);
|
let data;
|
||||||
console.log(json);
|
try {
|
||||||
};
|
data = JSON.parse(event.data);
|
||||||
|
} catch (error) {
|
||||||
|
this.setState({ error });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let update;
|
||||||
|
switch (data.type) {
|
||||||
|
case 'game-update':
|
||||||
|
update = data.update;
|
||||||
|
const error = (update.status !== 'success') ? update.status : undefined;
|
||||||
|
this.updateGame(update);
|
||||||
|
this.updateMessage();
|
||||||
|
this.setState({ error });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`Unknown event type: ${data.type}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.ws.onerror = (event) => {
|
this.ws.onerror = (event) => {
|
||||||
console.error(event);
|
this.setState({ error: event.message });
|
||||||
|
console.error(`WebSocket error:`, event);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ws.onclose = (event) => {
|
||||||
|
this.setState({ error: event.message });
|
||||||
|
console.error(`WebSocket close:`, event);
|
||||||
};
|
};
|
||||||
|
|
||||||
const params = {};
|
const params = {};
|
||||||
@ -982,7 +954,6 @@ class Table extends React.Component {
|
|||||||
this.setState({error: error.message});
|
this.setState({error: error.message});
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.setState({ loading: this.state.loading - 1 });
|
this.setState({ loading: this.state.loading - 1 });
|
||||||
this.resetGameLoad();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 29 KiB |
@ -4,7 +4,7 @@ module.exports = function(app) {
|
|||||||
const base = process.env.PUBLIC_URL;
|
const base = process.env.PUBLIC_URL;
|
||||||
console.log('http-proxy-middleware');
|
console.log('http-proxy-middleware');
|
||||||
app.use(createProxyMiddleware(
|
app.use(createProxyMiddleware(
|
||||||
`${base}/ws`, {
|
`${base}/api/v1/games/ws`, {
|
||||||
ws: true,
|
ws: true,
|
||||||
target: 'http://localhost:8930',
|
target: 'http://localhost:8930',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
@ -10,7 +10,10 @@ const express = require("express"),
|
|||||||
session = require('express-session'),
|
session = require('express-session'),
|
||||||
hb = require("handlebars"),
|
hb = require("handlebars"),
|
||||||
SQLiteStore = require('connect-sqlite3')(session),
|
SQLiteStore = require('connect-sqlite3')(session),
|
||||||
basePath = require("./basepath");
|
basePath = require("./basepath"),
|
||||||
|
app = express(),
|
||||||
|
server = require("http").createServer(app),
|
||||||
|
ws = require('express-ws')(app, server);
|
||||||
|
|
||||||
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
require("./console-line.js"); /* Monkey-patch console.log with line numbers */
|
||||||
|
|
||||||
@ -21,8 +24,6 @@ console.log("Hosting server from: " + basePath);
|
|||||||
|
|
||||||
let userDB, gameDB;
|
let userDB, gameDB;
|
||||||
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ app.use(basePath, index);
|
|||||||
/* /games loads the default index */
|
/* /games loads the default index */
|
||||||
app.use(basePath + "games", index);
|
app.use(basePath + "games", index);
|
||||||
|
|
||||||
|
|
||||||
/* Allow access to the 'users' API w/out being logged in */
|
/* Allow access to the 'users' API w/out being logged in */
|
||||||
/*
|
/*
|
||||||
const users = require("./routes/users");
|
const users = require("./routes/users");
|
||||||
@ -113,7 +115,8 @@ app.use(basePath, function(req, res, next) {
|
|||||||
/* Everything below here requires a successful authentication */
|
/* Everything below here requires a successful authentication */
|
||||||
app.use(basePath, express.static(frontendPath, { index: false }));
|
app.use(basePath, express.static(frontendPath, { index: false }));
|
||||||
|
|
||||||
app.use(basePath + "api/v1/games", require("./routes/games"));
|
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 */
|
/* Declare the "catch all" index route last; the final route is a 404 dynamic router */
|
||||||
app.use(basePath, index);
|
app.use(basePath, index);
|
||||||
@ -123,8 +126,6 @@ app.use(basePath, index);
|
|||||||
*/
|
*/
|
||||||
app.set("port", serverConfig.port);
|
app.set("port", serverConfig.port);
|
||||||
|
|
||||||
const server = require("http").createServer(app);
|
|
||||||
|
|
||||||
process.on('SIGINT', () => {
|
process.on('SIGINT', () => {
|
||||||
server.close(() => {
|
server.close(() => {
|
||||||
console.log("Gracefully shutting down from SIGINT (Ctrl-C)");
|
console.log("Gracefully shutting down from SIGINT (Ctrl-C)");
|
||||||
@ -132,8 +133,6 @@ process.on('SIGINT', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const WebSocket = require('ws');
|
|
||||||
|
|
||||||
require("./db/games").then(function(db) {
|
require("./db/games").then(function(db) {
|
||||||
gameDB = db;
|
gameDB = db;
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
@ -142,33 +141,6 @@ require("./db/games").then(function(db) {
|
|||||||
});
|
});
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
console.log("DB connected. Opening server.");
|
console.log("DB connected. Opening server.");
|
||||||
|
|
||||||
/* Create web socket server on top of a regular http server */
|
|
||||||
const ws = new WebSocket.Server({
|
|
||||||
server
|
|
||||||
});
|
|
||||||
|
|
||||||
/* Mount the Express app here */
|
|
||||||
|
|
||||||
//server.on('request', app);
|
|
||||||
|
|
||||||
app.set('ws', ws);
|
|
||||||
|
|
||||||
ws.on('connection', (req) => {/*
|
|
||||||
sessionParser(req.upgradeReq, {}, () => {
|
|
||||||
console.log("New websocket connection:");
|
|
||||||
var sess = req.upgradeReq.session;
|
|
||||||
console.log("working = " + sess.working);
|
|
||||||
});*/
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.on('message', (message) => {
|
|
||||||
console.log(`received: ${message}`);
|
|
||||||
ws.send(JSON.stringify({
|
|
||||||
answer: 42
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
server.listen(serverConfig.port, () => {
|
server.listen(serverConfig.port, () => {
|
||||||
console.log(`http/ws server listening on ${serverConfig.port}`);
|
console.log(`http/ws server listening on ${serverConfig.port}`);
|
||||||
});
|
});
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"core-js": "^3.2.1",
|
"core-js": "^3.2.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-session": "^1.17.1",
|
"express-session": "^1.17.1",
|
||||||
|
"express-ws": "^5.0.2",
|
||||||
"handlebars": "^4.7.6",
|
"handlebars": "^4.7.6",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
|
21
server/pass
Executable file
21
server/pass
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
ADMIN=$(jq -r .admin config/local.json)
|
||||||
|
if [[ "${ADMIN}" == "" ]]; then
|
||||||
|
echo "You need to set your { 'admin': 'secret' } in config/local.json"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
id=$1
|
||||||
|
|
||||||
|
if [[ "${id}" == "" ]]; then
|
||||||
|
echo "Usage: pass GAME-ID"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl --noproxy '*' -s -L \
|
||||||
|
--request PUT \
|
||||||
|
--header "PRIVATE-TOKEN: ${ADMIN}" \
|
||||||
|
--header "Content-Type: application/json" \
|
||||||
|
http://localhost:8930/ketr.ketran/api/v1/games/${id}/pass |
|
||||||
|
jq -r .status
|
||||||
|
|
8
server/reset
Executable file
8
server/reset
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cp games/held_riding_farm_hat.67 games/held_riding_farm_hat
|
||||||
|
set -m
|
||||||
|
npm start &
|
||||||
|
sleep 3
|
||||||
|
./pass held_riding_farm_hat
|
||||||
|
./roll held_riding_farm_hat 3-3
|
||||||
|
fg %1
|
@ -1,6 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const express = require("express"),
|
const express = require("express"),
|
||||||
|
router = express.Router(),
|
||||||
crypto = require("crypto"),
|
crypto = require("crypto"),
|
||||||
{ readFile, writeFile } = require("fs").promises,
|
{ readFile, writeFile } = require("fs").promises,
|
||||||
fs = require("fs"),
|
fs = require("fs"),
|
||||||
@ -19,8 +20,6 @@ require("../db/games").then(function(db) {
|
|||||||
gameDB = db;
|
gameDB = db;
|
||||||
});
|
});
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
function shuffle(array) {
|
function shuffle(array) {
|
||||||
var currentIndex = array.length, temporaryValue, randomIndex;
|
var currentIndex = array.length, temporaryValue, randomIndex;
|
||||||
|
|
||||||
@ -2490,6 +2489,22 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
return sendGame(req, res, game, error);
|
return sendGame(req, res, game, error);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
const session = getSession(game, req.session);
|
||||||
|
if (session) {
|
||||||
|
console.log(`WebSocket connected for ${session.name}`);
|
||||||
|
session.ws = ws;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.get("/:id", async (req, res/*, next*/) => {
|
router.get("/:id", async (req, res/*, next*/) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
// console.log("GET games/" + id);
|
// console.log("GET games/" + id);
|
||||||
@ -2640,6 +2655,9 @@ const sendGame = async (req, res, game, error) => {
|
|||||||
if (reduced.player) {
|
if (reduced.player) {
|
||||||
delete reduced.player;
|
delete reduced.player;
|
||||||
}
|
}
|
||||||
|
if (reduced.ws) {
|
||||||
|
delete reduced.ws;
|
||||||
|
}
|
||||||
reducedGame.sessions[id] = reduced;
|
reducedGame.sessions[id] = reduced;
|
||||||
|
|
||||||
/* Do not send session-id as those are secrets */
|
/* Do not send session-id as those are secrets */
|
||||||
@ -2658,29 +2676,48 @@ const sendGame = async (req, res, game, error) => {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
const player = session.player ? session.player : undefined;
|
for (let id in game.sessions) {
|
||||||
if (player) {
|
const target = game.sessions[id],
|
||||||
player.haveResources = player.wheat > 0 ||
|
useWS = target !== session,
|
||||||
player.brick > 0 ||
|
player = target.player ? target.player : undefined;
|
||||||
player.sheep > 0 ||
|
|
||||||
player.stone > 0 ||
|
if (player) {
|
||||||
player.wood > 0;
|
player.haveResources = player.wheat > 0 ||
|
||||||
|
player.brick > 0 ||
|
||||||
|
player.sheep > 0 ||
|
||||||
|
player.stone > 0 ||
|
||||||
|
player.wood > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strip out data that should not be shared with players */
|
||||||
|
delete reducedGame.developmentCards;
|
||||||
|
|
||||||
|
const playerGame = Object.assign({}, reducedGame, {
|
||||||
|
timestamp: Date.now(),
|
||||||
|
status: error ? error : "success",
|
||||||
|
name: target.name,
|
||||||
|
color: target.color,
|
||||||
|
order: (target.color in game.players) ? game.players[target.color].order : 0,
|
||||||
|
player: player,
|
||||||
|
sessions: reducedSessions,
|
||||||
|
layout: layout
|
||||||
|
});
|
||||||
|
|
||||||
|
if (useWS) {
|
||||||
|
if (!target.ws) {
|
||||||
|
console.error(`No WebSocket connection to ${target.name}`);
|
||||||
|
} else {
|
||||||
|
console.log(`Sending update to ${target.name}`);
|
||||||
|
target.ws.send(JSON.stringify({
|
||||||
|
type: 'game-update',
|
||||||
|
update: playerGame
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(`Returning update to ${target.name}`);
|
||||||
|
res.status(200).send(playerGame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Strip out data that should not be shared with players */
|
|
||||||
delete reducedGame.developmentCards;
|
|
||||||
|
|
||||||
const playerGame = Object.assign({}, reducedGame, {
|
|
||||||
timestamp: Date.now(),
|
|
||||||
status: error ? error : "success",
|
|
||||||
name: session.name,
|
|
||||||
color: session.color,
|
|
||||||
order: (session.color in game.players) ? game.players[session.color].order : 0,
|
|
||||||
player: player,
|
|
||||||
sessions: reducedSessions,
|
|
||||||
layout: layout
|
|
||||||
});
|
|
||||||
return res.status(200).send(playerGame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const resetGame = (game) => {
|
const resetGame = (game) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user