/* Construction of Game API endpoint paths. Logically all endpoints * are just local resources underneath the current path, but just * referring to them by a local name only works if the current path * has a trailing slash. * * That is, if the current path is: * * https://lmno.games/empires/WXYZ/ * * Then a path of "register" goes to: * * https://lmno.games/empires/WXYZ/register * * Just as we want. But if the current path happens to be: * * https://lmno.games/empires/WXYZ * * Then a path of "register" goes to: * * https://lmno.games/empires/register * * Which cannot work since we have lost the game ID in the path. * * Of course, we would like to have canonical URLs for the game (with * the trailing slash) but since that depends on macehinery outside * the scope of this file, let's construct API paths that will work * either way. */ function GAME_API(endpoint) { var path = window.location.pathname; if (! path.endsWith('/')); path += '/'; path += endpoint; return path; } function undisplay(element) { element.style.display="none"; } function add_message(severity, message) { message = `
${message} ×
`; const message_area = document.getElementById('message-area'); message_area.insertAdjacentHTML('beforeend', message); } function register(form) { var request = new XMLHttpRequest(); request.open("POST", GAME_API("register")); request.setRequestHeader("Content-Type", "application/json; charset=UTF-8"); var data = { "character": form.character.value }; request.send(JSON.stringify(data)); form.reset(); } function toggle_host_tools() { const host_tools = document.getElementById("host-tools"); console.log("Toggling, host_tools.style.display is '" + host_tools.style.display + "'"); if (host_tools.style.display === "block") host_tools.style.display = "none"; else host_tools.style.display = "block"; } function post_reveal() { const request = new XMLHttpRequest(); request.open("POST", GAME_API("reveal")); request.send(); } function post_start() { const request = new XMLHttpRequest(); request.open("POST", GAME_API("start")); request.send(); } function post_reset() { const request = new XMLHttpRequest(); request.open("POST", GAME_API("reset")); request.send(); } const events = new EventSource(GAME_API("events")); events.onerror = function(event) { if (event.target.readyState === EventSource.CLOSED) { add_message("danger", "Connection to server lost."); } }; events.addEventListener("players", function(event) { const players_div = document.getElementById("players-div"); const players_element = document.getElementById("players"); const players = JSON.parse(event.data); players_element.innerHTML = ''; for (const player of players) { var li = document.createElement('li'); li.id = "player-" + player.id; li.innerText = player.name; players_element.appendChild(li); } /* Force players list to be visible. */ players_div.style.display = "block"; }); events.addEventListener("player-join", function(event) { const players_div = document.getElementById("players-div"); const players = document.getElementById("players"); const player = JSON.parse(event.data); const li = document.createElement('li'); li.id = "player-" + player.id; li.innerText = player.name; players.appendChild(li); /* Force players list to be visible. */ players_div.style.display = "block"; }); events.addEventListener("player-leave", function(event) { const players = document.getElementById("players"); const id = JSON.parse(event.data); const player = document.getElementById("player-" + id.id); add_message("info", player.innerText + " has left the game."); players.removeChild(player); }); events.addEventListener("game-state", function(event) { const data = JSON.parse(event.data); const old_state = data.old_state; const new_state = data.new_state; const hide_selector = ".show-state-" +old_state+ ",.hide-state-" +new_state; const show_selector = ".hide-state-" +old_state+ ",.show-state-" +new_state; /* Hide all elements based on the state transition. */ var elts = document.querySelectorAll(hide_selector); for (const elt of elts) { elt.style.display = "none"; } /* And show all elements based on the same state transition. */ elts = document.querySelectorAll(show_selector); for (const elt of elts) { elt.style.display = "block"; } }); events.addEventListener("character-reveal", function(event) { const data = JSON.parse(event.data); const character_name = data.character; const character = document.getElementById("character-reveal"); character.innerText = character_name; }); events.addEventListener("capture", function(event_string) { const players = document.getElementById("players"); const event = JSON.parse(event_string.data); const player = document.getElementById("player-" + event.captee); players.removeChild(player); });