1
0

Auto reconnect hooked up

Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
James Ketrenos 2022-03-11 15:39:55 -08:00
parent 689b498f6b
commit def2afac6d
4 changed files with 84 additions and 45 deletions

View File

@ -15,10 +15,26 @@ body {
width: 100%;
bottom: 0;
flex-direction: row;
justify-content: space-between; /* left-justify 'board', right-justify 'game' */
background-image: url("./assets/tabletop.png");
}
.Table .ErrorDialog {
display: flex;
justify-content: space-around;
align-items: center;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: #00000060;
}
.Table .ErrorDialog .Error {
display: flex;
padding: 1rem;
}
.Table .Game {
display: flex;
flex-direction: column;
@ -34,8 +50,6 @@ body {
.Table .Hand {
display: flex;
position: relative;
border: 1px solid orange;
margin: 1rem;
height: 11rem;
}
@ -51,8 +65,6 @@ body {
.Table .Board {
display: flex;
flex-grow: 1;
margin: 1rem;
border: 1px solid purple;
}
.Table .Sidebar .Chat {

View File

@ -7,8 +7,8 @@ import {
Routes,
useParams
} from "react-router-dom";
import { base, gamesPath } from './Common.js';
import history from "./history.js";
import Paper from '@material-ui/core/Paper';
import { GlobalContext } from "./GlobalContext.js";
import { PingPong } from "./PingPong.js";
@ -17,7 +17,8 @@ import { Chat } from "./Chat.js";
import { MediaAgent } from "./MediaControl.js";
import { Board } from "./Board.js";
import { Actions } from "./Actions.js";
import { base, gamesPath, debounce } from './Common.js';
import history from "./history.js";
import "./App.css";
const Table = () => {
@ -29,6 +30,7 @@ const Table = () => {
const [ error, setError ] = useState(undefined);
const [ peers, setPeers ] = useState({});
const [loaded, setLoaded] = useState(false);
const [connecting, setConnecting] = useState(false);
useEffect(() => {
console.log(peers);
@ -41,7 +43,8 @@ const Table = () => {
/* We do not set the socket as bound until the 'open' message
* comes through */
setWs(event.target);
setConnecting(false);
/* Request a game-update */
event.target.send(JSON.stringify({
type: 'get',
@ -75,18 +78,32 @@ const Table = () => {
}
};
const resetConnection = (function () {
let timer = 0;
function reset() {
timer = 0;
setConnecting(false);
};
return _ => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(reset, 5000);
};
})();
const onWsError = (event) => {
console.log(`ws: error`, event);
const error = `Connection to Ketr Ketran game server failed! ` +
`Try refreshing in a few seconds.`;
`Connection attempt will be retried every 5 seconds.`;
console.error(error);
resetConnection();
setError(error);
};
const onWsClose = (event) => {
console.log(`ws: close`);
setWs(undefined);
global.ws = undefined;
resetConnection();
};
/* callback refs are used to provide correct state reference
@ -125,8 +142,8 @@ const Table = () => {
},
}).then((res) => {
if (res.status >= 400) {
const error = `Unable to connect to Ketr Ketran game server!` +
`Try refreshing in a few seconds.`;
const error = `Unable to connect to Ketr Ketran game server! ` +
`Try refreshing your browser in a few seconds.`;
console.error(error);
setError(error);
throw error;
@ -163,6 +180,7 @@ const Table = () => {
new_uri = `${new_uri}://${loc.host}${base}/api/v1/games/ws/${gameId}`;
console.log(`Attempting WebSocket connection to ${new_uri}`);
socket = new WebSocket(new_uri);
setConnecting(true);
}
console.log('table - bind');
@ -185,11 +203,7 @@ const Table = () => {
socket.removeEventListener('message', cbMessage);
}
}
}, [ setWs, gameId, ws, refWsOpen, refWsMessage, refWsClose, refWsError ]);
if (error) {
return <div>{ error }</div>;
}
}, [ setWs, connecting, setConnecting, gameId, ws, refWsOpen, refWsMessage, refWsClose, refWsError ]);
console.log(`Loaded: ${loaded}`);
@ -198,6 +212,7 @@ const Table = () => {
<MediaAgent/>
<PingPong/>
<div className="Table">
{ error && <div className="ErrorDialog"><Paper className="Error">{ error }</Paper></div> }
<div className="Game">
<Board/>
<div className="Hand">todo: player's hand</div>

View File

@ -9,9 +9,8 @@ const getPlayerName = (sessions, color) => {
return null;
}
function debounce(fn, ms) {
let timer
let timer;
return _ => {
clearTimeout(timer)
timer = setTimeout(_ => {
@ -19,7 +18,7 @@ function debounce(fn, ms) {
fn.apply(this, arguments)
}, ms)
};
}
};
const base = process.env.PUBLIC_URL;

View File

@ -2746,29 +2746,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
break;
case "state":
const state = value;
if (!state) {
error = `Invalid state.`;
break;
}
if (state === game.state) {
break;
}
switch (state) {
case "game-order":
if (game.state !== 'lobby') {
error = `You cannot start a game from other than the lobby.`;
break;
}
addChatMessage(game, null, `${name} requested to start the game.`);
game.state = state;
break;
}
break;
}
return sendGame(req, res, game, error);
@ -2804,6 +2782,30 @@ const wsInactive = (game, req) => {
}
}
const setGameState = (game, session, state) => {
if (!state) {
return `Invalid state.`;
}
if (!session.color) {
return `You must have an active player to start the game.`;
}
if (state === game.state) {
return;
}
switch (state) {
case "game-order":
if (game.state !== 'lobby') {
return `You cannot start a game from other than the lobby.`;
}
addChatMessage(game, null, `${session.name} requested to start the game.`);
game.state = state;
break;
}
}
const resetDisconnectCheck = (game, req) => {
if (req.disconnectCheck) {
clearTimeout(req.disconnectCheck);
@ -3122,6 +3124,15 @@ router.ws("/ws/:id", async (ws, req) => {
console.log(`${id}:${getName(session)} - ${data.type} ${data.field} = ${data.value}`);
update = {};
switch (data.field) {
case 'state':
error = setGameState(game, session, data.value);
if (error) {
console.warn(error);
session.ws.send(JSON.stringify({ type: 'error', error }));
break;
}
sendToPlayers(game, { state: game.state, chat });
break;
case 'color':
error = setPlayerColor(game, session, data.value);
if (error) {
@ -3129,6 +3140,8 @@ router.ws("/ws/:id", async (ws, req) => {
session.ws.send(JSON.stringify({ type: 'error', error }));
break;
}
/* Can't use sendToPlayers as the player name is a top level field
* and is unique to each player */
for (let key in game.sessions) {
const _session = game.sessions[key];
if (!_session.ws) {
@ -3143,7 +3156,7 @@ router.ws("/ws/:id", async (ws, req) => {
await saveGame(game);
break;
default:
console.warn(`WARNING: Requested SET unsupported field: ${field}`);
console.warn(`WARNING: Requested SET unsupported field: ${data.field}`);
break;
}
break;