1
0

Added WebSocket for responses

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-02-28 13:11:27 -08:00
parent 7ec798d0ed
commit 0bc96d5121
8 changed files with 130 additions and 120 deletions

View File

@ -530,8 +530,6 @@ class Table extends React.Component {
};
this.componentDidMount = this.componentDidMount.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.setGameState = this.setGameState.bind(this);
this.shuffleTable = this.shuffleTable.bind(this);
@ -612,7 +610,6 @@ class Table extends React.Component {
this.setState({error: error.message});
}).then(() => {
this.setState({ loading: this.state.loading - 1 });
this.resetGameLoad();
});
}
@ -679,53 +676,6 @@ class Table extends React.Component {
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) {
if (this.loadTimer) {
window.clearTimeout(this.loadTimer);
@ -755,7 +705,6 @@ class Table extends React.Component {
this.setState({error: error.message});
}).then(() => {
this.setState({ loading: this.state.loading + 1 });
this.resetGameLoad();
return this.game.state;
});
}
@ -808,7 +757,7 @@ class Table extends React.Component {
this.setState( { signature: game.signature });
}
// console.log("Update Game", game);
this.setState( { game: game });
this.setState( { game });
this.game = game;
}
@ -904,21 +853,44 @@ class Table extends React.Component {
} else {
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.onopen = (event) => {
console.log(event);
//ws.send(JSON.stringify(apiCall));
console.log(`WebSocket open:`, event);
};
this.ws.onmessage = (event) => {
const json = JSON.parse(event.data);
console.log(json);
};
let data;
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) => {
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 = {};
@ -982,7 +954,6 @@ class Table extends React.Component {
this.setState({error: error.message});
}).then(() => {
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

View File

@ -4,7 +4,7 @@ module.exports = function(app) {
const base = process.env.PUBLIC_URL;
console.log('http-proxy-middleware');
app.use(createProxyMiddleware(
`${base}/ws`, {
`${base}/api/v1/games/ws`, {
ws: true,
target: 'http://localhost:8930',
changeOrigin: true,

View File

@ -10,7 +10,10 @@ const express = require("express"),
session = require('express-session'),
hb = require("handlebars"),
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 */
@ -21,8 +24,6 @@ console.log("Hosting server from: " + basePath);
let userDB, gameDB;
const app = express();
app.use(bodyParser.json());
@ -81,6 +82,7 @@ app.use(basePath, index);
/* /games loads the default index */
app.use(basePath + "games", index);
/* Allow access to the 'users' API w/out being logged in */
/*
const users = require("./routes/users");
@ -113,7 +115,8 @@ app.use(basePath, function(req, res, next) {
/* Everything below here requires a successful authentication */
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 */
app.use(basePath, index);
@ -123,8 +126,6 @@ app.use(basePath, index);
*/
app.set("port", serverConfig.port);
const server = require("http").createServer(app);
process.on('SIGINT', () => {
server.close(() => {
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) {
gameDB = db;
}).then(function() {
@ -142,33 +141,6 @@ require("./db/games").then(function(db) {
});
}).then(function() {
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, () => {
console.log(`http/ws server listening on ${serverConfig.port}`);
});

View File

@ -17,6 +17,7 @@
"core-js": "^3.2.1",
"express": "^4.17.1",
"express-session": "^1.17.1",
"express-ws": "^5.0.2",
"handlebars": "^4.7.6",
"moment": "^2.24.0",
"morgan": "^1.9.1",

21
server/pass Executable file
View 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
View 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

View File

@ -1,6 +1,7 @@
"use strict";
const express = require("express"),
router = express.Router(),
crypto = require("crypto"),
{ readFile, writeFile } = require("fs").promises,
fs = require("fs"),
@ -19,8 +20,6 @@ require("../db/games").then(function(db) {
gameDB = db;
});
const router = express.Router();
function shuffle(array) {
var currentIndex = array.length, temporaryValue, randomIndex;
@ -2490,6 +2489,22 @@ router.put("/:id/:action/:value?", async (req, res) => {
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*/) => {
const { id } = req.params;
// console.log("GET games/" + id);
@ -2640,6 +2655,9 @@ const sendGame = async (req, res, game, error) => {
if (reduced.player) {
delete reduced.player;
}
if (reduced.ws) {
delete reduced.ws;
}
reducedGame.sessions[id] = reduced;
/* Do not send session-id as those are secrets */
@ -2658,7 +2676,11 @@ const sendGame = async (req, res, game, error) => {
console.error(error);
});
const player = session.player ? session.player : undefined;
for (let id in game.sessions) {
const target = game.sessions[id],
useWS = target !== session,
player = target.player ? target.player : undefined;
if (player) {
player.haveResources = player.wheat > 0 ||
player.brick > 0 ||
@ -2673,14 +2695,29 @@ const sendGame = async (req, res, game, error) => {
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,
name: target.name,
color: target.color,
order: (target.color in game.players) ? game.players[target.color].order : 0,
player: player,
sessions: reducedSessions,
layout: layout
});
return res.status(200).send(playerGame);
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);
}
}
}
const resetGame = (game) => {