1 /* Construction of Game API endpoint paths. Logically all endpoints
2 * are just local resources underneath the current path, but just
3 * referring to them by a local name only works if the current path
4 * has a trailing slash.
6 * That is, if the current path is:
8 * https://lmno.games/empires/WXYZ/
10 * Then a path of "register" goes to:
12 * https://lmno.games/empires/WXYZ/register
14 * Just as we want. But if the current path happens to be:
16 * https://lmno.games/empires/WXYZ
18 * Then a path of "register" goes to:
20 * https://lmno.games/empires/register
22 * Which cannot work since we have lost the game ID in the path.
24 * Of course, we would like to have canonical URLs for the game (with
25 * the trailing slash) but since that depends on macehinery outside
26 * the scope of this file, let's construct API paths that will work
29 function GAME_API(endpoint) {
30 var path = window.location.pathname;
31 if (! path.endsWith('/'));
37 function undisplay(element) {
38 element.style.display="none";
41 function add_message(severity, message) {
42 message = `<div class="message ${severity}" onclick="undisplay(this)">
44 <span class="hide-button" onclick="undisplay(this.parentElement)">×</span>
46 const message_area = document.getElementById('message-area');
47 message_area.insertAdjacentHTML('beforeend', message);
50 function register(form) {
51 var request = new XMLHttpRequest();
53 request.open("POST", GAME_API("register"));
54 request.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
56 "character": form.character.value
58 request.send(JSON.stringify(data));
63 function toggle_host_tools() {
64 const host_tools = document.getElementById("host-tools");
66 console.log("Toggling, host_tools.style.display is '" + host_tools.style.display + "'");
68 if (host_tools.style.display === "block")
69 host_tools.style.display = "none";
71 host_tools.style.display = "block";
74 function post_reveal() {
75 const request = new XMLHttpRequest();
77 request.open("POST", GAME_API("reveal"));
81 function post_start() {
82 const request = new XMLHttpRequest();
84 request.open("POST", GAME_API("start"));
88 function post_reset() {
89 const request = new XMLHttpRequest();
91 request.open("POST", GAME_API("reset"));
95 const events = new EventSource(GAME_API("events"));
97 events.onerror = function(event) {
98 if (event.target.readyState === EventSource.CLOSED) {
99 add_message("danger", "Connection to server lost.");
103 events.addEventListener("players", function(event) {
104 const players_div = document.getElementById("players-div");
105 const players_element = document.getElementById("players");
106 const players = JSON.parse(event.data);
108 players_element.innerHTML = '';
109 for (const player of players) {
110 var li = document.createElement('li');
111 li.id = "player-" + player.id;
112 li.innerText = player.name;
113 players_element.appendChild(li);
116 /* Force players list to be visible. */
117 players_div.style.display = "block";
120 events.addEventListener("player-join", function(event) {
121 const players_div = document.getElementById("players-div");
122 const players = document.getElementById("players");
123 const player = JSON.parse(event.data);
125 const li = document.createElement('li');
126 li.id = "player-" + player.id;
127 li.innerText = player.name;
128 players.appendChild(li);
130 /* Force players list to be visible. */
131 players_div.style.display = "block";
134 events.addEventListener("player-leave", function(event) {
135 const players = document.getElementById("players");
136 const id = JSON.parse(event.data);
137 const player = document.getElementById("player-" + id.id);
139 add_message("info", player.innerText + " has left the game.");
140 players.removeChild(player);
143 events.addEventListener("game-state", function(event) {
144 const data = JSON.parse(event.data);
145 const old_state = data.old_state;
146 const new_state = data.new_state;
148 const hide_selector = ".show-state-" +old_state+ ",.hide-state-" +new_state;
149 const show_selector = ".hide-state-" +old_state+ ",.show-state-" +new_state;
151 /* Hide all elements based on the state transition. */
152 var elts = document.querySelectorAll(hide_selector);
153 for (const elt of elts) {
154 elt.style.display = "none";
157 /* And show all elements based on the same state transition. */
158 elts = document.querySelectorAll(show_selector);
159 for (const elt of elts) {
160 elt.style.display = "block";
164 events.addEventListener("character-reveal", function(event) {
165 const data = JSON.parse(event.data);
166 const character_name = data.character;
168 const character = document.getElementById("character-reveal");
170 character.innerText = character_name;
173 events.addEventListener("capture", function(event_string) {
174 const players = document.getElementById("players");
175 const event = JSON.parse(event_string.data);
176 const player = document.getElementById("player-" + event.captee);
178 players.removeChild(player);