Riskless/static/js/modules/interface/main.js

136 lines
3.6 KiB
JavaScript
Raw Normal View History

import { generate_keypair } from "../crypto/main.js";
import { Random } from "./random.js";
import { Barrier } from "./barrier.js";
import { Packet } from "./packet.js";
import { updateDom } from "./dom.js";
export const ID = window.crypto.randomUUID();
export let us = null;
export const game = new Game();
export let socket;
let random;
let barrier;
let keys;
// Not totally reliable but better than nothing.
window.addEventListener("beforeunload", () => {
socket.emit("message", Packet.createDisconnect());
});
document.addEventListener("DOMContentLoaded", () => {
socket = io();
random = new Random();
barrier = new Barrier();
keys = generate_keypair();
socket.on("connect", () => {
window.console.log("Connected!");
socket.emit("message", Packet.createAnnounce());
game.addPlayer(ID, name, true);
});
socket.on("message", async (data) => {
// todo validate signature
switch (data.type) {
case "RANDOM":
if (data.author === ID) {
return;
}
await random.processCooperativeRandom(data);
break;
case "BARRIER":
if (data.author === ID) {
return;
}
barrier.resolve(data);
break;
default:
const event = new CustomEvent(data.type, { detail: data });
document.dispatchEvent(event);
break;
}
});
});
/**
* Process player connect packets: these inform that a new player has joined.
*
* @param data Packet received
*/
document.addEventListener("ANNOUNCE", (data) => {
if (data.author === ID) return;
let is_new = game.addPlayer(data.author, data.name, false);
// When a new player is seen, all announce to ensure they know all players.
if (is_new) {
socket.emit("message", Packet.createAnnounce());
}
});
document.addEventListener("DISCONNECT", (data) => {
game.removePlayer(data.author);
});
/**
* Process keep-alive packets: these are packets that check players are still online.
*
* @param data Packet received
*/
document.addEventListener("KEEPALIVE", (data) => {
game.keepAlive(data.author);
});
document.addEventListener("ACT", async (data) => {
if (data.author !== game.currentPlayer().id) {
if (data.action === "DEFENSE") {
await game.players[data.author].setDefense(data.amount);
}
return;
}
if (game.isWaiting()) {
game.setReady(data.author, data.ready);
} else if (game.isPregame()) {
if (!Region.allRegionsClaimed()) {
// Claim a region in the pregame.
if (game.currentPlayer().claim(data)) {
// Increment to next player.
game.currentPlayer().endTurn();
}
} else if (!Region.allReinforcementsPlaced()) {
if (game.currentPlayer().reinforce(data)) {
game.currentPlayer().endTurn();
}
}
if (Region.allReinforcementsPlaced()) {
game.incrementState();
}
} else {
if (await game.currentPlayer().act(data)) {
game.currentPlayer().endTurn();
}
}
});
export async function startPregame() {
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();
updateDom();
}