Seeders - RaiderIO/keystone.guru GitHub Wiki

Seeders

Keystone.guru uses seeders to "seed" data in its database. If you're unsure of what seeders are in the context of Laravel, please check out https://laravel.com/docs/8.x/seeding.

In short, Keystone.guru has a lot of static data which will never change during normal operation of the site (building routes etc). This is including but not limited to:

  • Expansions
  • Dungeons, floors, npcs and their mappings
  • Player races
  • Player classes
  • Player class specializations
  • Game server regions
  • Etc.

Some of this data is stored in .json files which can be found in database/seeders/, such as dungeondata and releases. This is data that changes over time and I want to have versioned using Git. Other data are more static and I've opted to store this data in the following way (usually).

Tkae Map Icon Types for example. There's a list of icons that the user can choose from. This list is stored in PHP in app/Models/MapIconType.php. There is a full list of individual map icon types, each their own constant. These constants can be referenced in the code if need be. This happens when searching for the Dungeon Start for example. The seeder for this class however (database/seeders/MapIconTypesSeeder.php) will build a list of all Map Icon Types, assign some properties to each of them and insert it in the database.

It's important to understand that these Map Icon Types after seeding will NEVER change. If you want to add a new map icon type you add the constant, then add the properties for it in the seeder and you re-run the seeder (php artisan db:seed --class=MapIconTypesSeeder --database=migrate). The existing table will be truncated and new data will be inserted.

There are some different versions of this, for example Player Races still store the bulk of the info in the actual Seeder and don't use the constants. That's some technical debt that needs to be sorted out.

Notable seeders

Most seeders are relatively straight forward. They will read from a file or from code, and insert into a single table in the database. Some seeders though, are a bit more complex.

DungeonDataSeeder

This seeder reads the saved mapping (database/seeders/dungeondata) and inserts all of it in the database. It will read all files recursively and handle them appropriately. One thing of note here is the RelationMapping system. In short, this sytem allows me to read data like this from file:

    {
        "id": 854,
        "mapping_version_id": 101,
        "floor_id": 149,
        "teeming": null,
        "faction": "any",
        "polyline": {
            "color": "#003280",
            "color_animated": null,
            "weight": 3,
            "vertices_json": "[{\"lat\":-83.15625,\"lng\":124.3125},{\"lat\":-89.15625,\"lng\":119.53125},{\"lat\":-89.40625,\"lng\":114.3125}]"
        }
    },

and manipulate the object before inserting. In this case, when inserting this enemy patrol, I don't want to actually insert the polyline object in the database, it will crash. So I take that data, store it aside and insert then. With the inserted ID I can then take that polyline and set its relation back properly (the polyline needs to know which object it belongs to). Then, when the polyline is inserted I need to set the polyline_id back on the main object. This system allows me to do that.

Mappings

The mappings folder is simply a relationship between a saved file and how to read the file.

class MappingVersionRelationMapping extends RelationMapping
{
    /**
     * @inheritDoc
     */
    public function __construct()
    {
        parent::__construct('mapping_versions.json', MappingVersion::class);

        $this->setAttributeParsers(collect([
            new TimestampAttributeParser(),
        ]));
    }
}

This simple mapping just tells us that the mapping_versions.json should map to a MappingVersion and while parsing, use the attribute parser TimestampAttributeParser to properly convert timestamps back into something the database understands. Things like the DungeonRouteRelationMapping are more complex since storing a full route to disk requires a lot of relationships to be saved and loaded again.

LaratrustSeeder

This seeder is ran ONCE when you're setting up your local environment (or any new environment). It will generate new default users such as the admin user. I don't use this permission system much at all but it's required to be ran once. Do NOT run this seeder against production. There's guards against it but if you bypass them it will DROP THE USERS TABLE. Which will obviously be problematic. So do not do this please.