Skip to content

Commit

Permalink
V10 support
Browse files Browse the repository at this point in the history
Fix #9
  • Loading branch information
mclemente committed Aug 16, 2022
1 parent 81d4051 commit 6bccda6
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 12 deletions.
42 changes: 42 additions & 0 deletions Combat.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { libWrapper } from "./shim.js";

let CombatantsInitiative = {};
let firstInitiative = 0;
let lastInitiative = 0;
Expand All @@ -16,6 +18,7 @@ function getInitiatives(combatTracker) {
lastInitiative = lastPlace + 1;
}
}

class FurnaceCombatQoL {
static renderCombatTracker(tracker, html, data) {
if (game.user.role < parseInt(game.settings.get("initiative-double-click", "player-access"))) return;
Expand Down Expand Up @@ -139,4 +142,43 @@ Hooks.once("init", () => {
type: Boolean,
default: false,
});
game.settings.register("initiative-double-click", "disableOpenSheet", {
name: game.i18n.localize("initiative-double-click.settings.disableOpenSheet.name"),
hint: game.i18n.localize("initiative-double-click.settings.disableOpenSheet.hint"),
scope: "world",
config: true,
type: Boolean,
default: true,
});
libWrapper.register(
"initiative-double-click",
"CombatTracker.prototype._onCombatantMouseDown",
function (wrapped, ...args) {
event.preventDefault();

const li = event.currentTarget;
const combatant = this.viewed.combatants.get(li.dataset.combatantId);
const token = combatant.token;
if (!combatant.actor?.testUserPermission(game.user, "OBSERVED")) return;
const now = Date.now();

// Handle double-left click to open sheet
if (!game.settings.get("initiative-double-click", "disableOpenSheet")) {
const dt = now - this._clickTime;
this._clickTime = now;
if (dt <= 250) return combatant.actor?.sheet.render(true);
}

// Control and pan to Token object
if (token?.object) {
token.object?.control({ releaseOthers: true });
if (game.version > 10) {
return canvas.animatePan(token.object.center);
} else {
return canvas.animatePan({ x: token.data.x, y: token.data.y });
}
}
},
"OVERRIDE"
);
});
4 changes: 4 additions & 0 deletions langs/en.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"initiative-double-click": {
"settings": {
"disableOpenSheet": {
"name": "Disable Double-click Opening Sheets",
"hint": "Disables the default Foundry behavior of opening a character's when double-clicking it on the Combat Tracker."
},
"player-access": {
"name": "Minimum Permission Level",
"hint": "Allows users with at least this permission level to modify initiative of owned tokens."
Expand Down
30 changes: 18 additions & 12 deletions module.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,24 @@
"name": "initiative-double-click",
"title": "Initiative Double Click",
"description": "Double click the initiative value in the combat tracker to quickly modify it.",
"author": "KaKaRoTo",
"authors": [],
"authors": [
{
"name": "Matheus Clemente",
"discord": "mclemente#5524",
"ko-fi": "mclemente"
},
{
"name": "KaKaRoTo"
}
],
"url": "https://github.com/League-of-Foundry-Developers/fvtt-initiative-double-click",
"flags": {},
"version": "1.4",
"minimumCoreVersion": "9",
"compatibleCoreVersion": "9",
"version": "1.6",
"minimumCoreVersion": "0.8.4",
"compatibleCoreVersion": "10",
"compatibility": {
"minimum": 9,
"verified": "10.277"
},
"esmodules": ["Combat.js"],
"styles": ["initiative.css"],
"languages": [
Expand All @@ -18,12 +29,7 @@
"path": "langs/en.json"
}
],
"packs": [],
"system": [],
"dependencies": [],
"socket": true,
"manifest": "https://github.com/League-of-Foundry-Developers/fvtt-initiative-double-click/releases/latest/download/module.json",
"download": "https://github.com/League-of-Foundry-Developers/fvtt-initiative-double-click/releases/latest/download/module.zip",
"protected": false,
"coreTranslation": false
"download": "https://github.com/League-of-Foundry-Developers/fvtt-initiative-double-click/releases/latest/download/module.zip"
}
131 changes: 131 additions & 0 deletions shim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: MIT
// Copyright © 2021 fvtt-lib-wrapper Rui Pinheiro


'use strict';

// A shim for the libWrapper library
export let libWrapper = undefined;

export const VERSIONS = [1,12,1];
export const TGT_SPLIT_RE = new RegExp("([^.[]+|\\[('([^'\\\\]|\\\\.)+?'|\"([^\"\\\\]|\\\\.)+?\")\\])", 'g');
export const TGT_CLEANUP_RE = new RegExp("(^\\['|'\\]$|^\\[\"|\"\\]$)", 'g');

// Main shim code
Hooks.once('init', () => {
// Check if the real module is already loaded - if so, use it
if(globalThis.libWrapper && !(globalThis.libWrapper.is_fallback ?? true)) {
libWrapper = globalThis.libWrapper;
return;
}

// Fallback implementation
libWrapper = class {
static get is_fallback() { return true };

static get WRAPPER() { return 'WRAPPER' };
static get MIXED() { return 'MIXED' };
static get OVERRIDE() { return 'OVERRIDE' };

static register(package_id, target, fn, type="MIXED", {chain=undefined, bind=[]}={}) {
const is_setter = target.endsWith('#set');
target = !is_setter ? target : target.slice(0, -4);
const split = target.match(TGT_SPLIT_RE).map((x)=>x.replace(/\\(.)/g, '$1').replace(TGT_CLEANUP_RE,''));
const root_nm = split.splice(0,1)[0];

let obj, fn_name;
if(split.length == 0) {
obj = globalThis;
fn_name = root_nm;
}
else {
const _eval = eval;
fn_name = split.pop();
obj = split.reduce((x,y)=>x[y], globalThis[root_nm] ?? _eval(root_nm));
}

let iObj = obj;
let descriptor = null;
while(iObj) {
descriptor = Object.getOwnPropertyDescriptor(iObj, fn_name);
if(descriptor) break;
iObj = Object.getPrototypeOf(iObj);
}
if(!descriptor || descriptor?.configurable === false) throw new Error(`libWrapper Shim: '${target}' does not exist, could not be found, or has a non-configurable descriptor.`);

let original = null;
const wrapper = (chain ?? (type.toUpperCase?.() != 'OVERRIDE' && type != 3)) ?
function(...args) { return fn.call(this, original.bind(this), ...bind, ...args); } :
function(...args) { return fn.call(this, ...bind, ...args); }
;

if(!is_setter) {
if(descriptor.value) {
original = descriptor.value;
descriptor.value = wrapper;
}
else {
original = descriptor.get;
descriptor.get = wrapper;
}
}
else {
if(!descriptor.set) throw new Error(`libWrapper Shim: '${target}' does not have a setter`);
original = descriptor.set;
descriptor.set = wrapper;
}

descriptor.configurable = true;
Object.defineProperty(obj, fn_name, descriptor);
}
}

//************** USER CUSTOMIZABLE:
// Set up the ready hook that shows the "libWrapper not installed" warning dialog. Remove if undesired.
{
//************** USER CUSTOMIZABLE:
// Package ID & Package Title - by default attempts to auto-detect, but you might want to hardcode your package ID and title here to avoid potential auto-detect issues
const [PACKAGE_ID, PACKAGE_TITLE] = (()=>{
const match = (import.meta?.url ?? Error().stack)?.match(/\/(worlds|systems|modules)\/(.+)(?=\/)/i);
if(match?.length !== 3) return [null,null];
const dirs = match[2].split('/');
if(match[1] === 'worlds') return dirs.find(n => n && game.world.id === n) ? [game.world.id, game.world.title] : [null,null];
if(match[1] === 'systems') return dirs.find(n => n && game.system.id === n) ? [game.system.id, game.system.data.title] : [null,null];
const id = dirs.find(n => n && game.modules.has(n));
return [id, game.modules.get(id)?.data?.title];
})();

if(!PACKAGE_ID || !PACKAGE_TITLE) {
console.error("libWrapper Shim: Could not auto-detect package ID and/or title. The libWrapper fallback warning dialog will be disabled.");
return;
}

Hooks.once('ready', () => {
//************** USER CUSTOMIZABLE:
// Title and message for the dialog shown when the real libWrapper is not installed.
const FALLBACK_MESSAGE_TITLE = PACKAGE_TITLE;
const FALLBACK_MESSAGE = `
<p><b>'${PACKAGE_TITLE}' depends on the 'libWrapper' module, which is not present.</b></p>
<p>A fallback implementation will be used, which increases the chance of compatibility issues with other modules.</p>
<small><p>'libWrapper' is a library which provides package developers with a simple way to modify core Foundry VTT code, while reducing the likelihood of conflict with other packages.</p>
<p>You can install it from the "Add-on Modules" tab in the <a href="javascript:game.shutDown()">Foundry VTT Setup</a>, from the <a href="https://foundryvtt.com/packages/lib-wrapper">Foundry VTT package repository</a>, or from <a href="https://github.com/ruipin/fvtt-lib-wrapper/">libWrapper's Github page</a>.</p></small>
`;

// Settings key used for the "Don't remind me again" setting
const DONT_REMIND_AGAIN_KEY = "libwrapper-dont-remind-again";

// Dialog code
console.warn(`${PACKAGE_TITLE}: libWrapper not present, using fallback implementation.`);
game.settings.register(PACKAGE_ID, DONT_REMIND_AGAIN_KEY, { name: '', default: false, type: Boolean, scope: 'world', config: false });
if(game.user.isGM && !game.settings.get(PACKAGE_ID, DONT_REMIND_AGAIN_KEY)) {
new Dialog({
title: FALLBACK_MESSAGE_TITLE,
content: FALLBACK_MESSAGE, buttons: {
ok: { icon: '<i class="fas fa-check"></i>', label: 'Understood' },
dont_remind: { icon: '<i class="fas fa-times"></i>', label: "Don't remind me again", callback: () => game.settings.set(PACKAGE_ID, DONT_REMIND_AGAIN_KEY, true) }
}
}).render(true);
}
});
}
});

0 comments on commit 6bccda6

Please sign in to comment.