-
Notifications
You must be signed in to change notification settings - Fork 40
Data Management
The Global singleton maintains the schema, data store, and general game utility related methods of the game. Functions for adding test data and using id lookups of data are defined in Global. Storing the player's current run data (PlayerData) (link to player data) and generating some types of data are also handled here.
GlobalTestDataGenerator and GlobalProdDataGenerator are used to generate data that is used by the game. Generally speaking it's much easier to generate data using code and export it to be loaded back in, than to mess with JSON files directly. As such, it's strongly recommended to use these singletons when messing with the framework or your game.
A large amount of test data to showcase the framework has already been provided in GlobalTestDataGenerator.
StR uses lightweight data objects extending from Resource as its primary method of storing configuration and entity data. More specifically, they extend from SerializableData, a custom Resource class developed to provide additional support for object reflection and JSON (de)serialization.
As an additional note, if you wish to expand the interface of these data objects, make sure to include the @export flag to a property otherwise it will not be serialized/duplicated properly.
The Global singleton maintains several tables for the purposes of managing the game's internal schema. This is used to map file loads/exports and make data generation way less of a headache through the register_rod() method. If you add a new data type to the game, make sure to add it to Global.SCHEMA following the format provided.
To give a general idea, in StR data objects fall into 3 rough categories of usage, depending on the write-ability of the data type. Bar some exceptions, these objects will almost always either be created from or stored in the Global singleton except for embedded objects which by definition are not. Obtaining these is usually done via getter or a factory/prototype method.
Read only: These objects only have 1 instance at a time, created once on startup from external configs and data generation methods. Each of these objects has a unique string object_id, used to convert the string to the actual object itself via a getter in Global. Classes such as ConsumableData, StatusEffectData, and RestActionData fall under this type. As a general convention, avoid storing references to these anywhere except in Global. Storing references to them in UI components is also fine provided you do so in a read only capacity. These are obtained via Global.get_x_data(object_id) methods.
Prototype: The most common data type, following the Prototype Pattern and extending from the PrototypeData base class. Enemies, cards, player data, and artifacts are all prototyped, as they come from a single reference object which is duplicated to make more. The type of prototype is defined by the object_id, while the individual instances are differentiated by object_uid. While you can be a bit loose with storing read only object references above, you should NEVER store references to the original version of a prototype anywhere except Global. Instead store it by object_id. Instances can be freely stored and edited wherever, which should be referenced via object_uid. These instances are typically created from Global.get_x_from_prototype(object_id) methods.
Mutable: Objects which are freely mutated and don't fit into the above 2 categories. PlayerData, ProfileData, and UserSettingsData are example of a mutable data object. Filters and CardPlayRequest are mutable non-serialized data objects which follow similar patterns.
SerializableData/PrototypeData can also be embedded inside another SerializableData. That child object is considered "owned" by that object and will be converted into an embedded JSON object on save, and then completely generated as a new object on subsequent load. This means the object reference will break and will do so in a way that will be extremely hard to debug. As such, an embedded object should never have an object reference stored in more than one place. Instead, use a the embedded object's object_id or object_uid to reference them externally.
Important to note is that object embedding requires a pre-processing step on game start using some reflection hackery.
Player data is a bit of a weird one. It's a prototype instance representing a character, stored as a single instance in Global. These objects are paired with a CharacterData portion which controls the read only parts of the player data. If you wish to add a new character to the game, you'll need both.