]> git.cworth.org Git - empires-server/blobdiff - empires.js
Rename "app" to "router" within each game engine
[empires-server] / empires.js
index 69fc7c233a64c146b40cff97bb6826cb3e01be29..7907ce0c80a7711d4c92044f7391298156c2a664 100644 (file)
@@ -1,12 +1,6 @@
 const express = require("express");
-const cors = require("cors");
-const body_parser = require("body-parser");
-const path = require("path");
 
-const app = express();
-app.use(cors());
-app.use(body_parser.urlencoded({ extended: false }));
-app.use(body_parser.json());
+const router = express.Router();
 
 const GameState = {
   JOIN:    1,
@@ -38,9 +32,11 @@ function shuffle(a) {
 
 class Game {
   constructor() {
+    this._spectators = [];
+    this.next_spectator_id = 1;
     this._players = [];
-    this.characters_to_reveal = null;
     this.next_player_id = 1;
+    this.characters_to_reveal = null;
     this.clients = [];
     this.next_client_id = 1;
     this.state = GameState.JOIN;
@@ -49,6 +45,31 @@ class Game {
     setInterval(() => {this.broadcast_string(":");}, 15000);
   }
 
+  add_spectator(name, session_id) {
+    /* Don't add another spectator that matches an existing session. */
+    const existing = this._spectators.findIndex(
+      spectator => spectator.session_id === session_id);
+    if (existing >= 0)
+      return existing.id;
+
+    const new_spectator = {id: this.next_spectator_id,
+                           name: name,
+                           session_id: session_id
+                          };
+    this._spectators.push(new_spectator);
+    this.next_spectator_id++;
+    this.broadcast_event("spectator-join", JSON.stringify(new_spectator));
+
+    return new_spectator.id;
+  }
+
+  remove_spectator(id) {
+    const index = this._spectators.findIndex(spectator => spectator.id === id);
+    this._spectators.splice(index, 1);
+
+    this.broadcast_event("spectator-leave", `{"id": ${id}}`);
+  }
+
   add_player(name, character) {
     const new_player = {id: this.next_player_id,
                        name: name,
@@ -78,6 +99,7 @@ class Game {
 
     this.change_state(GameState.JOIN);
 
+    this.broadcast_event("spectators", "{}");
     this.broadcast_event("players", "{}");
   }
 
@@ -149,6 +171,14 @@ class Game {
     return this._players.map(player => ({id: player.id, captures: player.captures}));
   }
 
+  get spectators() {
+    /* We return only "id" and "name" here (specifically not session_id!). */
+    return this._spectators.map(spectator => ({
+      id: spectator.id,
+      name: spectator.name
+    }));
+  }
+
   get players() {
     return this._players.map(player => ({id: player.id, name: player.name }));
   }
@@ -221,7 +251,13 @@ function handle_events(request, response) {
   response.writeHead(200, headers);
 
   /* Now that a client has connected, first we need to stream all of
-   * the existing players (if any). */
+   * the existing spectators and players (if any). */
+  if (game._spectators.length > 0) {
+    const spectators_json = JSON.stringify(game.spectators);
+    const spectators_data = `event: spectators\ndata: ${spectators_json}\n\n`;
+    response.write(spectators_data);
+  }
+
   if (game._players.length > 0) {
     const players_json = JSON.stringify(game.players);
     const players_data = `event: players\ndata: ${players_json}\n\n`;
@@ -249,74 +285,107 @@ function handle_events(request, response) {
   });
 }
 
-app.get('/', (request, response) => {
-  response.sendFile(path.join(__dirname, './game.html'));
+router.get('/', (request, response) => {
+  if (! request.session.nickname)
+    response.render('choose-nickname.html', { game_name: "Empires" });
+  else
+    response.render('empires-game.html');
 });
 
-app.post('/register', (request, response) => {
+router.post('/spectator', (request, response) => {
   const game = request.game;
-  game.add_player(request.body.name, request.body.character);
+  var name = request.session.nickname;
+
+  /* If the request includes a name, that overrides the session nickname. */
+  if (request.body.name)
+    name = request.body.name;
+
+  const id = game.add_spectator(name, request.session.id);
+  response.send(JSON.stringify(id));
+});
+
+router.delete('/spectator/:id', (request, response) => {
+  const game = request.game;
+  game.remove_spectator(parseInt(request.params.id));
+  response.send();
+});
+
+router.post('/register', (request, response) => {
+  const game = request.game;
+  var name = request.session.nickname;;
+
+  /* If the request includes a name, that overrides the session nickname. */
+  if (request.body.name)
+    name = request.body.name;
+
+  game.add_player(name, request.body.character);
   response.send();
 });
 
-app.post('/deregister/:id', (request, response) => {
+router.post('/deregister/:id', (request, response) => {
   const game = request.game;
   game.remove_player(parseInt(request.params.id));
   response.send();
 });
 
-app.post('/reveal', (request, response) => {
+router.post('/reveal', (request, response) => {
   const game = request.game;
   game.reveal();
   response.send();
 });
 
-app.post('/start', (request, response) => {
+router.post('/start', (request, response) => {
   const game = request.game;
   game.start();
   response.send();
 });
 
-app.post('/reset', (request, response) => {
+router.post('/reset', (request, response) => {
   const game = request.game;
   game.reset();
   response.send();
 });
 
-app.post('/capture/:captor/:captee', (request, response) => {
+router.post('/capture/:captor/:captee', (request, response) => {
   const game = request.game;
   game.capture(parseInt(request.params.captor), parseInt(request.params.captee));
   response.send();
 });
 
-app.post('/liberate/:id', (request, response) => {
+router.post('/liberate/:id', (request, response) => {
   const game = request.game;
   game.liberate(parseInt(request.params.id));
   response.send();
 });
 
-app.post('/restart', (request, response) => {
+router.post('/restart', (request, response) => {
   const game = request.game;
   game.restart(parseInt(request.params.id));
     response.send();
 });
 
-app.get('/characters', (request, response) => {
+router.get('/characters', (request, response) => {
   const game = request.game;
   response.send(game.characters);
 });
 
-app.get('/empires', (request, response) => {
+router.get('/empires', (request, response) => {
   const game = request.game;
   response.send(game.empires);
 });
 
-app.get('/players', (request, response) => {
+router.get('/spectators', (request, response) => {
+  const game = request.game;
+  response.send(game.spectators);
+});
+
+router.get('/players', (request, response) => {
   const game = request.game;
   response.send(game.players);
 });
 
-app.get('/events', handle_events);
+router.get('/events', handle_events);
 
-exports.app = app;
+exports.router = router;
+exports.name = "empires";
 exports.Game = Game;