RanvierMUD / core

Core engine code for Ranvier
https://ranviermud.com
MIT License
45 stars 40 forks source link

Data Loader RFC #7

Closed shawncplus closed 5 years ago

shawncplus commented 5 years ago

Problem

The current way data is loaded into the engine is terrible. The Data class is nothing but static methods with hardcoded paths. This makes it impossible for someone to change where/how entities are stored without directly modifying core.

Goal

{
  // ...
  "dataSources": {
    "Yaml": {
      /* 'require' specifies which file or package to require. It will follow
      the same API as the node require() method, which is to say you could
      either have the class locally or it could be from a node module */
      "require": "./lib/path/to/classFile.js",
      /* An arbitrary config passed to the DataSource constructor.
      Each DataSorce might have a different config: file paths,
      database details, etc. */
      "config": {
        "bundlePath": "bundles",
      }
    },

    "Mysql": {
      "require": "ranvier-mysql-datasource",
      "config": {
        /* A config should also be able to pull from env variables
         to keep things like DB connection details out of source control */
        "hostname": "[ENV(RANVIER_MYSQL_HOSTNAME)]",
        /* FEEDBACK: seanohue: could just make ranvier.json a .js file and use process.env */
      }
    },

    "Json": {
      /* If a node module exports more than one data source you may specify
      which export to use with <module>.<object> */
      "require": "cool-datasources.JsonDataSource",
      "config": {
        "root": "data"
      }
    }
  },
  // ...
}
{
  // ...
  "entitySources": {
    /* The keys here will be a specific list of game entities which the
    BundleManager will use to load data. However, you should also be able
    to add additional entities if you have a bundle with some custom data
    like a vendor's product list or loot tables */
    "items": {
      /* specifies which registered DataSource to use */ 
      "source": "Yaml",
      /* Additional configuration for the datasource specific to this entity */
      "config": {
        "path": "items.yml",
      },
    },
    "npcs": {
      "source": "Mysql",
      "config": {
        "table": "npc",
      },
    },

    "players": {
      "source": "Json",
      "config": {
        "path": "data/players"
      }
    },
    "accounts": {
      "source": "Json",
      "config": {
        "path": "data/accounts"
      }
    }
  }
}
const itemLoader = state.EntityLoaderRegistry.getLoader('items');
/* EntityLoader will have setBundle/setArea methods to optionally specify
which bundle/area the data is coming from */
itemLoader.setBundle('example-areas');
itemLoader.setArea('limbo');
const items = await itemLoader.fetchAll();

/* player data won't be stored in a bundle, for example */
const playerLoader = state.EntityLoaderRegistry.getLoader('players');
const playerData = await playerLoader.fetch(playerName);
const player = new Player(playerData);
ratacat commented 5 years ago

I think that sounds great Shawn! I don't probably have very nuanced view of it, but I really like the idea of being able to easily adapt to different storages systems. Thankyou!!!!

shawncplus commented 5 years ago

Work is visible ongoing on the https://github.com/RanvierMUD/core/tree/data-refactor branch