Devtober Day 12: Map Syncing + Editing


I had a bit of a lighter weekend of work. Since I’m funemployed, I’m working on this almost every day of the week, so with my wife home from work for the weekend I wanted to disconnect after getting a little work knocked out in the mornings.

Over the weekend I released 0.0.1 of sqlx-simple-migrator. As the name implies, it’s really simple. However, after reviewing the built-in migration setup that sqlx has, I decided my crate still was useful for myself. It needs some work to be more generic, as it’s making specific assumptions about the database being Postgres right now.

With that crate released, I used it to start creating the schema for maps and map tiles. At the end of yesterday, I had finished replacing the hard-coded map with one coming from Postgres.

Today, I was back at it for most of the day. The video at the top of the page shows where I stopped for the night. It may seem simple, but here’s how it’s working behind the scenes:

  • Upon connecting, the client looks in its local database and sees what the latest timestamp on any maptile is. Client asks for all map tiles since that timestamp. If no timestamp is specified, all map tiles are returned.
  • Server responds only with the tiles that have changed since that timestamp, and takes a note of the latest value returned to the client.
  • When I right click on a tile, the client sends an UpdateTiles request setting that tile to TerranKind::Ground.
  • The server updates the tiles, and then asks Posstgres to notify over the ‘map_tiles_changed’ channel.
  • In the pubsub thread (potentially on multiple servers), the notification is received. Each server loops over all of the connected clients and looks to see what the last timestamp it was sent. It fetches only the tiles needed from the database once, and then sends only the tiles that each client needs to each client.

That may sound overly complicated, but I’m trying to design my systems to scale horizontally. The great news is that I find these challenges fun to solve. The not-so-great news is that there’s a fair amount of work remaining even though I already have a lot of the “fanout” problems solvd.

Last note I wanted to say is that I know my automatic-border-drawing code is wonky around convex corners. I could solve it with a brute force copy-paste style set of code, but I feel like there should be a better approach, so instead of spending more time on it today, I moved onto other problems.

Steps before the first submission

My initial goal in Devtober is to get a downloadable client that people can connect to. Here’s the steps that come to mind:

  • Hook up Twitch auth: Ncog already supports logging into Twitch, but there is no current mechanism for a client to connect to Ncog, and for it to use the authentication it receives from Ncog to authenticate against the game. Ncog essentially will need to create an OAuth server, although my servers will communicate to each other over persistent websocket communications. I think this chunk of work will probably take a couple days on its own.
  • Deploy: Ncog has the same model of websockets, so the Cloudformaion from that repository can be copied and simplified. However, I still need to configure Github Actions for the server, setup the various secrets, configure DNS, etc.
  • Create an initial map: I have designed these systems to have to publicly facing access. Unless I want to spend time setting up either a bastion or a VPN, I need to hardcode a map in the migration. It’s quite trivial to do, but I’ve avoided doing it because I’m mulling over what all editing capabilities I want to be able to do over the wire protocol, including creating maps. I might create a CLI to allow me to do some operations using the API without needing to create a full blown user interface.
  • Permissions: Isn’t it scary thinking that anyone can edit or create maps if they just sent the right websocket commands? Well, thankfully Ncog already supports RBAC permissions, so after hooking up the server to Ncog, I’ll be able to create roles and groups in Ncog to use within this game and be able to lock those APIs down so that only I can use them.
  • Two servers, one GameUpdate: I don’t need to solve this to deploy, as I can always opt to initially deploy with just one server. Since I talked about the challenges of scaling, I wanted to bring this challenge up here too. If I have two servers running, and one client is connected to each of the servers, which server handles moving characters around? Or do both try to tackle the problem together? I have two designs I’m mulling over. One design introduces a separate game server to handle the map interactions. This design I like because I’m planning on my battles being done in instances, and those battles could be their own server. The other design is to try to create a low-latency shared job queue. In either approach, I’m planning on using raft to sync the connected player states between the servers.

That does sound like a lot, but I’m optimistic that I can get there or close to there by the end of the week (outside of the last bullet). Sadly, the reason why I’m writing all of that out is that none of those items listed produce share-worthy screenshots. I’ll aim to post a short update on my twitter each day with my progress. As soon as I get this list knocked out, however, there will be something to download!

Hope everyone has an awesome week.

Leave a comment

Log in with itch.io to leave a comment.