1 /* Base class providing common code for game engine implementations. */
6 this.next_client_id = 1;
8 /* Send a comment to every connected client every 15 seconds. */
9 setInterval(() => {this.broadcast_string(":");}, 15000);
12 /* Suport for game meta-data.
14 * What we want here is an effectively static field that is
15 * accessible through either the class name (SomeGame.meta) or an
16 * instance (some_game.meta). To pull this off we do keep two copies
17 * of the data. But the game classes can just set SomeGame.meta once
18 * and then reference it either way.
20 static set meta(data) {
21 /* This allows class access (SomeGame.meta) via the get method below. */
24 /* While this allows access via an instance (some_game.meta). */
25 this.prototype.meta = data;
32 add_client(response) {
33 const id = this.next_client_id;
34 this.clients.push({id: id,
36 this.next_client_id++;
42 this.clients = this.clients.filter(client => client.id !== id);
45 /* Send a string to all clients */
46 broadcast_string(str) {
47 this.clients.forEach(client => client.response.write(str + '\n'));
50 /* Send an event to all clients.
52 * An event has both a declared type and a separate data block.
53 * It also ends with two newlines (to mark the end of the event).
55 broadcast_event(type, data) {
56 this.broadcast_string(`event: ${type}\ndata: ${data}\n`);
59 handle_events(request, response) {
60 /* These headers will keep the connection open so we can stream events. */
62 "Content-type": "text/event-stream",
63 "Connection": "keep-alive",
64 "Cache-Control": "no-cache"
66 response.writeHead(200, headers);
68 /* Add this new client to our list of clients. */
69 const id = this.add_client(response);
71 /* And queue up cleanup to be triggered on client close. */
72 request.on('close', () => {
73 this.remove_client(id);
76 /* Finally, if this game class has a "state" property, stream that
77 * current state to the client. */
79 const state_json = JSON.stringify(this.state);
80 response.write(`event: game-state\ndata: ${state_json}\n\n`);
84 broadcast_move(move) {
85 this.broadcast_event("move", move);
90 module.exports = Game;