]> git.cworth.org Git - empires-server/commitdiff
Incorporate empires.js as a sub-app within lmno.js
authorCarl Worth <cworth@cworth.org>
Sun, 17 May 2020 19:40:44 +0000 (12:40 -0700)
committerCarl Worth <cworth@cworth.org>
Sun, 17 May 2020 22:36:18 +0000 (15:36 -0700)
Now, instead of calling listen() the empires.js simply exports its app
object so that the higher level lmno server can mount all of its
available paths with app.use('/empires/<GAMEID>/', empires.app).

At the same time, empires.js no longer constructs a Game object, but
instead the higher-level /new API within lmno.js calls into
empires.Game to create a game for a specific ID. Then, there's also a
new middleware in lmno.js to lookup this game object by the ID from
the path and add it as a property of the request object. So all of the
empires.js entry points now fetch that game object from the request as
their first statement.

empires.js
lmno.js

index b744f0faa2e0cc68a8d90963055e1a64a8b7b3ab..20dfa78d2102e6e1fe0d3b77bc23eb6cba729b30 100644 (file)
@@ -207,12 +207,11 @@ class Game {
   }
 }
 
-const game = new Game();
-
 app.use(body_parser.urlencoded({ extended: false }));
 app.use(body_parser.json());
 
 function handle_events(request, response) {
+  const game = request.game;
   /* These headers will keep the connection open so we can stream events. */
   const headers = {
     "Content-type": "text/event-stream",
@@ -251,59 +250,69 @@ function handle_events(request, response) {
 }
 
 app.post('/register', (request, response) => {
+  const game = request.game;
   game.add_player(request.body.name, request.body.character);
   response.send();
 });
 
 app.post('/deregister/:id', (request, response) => {
+  const game = request.game;
   game.remove_player(parseInt(request.params.id));
   response.send();
 });
 
 app.post('/reveal', (request, response) => {
+  const game = request.game;
   game.reveal();
   response.send();
 });
 
 app.post('/start', (request, response) => {
+  const game = request.game;
   game.start();
   response.send();
 });
 
 app.post('/reset', (request, response) => {
+  const game = request.game;
   game.reset();
   response.send();
 });
 
 app.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) => {
+  const game = request.game;
   game.liberate(parseInt(request.params.id));
   response.send();
 });
 
 app.post('/restart', (request, response) => {
+  const game = request.game;
   game.restart(parseInt(request.params.id));
     response.send();
 });
 
 app.get('/characters', (request, response) => {
+  const game = request.game;
   response.send(game.characters);
 });
 
 app.get('/empires', (request, response) => {
+  const game = request.game;
   response.send(game.empires);
 });
 
 app.get('/players', (request, response) => {
+  const game = request.game;
   response.send(game.players);
 });
 
 app.get('/events', handle_events);
 
-app.listen(3000, function () {
-  console.log('Empires server listening on localhost:3000');
-});
+exports.app = app;
+exports.Game = Game;
diff --git a/lmno.js b/lmno.js
index dc23fc2556651626905bae6f10a47cf5fe227c3f..f79da3afd653cf1d7b89219aada1546d97aff036 100644 (file)
--- a/lmno.js
+++ b/lmno.js
@@ -5,6 +5,9 @@ const body_parser = require("body-parser");
 const app = express();
 app.use(cors());
 
+/* Load each of our game mini-apps. */
+var empires = require("./empires");
+
 class LMNO {
   constructor() {
     this.ids = {};
@@ -19,14 +22,15 @@ class LMNO {
       var id = this.generate_id();
     } while (id in this.ids);
 
-    const game = {
+    const game = new empires.Game();
+
+    this.ids[id] = {
        id: id,
        engine: engine,
+       game: game
     };
 
-    this.ids[id] = game;
-
-    return game;
+    return id;
   }
 }
 
@@ -44,10 +48,40 @@ const lmno = new LMNO();
 
 app.post('/new/:game_engine', (request, response) =>  {
   const game_engine = request.params.game_engine;
-  const game = lmno.create_game(game_engine);
-  response.send(JSON.stringify(game.id));
+  const game_id = lmno.create_game(game_engine);
+  response.send(JSON.stringify(game_id));
 });
 
+/* Redirect any requests to a game ID at the top-level.
+ *
+ * Specifically, after obtaining the game ID (from the path) we simply
+ * lookup the game engine for the corresponding game and then redirect
+ * to the engine- and game-specific path.
+ */
+app.get('/[a-zA-Z0-9]{4}', (request, response) => {
+  const game_id = request.path.replace(/\//g, "");
+
+  const game = lmno.ids[game_id];
+  if (game === undefined) {
+      response.sendStatus(404);
+      return;
+  }
+  response.redirect(301, `/${game.engine}/${game.id}/`);
+});
+
+/* LMNO middleware to lookup the game. */
+app.use('/empires/:game_id([a-zA-Z0-9]{4})', (request, response, next) => {
+  request.game = lmno.ids[request.params.game_id].game;
+  if (request.game === undefined) {
+    response.sendStatus(404);
+    return;
+  }
+  next();
+});
+
+/* Mount sub apps. only _after_ we have done all the middleware we need. */
+app.use('/empires/[a-zA-Z0-9]{4}/', empires.app);
+
 app.listen(4000, function () {
   console.log('LMNO server listening on localhost:4000');
 });