]> git.cworth.org Git - empires-server/log
empires-server
3 years agolmno: Generalize the support for multiple game engines
Carl Worth [Wed, 27 May 2020 03:57:27 +0000 (20:57 -0700)]
lmno: Generalize the support for multiple game engines

Rather than having repeated lists of the engines, we have one list at
the top of the file and then use that list to iterate over all engines
to mount their sub-apps at a path that is named by engine.name.

We also fix the construction of the Game class to use an imported
constructor (so that each game engine has objects of its own class
instead of only having games constructed via empires.Game()
exclusively).

3 years agoEnsure path ending with game ID always has a trailing slash
Carl Worth [Wed, 27 May 2020 03:43:58 +0000 (20:43 -0700)]
Ensure path ending with game ID always has a trailing slash

The trailing slash is essential here so that when JavaScript code
executing in the user agent accesses a relative resource, it is a
child of the game ID rather than a peer.

That is, from https://lmno.games/empires/WLWV/ a reference to the
"players" resource is https://lmno.games/empires/WLVW/players
(But if we started with https://lmno.games/empires/WLWV we would
end up referencing https://lmno.games/empires/players which will
not work.)

Here, we were already doing a redirect in the case of needing to
canonize the game ID, so we simply need to also do that redirect even
if the game ID was already canonical but the trailing slash was
missing.

3 years agogenerate_id: Use Array.fill(null) to initialize an array of null values
Carl Worth [Wed, 27 May 2020 03:39:20 +0000 (20:39 -0700)]
generate_id: Use Array.fill(null) to initialize an array of null values

When I first wrote this code I reached for a construct of:

Array(4).map(...)

but I found that map doesn't work on an array of empty items like
this. To get things to work I instead used:

[null, null, null, null].map(...)

which did the trick, but only because I happened to be using a
sufficiently small size that it was reasonable to type the complete
literal. For this commit I've found a cleaner approach of:

Array(4).fill(null).map(...)

3 years agoAdd the barest template of an implementation of a tictactoe game
Carl Worth [Tue, 26 May 2020 03:36:09 +0000 (20:36 -0700)]
Add the barest template of an implementation of a tictactoe game

This supports only the ability to select a nickname (which is provided
by lmno.js), and then the serving of minimal HTML into which the
tictactoe React cient can render itself.

There is not yet here any implementation of API endpoints specific to
the tictactoe game. Those will have to come later. (So, for now, each
player that joins a game of Tic Tac Toe will have an independent game
without any communication between them.)

3 years agochoose-nickname: Make this page parameterizable
Carl Worth [Tue, 26 May 2020 03:34:02 +0000 (20:34 -0700)]
choose-nickname: Make this page parameterizable

Accepting in the template context the name of a game to be rendered.

This allows for the same choose-nickname template to be used for
several different games.

3 years agolmno: Generalize middleware to not be specific to empires
Carl Worth [Sun, 24 May 2020 20:39:01 +0000 (13:39 -0700)]
lmno: Generalize middleware to not be specific to empires

We're planning to extend LMNO past the original single game of Empires
soon. So, we adjust this middleware here to work for any game engine
prior to the game ID in the path, (and simply preserve that engine
string in the result of the redirect).

3 years agoempires: Implement support for spectators
Carl Worth [Sun, 24 May 2020 16:19:50 +0000 (09:19 -0700)]
empires: Implement support for spectators

These are much like players, but without a selected character, and
they are displayed separately in the game UI.

This brings us up to version 0.7 of the empires protocol in
lmno-api:empires.txt.

3 years agoFix viewport meta tag to use proper separators
Carl Worth [Sun, 24 May 2020 15:53:31 +0000 (08:53 -0700)]
Fix viewport meta tag to use proper separators

I have no idea where these semicolons came from. Thanks to the
chromium console for reporting that they should be commas instead.

3 years agoempires: Bring in game client code as a template
Carl Worth [Sat, 23 May 2020 23:34:20 +0000 (16:34 -0700)]
empires: Bring in game client code as a template

So far, this is identical to the static HTML file we were using
before, but the idea is that, here as a template, we can add some
dynamic elements, (such as the game ID).

3 years ago/register: Optionally use the session profile nickname for the player's name
Carl Worth [Sat, 23 May 2020 17:40:54 +0000 (10:40 -0700)]
/register: Optionally use the session profile nickname for the player's name

This allows a UI to set a nickname once in the profile and then send
only the character name in the /register action.

