]> git.cworth.org Git - lmno-server/blob - game.js
Plumb a game's ID value down into the base class
[lmno-server] / game.js
1 /* Base class providing common code for game engine implementations. */
2 class Game {
3   constructor(id) {
4     this.id = id;
5     this.clients = [];
6     this.next_client_id = 1;
7   }
8
9   /* Suport for game meta-data.
10    *
11    * What we want here is an effectively static field that is
12    * accessible through either the class name (SomeGame.meta) or an
13    * instance (some_game.meta). To pull this off we do keep two copies
14    * of the data. But the game classes can just set SomeGame.meta once
15    * and then reference it either way.
16    */
17   static set meta(data) {
18     /* This allows class access (SomeGame.meta) via the get method below. */
19     this._meta = data;
20
21     /* While this allows access via an instance (some_game.meta). */
22     this.prototype.meta = data;
23   }
24
25   static get meta() {
26     return this._meta;
27   }
28
29   add_client(response) {
30     const id = this.next_client_id;
31     this.clients.push({id: id,
32                        response: response});
33     this.next_client_id++;
34
35     return id;
36   }
37
38   remove_client(id) {
39     this.clients = this.clients.filter(client => client.id !== id);
40   }
41
42   /* Send a string to all clients */
43   broadcast_string(str) {
44     this.clients.forEach(client => client.response.write(str + '\n'));
45   }
46
47   /* Send an event to all clients.
48    *
49    * An event has both a declared type and a separate data block.
50    * It also ends with two newlines (to mark the end of the event).
51    */
52   broadcast_event(type, data) {
53     this.broadcast_string(`event: ${type}\ndata: ${data}\n`);
54   }
55
56   handle_events(request, response) {
57     /* These headers will keep the connection open so we can stream events. */
58     const headers = {
59       "Content-type": "text/event-stream",
60       "Connection": "keep-alive",
61       "Cache-Control": "no-cache"
62     };
63     response.writeHead(200, headers);
64
65     /* Add this new client to our list of clients. */
66     const id = this.add_client(response);
67
68     /* And queue up cleanup to be triggered on client close. */
69     request.on('close', () => {
70       this.remove_client(id);
71     });
72   }
73
74 }
75
76 module.exports = Game;