]> git.cworth.org Git - lmno.games/blob - empires/game.js
Removing a debugging statement
[lmno.games] / empires / game.js
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.
5  *
6  * That is, if the current path is:
7  *
8  *      https://lmno.games/empires/WXYZ/
9  *
10  * Then a path of "register" goes to:
11  *
12  *      https://lmno.games/empires/WXYZ/register
13  *
14  * Just as we want. But if the current path happens to be:
15  *
16  *      https://lmno.games/empires/WXYZ
17  *
18  * Then a path of "register" goes to:
19  *
20  *      https://lmno.games/empires/register
21  *
22  * Which cannot work since we have lost the game ID in the path.
23  *
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
27  * either way.
28  */
29 function GAME_API(endpoint) {
30   var path = window.location.pathname;
31   if (! path.endsWith('/'));
32       path += '/';
33   path += endpoint;
34   return path;
35 }
36
37 var state = {
38   spectator_id: undefined,
39   spectators: [],
40   players: []
41 };
42
43 function undisplay(element) {
44   element.style.display="none";
45 }
46
47 function add_message(severity, message) {
48   message = `<div class="message ${severity}" onclick="undisplay(this)">
49 ${message}
50 <span class="hide-button" onclick="undisplay(this.parentElement)">&times</span>
51 </div>`;
52   const message_area = document.getElementById('message-area');
53   message_area.insertAdjacentHTML('beforeend', message);
54 }
55
56 function register(form) {
57   const spectator_req = new XMLHttpRequest();
58
59   /* Before registering as a player, first remove us as a spectator. */
60   spectator_req.open("DELETE", GAME_API("spectator/") + state.spectator_id);
61   spectator_req.send();
62
63   const register_req = new XMLHttpRequest();
64
65   register_req.open("POST", GAME_API("register"));
66   register_req.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
67   var data = {
68     "character": form.character.value
69   };
70   register_req.send(JSON.stringify(data));
71
72   form.reset();
73 }
74
75 function toggle_host_tools() {
76   const host_tools = document.getElementById("host-tools");
77
78   if (host_tools.style.display === "block")
79     host_tools.style.display = "none";
80   else
81     host_tools.style.display = "block";
82 }
83
84 function post_reveal() {
85   const request = new XMLHttpRequest();
86
87   request.open("POST", GAME_API("reveal"));
88   request.send();
89 }
90
91 function post_start() {
92   const request = new XMLHttpRequest();
93
94   request.open("POST", GAME_API("start"));
95   request.send();
96 }
97
98 function post_reset() {
99   const request = new XMLHttpRequest();
100
101   request.open("POST", GAME_API("reset"));
102   request.send();
103 }
104
105 const events = new EventSource(GAME_API("events"));
106
107 events.onerror = function(event) {
108   if (event.target.readyState === EventSource.CLOSED) {
109       add_message("danger", "Connection to server lost.");
110   }
111 };
112
113 events.addEventListener("spectators", function(event) {
114   const spectators_div = document.getElementById("spectators-div");
115   const spectators_element = document.getElementById("spectators");
116   const spectators = JSON.parse(event.data);
117
118   spectators_element.innerHTML = '';
119   for (const spectator of spectators) {
120     var li = document.createElement('li');
121     li.id = "spectator-" + spectator.id;
122     li.innerText = spectator.name;
123     spectators_element.appendChild(li);
124   }
125
126   /* Force players list to be visible. */
127   spectators_div.style.display = "block";
128 });
129
130 events.addEventListener("spectator-join", function(event) {
131   const spectators_div = document.getElementById("spectators-div");
132   const spectators = document.getElementById("spectators");
133   const spectator = JSON.parse(event.data);
134
135   const li = document.createElement('li');
136   li.id = "spectator-" + spectator.id;
137   li.innerText = spectator.name;
138   spectators.appendChild(li);
139
140   /* Force spectators list to be visible. */
141   spectators_div.style.display = "block";
142 });
143
144 events.addEventListener("spectator-leave", function(event) {
145   const spectators = document.getElementById("spectators");
146   const id = JSON.parse(event.data);
147   const spectator = document.getElementById("spectator-" + id.id);
148
149   spectators.removeChild(spectator);
150 });
151
152 events.addEventListener("players", function(event) {
153   const players_div = document.getElementById("players-div");
154   const players_element = document.getElementById("players");
155   const players = JSON.parse(event.data);
156
157   players_element.innerHTML = '';
158   for (const player of players) {
159     var li = document.createElement('li');
160     li.id = "player-" + player.id;
161     li.innerText = player.name;
162     players_element.appendChild(li);
163   }
164
165   /* Force players list to be visible. */
166   players_div.style.display = "block";
167 });
168
169 events.addEventListener("player-join", function(event) {
170   const players_div = document.getElementById("players-div");
171   const players = document.getElementById("players");
172   const player = JSON.parse(event.data);
173
174   const li = document.createElement('li');
175   li.id = "player-" + player.id;
176   li.innerText = player.name;
177   players.appendChild(li);
178
179   /* Force players list to be visible. */
180   players_div.style.display = "block";
181 });
182
183 events.addEventListener("player-leave", function(event) {
184   const players = document.getElementById("players");
185   const id = JSON.parse(event.data);
186   const player = document.getElementById("player-" + id.id);
187
188   add_message("info", player.innerText + " has left the game.");
189   players.removeChild(player);
190 });
191
192 function spectator_on_load() {
193   state.spectator_id = JSON.parse(this.response);
194 }
195
196 events.addEventListener("game-phase", function(event) {
197   const data = JSON.parse(event.data);
198   const old_phase = data.old_phase;
199   const new_phase = data.new_phase;
200
201   const hide_selector = ".show-phase-" +old_phase+ ",.hide-phase-" +new_phase;
202   const show_selector = ".hide-phase-" +old_phase+ ",.show-phase-" +new_phase;
203
204   /* Hide all elements based on the phase transition. */
205   var elts = document.querySelectorAll(hide_selector);
206   for (const elt of elts) {
207     elt.style.display = "none";
208   }
209
210   /* And show all elements based on the same phase transition. */
211   elts = document.querySelectorAll(show_selector);
212   for (const elt of elts) {
213     elt.style.display = "block";
214   }
215
216   /* Whenever the game enters the "join" phase, add ourselves as a spectator. */
217   if (new_phase === "join") {
218     const request = new XMLHttpRequest();
219
220     request.addEventListener("load", spectator_on_load);
221     request.open("POST", GAME_API("spectator"));
222     request.send();
223   }
224 });
225
226 events.addEventListener("character-reveal", function(event) {
227   const data = JSON.parse(event.data);
228   const character_name = data.character;
229
230   const character = document.getElementById("character-reveal");
231
232   character.innerText = character_name;
233 });
234
235 events.addEventListener("capture", function(event_string) {
236   const players = document.getElementById("players");
237   const event = JSON.parse(event_string.data);
238   const player = document.getElementById("player-" + event.captee);
239
240   players.removeChild(player);
241 });