From 3d22ff27f9105470827b4e8d6449222d70bafc14 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Sat, 16 Nov 2024 18:12:07 -0500 Subject: [PATCH] Send rendered rolls from DDB to DOM too and avoid duplicates debounces the fallback rendered roll so if a real one arrives within 500ms, it can override the fallback avoiding sending double rendered rolls when DDB renders it after a failure to find a VTT --- src/common/roll_renderer.js | 3 +++ src/common/utils.js | 37 +++++++++++++++++++++++++++++++++++- src/dndbeyond/base/dice.js | 8 ++++++-- src/generic-site/renderer.js | 2 +- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/common/roll_renderer.js b/src/common/roll_renderer.js index 7c0111cb..4dffa26a 100644 --- a/src/common/roll_renderer.js +++ b/src/common/roll_renderer.js @@ -380,6 +380,9 @@ class Beyond20RollRenderer { this._displayer.sendMessage(request, title, html, character, request.whisper, play_sound, source, attributes, description, json_attack_rolls, roll_info, json_damage_rolls, json_total_damages, open) } else if (canPostHTML) { this._displayer.postHTML(request, title, html, character, request.whisper, play_sound, source, attributes, description, json_attack_rolls, roll_info, json_damage_rolls, json_total_damages, open); + if (this._displayer.sendMessageToDOM) { + this._displayer.sendMessageToDOM(request, title, html, character, request.whisper, play_sound, source, attributes, description, json_attack_rolls, roll_info, json_damage_rolls, json_total_damages, open) + } } if (attack_rolls.length > 0) { diff --git a/src/common/utils.js b/src/common/utils.js index d3832640..efb75f9a 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -281,6 +281,17 @@ function initializeAlertify() { } +const bouncedFallbackRenders = {}; +function simpleHash(input) { + let hash = 0; + for (let i = 0; i < input.length; i++) { + const char = input.charCodeAt(i); + hash = (hash << 5) - hash + char; + hash |= 0; // Convert to 32-bit integer + } + return hash; +} + function forwardMessageToDOM(request) { if (request.action == "hp-update") { sendCustomEvent("UpdateHP", [request, request.character.name, request.character.hp, request.character["max-hp"], request.character["temp-hp"]]); @@ -294,6 +305,30 @@ function forwardMessageToDOM(request) { // Requires roll_renderer to be set (currently in generic-site and ddb pages) roll_renderer.handleRollRequest(request); } else if (request.action == "rendered-roll") { - sendCustomEvent("RenderedRoll", [request]); + // Hash the original request to be able to match it with the rendered one in case of fallback + // But don't use the whole request since it can change by the time we render it (original-whisper is added) + const reqHash = simpleHash(JSON.stringify({ + action: request.request.action, + type: request.request.type, + character: request.request.character, + roll: request.request.roll, + name: request.request.name, + ability: request.request.ability, + modifier: request.request.modifier, + description: request.request.description + })); + if (request.rendered === "fallback") { + // This is a fallback render, if we're sending it from DDB, we might end up with + // a double render, so bounce this one for 500ms to let the real render happen if it's + // going to, then override the fallback render if we do. + bouncedFallbackRenders[reqHash] = setTimeout(() => { + delete bouncedFallbackRenders[reqHash]; + sendCustomEvent("RenderedRoll", [request]); + }, 500); + } else { + clearTimeout(bouncedFallbackRenders[reqHash]); + delete bouncedFallbackRenders[reqHash]; + sendCustomEvent("RenderedRoll", [request]); + } } } \ No newline at end of file diff --git a/src/dndbeyond/base/dice.js b/src/dndbeyond/base/dice.js index 79e6d0a8..5685cd4e 100644 --- a/src/dndbeyond/base/dice.js +++ b/src/dndbeyond/base/dice.js @@ -36,7 +36,7 @@ class DNDBDisplayer { }); } - async sendMessage(request, title, html, character, whisper, play_sound, source, attributes, description, attack_rolls, roll_info, damage_rolls, total_damages, open) { + async sendMessageToDOM(request, title, html, character, whisper, play_sound, source, attributes, description, attack_rolls, roll_info, damage_rolls, total_damages, open) { const req = { action: "rendered-roll", request, @@ -54,9 +54,13 @@ class DNDBDisplayer { total_damages, open } + sendRollRequestToDOM(req); + return req; + } + async sendMessage(request, title, html, character, whisper, play_sound, source, attributes, description, attack_rolls, roll_info, damage_rolls, total_damages, open) { + const req = sendMessageToDOM(request, title, html, character, whisper, play_sound, source, attributes, description, attack_rolls, roll_info, damage_rolls, total_damages, open); console.log("Sending message: ", req); chrome.runtime.sendMessage(req, (resp) => beyond20SendMessageFailure(character, resp)); - sendRollRequestToDOM(req); } displayError(message) { alertify.error(message); diff --git a/src/generic-site/renderer.js b/src/generic-site/renderer.js index a875bc26..0166afdd 100644 --- a/src/generic-site/renderer.js +++ b/src/generic-site/renderer.js @@ -24,7 +24,7 @@ class GenericDisplayer { total_damages, open } - sendCustomEvent("RenderedRoll", [req]); + forwardMessageToDOM(req); } displayError(message) {