DuskWorks

DuskEngine - Asset Store Start

This is going to look like a pretty unusual post for a game engine since it's almost entirely webdev, but I think it's still going to be a fun read.

Besides, people often credit the asset stores to other engines' successes, and the functionality for such a store still needs to be written by someone.

I work on two projects in DuskEngine, the main one is the third person witchy project that you see me posting screens and videos from. The other is FPS-style, built so that it's different enough from the main one, in the hopes that it will shed light on otherwise hidden flaws in the engine.

I feel like sharing some assets between the two projects without an initial copy paste, and I want to be able to update those assets later on, also without copy paste.

In this episode I'll go through how I wrote the first super basic version of the asset store functionality for DuskEngine.

Start

Let's begin with what we're trying to achieve:

I feel like sharing some assets between the two projects without an initial copy paste, and I want to be able to update those assets later on, also without copy paste.

So we'll have to download some files from somewhere, and import them as assets into the project. The engine will have to call some web API for this so we'll build a RESTful API for it.

These files can get quite big (like pngs, audio files etc.) and quite many in number, in each asset pack, so to make things simpler and to save on bandwidth, we'll pack em up in a .zip or similar.

I hear y'all going like "duuuuuh" but bear with me. Anyway, this tells us that the engine will have to be able to make HTTP calls and unzip archives and I honestly have no idea which libraries might be best for this purpose in the C++ world, but I'll find out later.

So what exactly is an asset, just a .zip file containing a bunch of files? Let's try to build a schema in fake JSON:

Asset = {
    Filename: string // such as epic_fantasy_warriors.zip
}

We'll need a way to identify each asset and filenames are not a very good solution for this. Let's add in

Uuid: UUID

We also need a nice human readable name, thus:

Name: string // Epic Fantasy Warriors

Each asset has a creator so

Creator: ID

This will be the ID of the creator (basically a user) in our future database.

Assets need updating so a single .zip file won't really suffice because we want to keep a history of old versions (after all, it's up to the user if they want to update an asset or not, in their project). Filename now becomes:

Versions: [
    {
        Major: UInt, // such as 1
        Minor: UInt, // such as 0
        Filename: string // such as epic_fantasy_warriors_1.0.zip
                         // or maybe <asset_uuid>_1.0.zip
    }
]

I'll probably go with versions like 1.0, 1.1, ... because it's relatively simple.

Some creators might want to sell their assets instead of giving them away for free, which implies a whole lot of complicated things involving money and payment processors and the law in god knows what regions of the globe.

For the purposes of this first version however, the only thing we want to make sure we've got in place is a way to track which assets a particular user is allowed to access (as if they had bought a license). So let's add:

IsPaid: boolean

Finally, a creator might want to show a nice description on the asset's page, so let's add this for now:

Description: string

Now, a "nice description" usually means fancy text formatting and interesting media content, so I can already tell that the only reasonable way to achieve this would be to embed a browser into the engine's asset store window. I think that's what every other engine out there does, where every engine out there is Unity, the only one I have real experience with. Which essentially means most if not all of what I'll be writing on the engine side will be thrown out eventually. Great start here. I'm kidding, this kind of stuff is inevitable, try to write your code so that it can be easily thrown out and replaced later on and you'll have an easier life.

So what does our asset schema look like now?

Asset = {
    Uuid: UUID,
    Creator: ID,
    Name: string,
    Description: string,
    IsPaid: boolean,
    Versions: [
    {
        Major: UInt,
        Minor: UInt,
        Filename: string // such as epic_fantasy_warriors_1.0.zip
                         // or maybe <asset_uuid>_1.0.zip
    }
    ]
}

I mentioned creators being users and users having a license to download specific assets, so tackle the users (not IRL) next:

If there's no logged in user, we treat them as a kind of "Anonymous User" prototype and give them access to all the free assets.

Ok so with all that said, the extra things we'll need are:

I'll use SQLite for the database for now, it'll let me model the schema close enough to what it would look like in something larger like MySQL, while also allowing me to commit the database file to source control which will speed up development and ease the setup process in these early stages (so I can quickly run the asset store server on both Mac and Windows for example).

OK, so let's try to list some endpoints here, to have a rough idea of where we're heading:

' will probably leave this one out
' and create the users in the db directly
' don't feel like making an actual registration flow today
/users/register

/users/login

' also useless right now
/users/logout