It's still supported to set the name in the /register action as well.

3 years agoempires: Add an initial "choose nickname" step before joining a game
Carl Worth [Sat, 23 May 2020 17:25:44 +0000 (10:25 -0700)]
empires: Add an initial "choose nickname" step before joining a game

This lodges the selected nickname in the current session, (using a new
/profile API also added in this commit).

Having the nickname stored in the session has the advantage that when
playing multiple games in a row, a player won't need to keep re-typing
their own name each time.

3 years ago/logout: Destroy the session object on logout
Carl Worth [Sat, 23 May 2020 17:24:16 +0000 (10:24 -0700)]
/logout: Destroy the session object on logout

This allows for using the /logout API to clear a session, (even if the
user hasn't authenticated at all).

3 years ago/admin: Switch to rendering via a template
Carl Worth [Sat, 23 May 2020 12:47:36 +0000 (05:47 -0700)]
/admin: Switch to rendering via a template

Thanks to the common code of base.html, this looks lovely and styled
(compared to the previous text/plain output) while not even being that
much code.

We also now display the IDs of all games as well as the names of each
player.

3 years agoRename the /stats page to /admin
Carl Worth [Sat, 23 May 2020 02:33:40 +0000 (19:33 -0700)]
Rename the /stats page to /admin

We're about to change this to not only report statistics, but to also
allow the admin to perform administrative functions (such as deleting
games). So give the page a better name for that.

3 years agoConvert rendering of login.html to use a nunjucks template
Carl Worth [Sat, 23 May 2020 02:29:33 +0000 (19:29 -0700)]
Convert rendering of login.html to use a nunjucks template

This new base.html template will allow us to avoid duplicating a bunch
of boilerplate as we start adding additional HTML pages.

Also, we pull the undisplay, add_message, lmno_login, and
lmno_login_loaded functions in instead of including the static
JavaScript file from /lmno.js.

This makes things much more independent here, (rather than relying on
JavaScript functions defined in a script file that is maintained in a
separate git repository: lmno.games).

3 years agoAdd dependency for nunjucks
Carl Worth [Sat, 23 May 2020 02:29:22 +0000 (19:29 -0700)]
Add dependency for nunjucks

This was with:

npm install nunjucks

The nunjucks module gives us templating along the lines of jinja2
(along with inherited templates that overwrite only selected blocks).

3 years agoempires: Pull the body_parser use statements up to the top of the file
Carl Worth [Thu, 21 May 2020 16:23:40 +0000 (09:23 -0700)]
empires: Pull the body_parser use statements up to the top of the file

Just keeping things organized by enabling all of our dependencies up
at the top of the file.

3 years agoAdd a simple /stats endpoint to get a count of current games in progress
Carl Worth [Thu, 21 May 2020 16:13:11 +0000 (09:13 -0700)]
Add a simple /stats endpoint to get a count of current games in progress

This view is particularly spartan so far, (just two lines of next, not
even HTML).

Most of the work in this commit is actually setting up the
authentication mechanism, since /stats is the first page we have that
requires a user to be authenticated (and to also have the "admin"
role).

We have a nice-looking "/login" page with proper styling and clean
messages for login failure. If an unauthenticated user goes to /stats
they will be sent to /login?next=/stats and after successfully
authenticating, will be sent back to /stats (this time getting the
spartan view of the game statistics).

There is another set of pages that is more minmal than we really
want. This is all in the area of user that successfully authenticates
but doesn't have the "admin" role. I'm ignoring all of these issues
for now because I'm not going to actually configure any such
users. But here are the issues:

  * If a user without the admin role hits /stats they they will get a
    correct 401 status, but a very spartan page (just the word
    "Unauthorized" as plain text).

  * In that case, if the user wants to logout there are no links
    provided to do that.

  * There _is_ a page at /logout which does do a correct logout, but
    again returns a very spartan, plain-text message that you are
    logged out.

3 years agoAdd a utility lmno-passwd.py
Carl Worth [Thu, 21 May 2020 14:11:53 +0000 (07:11 -0700)]
Add a utility lmno-passwd.py

This is a convenience to help the admin generate user entries for the
configuration that include correctly hashed passwords.

3 years agoAdd dependencies for the prompt-sync module
Carl Worth [Thu, 21 May 2020 14:11:07 +0000 (07:11 -0700)]
Add dependencies for the prompt-sync module

Generated with "npm install prompt-sync"

This is for getting user input for a password-hashing utility.

3 years agoAdd dependencies for bcrypt
Carl Worth [Thu, 21 May 2020 14:04:37 +0000 (07:04 -0700)]
Add dependencies for bcrypt

The contents of this commit were created by "npm install bcrypt"

3 years agoAvoid an undefined reference when handed an unknwown game ID
Carl Worth [Thu, 21 May 2020 03:33:27 +0000 (20:33 -0700)]
Avoid an undefined reference when handed an unknwown game ID

We're on our way to a clean 404 error, but we don't want to
hit a JavaScript error along the way.

3 years agoAdd simple session tracking
Carl Worth [Wed, 20 May 2020 23:56:43 +0000 (16:56 -0700)]
Add simple session tracking

By taking advantage of the express-session module.

Note that we're not actually using the session for anything yet, so we
haven't configured anything such as the expiration time or even which
backend should be used for storing the session data (meaning the
session data will just be stored in memory for now).

We do add the very beginnings of a configuration file here, which for
now simply has a "secret_session" key with the random data for the
session manager to use.

Also, we configure both the "resave" and the "saveUninitialized"
properties on the session object to avoid the warnings about the
deprecated values for these two properties.

3 years agoAdd "express-session" as a dependency
Carl Worth [Wed, 20 May 2020 23:55:11 +0000 (16:55 -0700)]
Add "express-session" as a dependency

This commit was entirely created by "npm install express-session"

This module will give us some middleware for doing server-based
sessions, (stored in a cookie in the client).

3 years agolmno: Be forgiving in game ID values received from the user
Carl Worth [Wed, 20 May 2020 02:10:27 +0000 (19:10 -0700)]
lmno: Be forgiving in game ID values received from the user

Most significantly, we now accept a lowercase version of the ID.

But also, game ID values are intentionally chosen not to have
ambiguous character in them, (such as "M"/"N" or "S"/"F"), which might
sound similar when someone says a game ID aloud. So on the input side
we accept either form and canonicalize to the only letter which can
possibly exist in a game ID.

3 years agoempires: Serve the actual game file from the root of the app
Carl Worth [Sun, 17 May 2020 21:45:34 +0000 (14:45 -0700)]
empires: Serve the actual game file from the root of the app

This game.html file is actually totally static, but it lives at a
dynamic path (which includes the game ID in the path), so within the
dynamic app we need to serve the static file. To arrange for this we
symlink to the static file. Note that we're not committing the symlink
to git since the destination location can differ on each system.

3 years agoIncorporate empires.js as a sub-app within lmno.js
Carl Worth [Sun, 17 May 2020 19:40:44 +0000 (12:40 -0700)]
Incorporate empires.js as a sub-app within lmno.js

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.

3 years agoRemove old placeholder code for sending "Hello World"
Carl Worth [Sun, 17 May 2020 19:32:43 +0000 (12:32 -0700)]
Remove old placeholder code for sending "Hello World"

Obviously, this was a leftover from some tutorial content, and we
don't really need or want this.

3 years agoempires: Return immediately from reveal_next if we aren't in the REVEAL state
Carl Worth [Sun, 17 May 2020 19:28:35 +0000 (12:28 -0700)]
empires: Return immediately from reveal_next if we aren't in the REVEAL state

I think this fix came about after Kevin did some testing by mashing on
all of the host buttons as fast as possible.

It's definitely a correct fix as far as it's true we shouldn't be
revealing anything if we're not in the REVEAL state. But I think we're
due for a better audit of what's happening to various pieces of state
on state transitions, (such as, shouldn't the interval timer get
cleared before we _leave_ the REVEAL state).

3 years agoRename server.js to empires.js
Carl Worth [Sun, 17 May 2020 19:26:42 +0000 (12:26 -0700)]
Rename server.js to empires.js

We have multiple express-based server apps implemented here now, so
the name "server.js" is now ambiguous. We rename it "empires.js" to
make clear that its an implementation only of the empires game.

3 years agoAdd a new server: lmno.js
Carl Worth [Sun, 17 May 2020 19:19:53 +0000 (12:19 -0700)]
Add a new server: lmno.js

This is the new top-level server for all dynamic content and games
that we plan to host at https://lmno.games. The previous server
implementation (in server.js) will likely be subsumed as a
sub-application within this new server soon.

3 years agoImplement a more correct response to /reset
Carl Worth [Mon, 11 May 2020 23:03:54 +0000 (16:03 -0700)]
Implement a more correct response to /reset

Specifically, we fix things here to clear some internal state that was
previously being missed (the "characters_to_reveal" field) and we also
fix things to report to the clients the new game state and the emptty
list of players.

3 years agoSend multiple game-state events (if needed) when a client connects
Carl Worth [Mon, 11 May 2020 21:52:09 +0000 (14:52 -0700)]
Send multiple game-state events (if needed) when a client connects

This implements the latest change as of version 0.6 of the API protocol.

This change fixes a bug in the current empires-html client where
reloading the browser when in the middle of the game would break the
client, (by displaying some content that's inappropriate for the
current state). By sending each step-wise transition through the game
states, the client does not get confused.

3 years agoImplement the /reveal,/start endpoints as well as the "game-state" event
Carl Worth [Sun, 10 May 2020 22:45:46 +0000 (15:45 -0700)]
Implement the /reveal,/start endpoints as well as the "game-state" event

This brings us up to protocol version 0.5 and should be a pretty
playable server at this point. Upon receiving the "/reveal" API
request the server will transition to the "reveal" game-state and from
there will broadcast the names of each character to all clients, one
name every three seconds, (and sending an empty name at the end to
clear off the last name). The "/reveal" API request can be sent
additional times if the players want to see the names again.

3 years agoRename a variable from "player_string" to "player_data"
Carl Worth [Sun, 10 May 2020 21:21:19 +0000 (14:21 -0700)]
Rename a variable from "player_string" to "player_data"

The name of "player_string" made me think this is just a string
representation of a player's name. But instead, this variable is
holding the JSON representation of the data block of a
"player-register" event. So a name of "player_data" is much more
clear.

3 years agoRename player-register/player-deregister to player-join/player-leave
Carl Worth [Sun, 10 May 2020 16:54:39 +0000 (09:54 -0700)]
Rename player-register/player-deregister to player-join/player-leave

This brings the server into compliance with protocol version 0.3.

3 years agoReplace "Example app" with "Empires server" in the welcome message
Carl Worth [Sun, 10 May 2020 15:50:08 +0000 (08:50 -0700)]
Replace "Example app" with "Empires server" in the welcome message

Since this is far from being an example app at this point.

3 years agoSend a comment to every connected client every 15 seconds
Carl Worth [Sun, 10 May 2020 15:40:14 +0000 (08:40 -0700)]
Send a comment to every connected client every 15 seconds

This prevents timeouts when the client receives nothing from the
server. For example, firefox appeares to give up on the server when it
receives nothing for two minutes.

3 years agoRename broadcast() to broadcast_event() supported by broadcast_string()
Carl Worth [Sun, 10 May 2020 15:35:21 +0000 (08:35 -0700)]
Rename broadcast() to broadcast_event() supported by broadcast_string()

The lower-level broadcast_string() simply sends a string to all clients.

The higher-level broadcast_event() sends a structured event (with both an
event type and a separate data block, as well as ending with two newlines),
exactly as clients will be expecting.

3 years agoFix typo in comment
Carl Worth [Sun, 10 May 2020 15:34:23 +0000 (08:34 -0700)]
Fix typo in comment

No functional change here.

4 years agoPerform broadcasts of deregister and capture events
Carl Worth [Mon, 4 May 2020 00:34:23 +0000 (17:34 -0700)]
Perform broadcasts of deregister and capture events

Allowing clients to track this state

4 years agoAdd an API for server-sent events at `/events`
Carl Worth [Sun, 3 May 2020 22:05:23 +0000 (15:05 -0700)]
Add an API for server-sent events at `/events`

So far there are two event types being sent here:

  players: An event reporting the complete list of registered players

  player-register: An event reporting a new player has registered

I'm not 100% sure these are all formatted correctly yet. I'll need to
implement a client to listen to these events and then check that.

4 years agoAdd some linting fixes
Carl Worth [Sun, 3 May 2020 22:03:56 +0000 (15:03 -0700)]
Add some linting fixes

Specifically some missing semicolons and a missing const.

It's funny that I didn't realize that emacs was doing live linting of
JavaScript all along here, (and highlighting all problems with various
colors and underlining).

4 years agoUse the cors package to set a permissive CORS header
Carl Worth [Sun, 3 May 2020 02:28:12 +0000 (19:28 -0700)]
Use the cors package to set a permissive CORS header

Specifically, with this change the server will emit a header of:

Access-Control-Allow-Origin: *

allowing requests to come from anywhere (for now).

This was necessary in the testing that Kevin is currently doing (where
he his hosting his test front-end spearately from the server).

4 years agoAdd a dependency on the cors package
Carl Worth [Sun, 3 May 2020 02:26:43 +0000 (19:26 -0700)]
Add a dependency on the cors package

This commit was constructed with "npm install cors"

4 years agoAdd simple testing for the entire API
Carl Worth [Sun, 3 May 2020 02:24:34 +0000 (19:24 -0700)]
Add simple testing for the entire API

This is more "exercising" than testing, (it doesn't currently verify
the results), but I've verified the server isn't hitting any syntax
errors (with fairly decent code coverage I think) and I've manually
inspected the results to ensure they look correct.

4 years agoImplement the rest of the API
Carl Worth [Sun, 3 May 2020 02:23:37 +0000 (19:23 -0700)]
Implement the rest of the API

This is up to date with commit
0411bdc5c4dbad187f7e25fa1fb40a23c3e0e940 of the empires-api as found
at: https://git.cworth.org/git/empires-api

4 years agoAdd an ID value to each player
Carl Worth [Sat, 2 May 2020 23:53:13 +0000 (16:53 -0700)]
Add an ID value to each player

This is a first baby step toward implementing the more complete API
for the game which we defined today, and which can be found here:

https://git.cworth.org/git/empires-api

In this commit we also introduce a 'Game' class to encapsulate all
data necessary for the game, (so the 'players' array we had before,
but also the 'next_player_id' which we need now).

4 years agofixup errant newline
Carl Worth [Sun, 26 Apr 2020 22:29:52 +0000 (15:29 -0700)]
fixup errant newline

4 years agoBe a bit more berbose in variable names.
Carl Worth [Sun, 26 Apr 2020 22:29:07 +0000 (15:29 -0700)]
Be a bit more berbose in variable names.

Preferring actual words "request" and "response" instead of
abbreviations "req" and "res".

4 years agoMake the server store a list of players
Carl Worth [Sun, 26 Apr 2020 22:25:14 +0000 (15:25 -0700)]
Make the server store a list of players

Expecting both "name" and "character" on each post to the /register
API. Also add a /players API to list the players registered so far.

4 years agoExtend our simple web API with a new /register endpoint
Carl Worth [Sun, 26 Apr 2020 22:15:53 +0000 (15:15 -0700)]
Extend our simple web API with a new /register endpoint

Which uses body-parser and simply prints out the body of the request.

This can now be tested with curl by something as simple as:

curl -i -X POST -H "Content-Type: application/json" -d '{"foo": "bar"}' localhost:3000/register

4 years agoAdd dependency on body-parser package
Carl Worth [Sun, 26 Apr 2020 22:07:24 +0000 (15:07 -0700)]
Add dependency on body-parser package

This was done with:

npm install --save body-parser

4 years agostash: add gitignore (for 'Add dependency for express')
Carl Worth [Sun, 26 Apr 2020 22:06:56 +0000 (15:06 -0700)]
stash: add gitignore (for 'Add dependency for express')

4 years agoAdd Hello World node app
Carl Worth [Sun, 26 Apr 2020 21:55:34 +0000 (14:55 -0700)]
Add Hello World node app

This is similar to what is documented here:

https://medium.com/@adnanrahic/hello-world-app-with-node-js-and-express-c1eb7cfa8a30

but with some more modern content as recommended by Richard.

This can be run with:

node server

in the current directory, (and then pointing a user agent at localhost:3000).

4 years agoAdd resolved dependencies in package-lock.json file
Carl Worth [Sun, 26 Apr 2020 21:51:05 +0000 (14:51 -0700)]
Add resolved dependencies in package-lock.json file

The entire contents of this file were generated by the:

npm install --save express

command from the previous commit.

4 years agoAdd dependency for express package
Carl Worth [Sun, 26 Apr 2020 21:49:31 +0000 (14:49 -0700)]
Add dependency for express package

This was generated with:

npm install --save express

(This command also generated resolved dependencies in the
package-lock.json file but I'm not commiting that in this commit.)

4 years agoAdd new package.json for the families app
Carl Worth [Sun, 26 Apr 2020 21:46:22 +0000 (14:46 -0700)]
Add new package.json for the families app

This was generated with "npm init" (and accepting all defaults).