Riskless/static/js/index.js

189 lines
4.7 KiB
JavaScript
Raw Normal View History

2022-12-29 14:11:18 +00:00
const ID = window.crypto.randomUUID();
// Timeout to consider a player disconnected
const TIMEOUT = 30_000;
2022-12-29 14:11:18 +00:00
let players = {};
let us = null;
2023-02-06 13:03:25 +00:00
let currentPlayer = () => Object.values(players).filter((p) => p.isPlaying)[0];
2023-01-29 16:47:37 +00:00
const WAITING = 0;
const PRE_GAME = 1;
const PLAYING = 2;
const POST_GAME = 3;
2023-02-06 11:04:37 +00:00
let gameState = WAITING;
2023-01-29 16:47:37 +00:00
2023-01-31 12:34:13 +00:00
let socket;
let random;
let barrier;
2023-01-31 12:34:13 +00:00
// Not totally reliable but better than nothing.
window.addEventListener("beforeunload", () => {
socket.emit("message", Packet.createDisconnect());
});
document.addEventListener("DOMContentLoaded", () => {
2023-01-31 12:34:13 +00:00
socket = io();
random = new Random();
barrier = new Barrier();
2022-12-29 14:11:18 +00:00
socket.on("connect", () => {
console.log("Connected!");
socket.emit("message", Packet.createAnnounce());
2023-01-29 16:47:37 +00:00
// Create self
players[ID] = new Player(ID, name);
us = players[ID];
2022-12-29 14:11:18 +00:00
});
socket.on("message", async (data) => {
2023-01-29 16:47:37 +00:00
switch (data.type) {
case "ANNOUNCE":
2023-02-08 17:55:45 +00:00
if (data.author === ID) {
return;
}
2023-01-31 12:34:13 +00:00
playerConnected(data);
2023-01-29 16:47:37 +00:00
break;
case "DISCONNECT":
playerDisconnected(data);
break;
2023-01-29 16:47:37 +00:00
case "KEEPALIVE":
2023-02-08 17:55:45 +00:00
if (data.author === ID) {
return;
}
2023-01-29 16:47:37 +00:00
keepAlive(data);
break;
case "READY":
2023-02-08 17:55:45 +00:00
if (data.author === ID) {
return;
}
await setReady(data);
2023-01-29 16:47:37 +00:00
break;
case "RANDOM":
2023-02-08 17:55:45 +00:00
if (data.author === ID) {
return;
}
await random.processCooperativeRandom(data);
2023-01-29 16:47:37 +00:00
break;
case "BARRIER":
2023-02-08 17:55:45 +00:00
if (data.author === ID) {
return;
}
barrier.resolve(data);
break;
2023-02-06 11:04:37 +00:00
2023-02-10 15:47:21 +00:00
case "ACT":
2023-02-08 17:55:45 +00:00
if (data.author !== currentPlayer().id) {
return;
}
2023-02-10 15:47:21 +00:00
if (!allRegionsClaimed()) {
// Claim a region in the pregame.
if (currentPlayer().claim(data)) {
// Increment to next player.
currentPlayer().endTurn();
}
} else if (!allReinforcementsPlaced()) {
if (currentPlayer().reinforce(data)) {
currentPlayer().endTurn();
}
} else {
if (currentPlayer().act(data)) {
currentPlayer().endTurn();
}
2023-02-08 17:55:45 +00:00
}
2023-02-06 13:03:25 +00:00
updateDom();
2023-02-06 11:04:37 +00:00
break;
}
});
// Emit keepalive messages to inform other players we are still here
window.setInterval(() => {
socket.emit("message", Packet.createKeepAlive());
}, TIMEOUT / 5);
2022-12-29 14:11:18 +00:00
});
2023-01-29 16:47:37 +00:00
/**
* Process player connect packets: these inform that a new player has joined.
*
* @param data Packet received
*/
2023-01-31 12:34:13 +00:00
function playerConnected(data) {
2023-01-29 16:47:37 +00:00
// Block players from joining mid-game
2023-02-06 11:04:37 +00:00
if (gameState !== WAITING) {
2023-01-29 16:47:37 +00:00
return;
}
// When a new player is seen, all announce to ensure they know all players.
if (players[data.author] === undefined) {
2023-01-29 16:47:37 +00:00
players[data.author] = new Player(data.author, data.name);
socket.emit("message", Packet.createAnnounce());
2023-01-29 16:47:37 +00:00
players[data.author].resetTimeout();
} else {
}
2023-02-06 13:03:25 +00:00
updateDom();
}
function playerDisconnected(data) {
console.log("deleting player");
delete players[data.author];
2023-02-06 13:03:25 +00:00
updateDom();
}
2023-01-29 16:47:37 +00:00
/**
* Process keep-alive packets: these are packets that check players are still online.
*
* @param data Packet received
*/
function keepAlive(data) {
2023-01-29 16:47:37 +00:00
players[data.author].resetTimeout();
}
/**
* Process sync packets: update player details like status and name.
*
* @param data Packet received
*/
async function setReady(data) {
2023-01-29 16:47:37 +00:00
players[data.author].name = data.name;
players[data.author].ready = data.ready;
2023-02-06 13:03:25 +00:00
updateDom();
2023-01-29 16:47:37 +00:00
if (allPlayersReady()) {
await startPregame();
2023-01-29 16:47:37 +00:00
}
}
function allPlayersReady() {
for (let player of Object.values(players)) {
if (!player.ready) {
return false;
}
}
return true;
}
async function startPregame() {
console.log("all players ready.");
2023-02-06 11:04:37 +00:00
gameState = PRE_GAME;
let firstPlayerIndex = await random.get(Object.keys(players).length, "first-player");
let firstPlayer = Object.values(players).sort((a, b) => (a.id < b.id ? -1 : 1))[
firstPlayerIndex
];
firstPlayer.isPlaying = true;
await barrier.wait();
2023-02-06 13:03:25 +00:00
updateDom();
}