172 lines
4.6 KiB
JavaScript
172 lines
4.6 KiB
JavaScript
if (typeof FAIRHOPPER_WS_SERVER === "undefined") {
|
|
var FAIRHOPPER_WS_SERVER = "ws://127.0.0.1:8011";
|
|
}
|
|
|
|
let ws = null;
|
|
let playerOnDestinationModal = null;
|
|
|
|
const BOARD_ICONS = {
|
|
PLAYER: "😀",
|
|
PLAYER_ON_DESTINATION: "😎",
|
|
OBSTACLE: "🔥",
|
|
DESTINATION: "🏠",
|
|
};
|
|
|
|
function createBoard(board) {
|
|
let html = "";
|
|
for (let y = 0; y < board.height; y++) {
|
|
let colHtml = "";
|
|
for (let x = 0; x < board.width; x++) {
|
|
colHtml += `<div class="cell" id="cell-${x}-${y}"> </div>`;
|
|
}
|
|
html += `
|
|
<div class="flex-grid">
|
|
${colHtml}
|
|
</div>
|
|
`;
|
|
}
|
|
document.getElementById("board-content").innerHTML = html;
|
|
}
|
|
|
|
function findCell(position) {
|
|
return document.getElementById(`cell-${position.x}-${position.y}`);
|
|
}
|
|
|
|
function renderCellContent(position, content) {
|
|
const cell = findCell(position);
|
|
if (cell) {
|
|
cell.innerText = content;
|
|
}
|
|
}
|
|
|
|
function renderPlayerList(players) {
|
|
document.getElementById("players-content").innerHTML = players
|
|
.filter((player) => player.active)
|
|
.map((player) => {
|
|
const onDestination = player.state === "ON_DESTINATION";
|
|
return `
|
|
<li class="${onDestination ? "text-success" : ""}">
|
|
${player.name} (${player.move_count})
|
|
${onDestination ? "✅" : ""}
|
|
</li>
|
|
`;
|
|
})
|
|
.join("");
|
|
}
|
|
|
|
function renderPlayers(players) {
|
|
players
|
|
.filter((player) => player.active)
|
|
.forEach((player) => {
|
|
const cell = findCell(player.position);
|
|
const onDestination = player.state === "ON_DESTINATION";
|
|
const playerIcon = onDestination ? BOARD_ICONS.PLAYER_ON_DESTINATION : BOARD_ICONS.PLAYER;
|
|
if (cell) {
|
|
cell.innerHTML = `
|
|
<div class="player-tooltip">${player.name}</div>
|
|
${playerIcon}
|
|
`;
|
|
}
|
|
});
|
|
}
|
|
|
|
function getLayerObjectsOfType(layers, type) {
|
|
let objects = [];
|
|
layers.forEach((layer) => {
|
|
objects = objects.concat(layer.objects.filter((obj) => obj.type === type));
|
|
});
|
|
return objects;
|
|
}
|
|
|
|
function renderObstacles(layers) {
|
|
const objects = getLayerObjectsOfType(layers, "OBSTACLE");
|
|
objects.forEach((obj) => {
|
|
renderCellContent(obj.position, BOARD_ICONS.OBSTACLE);
|
|
});
|
|
}
|
|
|
|
function renderDestination(position) {
|
|
renderCellContent(position, BOARD_ICONS.DESTINATION);
|
|
}
|
|
|
|
function renderGameDump(data) {
|
|
createBoard(data.board);
|
|
renderObstacles(data.layers);
|
|
renderDestination(data.destination.position);
|
|
renderPlayerList(data.players);
|
|
renderPlayers(data.players);
|
|
}
|
|
|
|
function playerReachedDestination(data) {
|
|
const dlgElement = document.getElementById("player-on-destination-modal");
|
|
dlgElement.querySelector(".player-name").textContent = data.player.name;
|
|
dlgElement.querySelector(".move-count").textContent = data.player.move_count;
|
|
playerOnDestinationModal.show();
|
|
}
|
|
|
|
function productSelectionDone() {
|
|
playerOnDestinationModal.hide();
|
|
}
|
|
|
|
function wsConnect() {
|
|
console.log("Attempting to connect to", FAIRHOPPER_WS_SERVER);
|
|
ws = new WebSocket(FAIRHOPPER_WS_SERVER);
|
|
|
|
ws.onopen = () => {
|
|
console.log("WS connected");
|
|
};
|
|
|
|
ws.onmessage = (e) => {
|
|
const wsMessage = JSON.parse(e.data);
|
|
console.log("WS message received:", wsMessage);
|
|
|
|
switch (wsMessage.message) {
|
|
case "game_dump":
|
|
renderGameDump(wsMessage.data);
|
|
break;
|
|
case "player_reached_destination":
|
|
playerReachedDestination(wsMessage.data);
|
|
break;
|
|
case "product_selection_done":
|
|
productSelectionDone();
|
|
break;
|
|
default:
|
|
console.error("Unknown message:", wsMessage);
|
|
}
|
|
};
|
|
|
|
ws.onclose = (e) => {
|
|
ws = null;
|
|
setTimeout(() => {
|
|
wsConnect();
|
|
}, 1000);
|
|
};
|
|
|
|
ws.onerror = (err) => {
|
|
console.error("Socket encountered error:", err.message, "Closing socket");
|
|
ws.close();
|
|
};
|
|
}
|
|
|
|
function finishProductSelection() {
|
|
if (!ws) {
|
|
return;
|
|
}
|
|
const wsMessage = {
|
|
message: "product_selection_done",
|
|
data: null,
|
|
};
|
|
ws.send(JSON.stringify(wsMessage));
|
|
}
|
|
|
|
window.onload = () => {
|
|
const dlgElement = document.getElementById("player-on-destination-modal");
|
|
playerOnDestinationModal = new bootstrap.Modal(dlgElement);
|
|
|
|
document.getElementById("finish-product-selection").onclick = () => {
|
|
finishProductSelection();
|
|
};
|
|
|
|
wsConnect();
|
|
};
|