diff --git a/src/module/ds4.ts b/src/module/ds4.ts index 59904351..337bb604 100644 --- a/src/module/ds4.ts +++ b/src/module/ds4.ts @@ -1,107 +1,3 @@ -import { DS4Actor } from "./actor/actor"; -import { DS4CharacterActorSheet } from "./actor/sheets/character-sheet"; -import { DS4CreatureActorSheet } from "./actor/sheets/creature-sheet"; -import { DS4 } from "./config"; -import registerHandlebarsHelpers from "./handlebars/handlebars-helpers"; -import registerHandlebarsPartials from "./handlebars/handlebars-partials"; import registerForHooks from "./hooks/hooks"; -import { DS4Item } from "./item/item"; -import { DS4ItemSheet } from "./item/item-sheet"; -import { macros } from "./macros/macros"; -import { migration } from "./migrations"; -import { DS4Check } from "./rolls/check"; -import { createCheckRoll } from "./rolls/check-factory"; -import { DS4Roll } from "./rolls/roll"; -import registerSlayingDiceModifier from "./rolls/slaying-dice-modifier"; -import { registerSystemSettings } from "./settings"; -Hooks.once("init", async () => { - console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`); - - game.ds4 = { - DS4Actor, - DS4Item, - DS4, - createCheckRoll, - migration, - macros, - }; - - CONFIG.DS4 = DS4; - - CONFIG.Actor.entityClass = DS4Actor; - CONFIG.Item.entityClass = DS4Item; - - CONFIG.Actor.typeLabels = DS4.i18n.actorTypes; - CONFIG.Item.typeLabels = DS4.i18n.itemTypes; - - CONFIG.Dice.types.push(DS4Check); - CONFIG.Dice.terms.s = DS4Check; - - CONFIG.Dice.rolls.unshift(DS4Roll); - - registerSlayingDiceModifier(); - - registerSystemSettings(); - - Actors.unregisterSheet("core", ActorSheet); - Actors.registerSheet("ds4", DS4CharacterActorSheet, { types: ["character"], makeDefault: true }); - Actors.registerSheet("ds4", DS4CreatureActorSheet, { types: ["creature"], makeDefault: true }); - Items.unregisterSheet("core", ItemSheet); - Items.registerSheet("ds4", DS4ItemSheet, { makeDefault: true }); - - await registerHandlebarsPartials(); - registerHandlebarsHelpers(); - - registerForHooks(); -}); - -/** - * This function runs after game data has been requested and loaded from the servers, so entities exist - */ -Hooks.once("setup", () => { - localizeAndSortConfigObjects(); -}); - -Hooks.once("ready", () => { - migration.migrate(); -}); - -/** - * Select the text of input elements in given sheets via onfocus listener. - * The hook names are of the form "render"+sheet_superclassname and are called within - * the render() method of the foundry Application class. - * Note: The render hooks of all classes in the class hierarchy are called, - * so e.g. for a Dialog, both "renderDialog" and "renderApplication" are called - * (in this order). - */ -["renderApplication", "renderActorSheet", "renderItemSheet"].forEach((hookName: string) => { - Hooks.on(hookName, (app: Dialog, html: JQueryStatic) => { - $(html) - .find("input") - .on("focus", (ev: JQuery.FocusEvent) => { - ev.currentTarget.select(); - }); - }); -}); - -/** - * Localizes all objects in {@link DS4.i18n} and sorts them unless they are explicitly excluded. - */ -function localizeAndSortConfigObjects() { - const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"]; - - const localizeObject = (obj: T, sort = true): T => { - const localized = Object.entries(obj).map(([key, value]) => { - return [key, game.i18n.localize(value)]; - }); - if (sort) localized.sort((a, b) => a[1].localeCompare(b[1])); - return Object.fromEntries(localized); - }; - - DS4.i18n = Object.fromEntries( - Object.entries(DS4.i18n).map(([key, value]) => { - return [key, localizeObject(value, !noSort.includes(key))]; - }), - ) as typeof DS4.i18n; -} +registerForHooks(); diff --git a/src/module/hooks/hooks.ts b/src/module/hooks/hooks.ts index 5b0da07c..72509895 100644 --- a/src/module/hooks/hooks.ts +++ b/src/module/hooks/hooks.ts @@ -1,5 +1,13 @@ import registerForHotbarDropHook from "./hotbar-drop"; +import registerForInitHook from "./init"; +import registerForReadyHook from "./ready"; +import registerForRenderHooks from "./render"; +import registerForSetupHook from "./setup"; export default function registerForHooks(): void { registerForHotbarDropHook(); + registerForInitHook(); + registerForReadyHook(); + registerForRenderHooks(); + registerForSetupHook(); } diff --git a/src/module/hooks/init.ts b/src/module/hooks/init.ts new file mode 100644 index 00000000..4722da94 --- /dev/null +++ b/src/module/hooks/init.ts @@ -0,0 +1,58 @@ +import { DS4Actor } from "../actor/actor"; +import { DS4CharacterActorSheet } from "../actor/sheets/character-sheet"; +import { DS4CreatureActorSheet } from "../actor/sheets/creature-sheet"; +import { DS4 } from "../config"; +import registerHandlebarsHelpers from "../handlebars/handlebars-helpers"; +import registerHandlebarsPartials from "../handlebars/handlebars-partials"; +import { DS4Item } from "../item/item"; +import { DS4ItemSheet } from "../item/item-sheet"; +import { macros } from "../macros/macros"; +import { migration } from "../migrations"; +import { DS4Check } from "../rolls/check"; +import { createCheckRoll } from "../rolls/check-factory"; +import { DS4Roll } from "../rolls/roll"; +import registerSlayingDiceModifier from "../rolls/slaying-dice-modifier"; +import { registerSystemSettings } from "../settings"; + +export default function registerForInitHook(): void { + Hooks.once("init", init); +} + +async function init() { + console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`); + + game.ds4 = { + DS4Actor, + DS4Item, + DS4, + createCheckRoll, + migration, + macros, + }; + + CONFIG.DS4 = DS4; + + CONFIG.Actor.entityClass = DS4Actor; + CONFIG.Item.entityClass = DS4Item; + + CONFIG.Actor.typeLabels = DS4.i18n.actorTypes; + CONFIG.Item.typeLabels = DS4.i18n.itemTypes; + + CONFIG.Dice.types.push(DS4Check); + CONFIG.Dice.terms.s = DS4Check; + + CONFIG.Dice.rolls.unshift(DS4Roll); + + registerSlayingDiceModifier(); + + registerSystemSettings(); + + Actors.unregisterSheet("core", ActorSheet); + Actors.registerSheet("ds4", DS4CharacterActorSheet, { types: ["character"], makeDefault: true }); + Actors.registerSheet("ds4", DS4CreatureActorSheet, { types: ["creature"], makeDefault: true }); + Items.unregisterSheet("core", ItemSheet); + Items.registerSheet("ds4", DS4ItemSheet, { makeDefault: true }); + + await registerHandlebarsPartials(); + registerHandlebarsHelpers(); +} diff --git a/src/module/hooks/ready.ts b/src/module/hooks/ready.ts new file mode 100644 index 00000000..07cbb899 --- /dev/null +++ b/src/module/hooks/ready.ts @@ -0,0 +1,7 @@ +import { migration } from "../migrations"; + +export default function registerForReadyHook(): void { + Hooks.once("ready", () => { + migration.migrate(); + }); +} diff --git a/src/module/hooks/render.ts b/src/module/hooks/render.ts new file mode 100644 index 00000000..b1e0fc2e --- /dev/null +++ b/src/module/hooks/render.ts @@ -0,0 +1,23 @@ +/** + * @remarks The render hooks of all classes in the class hierarchy are called, so e.g. for a {@link Dialog}, both the + * "renderDialog" hook and the "renderApplication" hook are called (in this order). + */ +export default function registerForRenderHooks(): void { + ["renderApplication", "renderActorSheet", "renderItemSheet"].forEach((hook) => { + Hooks.on(hook, selectTargetInputOnFocus); + }); +} + +/** + * Select the text of input elements in given application when focused via an on focus listener. + * + * @param app - The application in which to activate the listener. + * @param html - The {@link JQuery} representing the HTML of the application. + */ +function selectTargetInputOnFocus(app: Application, html: JQuery) { + $(html) + .find("input") + .on("focus", (ev: JQuery.FocusEvent) => { + ev.currentTarget.select(); + }); +} diff --git a/src/module/hooks/setup.ts b/src/module/hooks/setup.ts new file mode 100644 index 00000000..78bce9b3 --- /dev/null +++ b/src/module/hooks/setup.ts @@ -0,0 +1,32 @@ +import { DS4 } from "../config"; + +/** + * @remarks The "setup" hook is called after game data has been requested and loaded from the server, so entities + * already exist. + */ +export default function registerForSetupHooks(): void { + Hooks.once("setup", () => { + localizeAndSortConfigObjects(); + }); +} + +/** + * Localizes all objects in {@link DS4.i18n} and sorts them unless they are explicitly excluded. + */ +function localizeAndSortConfigObjects() { + const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"]; + + const localizeObject = (obj: T, sort = true): T => { + const localized = Object.entries(obj).map(([key, value]) => { + return [key, game.i18n.localize(value)]; + }); + if (sort) localized.sort((a, b) => a[1].localeCompare(b[1])); + return Object.fromEntries(localized); + }; + + DS4.i18n = Object.fromEntries( + Object.entries(DS4.i18n).map(([key, value]) => { + return [key, localizeObject(value, !noSort.includes(key))]; + }), + ) as typeof DS4.i18n; +} diff --git a/src/module/macros/roll-item-macro.ts b/src/module/macros/roll-item-macro.ts index 0ceabcf5..2bf36588 100644 --- a/src/module/macros/roll-item-macro.ts +++ b/src/module/macros/roll-item-macro.ts @@ -4,7 +4,7 @@ import { DS4ItemData } from "../item/item-data"; import notifications from "../ui/notifications"; /** - * Create a Macro from an item drop. + * Creates a macro from an item drop. * Get an existing item macro if one exists, otherwise create a new one. * @param itemData - The item data * @param slot - The hotbar slot to use @@ -27,7 +27,7 @@ export async function createRollItemMacro(itemData: DS4ItemData, slot: string): } /** - * Execute the roll item macro for the given itemId. + * Executes the roll item macro for the given itemId. * @param itemId */ export async function rollItem(itemId: string): Promise {