From ba493f4f18c5e50faa92795a5989cab987aeade2 Mon Sep 17 00:00:00 2001
From: Johannes Loher <johannes.loher@fg4f.de>
Date: Wed, 30 Jun 2021 04:32:10 +0200
Subject: [PATCH] More WIP on 0.8.x migration

---
 src/module/actor/sheets/character-sheet.ts |  9 +++++----
 src/module/actor/sheets/creature-sheet.ts  |  9 +++++----
 src/module/global.d.ts                     |  6 ++++++
 src/module/item/item-sheet.ts              |  6 ++++--
 src/module/macros/helpers.ts               |  3 +++
 src/module/macros/roll-check.ts            | 10 ++++------
 src/module/macros/roll-item.ts             | 11 +++++------
 src/module/migrations/001.ts               |  2 +-
 src/module/rolls/check-factory.ts          | 19 +++++++++++++------
 src/module/rolls/check.ts                  |  2 +-
 src/module/rolls/roll.ts                   |  6 +++---
 src/module/rolls/slaying-dice-modifier.ts  |  6 +++---
 yarn.lock                                  |  4 ++--
 13 files changed, 55 insertions(+), 38 deletions(-)

diff --git a/src/module/actor/sheets/character-sheet.ts b/src/module/actor/sheets/character-sheet.ts
index ad2194ac..b101e86b 100644
--- a/src/module/actor/sheets/character-sheet.ts
+++ b/src/module/actor/sheets/character-sheet.ts
@@ -9,10 +9,11 @@ import { DS4ActorSheet } from "./actor-sheet";
  */
 export class DS4CharacterActorSheet extends DS4ActorSheet {
     /** @override */
-    static get defaultOptions(): BaseEntitySheet.Options {
-        const superDefaultOptions = super.defaultOptions;
-        return mergeObject(superDefaultOptions, {
-            ...superDefaultOptions,
+    static get defaultOptions(): ActorSheet.Options {
+        // TODO: Improve
+        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+        // @ts-ignore
+        return mergeObject(super.defaultOptions, {
             classes: ["ds4", "sheet", "actor", "character"],
         });
     }
diff --git a/src/module/actor/sheets/creature-sheet.ts b/src/module/actor/sheets/creature-sheet.ts
index 4364f25b..dada4e34 100644
--- a/src/module/actor/sheets/creature-sheet.ts
+++ b/src/module/actor/sheets/creature-sheet.ts
@@ -9,10 +9,11 @@ import { DS4ActorSheet } from "./actor-sheet";
  */
 export class DS4CreatureActorSheet extends DS4ActorSheet {
     /** @override */
-    static get defaultOptions(): BaseEntitySheet.Options {
-        const superDefaultOptions = super.defaultOptions;
-        return mergeObject(superDefaultOptions, {
-            ...superDefaultOptions,
+    static get defaultOptions(): ActorSheet.Options {
+        // TODO: Improve
+        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+        // @ts-ignore
+        return mergeObject(super.defaultOptions, {
             classes: ["ds4", "sheet", "actor", "creature"],
         });
     }
diff --git a/src/module/global.d.ts b/src/module/global.d.ts
index 72a5fcff..2b405c52 100644
--- a/src/module/global.d.ts
+++ b/src/module/global.d.ts
@@ -13,6 +13,12 @@ declare global {
         }
     }
 
+    namespace PoolTerm {
+        interface Modifiers {
+            x: (this: PoolTerm, modifier: string) => void;
+        }
+    }
+
     interface CONFIG {
         DS4: typeof DS4;
     }
diff --git a/src/module/item/item-sheet.ts b/src/module/item/item-sheet.ts
index 7d496423..5e53175d 100644
--- a/src/module/item/item-sheet.ts
+++ b/src/module/item/item-sheet.ts
@@ -15,8 +15,10 @@ import { isDS4ItemDataTypePhysical } from "./item-data-source";
 export class DS4ItemSheet extends ItemSheet {
     /** @override */
     static get defaultOptions(): ItemSheet.Options {
-        const superDefaultOptions = super.defaultOptions;
-        return mergeObject(superDefaultOptions, {
+        // TODO: Improve
+        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+        // @ts-ignore
+        return mergeObject(super.defaultOptions, {
             width: 540,
             height: 400,
             classes: ["ds4", "sheet", "item"],
diff --git a/src/module/macros/helpers.ts b/src/module/macros/helpers.ts
index f556cfce..1c978682 100644
--- a/src/module/macros/helpers.ts
+++ b/src/module/macros/helpers.ts
@@ -11,6 +11,9 @@ import { getCanvas } from "../helpers";
  * @returns The currently active {@link DS4Actor} if any, and `undefined` otherwise.
  */
 export function getActiveActor(): DS4Actor | undefined {
+    // TODO: Improve once ChatMessage is typed in upstream
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore
     const speaker = ChatMessage.getSpeaker();
 
     const speakerToken = speaker.token ? getCanvas().tokens.get(speaker.token) : undefined;
diff --git a/src/module/macros/roll-check.ts b/src/module/macros/roll-check.ts
index 4e24127f..86ce65a4 100644
--- a/src/module/macros/roll-check.ts
+++ b/src/module/macros/roll-check.ts
@@ -15,15 +15,13 @@ import { getActiveActor } from "./helpers";
  */
 export async function createRollCheckMacro(check: Check, slot: string): Promise<void> {
     const macro = await getOrCreateRollCheckMacro(check);
-    game.user?.assignHotbarMacro(macro, slot);
+    game.user?.assignHotbarMacro(macro ?? null, slot);
 }
 
-async function getOrCreateRollCheckMacro(check: Check): Promise<Macro | null> {
+async function getOrCreateRollCheckMacro(check: Check): Promise<Macro | undefined> {
     const command = `game.ds4.macros.rollCheck("${check}");`;
 
-    const existingMacro = game.macros?.entities.find(
-        (m) => m.name === DS4.i18n.checks[check] && m.data.command === command,
-    );
+    const existingMacro = game.macros?.find((m) => m.name === DS4.i18n.checks[check] && m.data.command === command);
     if (existingMacro) {
         return existingMacro;
     }
@@ -36,7 +34,7 @@ async function getOrCreateRollCheckMacro(check: Check): Promise<Macro | null> {
             img: DS4.icons.checks[check],
             flags: { "ds4.checkMacro": true },
         },
-        { displaySheet: false },
+        { renderSheet: false },
     );
 }
 
diff --git a/src/module/macros/roll-item.ts b/src/module/macros/roll-item.ts
index 8392d454..7be48a9d 100644
--- a/src/module/macros/roll-item.ts
+++ b/src/module/macros/roll-item.ts
@@ -2,7 +2,6 @@
 //
 // SPDX-License-Identifier: MIT
 
-import { DS4ItemData } from "../item/item-data-source";
 import notifications from "../ui/notifications";
 import { getActiveActor } from "./helpers";
 
@@ -12,15 +11,15 @@ import { getActiveActor } from "./helpers";
  * @param itemData - The item data
  * @param slot     - The hotbar slot to use
  */
-export async function createRollItemMacro(itemData: DS4ItemData, slot: string): Promise<void> {
+export async function createRollItemMacro(itemData: foundry.data.ItemData["_source"], slot: string): Promise<void> {
     const macro = await getOrCreateRollItemMacro(itemData);
-    game.user?.assignHotbarMacro(macro, slot);
+    game.user?.assignHotbarMacro(macro ?? null, slot);
 }
 
-async function getOrCreateRollItemMacro(itemData: DS4ItemData): Promise<Macro | null> {
+async function getOrCreateRollItemMacro(itemData: foundry.data.ItemData["_source"]): Promise<Macro | undefined> {
     const command = `game.ds4.macros.rollItem("${itemData._id}");`;
 
-    const existingMacro = game.macros?.entities.find((m) => m.name === itemData.name && m.data.command === command);
+    const existingMacro = game.macros?.find((m) => m.name === itemData.name && m.data.command === command);
     if (existingMacro) {
         return existingMacro;
     }
@@ -33,7 +32,7 @@ async function getOrCreateRollItemMacro(itemData: DS4ItemData): Promise<Macro |
             img: itemData.img,
             flags: { "ds4.itemMacro": true },
         },
-        { displaySheet: false },
+        { renderSheet: false },
     );
 }
 
diff --git a/src/module/migrations/001.ts b/src/module/migrations/001.ts
index 9ca2143b..f210ec76 100644
--- a/src/module/migrations/001.ts
+++ b/src/module/migrations/001.ts
@@ -5,7 +5,7 @@
 import logger from "../logger";
 
 export async function migrate(): Promise<void> {
-    for (const a of game.actors?.entities ?? []) {
+    for (const a of game.actors ?? []) {
         const updateData = getActorUpdateData();
         logger.info(`Migrating actor ${a.name}`);
         await a.update(updateData, { enforceTypes: false });
diff --git a/src/module/rolls/check-factory.ts b/src/module/rolls/check-factory.ts
index 4db78c97..9cbaec31 100644
--- a/src/module/rolls/check-factory.ts
+++ b/src/module/rolls/check-factory.ts
@@ -10,7 +10,7 @@ class DefaultCheckOptions implements DS4CheckFactoryOptions {
     readonly maximumCoupResult = 1;
     readonly minimumFumbleResult = 20;
     readonly useSlayingDice = false;
-    readonly rollMode: Const.DiceRollMode = "roll";
+    readonly rollMode: foundry.CONST.DiceRollMode = "roll";
     readonly flavor: undefined;
 
     mergeWith(other: Partial<DS4CheckFactoryOptions>): DS4CheckFactoryOptions {
@@ -37,17 +37,24 @@ class CheckFactory {
 
     private options: DS4CheckFactoryOptions;
 
-    async execute(): Promise<ChatMessage> {
+    async execute(): Promise<ChatMessage | undefined> {
         const innerFormula = ["ds", this.createCheckTargetNumberModifier(), this.createCoupFumbleModifier()].filterJoin(
             "",
         );
         const formula = this.options.useSlayingDice ? `{${innerFormula}}x` : innerFormula;
         const roll = Roll.create(formula);
 
-        return roll.toMessage(
-            { speaker: ChatMessage.getSpeaker(), flavor: this.options.flavor },
+        // TODO: Improve once ChatMessage is typed in upstream
+        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+        // @ts-ignore
+        const speaker = ChatMessage.getSpeaker();
+
+        const a = roll.toMessage(
+            { speaker, flavor: this.options.flavor },
             { rollMode: this.options.rollMode, create: true },
         );
+
+        return a;
     }
 
     createCheckTargetNumberModifier(): string {
@@ -190,7 +197,7 @@ function parseDialogFormData(formData: HTMLFormElement): Partial<IntermediateGmM
  */
 interface GmModifierData {
     gmModifier: number;
-    rollMode: Const.DiceRollMode;
+    rollMode: foundry.CONST.DiceRollMode;
 }
 
 /**
@@ -221,6 +228,6 @@ export interface DS4CheckFactoryOptions {
     maximumCoupResult: number;
     minimumFumbleResult: number;
     useSlayingDice: boolean;
-    rollMode: Const.DiceRollMode;
+    rollMode: foundry.CONST.DiceRollMode;
     flavor?: string;
 }
diff --git a/src/module/rolls/check.ts b/src/module/rolls/check.ts
index f41dc614..d3692c89 100644
--- a/src/module/rolls/check.ts
+++ b/src/module/rolls/check.ts
@@ -72,7 +72,7 @@ export class DS4Check extends DiceTerm {
     }
 
     /** @override */
-    get total(): number | null {
+    get total(): string | number | null | undefined {
         if (this.fumble) return 0;
         return super.total;
     }
diff --git a/src/module/rolls/roll.ts b/src/module/rolls/roll.ts
index eb58f65c..8860a854 100644
--- a/src/module/rolls/roll.ts
+++ b/src/module/rolls/roll.ts
@@ -12,10 +12,10 @@ export class DS4Roll<D extends Record<string, unknown> = Record<string, unknown>
      * template if the first dice term is a ds4 check.
      * @override
      */
-    async render(chatOptions: Roll.ChatOptions = {}): Promise<string> {
+    async render(chatOptions: Parameters<Roll["render"]>[0] = {}): Promise<string> {
         chatOptions = mergeObject(
             {
-                user: game.user?._id,
+                user: game.user?.id,
                 flavor: null,
                 template: DS4Roll.CHAT_TEMPLATE,
                 blind: false,
@@ -25,7 +25,7 @@ export class DS4Roll<D extends Record<string, unknown> = Record<string, unknown>
         const isPrivate = chatOptions.isPrivate;
 
         // Execute the roll, if needed
-        if (!this._rolled) this.roll();
+        if (!this._evaluated) this.evaluate();
 
         // Define chat data
         const firstDiceTerm = this.dice[0];
diff --git a/src/module/rolls/slaying-dice-modifier.ts b/src/module/rolls/slaying-dice-modifier.ts
index f178c038..bdd849ee 100644
--- a/src/module/rolls/slaying-dice-modifier.ts
+++ b/src/module/rolls/slaying-dice-modifier.ts
@@ -6,11 +6,11 @@
 import { DS4Check } from "./check";
 
 export default function registerSlayingDiceModifier(): void {
-    DicePool.MODIFIERS.x = slay;
-    DicePool.POOL_REGEX = /^{([^}]+)}([A-z]([A-z0-9<=>]+)?)?$/;
+    PoolTerm.MODIFIERS.x = slay;
+    PoolTerm.POOL_REGEX = /^{([^}]+)}([A-z]([A-z0-9<=>]+)?)?$/;
 }
 
-function slay(this: DicePool, modifier: string): void {
+function slay(this: PoolTerm, modifier: string): void {
     const rgx = /[xX]/;
     const match = modifier.match(rgx);
     if (!match || !this.rolls) return;
diff --git a/yarn.lock b/yarn.lock
index 08498fc1..830fab24 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -841,7 +841,7 @@ __metadata:
 
 "@league-of-foundry-developers/foundry-vtt-types@https://github.com/League-of-Foundry-Developers/foundry-vtt-types.git#foundry-0.8.x":
   version: 0.7.9-6
-  resolution: "@league-of-foundry-developers/foundry-vtt-types@https://github.com/League-of-Foundry-Developers/foundry-vtt-types.git#commit=f242ac76237f2099f946b10d642f0b3272ead043"
+  resolution: "@league-of-foundry-developers/foundry-vtt-types@https://github.com/League-of-Foundry-Developers/foundry-vtt-types.git#commit=9ea68fe6147f4e3da061754c599482c8607f93fa"
   dependencies:
     "@types/jquery": ~3.5.5
     "@types/simple-peer": ~9.11.0
@@ -851,7 +851,7 @@ __metadata:
     socket.io-client: 4.1.2
     tinymce: 5.8.1
     typescript: ^4.1.6
-  checksum: ae81444ddf4b36bff67a2483cc559ff64dd1fdaaada277439e2ed14a8ec8233f06723b9421be70033b38383d9c275de18b216307bb14b17feafc5866156b0ac3
+  checksum: 6945db2b6be3204e63d2be0f3a05115b810875de3a8031383b409049c03a65b3c3e033323b47c819b1d773d57c51e495eac1af343a0325e07f075acd988998d5
   languageName: node
   linkType: hard