diff --git a/module/api.mjs b/module/api.mjs index b139ef9..8655eb3 100644 --- a/module/api.mjs +++ b/module/api.mjs @@ -6,6 +6,7 @@ import { PlayerSheet } from "./apps/PlayerSheet.mjs"; // Utils import { attributeSorter } from "./utils/attributeSort.mjs"; import { DialogManager } from "./utils/DialogManager.mjs"; +import { QueryManager } from "./utils/QueryManager.mjs"; import { toID } from "./utils/toID.mjs"; const { deepFreeze } = foundry.utils; @@ -16,6 +17,7 @@ Object.defineProperty( { value: deepFreeze({ DialogManager, + QueryManager, Apps: { Ask, AttributeManager, diff --git a/module/utils/QueryManager.mjs b/module/utils/QueryManager.mjs new file mode 100644 index 0000000..2dfc381 --- /dev/null +++ b/module/utils/QueryManager.mjs @@ -0,0 +1,77 @@ +/** + * @typedef Apple + * @property {string[]} users + * @property {Function} resolve + * @property {Record} responses + */ + +const { randomID } = foundry.utils; + +export class QueryManager { + static #queries = new Map(); + static #promises = new Map(); + + static has(requestID) { + return this.#queries.has(requestID); + }; + + static async query(request, users = null, config = undefined) { + request.id ??= randomID(); + + game.socket.emit(`system.taf`, { + event: `query.prompt`, + payload: { + id: request.id, + users, + request, + config, + }, + }); + + if (this.#promises.has(request.id)) { + return null; + }; + + const promise = new Promise((resolve) => { + this.#queries.set( + request.id, + { + users: users ?? game.users.filter(u => u.id !== game.user.id), + resolve, + responses: {}, + }, + ); + }); + return promise; + }; + + static async submit(requestID, answers) { + game.socket.emit(`system.taf`, { + event: `query.submit`, + payload: { + id: requestID, + answers, + }, + }); + }; + + static async addResponse(requestID, userID, answers) { + const data = this.#queries.get(requestID); + data.responses[userID] = answers; + + // Validate for responses from everyone + if (data.users.length === Object.keys(data.responses).length) { + data.resolve(data.responses); + }; + }; + + static async cancel(requestID) { + // prevent cancelling other people's queries + if (!this.#queries.has(requestID)) { return }; + + game.socket.emit(`system.taf`, { + event: `query.cancel`, + payload: { id: requestID }, + }); + }; +};