/* eslint-disable no-unused-vars */ /* NOTE: This database design currently does not support anything like a default subtable or nested tables more than 1-layer deep. These limitations are currently intentional and if the desire for those functionalities is requested, this is some information on how they can be implemented. Tables >= 1 layer deep: Adding a "parent" property to each table that accepts a table's ID, there will need to be a defined table at the specified ID, and each table's ID should no longer contain the parent table(s) within it (e.g. "Dice/d4" -> "d4"). This could also be made in such a way where any buckets/graph settings on the parent are applied to the subtable when it is created. The primary unknown with this idea is what do we do when someone has a table like "Dice/d4" and then attempts to make a subtable "Dice/d4/crits" or something like that. Default Subtables: This would require a partial implementation similar to the Tables >= 1 layer deep, however each table would accept an "options" top level property that accepts a "defaultSubtable" property specifying the ID of the subtable that should be selected by default, this defaultSubtable property would *only* be valid on tables that are parents to other tables. */ export class Database { // MARK: Table Ops static createTable(tableConfig) { if (!game.user.isGM) { ui.notifications.error(`You do not have the required permission to create a new table`); return false; }; const name = tableConfig.name; if (name.split(`/`).length > 2) { ui.notifications.error(`Subtables are not able to have subtables`); return false; } const tables = game.settings.get(__ID__, `tables`); const [ table, subtable ] = name.split(`/`); if (subtable && tables[table]) { ui.notifications.error(`Cannot add subtable for a table that already exists`); return false; } if (tables[name]) { ui.notifications.error(`Cannot create table that already exists`); return false; }; tables[name] = tableConfig; game.settings.set(__ID__, `tables`, tables); this.render(); return true; }; /** @returns {Array} */ static getTables() { const tables = game.settings.get(__ID__, `tables`); return Object.values(tables) ?? []; }; static getTable(tableID) { const tables = game.settings.get(__ID__, `tables`); if (!tables[tableID]) { return }; return tables[tableID]; }; static deleteTable(tableID) { if (!game.user.isGM) { ui.notifications.error(`You do not have the required permission to delete a table`); return false; }; const tables = game.settings.get(__ID__, `tables`); if (!tables[tableID]) { ui.notifications.error(`Cannot delete a table that doesn't exist`); return false; }; delete tables[tableID]; game.settings.set(__ID__, `tables`, tables); return true; }; // MARK: Row Ops static createRow(table, userID, row, opts) { throw new Error(`createRow() must be implemented`); }; static createRows(table, userID, rows, opts) { throw new Error(`createRows() must be implemented`); }; static getRows(tableID, userIDs, privacy = `none`) { throw new Error(`getRows() must be implemented`); }; static updateRow(table, userID, rowID, changes) { throw new Error(`updateRow() must be implemented`); }; static deleteRow(table, userID, rowID) { throw new Error(`deleteRow() must be implemented`); }; // MARK: Applications static _apps = new Map(); /** * Adds an application into the registry so that when a data update * is received, we can re-render the sheets. * * @param app an ApplicationV2 instance */ static addApp(app) { this._apps.set(app.id, app); this.registerListeners(); }; /** * Adds an application into the registry so that when a data update * is received, we can re-render the sheets. * * @param app an ApplicationV2 instance */ static removeApp(app) { this._apps.delete(app.id); if (this._apps.size === 0) { this.unregisterListeners(); }; }; /** * Rerenders all of the applications that are displaying data from * this database */ static render(opts) { for (const app of this._apps.values()) { app.render(opts); }; }; // MARK: Listeners /** * Used to listen for changes from other clients and rerender the apps * as required in order to keep the data as up-to-date as possible. */ static registerListeners() {}; static unregisterListeners() {}; }; /* eslint-enable no-unused-vars */