diff --git a/langs/en-ca.json b/langs/en-ca.json index fb9462f..7f94af9 100644 --- a/langs/en-ca.json +++ b/langs/en-ca.json @@ -1,6 +1,10 @@ { "OFT": { "setting": { + "autoUnpauseOnLoad": { + "name": "Auto Unpause On Load", + "hint": "(v13+, GM-Only) Automatically unpauses the game when you load into the world. This will happen EVERY time you load into the world, including if you reload the website." + }, "chatSidebarBackground": { "name": "Chat Background", "hint": "(v13+) Adds a background to the chat tab of the right-hand sidebar." @@ -32,6 +36,16 @@ "blank": "No Custom Default Tab" } } + }, + "menu": { + "devSettings": { + "name": "Developer Settings", + "hint": "Tweaks that are relevant if you are developing something within Foundry, but are rarely useful outside of that context.", + "label": "Configure Dev Settings" + } + }, + "apps": { + "no-settings-to-display": "No settings to display" } } } diff --git a/module/apps/DevSettingsMenu.mjs b/module/apps/DevSettingsMenu.mjs new file mode 100644 index 0000000..909fbab --- /dev/null +++ b/module/apps/DevSettingsMenu.mjs @@ -0,0 +1,20 @@ +import { devSettings } from "../utils/DevSettings.mjs"; +import { OFTSettingsMenu } from "./OFTSettingsMenu.mjs"; + +export class DevSettingsMenu extends OFTSettingsMenu { + static DEFAULT_OPTIONS = { + window: { + title: `OFT.menu.devSettings.name`, + }, + }; + + static get _SETTINGS() { + const settingIDs = []; + for (const [settingID, shown] of devSettings.entries()) { + if (shown) { + settingIDs.push(settingID); + }; + }; + return settingIDs; + }; +}; diff --git a/module/hooks/renderSettingsConfig.mjs b/module/hooks/renderSettingsConfig.mjs new file mode 100644 index 0000000..b4e28d8 --- /dev/null +++ b/module/hooks/renderSettingsConfig.mjs @@ -0,0 +1,19 @@ +import { __ID__ } from "../consts.mjs"; + +/* +Repositions the dev settings menu entry to the bottom of the settings list to +prevent it from being as attention-grabbing compared to being at the top of the +list. +*/ +Hooks.on(`renderSettingsConfig`, (app) => { + /** @type {Node | undefined} */ + const settingList = app.element.querySelector(`.tab[data-group="categories"][data-tab="oft"]`); + + + // MARK: devSettings Menu + /** @type {Node | undefined} */ + const devSettingsMenu = app.element.querySelector(`.form-group:has(button[data-key="${__ID__}.devSettings"])`); + if (settingList && devSettingsMenu) { + settingList.appendChild(devSettingsMenu); + }; +}); diff --git a/module/oft.mjs b/module/oft.mjs index b3af40b..da43fac 100644 --- a/module/oft.mjs +++ b/module/oft.mjs @@ -1,3 +1,6 @@ +// Hooks +import "./hooks/renderSettingsConfig.mjs"; + // Settings import { chatSidebarBackground } from "./settings/chatSidebarBackground.mjs"; import { hotbarButtonGap } from "./settings/hotbarButtonGap.mjs"; @@ -7,7 +10,24 @@ import { repositionHotbar } from "./settings/repositionHotbar.mjs"; import { startingSidebarTab } from "./settings/startingSidebarTab.mjs"; import { startSidebarExpanded } from "./settings/startSidebarExpanded.mjs"; -Hooks.on(`init`, () => { +// Apps +import { DevSettingsMenu } from "./apps/DevSettingsMenu.mjs"; + +// Misc +import { __ID__ } from "./consts.mjs"; +import { autoUnpauseOnLoad } from "./settings/autoUnpauseOnLoad.mjs"; + +Hooks.on(`setup`, () => { + + game.settings.registerMenu(__ID__, `devSettings`, { + name: `OFT.menu.devSettings.name`, + hint: `OFT.menu.devSettings.hint`, + label: `OFT.menu.devSettings.label`, + restricted: false, + type: DevSettingsMenu, + }); + autoUnpauseOnLoad(); + chatSidebarBackground(); startSidebarExpanded(); startingSidebarTab(); diff --git a/module/settings/autoUnpauseOnLoad.mjs b/module/settings/autoUnpauseOnLoad.mjs new file mode 100644 index 0000000..03ddea4 --- /dev/null +++ b/module/settings/autoUnpauseOnLoad.mjs @@ -0,0 +1,37 @@ +import { __ID__ } from "../consts.mjs"; +import { Logger } from "../utils/Logger.mjs"; +import { registerDevSetting } from "../utils/DevSettings.mjs"; + +const key = `autoUnpauseOnLoad`; + +export function autoUnpauseOnLoad() { + + const prevented = Hooks.call(`${__ID__}.preventSetting`, key); + if (!prevented) { + Logger.log(`Preventing setting "${key}" from being registered`); + return; + }; + + // #region Registration + Logger.log(`Registering setting: ${key}`); + registerDevSetting(__ID__, key, { + name: `OFT.setting.${key}.name`, + hint: `OFT.setting.${key}.hint`, + scope: `client`, + type: Boolean, + default: false, + config: game.user.isGM, + requiresReload: false, + }); + // #endregion Registration + + // #region Implementation + Hooks.once(`ready`, () => { + const autoUnpause = game.settings.get(__ID__, key); + if (autoUnpause && game.paused) { + Logger.debug(`setting:${key} | Unpausing the game`); + game.togglePause(false, { broadcast: true }); + }; + }); + // #endregion Implementation +}; diff --git a/module/utils/DevSettings.mjs b/module/utils/DevSettings.mjs new file mode 100644 index 0000000..7d847fa --- /dev/null +++ b/module/utils/DevSettings.mjs @@ -0,0 +1,9 @@ +/** @type {Map} */ +export const devSettings = new Map(); + +export function registerDevSetting(namespace, key, config) { + const visible = config.config; + config.config = false; + game.settings.register(namespace, key, config); + devSettings.set(`${namespace}.${key}`, visible); +};