Add the very first dev-oriented setting and a DevSettingsConfig to manage it

This commit is contained in:
Oliver 2025-12-07 17:38:08 -07:00
parent 28d0105397
commit 5573a5b674
6 changed files with 120 additions and 1 deletions

View file

@ -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"
}
}
}

View file

@ -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;
};
};

View file

@ -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);
};
});

View file

@ -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();

View file

@ -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
};

View file

@ -0,0 +1,9 @@
/** @type {Map<string, boolean>} */
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);
};