Merge pull request #42 from Oliver-Akins/feature/chatMessageHook
Update parsing for the roll auto-tracking to provide a more robust privacy detection when roll mode isn't provided
This commit is contained in:
commit
2cb4268400
6 changed files with 82 additions and 34 deletions
|
|
@ -13,6 +13,7 @@ import { UserFlagDatabase } from "./utils/databases/UserFlag.mjs";
|
|||
import { barGraphSchema, numberBucketSchema, rowSchema, stringBucketSchema, tableSchema } from "./utils/databases/model.mjs";
|
||||
import { determinePrivacyFromRollMode, filterPrivateRows, PrivacyMode } from "./utils/privacy.mjs";
|
||||
import { validateBucketConfig, validateValue } from "./utils/buckets.mjs";
|
||||
import { inferRollMode } from "./utils/inferRollMode.mjs";
|
||||
|
||||
const { deepFreeze } = foundry.utils;
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ export const api = deepFreeze({
|
|||
},
|
||||
utils: {
|
||||
determinePrivacyFromRollMode,
|
||||
inferRollMode,
|
||||
filterPrivateRows,
|
||||
validateValue,
|
||||
validateBucketConfig,
|
||||
|
|
|
|||
40
module/hooks/createChatMessage.mjs
Normal file
40
module/hooks/createChatMessage.mjs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { determinePrivacyFromRollMode } from "../utils/privacy.mjs";
|
||||
import { inferRollMode } from "../utils/inferRollMode.mjs";
|
||||
|
||||
Hooks.on(`createChatMessage`, (message, options, author) => {
|
||||
const isSelf = author === game.user.id;
|
||||
const isNew = options.action === `create`;
|
||||
const hasRolls = message.rolls?.length > 0;
|
||||
const autoTracking = game.settings.get(__ID__, `autoTrackRolls`);
|
||||
if (!isSelf || !isNew || !hasRolls || !autoTracking) { return };
|
||||
|
||||
/** An object of dice denomination to database rows */
|
||||
const rows = {};
|
||||
|
||||
const privacy = determinePrivacyFromRollMode(options.rollMode ?? inferRollMode(message));
|
||||
|
||||
/*
|
||||
Goes through all of the dice within the message and grabs their result in order
|
||||
to batch-save them all to the database handler.
|
||||
*/
|
||||
for (const roll of message.rolls) {
|
||||
for (const die of roll.dice) {
|
||||
const size = die.denomination;
|
||||
rows[size] ??= [];
|
||||
for (const result of die.results) {
|
||||
rows[size].push({ privacy, value: result.result });
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// save all the rows, then rerender once we're properly done
|
||||
for (const denomination in rows) {
|
||||
CONFIG.stats.db.createRows(
|
||||
`Dice/${denomination}`,
|
||||
author,
|
||||
rows[denomination],
|
||||
{ rerender: false },
|
||||
);
|
||||
};
|
||||
CONFIG.stats.db.render({ userUpdated: author });
|
||||
});
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import { determinePrivacyFromRollMode } from "../utils/privacy.mjs";
|
||||
|
||||
Hooks.on(`preCreateChatMessage`, (_message, context, options, author) => {
|
||||
const isNew = options.action === `create`;
|
||||
const hasRolls = context.rolls?.length > 0;
|
||||
const autoTracking = game.settings.get(__ID__, `autoTrackRolls`);
|
||||
if (!isNew || !hasRolls || !autoTracking) { return };
|
||||
|
||||
/** An object of dice denomination to rows to add */
|
||||
const rows = {};
|
||||
|
||||
const privacy = determinePrivacyFromRollMode(options.rollMode);
|
||||
for (const roll of context.rolls) {
|
||||
for (const die of roll.dice) {
|
||||
const size = die.denomination;
|
||||
rows[size] ??= [];
|
||||
for (const result of die.results) {
|
||||
rows[size].push({ privacy, value: result.result });
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
for (const denomination in rows) {
|
||||
CONFIG.stats.db.createRows(
|
||||
`Dice/${denomination}`,
|
||||
author,
|
||||
rows[denomination],
|
||||
);
|
||||
};
|
||||
});
|
||||
|
|
@ -5,7 +5,7 @@ import "./hooks/init.mjs";
|
|||
import "./hooks/ready.mjs";
|
||||
|
||||
// Document Hooks
|
||||
import "./hooks/preCreateChatMessage.mjs";
|
||||
import "./hooks/createChatMessage.mjs";
|
||||
|
||||
// Dev Only imports
|
||||
if (import.meta.env.DEV) {
|
||||
|
|
|
|||
36
module/utils/inferRollMode.mjs
Normal file
36
module/utils/inferRollMode.mjs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* A helper function to try and infer what roll mode was used when creating a
|
||||
* chat message in case the roll mode was not provided during the createChatMessage
|
||||
* hook for whatever reason.
|
||||
*
|
||||
* **Disclaimer**: This inference is not totally correct. Particularly when inferring
|
||||
* a GM's message, as it won't be able to distinguish between a self-roll and a
|
||||
* private GM roll when it's
|
||||
*
|
||||
* @param {ChatMessage} message The ChatMessage document to infer from
|
||||
* @returns The Foundry-specified roll mode
|
||||
*/
|
||||
export function inferRollMode(message) {
|
||||
const whisperCount = message.whisper.length;
|
||||
if (whisperCount === 0) {
|
||||
return CONST.DICE_ROLL_MODES.PUBLIC;
|
||||
};
|
||||
|
||||
if (whisperCount === 1 && message.whisper[0] === game.user.id) {
|
||||
return CONST.DICE_ROLL_MODES.SELF;
|
||||
};
|
||||
|
||||
let allGMs = true;
|
||||
for (const userID of message.whisper) {
|
||||
const user = game.users.get(userID);
|
||||
if (!user) { continue };
|
||||
allGMs &&= user.isGM;
|
||||
};
|
||||
|
||||
if (!allGMs) {
|
||||
return CONST.DICE_ROLL_MODES.PUBLIC;
|
||||
};
|
||||
return message.blind
|
||||
? CONST.DICE_ROLL_MODES.BLIND
|
||||
: CONST.DICE_ROLL_MODES.PRIVATE;
|
||||
};
|
||||
|
|
@ -250,7 +250,7 @@
|
|||
"image": {},
|
||||
"text": {
|
||||
"format": 1,
|
||||
"content": "<p>The module provides a multitude of utility functions through it's API for usage however desired. This will go over them and describe their purpose.</p><p></p><h2>filterPrivateRows</h2><p>This method is intended to take @UUID[Compendium.stat-tracker.docs.JournalEntry.pBOyeBDuTeowuDOE.JournalEntryPage.S7Z6mZ0JablJVQJu]{rows} provided by the database and filter out any that the user would not be able to see normally. This is usually called by the database adapters so there's unlikely to be any reason to use it externally.</p><p>Available under <code><api>.utils.filterPrivateRows</code>.</p><p></p><h2>validateValue</h2><p>Available under <code><api>.utils.validateValue</code>.</p><p></p><h2>validateBucketConfig</h2><p>Available under <code><api>.utils.validateBucketConfig</code>.</p>"
|
||||
"content": "<p>The module provides a multitude of utility functions through it's API for usage however desired. This will go over them and describe their purpose.</p><p></p><h2>filterPrivateRows</h2><p>This method is intended to take @UUID[Compendium.stat-tracker.docs.JournalEntry.pBOyeBDuTeowuDOE.JournalEntryPage.S7Z6mZ0JablJVQJu]{rows} provided by the database and filter out any that the user would not be able to see normally. This is usually called by the database adapters so there's unlikely to be any reason to use it externally.</p><p>Available under <code><api>.utils.filterPrivateRows</code>.</p><p></p><h2>inferRollMode</h2><p>This utility is intended to try and determine what roll mode was used to create a chat message. The inference is not entirely accurate because it struggles to differentiate between a GM rolling with a Private GM Roll and a Self Roll when there is only one GM present in the world.</p><p>Available under <code><api>.utils.inferRollMode</code></p><p></p><h2>validateValue</h2><p>Available under <code><api>.utils.validateValue</code>.</p><p></p><h2>validateBucketConfig</h2><p>Available under <code><api>.utils.validateBucketConfig</code>.</p>"
|
||||
},
|
||||
"video": {
|
||||
"controls": true,
|
||||
|
|
@ -266,11 +266,11 @@
|
|||
"compendiumSource": null,
|
||||
"duplicateSource": null,
|
||||
"exportSource": null,
|
||||
"coreVersion": "13.344",
|
||||
"coreVersion": "13.345",
|
||||
"systemId": "empty-system",
|
||||
"systemVersion": "0.0.0",
|
||||
"createdTime": 1748330904988,
|
||||
"modifiedTime": 1748394635911,
|
||||
"modifiedTime": 1749864406851,
|
||||
"lastModifiedBy": "t2sWGWEYSMFrfBu3"
|
||||
},
|
||||
"_key": "!journal.pages!pBOyeBDuTeowuDOE.TQzWrVTEz4oQhLPD"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue