Groovelet v.8d028eb - Dard Catabase

Behold the advent of the world's least good database.

After our last update, we had turns working, and some basic UI, and even some fun dragging behaviors, but what we were dragging was meaningless tokens representing cards with no data attached.

So in this past two weeks, I’ve … attached data to those cards. The cards are selectable, and when you select a card its whole deal comes up in the “View” window.

Again, I’d like to reiterate that this is all in “developer art” mode right now.

Storing data about these cards was a bit of a Project.

At first, a database of cards seemed like a slam dunk win for MongoDB - permanent, unstructured card data? Obviously mongo. The problem came when I started to think about where card logic would go. Of course, I could store card logic as serialized javascript against the cards in the database and simply pull and eval it as necessary - but that’s a strategy with Problems Manifold:

  • I want my cards’ code to be testable.

  • I want my cards’ code to be version controlled.

  • I want my cards’ code to be easy to modify in a modern editor.

  • I’d want any code loaded and eval’d from the database to be sandboxed and carefully guarded against exploding the server.

Planning around structuring my database code this way made me think that I was perhaps doing something very stupid, so instead I started to think “what if I kept the card data and the card code separate” - that way, I could have a database with all of the card data, and the code that attaches to it in the nice, version-controlled codebase.

At that point, though, why even bother having a database? I’m unlikely to have more than 1000 cards ever, can’t I just load the whole shebang in memory, up front? That’d mean that any change to a card would force a full re-deploy (not great), but… aside from that it’s a surprisingly workable strategy. You’d be surprised at how often “the server just reads that when it boots and holds on to it” is the fastest and most expedient strategy for data that doesn’t change very often, especially when you have a rapid deploy cycle on your hands.

So behold, my extremely architecture++ card database. Whoa there, mister distributed systems, don’t go blowing our minds with your crazy moon techniques.

Even with card-hoded hard data… uh, hard-coded card data, I still reserve the right to create a “patch database” to allow for in-situ card data replacements between deploys. The way that this would work would be, upon getting a card, the server would pull that card’s information from Mongo (or none, if no patch exists) and simply apply it on top of any hard-coded data. At the end of a deployment cycle, the patch could be applied (even automatically) against the hard-coded data file and the patch database could be emptied. I haven’t done this yet, but I will if I start needing to update cards quickly.

I’ve decided that cards have tags, which will encapsulate all kinds of shared behaviors. “unplayable”, for example, models a card that cannot be played on its own, and just sits in your deck, like “Wood”. “resource” is for a card that’s intended to be more of a Thing than an Action, like… “Wood” again. Wood is an unplayable resource. These tags may also affect card rendering in the UI - maybe resources will have a different color or icon. I’ve also made the card images a stack - I’m going to display them, bottom-to-top, so if I want to re-use backgrounds or borders I can do that without having to bake different images for each individual card.

With that out of the way, I put together the plumbing allowing the game’s UI code to download and sync a player’s current backpack of cards, as well as some code to allow them to click on cards and see them.

Which is where we’re at, now: the cards are Real! It hardly seems like two whole weeks of work, but here we are.