MWI_Toolkit

MWI工具集

// ==UserScript==
// @name         MWI_Toolkit
// @namespace    http://tampermonkey.net/
// @version      5.0.5
// @description  MWI工具集
// @author       zqzhang1996
// @match        https://www.milkywayidle.com/*
// @match        https://test.milkywayidle.com/*
// @require      https://cdn.jsdelivr.net/npm/[email protected]/libs/lz-string.min.js
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-body
// @license      MIT
// ==/UserScript==
(function () {
    'use strict';
    //#region Calculator
    class TargetItemCategory {
        constructor(categoryHrid, needCalc = true) {
            this.needCalc = true;
            this.categoryDetailsElement = null;
            this.categorySummaryElement = null;
            this.needCalcCheckbox = null;
            this.categoryHrid = categoryHrid;
            this.needCalc = needCalc;
        }
        updateDisplayElement() {
            this.categoryDetailsElement.style.background = this.needCalc ? '#0E4F32' : '#2c2e45';
            this.categorySummaryElement.style.background = this.needCalc ? '#147147' : '#393a5b';
            this.needCalcCheckbox.checked = this.needCalc;
        }
    }
    class DisplayItem {
        constructor(itemHrid, count) {
            this.itemHrid = itemHrid;
            this.count = count;
            this.initDisplayProperties();
        }
        initDisplayProperties() {
            if (Object.values(MWI_Toolkit_ActionDetailPlus.processableItemList).includes(this.itemHrid)) {
                this.categoryHrid = '/item_categories/materials';
            }
            else {
                this.categoryHrid = MWI_Toolkit.initClientData?.itemDetailMap?.[this.itemHrid].categoryHrid;
            }
            this.displayName = MWI_Toolkit_I18n.getItemName(this.itemHrid);
            this.iconHref = MWI_Toolkit_Utils.getIconHrefByItemHrid(this.itemHrid);
            this.sortIndex = MWI_Toolkit_Utils.getSortIndexByItemHrid(this.itemHrid);
        }
        getOwnedCount() {
            return MWI_Toolkit_ItemsMap.getCount(this.itemHrid);
        }
    }
    class TargetItem extends DisplayItem {
        constructor(itemHrid, count, needCalc = true) {
            super(itemHrid, count);
            this.needCalc = true;
            this.displayElement = null;
            this.needCalcCheckbox = null;
            this.ownedSpan = null;
            this.targetInput = null;
            this.needCalc = needCalc;
        }
        updateDisplayElement() {
            if (this.needCalcCheckbox) {
                this.needCalcCheckbox.checked = this.needCalc;
                this.displayElement.style.background = this.needCalc ? '' : '#2c2e45';
            }
            if (this.ownedSpan) {
                const newText = MWI_Toolkit_Utils.formatNumber(this.getOwnedCount());
                if (this.ownedSpan.textContent !== newText) {
                    this.ownedSpan.textContent = newText;
                }
            }
            if (this.targetInput) {
                const newText = this.count.toString();
                if (this.targetInput.value.trim() === '' && this.count != 0) {
                    this.targetInput.value = newText;
                }
            }
        }
        removeDisplayElement() {
            this.displayElement?.remove();
        }
    }
    class TargetHouseRoom extends TargetItem {
        constructor(houseRoomHrid, level, needCalc = true) {
            super(houseRoomHrid, level, needCalc);
        }
        initDisplayProperties() {
            this.categoryHrid = '/item_categories/house_rooms';
            this.displayName = MWI_Toolkit_I18n.getName(this.itemHrid, 'houseRoomNames');
            this.iconHref = MWI_Toolkit_Utils.getIconHrefByHouseRoomHrid(this.itemHrid);
            this.sortIndex = MWI_Toolkit_Utils.getSortIndexByHouseRoomHrid(this.itemHrid);
        }
        getOwnedCount() {
            return MWI_Toolkit.gameObject?.state?.characterHouseRoomDict?.[this.itemHrid]?.level || 0;
        }
    }
    class RequiredItem extends DisplayItem {
        constructor(itemHrid, count, equivalentCount) {
            super(itemHrid, count);
            this.equivalentCount = 0;
            this.shortageDisplayElement = null;
            this.requiredDisplayElement = null;
            this.shortageSpan = null;
            this.ownedSpan = null;
            this.equivalentSpan = null;
            this.requiredSpan = null;
            this.requiredDiv = null;
            this.equivalentCount = equivalentCount;
        }
        getShortageCount() {
            return this.count - this.getOwnedCount() - this.equivalentCount;
        }
        updateDisplayElement() {
            const ownedCount = this.getOwnedCount();
            const shortageCount = this.getShortageCount();
            if (this.shortageSpan) {
                const newText = MWI_Toolkit_Utils.formatNumber(shortageCount);
                if (this.shortageSpan.textContent !== newText) {
                    this.shortageSpan.textContent = newText;
                }
                this.shortageDisplayElement.style.display = shortageCount > 0 ? 'flex' : 'none';
            }
            if (this.equivalentSpan) {
                const newText = MWI_Toolkit_Utils.formatNumber(this.equivalentCount) + '+';
                if (this.equivalentSpan.textContent !== newText) {
                    this.equivalentSpan.textContent = newText;
                }
                this.equivalentSpan.hidden = this.equivalentCount <= 0;
            }
            if (this.ownedSpan) {
                const newText = MWI_Toolkit_Utils.formatNumber(ownedCount) + '/';
                if (this.ownedSpan.textContent !== newText) {
                    this.ownedSpan.textContent = newText;
                }
            }
            if (this.requiredSpan) {
                const newText = MWI_Toolkit_Utils.formatNumber(this.count);
                if (this.requiredSpan.textContent !== newText) {
                    this.requiredSpan.textContent = newText;
                }
                this.requiredDiv.style.color = shortageCount > 0 ? '#f44336' : '#E7E7E7';
            }
        }
        removeDisplayElement() {
            this.shortageDisplayElement?.remove();
            this.requiredDisplayElement?.remove();
        }
    }
    class MWI_Toolkit_Calculator {
        static getStorageKey(characterID = null) {
            if (!characterID) {
                characterID = MWI_Toolkit?.gameObject?.state?.character?.id;
            }
            return `MWI_Toolkit_Calculator_TargetItems_${characterID}`;
        }
        // 保存目标物品
        static saveTargetItems() {
            const storageKey = MWI_Toolkit_Calculator.getStorageKey();
            const storageKey_Category = storageKey.replace('TargetItems', 'TargetItemCategories');
            const dataToSave = [...MWI_Toolkit_Calculator.targetItemsMap.values()].map(item => ({
                itemHrid: item.itemHrid,
                count: item.count,
                needCalc: item.needCalc
            }));
            const dataToSave_Category = [...MWI_Toolkit_Calculator.targetItemCategoryMap.values()].map(category => ({
                categoryHrid: category.categoryHrid,
                needCalc: category.needCalc
            }));
            try {
                GM_setValue(storageKey, JSON.stringify(dataToSave));
                GM_setValue(storageKey_Category, JSON.stringify(dataToSave_Category));
                return true;
            }
            catch (error) {
                console.error('[MWI_Toolkit]' + error);
                return false;
            }
        }
        // 从特定角色ID加载数据
        static loadTargetItems(characterID = null) {
            const storageKey = MWI_Toolkit_Calculator.getStorageKey(characterID);
            const storageKey_Category = storageKey.replace('TargetItems', 'TargetItemCategories');
            try {
                const savedData = GM_getValue(storageKey, '[]');
                const savedData_Category = GM_getValue(storageKey_Category, '[]');
                const loadedItems = JSON.parse(savedData);
                const loadedCategories = JSON.parse(savedData_Category);
                // 验证并转换为Item实例
                const validItemsMap = new Map(loadedItems.map((item) => {
                    try {
                        if (item.itemHrid.includes('/items/')) {
                            return [item.itemHrid, new TargetItem(item.itemHrid, item.count, typeof item.needCalc === 'boolean' ? item.needCalc : true)];
                        }
                        if (item.itemHrid.includes('/house_rooms/')) {
                            return [item.itemHrid, new TargetHouseRoom(item.itemHrid, item.count, typeof item.needCalc === 'boolean' ? item.needCalc : true)];
                        }
                    }
                    catch {
                        return null;
                    }
                }).filter((item) => item !== null));
                loadedCategories.forEach((category) => {
                    if (MWI_Toolkit_Calculator.targetItemCategoryMap.has(category.categoryHrid)) {
                        MWI_Toolkit_Calculator.targetItemCategoryMap.get(category.categoryHrid).needCalc = category.needCalc;
                    }
                    else {
                        MWI_Toolkit_Calculator.targetItemCategoryMap.set(category.categoryHrid, new TargetItemCategory(category.categoryHrid, category.needCalc));
                    }
                });
                if (validItemsMap.size > 0) {
                    MWI_Toolkit_Calculator.clearAllTargetItems();
                    MWI_Toolkit_Calculator.targetItemsMap = validItemsMap;
                    MWI_Toolkit_Calculator.renderItemsDisplay();
                    MWI_Toolkit_Calculator.saveTargetItems();
                }
            }
            catch (error) {
                console.error('[MWI_Toolkit]' + error);
            }
        }
        // 更新目标物品
        static updateTargetItem(itemHrid, count = 1) {
            if (!itemHrid)
                return;
            const item = MWI_Toolkit_Calculator.targetItemsMap.get(itemHrid);
            if (item) {
                item.count = count;
            }
            else {
                // 添加新物品
                if (itemHrid.includes('/items/')) {
                    MWI_Toolkit_Calculator.targetItemsMap.set(itemHrid, new TargetItem(itemHrid, count));
                }
                if (itemHrid.includes('/house_rooms/')) {
                    MWI_Toolkit_Calculator.targetItemsMap.set(itemHrid, new TargetHouseRoom(itemHrid, count));
                }
            }
            MWI_Toolkit_Calculator.saveAndScheduleRender();
        }
        // 删除目标物品
        static removeTargetItem(itemHrid) {
            if (!itemHrid)
                return;
            MWI_Toolkit_Calculator.targetItemsMap.get(itemHrid)?.removeDisplayElement();
            MWI_Toolkit_Calculator.targetItemsMap.delete(itemHrid);
            MWI_Toolkit_Calculator.saveAndScheduleRender();
        }
        // 清空目标物品
        static clearAllTargetItems() {
            MWI_Toolkit_Calculator.targetItemsMap.forEach(item => item.removeDisplayElement());
            MWI_Toolkit_Calculator.targetItemsMap.clear();
            MWI_Toolkit_Calculator.saveAndScheduleRender();
        }
        // 保存数据并计划渲染
        static saveAndScheduleRender() {
            // 保存数据到存储
            MWI_Toolkit_Calculator.saveTargetItems();
            MWI_Toolkit_Calculator.scheduleRender();
        }
        // 计划延迟渲染
        static scheduleRender() {
            // 清除之前的计时器
            if (MWI_Toolkit_Calculator.renderTimeout) {
                clearTimeout(MWI_Toolkit_Calculator.renderTimeout);
            }
            // 设置新的计时器
            MWI_Toolkit_Calculator.renderTimeout = setTimeout(() => {
                MWI_Toolkit_Calculator.renderItemsDisplay();
                MWI_Toolkit_Calculator.renderTimeout = null;
            }, 300); // 300ms 防抖延迟
        }
        // 递归计算所需材料
        static calculateRequiredItems(targetItem) {
            if (targetItem.count === 0)
                return [];
            if (targetItem.itemHrid.includes('/house_rooms/')) {
                // 处理房屋房间逻辑
                return this.calculateRequiredItemsForHouseRoom(targetItem.itemHrid, targetItem.count);
            }
            let requiredItems = new Array();
            requiredItems.push({ itemHrid: targetItem.itemHrid, count: targetItem.count });
            const actionTypes = ["cheesesmithing", "crafting", "tailoring", "cooking", "brewing"];
            const itemName = targetItem.itemHrid.split('/').pop();
            for (const actionType of actionTypes) {
                const actionHrid = `/actions/${actionType}/${itemName}`;
                if (MWI_Toolkit.initClientData?.actionDetailMap?.hasOwnProperty(actionHrid)) {
                    const actionDetail = MWI_Toolkit.initClientData?.actionDetailMap[actionHrid];
                    const upgradeItemHrid = actionDetail.upgradeItemHrid;
                    const inputItems = actionDetail.inputItems;
                    let outputCount = 1;
                    const outputItems = actionDetail.outputItems;
                    if (outputItems && outputItems.length > 0) {
                        const matchingOutput = outputItems.find(output => output.itemHrid === targetItem.itemHrid);
                        if (matchingOutput) {
                            outputCount = matchingOutput.count;
                        }
                    }
                    const actionTypeDrinkSlots = MWI_Toolkit_ActionDetailPlus.getActionTypeDrinkSlots(actionType);
                    // 检查工匠茶加成
                    let artisanBuff = 0;
                    if (actionTypeDrinkSlots?.some(itemHrid => itemHrid === '/items/artisan_tea')) {
                        artisanBuff = 0.1 * MWI_Toolkit_ActionDetailPlus.getDrinkConcentration();
                    }
                    // 检查美食茶加成
                    let gourmetBuff = 0;
                    if (actionTypeDrinkSlots?.some(itemHrid => itemHrid === '/items/gourmet_tea')) {
                        gourmetBuff = 0.12 * MWI_Toolkit_ActionDetailPlus.getDrinkConcentration();
                    }
                    // 递归计算输入材料
                    for (const input of inputItems) {
                        const adjustedCount = input.count * targetItem.count / outputCount / (1 + gourmetBuff) * (1 - artisanBuff);
                        requiredItems = MWI_Toolkit_Calculator.mergeItemArrays(requiredItems, MWI_Toolkit_Calculator.calculateRequiredItems({ itemHrid: input.itemHrid, count: adjustedCount }));
                    }
                    // 处理升级物品(不适用工匠茶加成)
                    if (upgradeItemHrid) {
                        requiredItems = MWI_Toolkit_Calculator.mergeItemArrays(requiredItems, MWI_Toolkit_Calculator.calculateRequiredItems({ itemHrid: upgradeItemHrid, count: targetItem.count / outputCount / (1 + gourmetBuff) }));
                    }
                    return requiredItems;
                }
            }
            // 添加地下城代币兑换材料计算
            if (requiredItems.length === 1) {
                const shopHrid = `/shop_items/${itemName}`;
                if (MWI_Toolkit.initClientData?.shopItemDetailMap?.hasOwnProperty(shopHrid)) {
                    const shopItemDetail = MWI_Toolkit.initClientData?.shopItemDetailMap[shopHrid];
                    if (shopItemDetail.category === "/shop_categories/dungeon") {
                        shopItemDetail.costs.forEach(cost => {
                            requiredItems.push({ itemHrid: cost.itemHrid, count: cost.count * targetItem.count });
                        });
                    }
                }
            }
            return requiredItems;
        }
        // 批量计算材料需求
        static batchCalculateRequiredItems(targetItems) {
            let allRequiredItems = new Array();
            for (const targetItem of targetItems) {
                const requiredItems = MWI_Toolkit_Calculator.calculateRequiredItems(targetItem);
                allRequiredItems = MWI_Toolkit_Calculator.mergeItemArrays(allRequiredItems, requiredItems);
            }
            return allRequiredItems;
        }
        // 计算房屋房间所需材料
        static calculateRequiredItemsForHouseRoom(targetHouseRoomHrid, targetHouseRoomLevel) {
            let targetItems = Array();
            const characterHouseRoomLevel = MWI_Toolkit.gameObject.state.characterHouseRoomDict?.[targetHouseRoomHrid]?.level || 0;
            const upgradeCostsMap = MWI_Toolkit.initClientData?.houseRoomDetailMap?.[targetHouseRoomHrid]?.upgradeCostsMap;
            for (let i = characterHouseRoomLevel + 1; i <= targetHouseRoomLevel && i <= 8; i++) {
                targetItems = targetItems.concat(upgradeCostsMap[i] || []);
            }
            return MWI_Toolkit_Calculator.batchCalculateRequiredItems(targetItems);
        }
        // 计算等效材料
        static calculateEquivalentItems(requiredItems) {
            const ownedItems = new Array();
            const ownedItemsNG = new Array();
            for (const requiredItem of requiredItems) {
                const ownedCount = MWI_Toolkit_ItemsMap.getCount(requiredItem.itemHrid);
                // 负目标数量用于手动标记已有的等效物品
                const targetItemNG = MWI_Toolkit_Calculator.targetItemsMap.get(requiredItem.itemHrid);
                const targetCountNG = Math.min((targetItemNG?.needCalc && targetItemNG?.count) ? targetItemNG.count : 0, 0);
                // 这里count取required和owned-equivalent中的较小值,用于抵消需求
                ownedItems.push({ itemHrid: requiredItem.itemHrid, count: Math.min(requiredItem.count, ownedCount - targetCountNG) });
                ownedItemsNG.push({ itemHrid: requiredItem.itemHrid, count: Math.min(requiredItem.count, ownedCount) * -1 });
            }
            // 减掉原值得到等效值
            return MWI_Toolkit_Calculator.mergeItemArrays(MWI_Toolkit_Calculator.batchCalculateRequiredItems(ownedItems), ownedItemsNG);
        }
        // 合并材料数组并按排序顺序返回
        static mergeItemArrays(arr1, arr2) {
            const map = new Map();
            for (const item of arr1.concat(arr2)) {
                if (map.has(item.itemHrid)) {
                    if (item.itemHrid.includes('/items/')) {
                        map.get(item.itemHrid).count += item.count;
                    }
                    if (item.itemHrid.includes('/house_rooms/')) {
                        map.get(item.itemHrid).count = Math.max(map.get(item.itemHrid).count, item.count);
                    }
                }
                else {
                    map.set(item.itemHrid, { itemHrid: item.itemHrid, count: item.count });
                }
            }
            // 排序
            return Array.from(map.values()).sort((a, b) => MWI_Toolkit_Utils.getSortIndexByItemHrid(a.itemHrid) - MWI_Toolkit_Utils.getSortIndexByItemHrid(b.itemHrid));
        }
        static initialize() {
            MWI_Toolkit_ItemsMap.itemsUpdatedCallbacks.push((enditemsMap) => {
                MWI_Toolkit_Calculator.scheduleRender();
            });
        }
        static initializeCalculatorUI() {
            MWI_Toolkit.waitForElement('[class^="CharacterManagement_tabsComponentContainer"] [class*="TabsComponent_tabsContainer"]', () => {
                MWI_Toolkit_Calculator.createCalculatorUI();
            });
        }
        // 初始化UI
        static createCalculatorUI() {
            // 已有标签页则不重复初始化
            if (document.querySelector('[class^="Toolkit_Calculator_Container"]')) {
                return;
            }
            // 获取容器
            const tabsContainer = document.querySelector('[class^="CharacterManagement_tabsComponentContainer"] [class*="TabsComponent_tabsContainer"]');
            const tabPanelsContainer = document.querySelector('[class^="CharacterManagement_tabsComponentContainer"] [class*="TabsComponent_tabPanelsContainer"]');
            if (!tabsContainer || !tabPanelsContainer) {
                console.error('[MWI_Toolkit_Calculator] 无法找到标签页容器');
                return;
            }
            MWI_Toolkit_Calculator.createCalculatorTab(tabsContainer, tabPanelsContainer);
            MWI_Toolkit_Calculator.targetItemsMap = new Map();
            MWI_Toolkit_Calculator.requiredItemsMap = new Map();
            // 加载保存数据
            MWI_Toolkit_Calculator.loadTargetItems();
            console.log('[MWI_Toolkit_Calculator] UI初始化完成');
        }
        // 创建MWI计算器标签页
        static createCalculatorTab(tabsContainer, tabPanelsContainer) {
            // 新增"MWI计算器"按钮
            const oldTabButtons = tabsContainer.querySelectorAll("button");
            MWI_Toolkit_Calculator.tabButton = oldTabButtons[1].cloneNode(true);
            MWI_Toolkit_Calculator.tabButton.children[0].textContent = (MWI_Toolkit.getGameLanguage() === 'zh') ? 'MWI计算器' : 'MWI_Calculator';
            oldTabButtons[0].parentElement.appendChild(MWI_Toolkit_Calculator.tabButton);
            // 新增MWI计算器tabPanel
            const oldTabPanels = tabPanelsContainer.querySelectorAll('[class*="TabPanel_tabPanel"]');
            MWI_Toolkit_Calculator.tabPanel = oldTabPanels[1].cloneNode(false);
            oldTabPanels[0].parentElement.appendChild(MWI_Toolkit_Calculator.tabPanel);
            MWI_Toolkit_Calculator.bindCalculatorTabEvents(oldTabButtons, oldTabPanels);
            // 创建计算器面板
            const calculatorPanel = MWI_Toolkit_Calculator.createCalculatorPanel();
            MWI_Toolkit_Calculator.tabPanel.appendChild(calculatorPanel);
        }
        // 绑定标签页事件
        static bindCalculatorTabEvents(oldTabButtons, oldTabPanels) {
            for (let i = 0; i < oldTabButtons.length; i++) {
                oldTabButtons[i].addEventListener('click', () => {
                    MWI_Toolkit_Calculator.tabPanel.hidden = true; // 强制隐藏
                    MWI_Toolkit_Calculator.tabPanel.classList.add('TabPanel_hidden__26UM3');
                    MWI_Toolkit_Calculator.tabButton.classList.remove('Mui-selected');
                    MWI_Toolkit_Calculator.tabButton.setAttribute('aria-selected', 'false');
                    MWI_Toolkit_Calculator.tabButton.tabIndex = -1;
                    oldTabButtons[i].classList.add('Mui-selected');
                    oldTabButtons[i].setAttribute('aria-selected', 'true');
                    oldTabButtons[i].tabIndex = 0;
                    oldTabPanels[i].classList.remove('TabPanel_hidden__26UM3');
                    oldTabPanels[i].hidden = false; // 显示目标
                }, true);
            }
            MWI_Toolkit_Calculator.tabButton.addEventListener('click', () => {
                oldTabButtons.forEach(btn => {
                    btn.classList.remove('Mui-selected');
                    btn.setAttribute('aria-selected', 'false');
                    btn.tabIndex = -1;
                });
                oldTabPanels.forEach(panel => {
                    panel.hidden = true; // 强制隐藏
                    panel.classList.add('TabPanel_hidden__26UM3');
                });
                MWI_Toolkit_Calculator.tabButton.classList.add('Mui-selected');
                MWI_Toolkit_Calculator.tabButton.setAttribute('aria-selected', 'true');
                MWI_Toolkit_Calculator.tabButton.tabIndex = 0;
                MWI_Toolkit_Calculator.tabPanel.classList.remove('TabPanel_hidden__26UM3');
                MWI_Toolkit_Calculator.tabPanel.hidden = false; // 显示目标
            }, true);
        }
        // 创建计算器面板
        static createCalculatorPanel() {
            const calculatorPanel = document.createElement('div');
            calculatorPanel.className = 'Toolkit_Calculator_Container';
            // 创建物品搜索区域
            const addItemSection = MWI_Toolkit_Calculator.createAddItemSection();
            calculatorPanel.appendChild(addItemSection);
            // 左侧区域
            const leftDiv = document.createElement('div');
            leftDiv.style.display = 'inline-block';
            leftDiv.style.verticalAlign = 'top';
            leftDiv.style.width = '60%';
            leftDiv.style.padding = '0px 2px';
            MWI_Toolkit_Calculator.createItemDetailsMap(leftDiv, MWI_Toolkit_Calculator.targetItemDetailsMap);
            calculatorPanel.appendChild(leftDiv);
            MWI_Toolkit_Calculator.targetItemDetailsMap.forEach((details, categoryHrid) => {
                const summary = details.querySelector('summary');
                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.style.verticalAlign = 'middle';
                if (!MWI_Toolkit_Calculator.targetItemCategoryMap.has(categoryHrid)) {
                    MWI_Toolkit_Calculator.targetItemCategoryMap.set(categoryHrid, new TargetItemCategory(categoryHrid));
                }
                MWI_Toolkit_Calculator.targetItemCategoryMap.get(categoryHrid).categoryDetailsElement = details;
                MWI_Toolkit_Calculator.targetItemCategoryMap.get(categoryHrid).categorySummaryElement = summary;
                MWI_Toolkit_Calculator.targetItemCategoryMap.get(categoryHrid).needCalcCheckbox = checkbox;
                checkbox.checked = MWI_Toolkit_Calculator.targetItemCategoryMap.get(categoryHrid).needCalc;
                checkbox.addEventListener('change', () => {
                    MWI_Toolkit_Calculator.targetItemCategoryMap.get(categoryHrid).needCalc = checkbox.checked;
                    MWI_Toolkit_Calculator.saveAndScheduleRender();
                });
                summary.prepend(checkbox);
            });
            // 右侧区域
            const rightDiv = document.createElement('div');
            rightDiv.style.display = 'inline-block';
            rightDiv.style.verticalAlign = 'top';
            rightDiv.style.width = '40%';
            rightDiv.style.padding = '0px 2px';
            const shortageItemDetails = document.createElement('details');
            shortageItemDetails.style.background = '#902f10';
            shortageItemDetails.style.borderRadius = '4px';
            shortageItemDetails.style.padding = '2px';
            shortageItemDetails.open = true;
            const shortageSummary = document.createElement('summary');
            shortageSummary.textContent = MWI_Toolkit.getGameLanguage() === 'zh' ? '缺口' : 'Shortages';
            shortageSummary.style.background = '#af3914';
            shortageSummary.style.borderRadius = '4px';
            shortageSummary.style.fontSize = '14px';
            shortageSummary.style.padding = '2px 6px';
            shortageSummary.style.textAlign = 'left';
            shortageSummary.style.cursor = 'pointer';
            shortageItemDetails.appendChild(shortageSummary);
            MWI_Toolkit_Calculator.createItemDetailsMap(shortageItemDetails, MWI_Toolkit_Calculator.shortageItemDetailsMap);
            rightDiv.appendChild(shortageItemDetails);
            const requiredItemDetails = document.createElement('details');
            requiredItemDetails.style.background = '#0c385a';
            requiredItemDetails.style.borderRadius = '4px';
            requiredItemDetails.style.padding = '2px';
            const requiredSummary = document.createElement('summary');
            requiredSummary.textContent = MWI_Toolkit.getGameLanguage() === 'zh' ? '详情(等效+库存/需求)' : 'Status(Equivalent+Owned/Required)';
            requiredSummary.style.background = '#1770b3';
            requiredSummary.style.borderRadius = '4px';
            requiredSummary.style.fontSize = '14px';
            requiredSummary.style.padding = '2px 6px';
            requiredSummary.style.textAlign = 'left';
            requiredSummary.style.cursor = 'pointer';
            requiredItemDetails.appendChild(requiredSummary);
            MWI_Toolkit_Calculator.createItemDetailsMap(requiredItemDetails, MWI_Toolkit_Calculator.requiredItemDetailsMap);
            rightDiv.appendChild(requiredItemDetails);
            calculatorPanel.appendChild(rightDiv);
            return calculatorPanel;
        }
        // 创建物品分类区域
        static createItemDetailsMap(container, ItemDetailsMap) {
            MWI_Toolkit_Calculator.itemCategoryList.forEach(categoryHrid => {
                const details = document.createElement('details');
                details.style.background = '#2c2e45';
                details.style.borderRadius = '4px';
                details.style.margin = '2px 0px';
                details.open = true;
                const summary = document.createElement('summary');
                summary.textContent = MWI_Toolkit_I18n.getName(categoryHrid, 'itemCategoryNames');
                summary.style.background = '#393a5b';
                summary.style.borderRadius = '4px';
                summary.style.fontSize = '14px';
                summary.style.padding = '2px 6px';
                summary.style.textAlign = 'left';
                summary.style.cursor = 'pointer';
                details.appendChild(summary);
                container.appendChild(details);
                ItemDetailsMap.set(categoryHrid, details);
            });
        }
        // 创建添加物品区域
        static createAddItemSection() {
            const addItemSection = document.createElement('div');
            // 左侧60%:物品搜索区域
            const leftSection = document.createElement('div');
            leftSection.style.display = 'inline-block';
            leftSection.style.verticalAlign = 'top';
            leftSection.style.width = '60%';
            const searchContainer = MWI_Toolkit_Calculator.createItemSearchComponent();
            leftSection.appendChild(searchContainer);
            // 右侧40%:房屋选择区域
            const rightSection = document.createElement('div');
            rightSection.style.display = 'inline-block';
            rightSection.style.verticalAlign = 'top';
            rightSection.style.width = '40%';
            const houseContainer = MWI_Toolkit_Calculator.createHouseRoomSelectionComponent();
            rightSection.appendChild(houseContainer);
            addItemSection.appendChild(leftSection);
            addItemSection.appendChild(rightSection);
            return addItemSection;
        }
        // 创建物品搜索组件
        static createItemSearchComponent() {
            const itemSearchComponent = document.createElement('div');
            itemSearchComponent.style.background = '#2c2e45';
            itemSearchComponent.style.border = 'none';
            itemSearchComponent.style.borderRadius = '4px';
            itemSearchComponent.style.padding = '4px';
            itemSearchComponent.style.margin = '2px';
            itemSearchComponent.style.display = 'flex';
            itemSearchComponent.style.position = 'relative';
            // 物品搜索输入框
            const itemSearchInput = document.createElement('input');
            itemSearchInput.type = 'text';
            itemSearchInput.placeholder = (MWI_Toolkit.getGameLanguage() === 'zh') ? '搜索物品名称...' : 'Search item name...';
            itemSearchInput.style.background = '#dde2f8';
            itemSearchInput.style.color = '#000000';
            itemSearchInput.style.border = 'none';
            itemSearchInput.style.borderRadius = '4px';
            itemSearchInput.style.padding = '4px';
            itemSearchInput.style.margin = '2px';
            itemSearchInput.style.minWidth = '40px';
            itemSearchInput.style.flex = '1';
            // 搜索结果下拉列表
            const searchResults = document.createElement('div');
            searchResults.style.background = '#2c2e45';
            searchResults.style.border = 'none';
            searchResults.style.borderRadius = '4px';
            searchResults.style.padding = '4px';
            searchResults.style.margin = '2px';
            searchResults.style.width = '200px';
            searchResults.style.maxHeight = '335px';
            searchResults.style.overflowY = 'auto';
            searchResults.style.zIndex = '1000';
            searchResults.style.display = 'none';
            searchResults.style.position = 'absolute';
            searchResults.style.left = '4px';
            searchResults.style.top = '32px';
            // 数量输入框
            const countInput = document.createElement('input');
            countInput.type = 'text';
            countInput.value = '1';
            countInput.placeholder = (MWI_Toolkit.getGameLanguage() === 'zh') ? '数量' : 'Count';
            countInput.style.background = '#dde2f8';
            countInput.style.color = '#000000';
            countInput.style.border = 'none';
            countInput.style.borderRadius = '4px';
            countInput.style.padding = '4px';
            countInput.style.margin = '2px';
            countInput.style.width = '60px';
            // 添加按钮
            const addButton = document.createElement('button');
            addButton.textContent = (MWI_Toolkit.getGameLanguage() === 'zh') ? '添加' : 'Add';
            addButton.style.background = '#4CAF50';
            addButton.style.color = '#FFFFFF';
            addButton.style.border = 'none';
            addButton.style.borderRadius = '4px';
            addButton.style.padding = '4px';
            addButton.style.margin = '2px';
            addButton.style.cursor = 'pointer';
            // 清空按钮
            const clearAllButton = document.createElement('button');
            clearAllButton.textContent = (MWI_Toolkit.getGameLanguage() === 'zh') ? '清空' : 'Clear';
            clearAllButton.style.background = '#f44336';
            clearAllButton.style.color = '#FFFFFF';
            clearAllButton.style.border = 'none';
            clearAllButton.style.borderRadius = '4px';
            clearAllButton.style.padding = '4px';
            clearAllButton.style.margin = '2px';
            clearAllButton.style.cursor = 'pointer';
            // 绑定搜索事件
            MWI_Toolkit_Calculator.bindItemSearchComponentEvents(itemSearchInput, countInput, searchResults, addButton, clearAllButton);
            itemSearchComponent.appendChild(itemSearchInput);
            itemSearchComponent.appendChild(countInput);
            itemSearchComponent.appendChild(addButton);
            itemSearchComponent.appendChild(clearAllButton);
            itemSearchComponent.appendChild(searchResults);
            return itemSearchComponent;
        }
        // 绑定搜索相关事件
        static bindItemSearchComponentEvents(itemSearchInput, countInput, searchResults, addButton, clearAllButton) {
            // 输入框获得焦点时全选内容
            itemSearchInput.addEventListener('focus', () => {
                setTimeout(() => {
                    itemSearchInput.select();
                }, 0);
            });
            // 搜索功能
            itemSearchInput.addEventListener('input', () => {
                const searchTerm = itemSearchInput.value.toLowerCase().trim();
                if (searchTerm.length < 2) {
                    searchResults.style.display = 'none';
                    return;
                }
                // 获取并过滤物品
                const itemDetailMap = MWI_Toolkit?.initClientData?.itemDetailMap;
                if (!itemDetailMap)
                    return;
                const filteredItems = Object.keys(itemDetailMap)
                    .filter(itemHrid => {
                    return MWI_Toolkit_I18n.getItemName(itemHrid).toLowerCase().includes(searchTerm);
                })
                    .sort((a, b) => {
                    const sortIndexA = MWI_Toolkit_Utils.getSortIndexByItemHrid(a);
                    const sortIndexB = MWI_Toolkit_Utils.getSortIndexByItemHrid(b);
                    return sortIndexA - sortIndexB;
                });
                if (filteredItems.length === 0) {
                    searchResults.style.display = 'none';
                    return;
                }
                MWI_Toolkit_Calculator.populateSearchResults(searchResults, filteredItems, (itemHrid) => {
                    itemSearchInput.value = MWI_Toolkit_I18n.getItemName(itemHrid);
                    searchResults.style.display = 'none';
                });
                searchResults.style.display = 'block';
            });
            // 键盘操作
            itemSearchInput.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    e.preventDefault();
                    MWI_Toolkit_Calculator.addItemAndResetItemSearchComponent(itemSearchInput, countInput, searchResults);
                }
                else if (e.key === 'Escape') {
                    searchResults.style.display = 'none';
                }
            });
            // 输入框获得焦点时全选内容
            countInput.addEventListener('focus', () => {
                setTimeout(() => {
                    countInput.select();
                }, 0);
            });
            // 仅允许输入数字
            countInput.addEventListener('input', () => {
                // 只允许负号在首位,其余为数字
                countInput.value = countInput.value.replace(/(?!^)-|[^\d-]/g, '');
            });
            // 键盘操作
            countInput.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    e.preventDefault();
                    MWI_Toolkit_Calculator.addItemAndResetItemSearchComponent(itemSearchInput, countInput, searchResults);
                }
                else if (e.key === 'Escape') {
                    searchResults.style.display = 'none';
                }
            });
            // 添加按钮事件
            addButton.addEventListener('click', () => {
                MWI_Toolkit_Calculator.addItemAndResetItemSearchComponent(itemSearchInput, countInput, searchResults);
            });
            // 清空按钮事件
            clearAllButton.addEventListener('click', () => {
                if (confirm((MWI_Toolkit.getGameLanguage() === 'zh') ? '确定要清空所有目标物品吗?' : 'Are you sure you want to clear all target items?')) {
                    // 通过事件处理器清空
                    MWI_Toolkit_Calculator.clearAllTargetItems();
                }
            });
            // 点击其他地方隐藏搜索结果
            document.addEventListener('click', () => {
                searchResults.style.display = 'none';
            });
        }
        // 填充搜索结果
        static populateSearchResults(searchResults, filteredItems, onItemSelect) {
            searchResults.innerHTML = '';
            filteredItems.forEach((itemHrid, index) => {
                const resultItem = document.createElement('div');
                resultItem.style.borderBottom = '1px solid #98a7e9';
                resultItem.style.borderRadius = '4px';
                resultItem.style.padding = '4px';
                resultItem.style.alignItems = 'center';
                resultItem.style.display = 'flex';
                resultItem.style.cursor = 'pointer';
                if (index === 0) {
                    resultItem.style.background = '#4a4c6a';
                }
                // 物品图标
                const itemIcon = document.createElement('div');
                const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
                svg.setAttribute('width', '16px');
                svg.setAttribute('height', '16px');
                svg.style.display = 'block';
                const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
                use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', MWI_Toolkit_Utils.getIconHrefByItemHrid(itemHrid));
                svg.appendChild(use);
                itemIcon.appendChild(svg);
                // 物品名称
                const itemName = document.createElement('span');
                itemName.textContent = MWI_Toolkit_I18n.getItemName(itemHrid);
                itemName.style.marginLeft = '2px';
                resultItem.appendChild(itemIcon);
                resultItem.appendChild(itemName);
                // 悬停高亮
                resultItem.addEventListener('mouseenter', () => {
                    resultItem.style.background = '#4a4c6a';
                });
                resultItem.addEventListener('mouseleave', () => {
                    resultItem.style.background = 'transparent';
                });
                resultItem.addEventListener('click', () => onItemSelect(itemHrid));
                searchResults.appendChild(resultItem);
            });
        }
        // 添加物品并重置搜索组件(包含itemHrid获取和判空)
        static addItemAndResetItemSearchComponent(itemSearchInput, countInput, searchResults) {
            const InputValue = itemSearchInput.value.trim();
            // 如果InputValue是纯数字,则视为从特定角色加载数据
            if (/^\d+$/.test(InputValue)) {
                const characterID = parseInt(InputValue, 10);
                MWI_Toolkit_Calculator.loadTargetItems(characterID);
                return;
            }
            const itemHrid = MWI_Toolkit_I18n.getItemHridByName(InputValue);
            if (!itemHrid)
                return;
            const count = parseInt(countInput.value, 10) || 1;
            MWI_Toolkit_Calculator.updateTargetItem(itemHrid, count);
            itemSearchInput.value = '';
            countInput.value = '1';
            searchResults.style.display = 'none';
        }
        // 创建房屋选择区域
        static createHouseRoomSelectionComponent() {
            const HouseRoomSelectionComponent = document.createElement('div');
            HouseRoomSelectionComponent.style.background = '#2c2e45';
            HouseRoomSelectionComponent.style.border = 'none';
            HouseRoomSelectionComponent.style.borderRadius = '4px';
            HouseRoomSelectionComponent.style.padding = '4px';
            HouseRoomSelectionComponent.style.margin = '2px';
            HouseRoomSelectionComponent.style.display = 'flex';
            // 下拉菜单
            const dropdown = MWI_Toolkit_Calculator.createHouseRoomTypeDropdown();
            // 等级输入框
            const levelInput = document.createElement('input');
            levelInput.type = 'number';
            levelInput.min = '1';
            levelInput.max = '8';
            levelInput.step = '1';
            levelInput.value = '1';
            levelInput.placeholder = (MWI_Toolkit.getGameLanguage() === 'zh') ? '等级' : 'Level';
            levelInput.style.background = '#dde2f8';
            levelInput.style.color = '#000000';
            levelInput.style.border = 'none';
            levelInput.style.borderRadius = '4px';
            levelInput.style.padding = '4px';
            levelInput.style.margin = '2px';
            levelInput.style.width = '35px';
            // 添加按钮
            const addListButton = document.createElement('button');
            addListButton.textContent = (MWI_Toolkit.getGameLanguage() === 'zh') ? '添加' : 'Add';
            addListButton.style.background = '#4CAF50';
            addListButton.style.color = '#FFFFFF';
            addListButton.style.border = 'none';
            addListButton.style.borderRadius = '4px';
            addListButton.style.padding = '4px';
            addListButton.style.margin = '2px';
            addListButton.style.width = '35px';
            addListButton.style.cursor = 'pointer';
            // 绑定事件
            MWI_Toolkit_Calculator.bindHouseRoomSelectionComponentEvents(dropdown, levelInput, addListButton);
            HouseRoomSelectionComponent.appendChild(dropdown);
            HouseRoomSelectionComponent.appendChild(levelInput);
            HouseRoomSelectionComponent.appendChild(addListButton);
            return HouseRoomSelectionComponent;
        }
        // 创建房屋类型下拉菜单
        static createHouseRoomTypeDropdown() {
            // 创建容器
            const dropdown = document.createElement('div');
            dropdown.style.display = 'flex';
            dropdown.style.minWidth = '20px';
            dropdown.style.flex = '1';
            dropdown.style.position = 'relative';
            // 选中项显示区
            const selected = document.createElement('div');
            selected.style.background = '#393a5b';
            selected.style.color = '#000000';
            selected.style.border = 'none';
            selected.style.borderRadius = '4px';
            selected.style.paddingLeft = '4px';
            selected.style.margin = '2px';
            selected.style.minWidth = '40px';
            selected.style.flex = '1';
            selected.style.cursor = 'pointer';
            selected.style.display = 'flex';
            selected.style.alignItems = 'center';
            // 下拉菜单列表
            const list = document.createElement('div');
            list.style.background = '#2c2e45';
            list.style.border = 'none';
            list.style.borderRadius = '4px';
            list.style.padding = '4px';
            list.style.margin = '2px';
            list.style.width = '150px';
            list.style.maxHeight = '335px';
            list.style.overflowY = 'auto';
            list.style.zIndex = '1000';
            list.style.display = 'none';
            list.style.position = 'absolute';
            list.style.left = '0px';
            list.style.top = '32px';
            const HouseRoomTypeOptions = MWI_Toolkit_Calculator.createHouseRoomTypeOptions(selected, dropdown);
            HouseRoomTypeOptions.forEach(optionItem => { list.appendChild(optionItem); });
            HouseRoomTypeOptions[0] && HouseRoomTypeOptions[0].click(); // 默认选中第一个
            dropdown.appendChild(selected);
            dropdown.appendChild(list);
            // 点击展开/收起
            selected.addEventListener('click', (e) => {
                e.stopPropagation();
                list.style.display = list.style.display === 'block' ? 'none' : 'block';
            });
            // 点击外部关闭
            document.addEventListener('click', () => {
                list.style.display = 'none';
            });
            return dropdown;
        }
        // 创建房屋类型选项
        static createHouseRoomTypeOptions(selected, dropdown) {
            const houseRoomDetailMap = MWI_Toolkit.initClientData?.houseRoomDetailMap;
            if (!houseRoomDetailMap) {
                return [];
            }
            return Object.values(houseRoomDetailMap)
                .sort((a, b) => (a.sortIndex ?? 9999) - (b.sortIndex ?? 9999))
                .map(houseRoomDetail => {
                const optionItem = document.createElement('div');
                optionItem.style.borderBottom = '1px solid #98a7e9';
                optionItem.style.borderRadius = '4px';
                optionItem.style.padding = '4px';
                optionItem.style.alignItems = 'center';
                optionItem.style.display = 'flex';
                optionItem.style.cursor = 'pointer';
                // 房屋房间图标
                const houseRoomIcon = document.createElement('div');
                const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
                svg.setAttribute('width', '16px');
                svg.setAttribute('height', '16px');
                svg.style.display = 'block';
                const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
                use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', MWI_Toolkit_Utils.getIconHrefBySkillHrid(houseRoomDetail.skillHrid));
                svg.appendChild(use);
                houseRoomIcon.appendChild(svg);
                // 房屋房间名称
                const houseRoomName = document.createElement('span');
                houseRoomName.textContent = MWI_Toolkit_I18n?.getName(houseRoomDetail.hrid, "houseRoomNames") || houseRoomDetail.hrid;
                houseRoomName.style.marginLeft = '2px';
                houseRoomName.style.whiteSpace = 'nowrap';
                houseRoomName.style.overflow = 'hidden';
                optionItem.appendChild(houseRoomIcon);
                optionItem.appendChild(houseRoomName);
                optionItem.addEventListener('click', () => {
                    selected.innerHTML = '';
                    const selectedIcon = houseRoomIcon.cloneNode(true);
                    selected.appendChild(selectedIcon);
                    const selectedName = houseRoomName.cloneNode(true);
                    selectedName.style.color = '#FFFFFF';
                    selected.appendChild(selectedName);
                    dropdown.dataset.houseRoomHrid = houseRoomDetail.hrid;
                    optionItem.parentElement.style.display = 'none';
                });
                // 悬停高亮
                optionItem.addEventListener('mouseenter', () => {
                    optionItem.style.background = '#4a4c6a';
                });
                optionItem.addEventListener('mouseleave', () => {
                    optionItem.style.background = 'transparent';
                });
                optionItem.dataset.houseRoomHrid = houseRoomDetail.hrid;
                return optionItem;
            });
        }
        // 绑定房屋选择相关事件
        static bindHouseRoomSelectionComponentEvents(dropdown, levelInput, addListButton) {
            // 输入框获得焦点时全选内容
            levelInput.addEventListener('focus', function () {
                setTimeout(() => {
                    levelInput.select();
                }, 0);
            });
            // 添加按钮事件
            addListButton.addEventListener('click', () => {
                const houseRoomHrid = dropdown.dataset.houseRoomHrid;
                const level = parseInt(levelInput.value) || 1;
                MWI_Toolkit_Calculator.updateTargetItem(houseRoomHrid, level);
            });
        }
        // 渲染物品列表
        static renderItemsDisplay() {
            MWI_Toolkit_Calculator.targetItemCategoryMap.forEach((category) => {
                category.updateDisplayElement();
            });
            // 这里只需要新增或更新,删除在targetItems变动时进行处理
            MWI_Toolkit_Calculator.itemCategoryList.forEach(categoryHrid => {
                const details = MWI_Toolkit_Calculator.targetItemDetailsMap.get(categoryHrid);
                let lastElement = details.querySelector('summary');
                let itemCount = 0;
                [...MWI_Toolkit_Calculator.targetItemsMap.values()]
                    .sort((a, b) => a.sortIndex - b.sortIndex)
                    .forEach(targetItem => {
                    if (targetItem.categoryHrid !== categoryHrid) {
                        return;
                    }
                    if (!targetItem.displayElement) {
                        MWI_Toolkit_Calculator.createTargetItemDisplayElement(targetItem);
                        lastElement.insertAdjacentElement('afterend', targetItem.displayElement);
                    }
                    targetItem.updateDisplayElement();
                    lastElement = targetItem.displayElement;
                    itemCount++;
                });
                details.hidden = itemCount === 0;
            });
            const targetItemsToCalc = [...MWI_Toolkit_Calculator.targetItemsMap.values()]
                .sort((a, b) => a.sortIndex - b.sortIndex)
                .filter(item => item.needCalc && item.count > 0 && (MWI_Toolkit_Calculator.targetItemCategoryMap.get(item.categoryHrid)?.needCalc ?? true))
                .map(item => ({ itemHrid: item.itemHrid, count: item.count }));
            // 计算需求物品显示数据
            // batchCalculateRequiredItems返回的requiredItems已经是有序的
            const requiredItems = MWI_Toolkit_Calculator.batchCalculateRequiredItems(targetItemsToCalc);
            const equivalentItems = MWI_Toolkit_Calculator.calculateEquivalentItems(requiredItems);
            // 移除不存在的物品
            [...MWI_Toolkit_Calculator.requiredItemsMap.keys()].forEach(itemHrid => {
                if (!requiredItems.find(ri => ri.itemHrid === itemHrid)) {
                    MWI_Toolkit_Calculator.requiredItemsMap.get(itemHrid)?.removeDisplayElement();
                    MWI_Toolkit_Calculator.requiredItemsMap.delete(itemHrid);
                }
            });
            requiredItems.forEach(requiredItem => {
                const equivalentCount = equivalentItems.find(ei => ei.itemHrid === requiredItem.itemHrid)?.count || 0;
                const item = MWI_Toolkit_Calculator.requiredItemsMap.get(requiredItem.itemHrid);
                if (item) {
                    item.count = requiredItem.count;
                    item.equivalentCount = equivalentCount;
                }
                else {
                    MWI_Toolkit_Calculator.requiredItemsMap.set(requiredItem.itemHrid, new RequiredItem(requiredItem.itemHrid, requiredItem.count, equivalentCount));
                }
            });
            MWI_Toolkit_Calculator.itemCategoryList.forEach(categoryHrid => {
                const shortageDetails = MWI_Toolkit_Calculator.shortageItemDetailsMap.get(categoryHrid);
                const requiredDetails = MWI_Toolkit_Calculator.requiredItemDetailsMap.get(categoryHrid);
                let lastShortageElement = shortageDetails.querySelector('summary');
                let lastRequiredElement = requiredDetails.querySelector('summary');
                let shortageItemCount = 0;
                let requiredItemCount = 0;
                [...MWI_Toolkit_Calculator.requiredItemsMap.values()]
                    .sort((a, b) => a.sortIndex - b.sortIndex)
                    .forEach(requiredItem => {
                    if (requiredItem.categoryHrid !== categoryHrid) {
                        return;
                    }
                    if (!requiredItem.shortageDisplayElement) {
                        MWI_Toolkit_Calculator.createShortageItemDisplayElement(requiredItem);
                        lastShortageElement.insertAdjacentElement('afterend', requiredItem.shortageDisplayElement);
                    }
                    if (!requiredItem.requiredDisplayElement) {
                        MWI_Toolkit_Calculator.createRequiredItemDisplayElement(requiredItem);
                        lastRequiredElement.insertAdjacentElement('afterend', requiredItem.requiredDisplayElement);
                    }
                    requiredItem.updateDisplayElement();
                    lastShortageElement = requiredItem.shortageDisplayElement;
                    lastRequiredElement = requiredItem.requiredDisplayElement;
                    shortageItemCount += requiredItem.getShortageCount() > 0 ? 1 : 0;
                    requiredItemCount++;
                });
                shortageDetails.hidden = shortageItemCount === 0;
                requiredDetails.hidden = requiredItemCount === 0;
            });
        }
        // 创建物品容器(图标+名称)
        static createItemContainer(displayItem) {
            const container = document.createElement('div');
            // container.style.background = '#393a5b';
            // container.style.border = '1px solid';
            // container.style.borderRadius = '4px';
            // container.style.height = '21px';
            container.style.minWidth = '40px';
            container.style.alignItems = 'center';
            container.style.display = 'flex';
            // 物品图标
            const iconContainer = document.createElement('div');
            iconContainer.style.marginLeft = '2px';
            const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('width', '18px');
            svg.setAttribute('height', '18px');
            svg.style.display = 'block';
            const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
            use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', displayItem.iconHref);
            svg.appendChild(use);
            iconContainer.appendChild(svg);
            // 物品名称
            const displayNameDiv = document.createElement('div');
            displayNameDiv.textContent = displayItem.displayName;
            displayNameDiv.style.padding = "4px 1px";
            displayNameDiv.style.marginLeft = '2px';
            displayNameDiv.style.whiteSpace = 'nowrap';
            displayNameDiv.style.overflow = 'hidden';
            container.appendChild(iconContainer);
            container.appendChild(displayNameDiv);
            return container;
        }
        // 创建目标物品元素
        static createTargetItemDisplayElement(targetItem) {
            const { container, itemContainer, rightDiv } = MWI_Toolkit_Calculator.createBaseItemDisplayItem(targetItem);
            const needCalcCheckbox = document.createElement('input');
            needCalcCheckbox.type = 'checkbox';
            container.prepend(needCalcCheckbox);
            needCalcCheckbox.addEventListener('change', () => {
                targetItem.needCalc = needCalcCheckbox.checked;
                MWI_Toolkit_Calculator.saveAndScheduleRender();
            });
            // 拥有数量
            const ownedSpan = document.createElement('span');
            ownedSpan.style.padding = '4px 1px';
            ownedSpan.style.marginLeft = '4px';
            // 斜杠分隔符
            const slash = document.createElement('span');
            slash.textContent = "/";
            slash.style.padding = '4px 1px';
            // 可编辑的需求数量输入框
            const targetInput = document.createElement('input');
            targetInput.type = 'text';
            targetInput.placeholder = '需求';
            targetInput.style.background = '#dde2f8';
            targetInput.style.color = '#000000';
            targetInput.style.border = 'none';
            targetInput.style.borderRadius = '4px';
            targetInput.style.padding = '4px';
            targetInput.style.margin = '2px';
            targetInput.style.width = '60px';
            // 绑定输入事件
            targetInput.addEventListener('input', function () {
                // 清理非数字字符
                this.value = this.value.replace(/(?!^)-|[^\d-]/g, '');
                const newCount = parseInt(this.value) || 0;
                MWI_Toolkit_Calculator.updateTargetItem(targetItem.itemHrid, newCount);
            });
            // 输入框获得焦点时全选内容
            targetInput.addEventListener('focus', function () {
                setTimeout(() => {
                    targetInput.select();
                }, 0);
            });
            // 删除按钮
            const removeButton = document.createElement('button');
            removeButton.style.background = '#f44336';
            removeButton.style.border = 'none';
            removeButton.style.borderRadius = '4px';
            removeButton.style.padding = '4px';
            removeButton.style.margin = '2px';
            removeButton.style.cursor = 'pointer';
            const removeSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            removeSvg.setAttribute('width', '18px');
            removeSvg.setAttribute('height', '18px');
            removeSvg.style.display = 'block';
            const removeUse = document.createElementNS('http://www.w3.org/2000/svg', 'use');
            removeUse.setAttributeNS('http://www.w3.org/1999/xlink', 'href', MWI_Toolkit_Utils.getIconHrefByMiscHrid('remove'));
            removeSvg.appendChild(removeUse);
            removeButton.appendChild(removeSvg);
            removeButton.addEventListener('click', () => {
                MWI_Toolkit_Calculator.removeTargetItem(targetItem.itemHrid);
            });
            rightDiv.appendChild(ownedSpan);
            rightDiv.appendChild(slash);
            rightDiv.appendChild(targetInput);
            rightDiv.appendChild(removeButton);
            targetItem.displayElement = container;
            targetItem.needCalcCheckbox = needCalcCheckbox;
            targetItem.ownedSpan = ownedSpan;
            targetItem.targetInput = targetInput;
        }
        // 创建缺口物品元素
        static createShortageItemDisplayElement(requiredItem) {
            const { container, itemContainer, rightDiv } = MWI_Toolkit_Calculator.createBaseItemDisplayItem(requiredItem);
            const shortageSpan = document.createElement('span');
            shortageSpan.style.background = '#393a5b';
            shortageSpan.style.borderRadius = '4px';
            shortageSpan.style.padding = '2px 6px';
            shortageSpan.style.marginLeft = '4px';
            shortageSpan.style.cursor = 'pointer';
            shortageSpan.addEventListener('click', (e) => {
                if (e.ctrlKey || e.metaKey) {
                    MWI_Toolkit_Calculator.TryGotoActionDetailByRequiredItem(requiredItem);
                }
            });
            rightDiv.appendChild(shortageSpan);
            requiredItem.shortageDisplayElement = container;
            requiredItem.shortageSpan = shortageSpan;
        }
        // 创建需求物品元素
        static createRequiredItemDisplayElement(requiredItem) {
            const { container, itemContainer, rightDiv } = MWI_Toolkit_Calculator.createBaseItemDisplayItem(requiredItem);
            const RequiredCountDiv = document.createElement('div');
            RequiredCountDiv.style.padding = '4px 1px';
            RequiredCountDiv.style.marginLeft = '4px';
            const ownedSpan = document.createElement('span');
            const equivalentSpan = document.createElement('span');
            const requiredSpan = document.createElement('span');
            RequiredCountDiv.appendChild(equivalentSpan);
            RequiredCountDiv.appendChild(ownedSpan);
            RequiredCountDiv.appendChild(requiredSpan);
            rightDiv.appendChild(RequiredCountDiv);
            requiredItem.requiredDisplayElement = container;
            requiredItem.equivalentSpan = equivalentSpan;
            requiredItem.ownedSpan = ownedSpan;
            requiredItem.requiredSpan = requiredSpan;
            requiredItem.requiredDiv = RequiredCountDiv;
        }
        static createBaseItemDisplayItem(displayItem) {
            const container = document.createElement('div');
            container.className = 'Toolkit_Calculator_Container';
            container.style.border = 'none';
            container.style.borderRadius = '4px';
            container.style.padding = '1px 4px';
            container.style.margin = '2px';
            container.style.display = 'flex';
            container.style.alignItems = 'center';
            const itemContainer = MWI_Toolkit_Calculator.createItemContainer(displayItem);
            container.appendChild(itemContainer);
            const leftDiv = document.createElement('div');
            leftDiv.style.flex = '1';
            container.appendChild(leftDiv);
            // 右侧内容
            const rightDiv = document.createElement('div');
            rightDiv.style.display = 'flex';
            container.appendChild(rightDiv);
            return { container, itemContainer, rightDiv };
        }
        // 尝试打开动作面板
        static TryGotoActionDetailByRequiredItem(requiredItem) {
            const actionHrid = MWI_Toolkit_ActionDetailPlus.getActionHrid(requiredItem.displayName)
                ?? MWI_Toolkit_ActionDetailPlus.processableActionList[requiredItem.itemHrid]
                ?? null;
            if (!actionHrid) {
                return;
            }
            const { upgradeItemHrid, inputItems, outputItems } = MWI_Toolkit_ActionDetailPlus.calculateActionDetail(actionHrid, true);
            const outputCount = outputItems.find(oi => oi.itemHrid === requiredItem.itemHrid)?.count || 1;
            if (outputCount === 1 || outputCount === 15) {
                const actionCount = Math.ceil(requiredItem.getShortageCount() / outputCount);
                MWI_Toolkit.gameObject.handleGoToAction(actionHrid, actionCount);
            }
            else {
                const actionCount = MWI_Toolkit_Calculator.getRequiredTrials99(outputCount, requiredItem.getShortageCount());
                MWI_Toolkit.gameObject.handleGoToAction(actionHrid, actionCount);
            }
        }
        static getRequiredTrials99(mu, target) {
            // 用拟合公式简化标准差
            // sigma ≈ 0.2912 * mu^1.032
            const sigma = 0.2912 * Math.pow(mu, 1.032);
            const z = 2.326; // 99%置信度
            // 解一元二次方程 n*mu - z*sigma*sqrt(n) - target = 0
            // x = sqrt(n) = (z*sigma + sqrt(z^2*sigma^2 + 4*mu*target)) / (2*mu)
            const x = (z * sigma + Math.sqrt(z * z * sigma * sigma + 4 * mu * target)) / (2 * mu);
            return Math.ceil(x * x);
        }
    }
    MWI_Toolkit_Calculator.targetItemCategoryMap = new Map();
    MWI_Toolkit_Calculator.targetItemsMap = new Map();
    MWI_Toolkit_Calculator.requiredItemsMap = new Map();
    MWI_Toolkit_Calculator.tabButton = null;
    MWI_Toolkit_Calculator.tabPanel = null;
    MWI_Toolkit_Calculator.targetItemDetailsMap = new Map();
    MWI_Toolkit_Calculator.shortageItemDetailsMap = new Map();
    MWI_Toolkit_Calculator.requiredItemDetailsMap = new Map();
    MWI_Toolkit_Calculator.itemCategoryList = [
        '/item_categories/house_rooms',
        '/item_categories/currency',
        '/item_categories/loot',
        '/item_categories/key',
        '/item_categories/food',
        '/item_categories/drink',
        '/item_categories/ability_book',
        '/item_categories/equipment',
        '/item_categories/materials',
        '/item_categories/resource',
    ];
    MWI_Toolkit_Calculator.renderTimeout = null;
    //#endregion
    //#region ActionDetailPlus
    class ItemCountComponent {
    }
    class MWI_Toolkit_ActionDetailPlus {
        /**
         * 监听页面变化
         */
        static initialize() {
            let lastPanel = null;
            const observer = new MutationObserver(() => {
                const panel = document.querySelector('[class^="SkillActionDetail_regularComponent"]');
                if (panel && panel !== lastPanel) {
                    lastPanel = panel;
                    setTimeout(() => {
                        MWI_Toolkit_ActionDetailPlus.enhanceSkillActionDetail();
                    }, 50);
                }
            });
            observer.observe(document.body, { childList: true, subtree: true });
        }
        /**
         * 增强技能行动详情面板
         */
        static enhanceSkillActionDetail() {
            const actionName = MWI_Toolkit_ActionDetailPlus.getActionName();
            const actionHrid = MWI_Toolkit_ActionDetailPlus.getActionHrid(actionName);
            const { upgradeItemHrid, inputItems, outputItems } = MWI_Toolkit_ActionDetailPlus.calculateActionDetail(actionHrid);
            const upgradeItemComponent = { itemHrid: '', count: 0 };
            if (upgradeItemHrid) {
                const shortageCountContainer = document.querySelector('[class^="SkillActionDetail_upgradeItemSelectorInput"]')?.parentElement?.previousElementSibling;
                if (shortageCountContainer) {
                    const newTextSpan = document.createElement('span');
                    newTextSpan.textContent = shortageCountContainer.textContent;
                    newTextSpan.style.height = window.getComputedStyle(document.querySelector('[class*="SkillActionDetail_levelRequirement"]')).height;
                    shortageCountContainer.innerHTML = '';
                    shortageCountContainer.appendChild(newTextSpan);
                    const shortageCountComponent = document.createElement('div');
                    shortageCountComponent.style.display = 'flex';
                    shortageCountComponent.style.alignItems = 'flex-end';
                    shortageCountComponent.style.flexDirection = 'column';
                    const shortageCountSpan = document.createElement('span');
                    shortageCountSpan.style.display = 'flex';
                    shortageCountSpan.style.alignItems = 'center';
                    shortageCountSpan.style.color = '#faa21e';
                    shortageCountComponent.appendChild(shortageCountSpan);
                    upgradeItemComponent.itemHrid = upgradeItemHrid;
                    upgradeItemComponent.shortageCountSpan = shortageCountSpan;
                    upgradeItemComponent.count = 1; // 升级物品固定需求1个
                    shortageCountContainer.appendChild(shortageCountComponent);
                }
            }
            // [{itemHrid, shortageCountSpan, inventoryCountSpan, inputCountSpan, count}]
            const inputItemComponents = Array();
            if (inputItems) {
                const inputItemComponentContainer = document.querySelector('[class^="SkillActionDetail_itemRequirements"]');
                const shortageCountContainer = inputItemComponentContainer?.parentElement?.previousElementSibling;
                if (shortageCountContainer) {
                    const newTextSpan = document.createElement('span');
                    newTextSpan.textContent = shortageCountContainer.textContent;
                    newTextSpan.style.height = window.getComputedStyle(document.querySelector('[class*="SkillActionDetail_levelRequirement"]')).height;
                    shortageCountContainer.innerHTML = '';
                    shortageCountContainer.appendChild(newTextSpan);
                    const shortageCountComponent = document.createElement('div');
                    shortageCountComponent.style.display = 'flex';
                    shortageCountComponent.style.alignItems = 'flex-end';
                    shortageCountComponent.style.flexDirection = 'column';
                    const inventoryCountSpans = inputItemComponentContainer?.querySelectorAll('[class*="SkillActionDetail_inventoryCount"]');
                    const inputCountSpans = inputItemComponentContainer?.querySelectorAll('[class*="SkillActionDetail_inputCount"]');
                    const itemContainers = inputItemComponentContainer?.querySelectorAll('[class*="Item_itemContainer"]');
                    for (let i = 0; i < itemContainers.length; i++) {
                        inputCountSpans[i].style.color = '#E7E7E7';
                        const inputItemHrid = '/items/' + itemContainers[i].querySelector('svg use').getAttribute('href').split('#').pop();
                        const inputItemCount = inputItems.find(item => item.itemHrid === inputItemHrid)?.count || 0;
                        const shortageCountSpan = document.createElement('span');
                        shortageCountSpan.style.height = window.getComputedStyle(itemContainers[i]).height;
                        shortageCountSpan.style.display = 'flex';
                        shortageCountSpan.style.alignItems = 'center';
                        shortageCountSpan.style.color = '#faa21e';
                        shortageCountComponent.appendChild(shortageCountSpan);
                        inputItemComponents.push({ itemHrid: inputItemHrid, shortageCountSpan: shortageCountSpan, inventoryCountSpan: inventoryCountSpans[i], inputCountSpan: inputCountSpans[i], count: inputItemCount });
                    }
                    shortageCountContainer.appendChild(shortageCountComponent);
                }
            }
            // [{itemHrid, input, count}]
            const outputItemComponents = Array();
            let lastOutputItemComponent = document.querySelector('[class^="SkillActionDetail_maxActionCountInput"]');
            const outputItemComponentContainer = lastOutputItemComponent.parentElement;
            const skillActionTimeInput = lastOutputItemComponent.querySelector('input');
            const skillActionTimeButtons = lastOutputItemComponent.querySelectorAll('button');
            for (const outputItem of outputItems) {
                if (outputItem.count === 1 && outputItems.length === 1)
                    break; // 仅有一个产出且数量为1时不创建额外输入框
                const { component, input } = MWI_Toolkit_ActionDetailPlus.createOutputItemComponent(outputItem.itemHrid);
                if (component && input) {
                    outputItemComponentContainer.insertBefore(component, lastOutputItemComponent.nextSibling);
                    outputItemComponents.push({ itemHrid: outputItem.itemHrid, outputItemInput: input, count: outputItem.count });
                    lastOutputItemComponent = component;
                }
            }
            // 联动
            let linking = false;
            function updateSkillActionDetail(e) {
                if (linking)
                    return;
                linking = true;
                const target = e.target;
                const index = outputItemComponents.findIndex(component => component.outputItemInput === target);
                const targetValue = parseInt(target.value, 10);
                if (index !== -1) {
                    skillActionTimeInput.value = (isNaN(targetValue)) ? '∞' : Math.ceil(targetValue / outputItemComponents[index].count).toString();
                    MWI_Toolkit_Utils.reactInputTriggerHack(skillActionTimeInput);
                }
                const skillActionTimes = parseInt(skillActionTimeInput.value, 10);
                outputItemComponents.forEach(component => {
                    if (component.outputItemInput !== target) {
                        component.outputItemInput.value = (isNaN(skillActionTimes)) ? '∞' : Math.ceil(skillActionTimes * component.count).toString();
                    }
                });
                inputItemComponents.forEach(component => {
                    const inventoryCount = MWI_Toolkit_ItemsMap.getCount(component.itemHrid);
                    const requiredCount = component.count * skillActionTimes;
                    if (isNaN(skillActionTimes)) {
                        component.shortageCountSpan.textContent = '';
                        component.inventoryCountSpan.style.color = '';
                    }
                    else {
                        if (requiredCount > inventoryCount) {
                            component.shortageCountSpan.textContent = MWI_Toolkit_Utils.formatNumber(requiredCount - inventoryCount);
                            component.inventoryCountSpan.style.color = '#f44336';
                        }
                        else {
                            component.shortageCountSpan.textContent = ' ';
                            component.inventoryCountSpan.style.color = '#E7E7E7';
                        }
                    }
                    component.inputCountSpan.textContent = '\u00A0/ ' + MWI_Toolkit_Utils.formatNumber(component.count * ((isNaN(skillActionTimes) ? 1 : skillActionTimes))) + '\u00A0';
                });
                if (upgradeItemComponent.shortageCountSpan) {
                    if (isNaN(skillActionTimes)) {
                        upgradeItemComponent.shortageCountSpan.textContent = '';
                    }
                    else {
                        const requiredCount = upgradeItemComponent.count * skillActionTimes;
                        const inventoryCount = MWI_Toolkit_ItemsMap.getCount(upgradeItemComponent.itemHrid);
                        if (requiredCount > inventoryCount) {
                            upgradeItemComponent.shortageCountSpan.textContent = MWI_Toolkit_Utils.formatNumber(requiredCount - inventoryCount);
                        }
                        else {
                            upgradeItemComponent.shortageCountSpan.textContent = ' ';
                        }
                    }
                }
                linking = false;
            }
            skillActionTimeInput.addEventListener('input', updateSkillActionDetail);
            outputItemComponents.forEach(component => {
                component.outputItemInput.addEventListener('input', updateSkillActionDetail);
            });
            skillActionTimeButtons.forEach(btn => {
                btn.addEventListener('click', () => {
                    setTimeout(() => {
                        skillActionTimeInput.dispatchEvent(new Event('input', { bubbles: false }));
                    }, 20);
                });
            });
            // 初次填充
            setTimeout(() => {
                skillActionTimeInput.dispatchEvent(new Event('input', { bubbles: false }));
            }, 20);
        }
        static calculateActionDetail(actionHrid, ignoreProcessingTea = false) {
            const actionDetail = MWI_Toolkit_ActionDetailPlus.getActionDetail(actionHrid);
            const actionType = actionDetail?.type?.split('/').pop() || '';
            // 仅支持八种常规类型
            if (!actionDetail || !actionType || !['milking', 'foraging', 'woodcutting', 'cheesesmithing', 'crafting', 'tailoring', 'cooking', 'brewing'].includes(actionType)) {
                console.warn('[MWI_Toolkit] 无法获取动作详情' + MWI_Toolkit_ActionDetailPlus.getActionName());
                return { upgradeItemHrid: null, inputItems: null, outputItems: null };
            }
            // console.log('MWI_Toolkit_ActionDetailPlus: 获取到动作详情', actionDetail);
            const upgradeItemHrid = actionDetail.upgradeItemHrid;
            const inputItems = actionDetail.inputItems ? JSON.parse(JSON.stringify(actionDetail.inputItems)) : null;
            const outputItems = actionDetail.outputItems ? JSON.parse(JSON.stringify(actionDetail.outputItems)) : Array();
            const drinkSlots = MWI_Toolkit_ActionDetailPlus.getActionTypeDrinkSlots(actionType);
            const drinkConcentration = MWI_Toolkit_ActionDetailPlus.getDrinkConcentration();
            // console.log('MWI_Toolkit_ActionDetailPlus: 获取到茶列表', drinkSlots, drinkConcentration);
            // 检查采集数量加成
            const gatheringBuff = (drinkSlots?.some(itemHrid => itemHrid === '/items/gathering_tea') ? 0.15 * drinkConcentration : 0)
                + MWI_Toolkit_ActionDetailPlus.getEquipmentGatheringBuff() + MWI_Toolkit_ActionDetailPlus.getCommunityGatheringBuff();
            // 检查加工茶加成
            const processingBuff = (drinkSlots?.some(itemHrid => itemHrid === '/items/processing_tea') ? 0.15 * drinkConcentration : 0);
            // 检查美食茶加成
            const gourmetBuff = (drinkSlots?.some(itemHrid => itemHrid === '/items/gourmet_tea') ? 0.12 * drinkConcentration : 0);
            // 检查工匠茶加成
            const artisanBuff = (drinkSlots?.some(itemHrid => itemHrid === '/items/artisan_tea') ? 0.1 * drinkConcentration : 0);
            if (['milking', 'foraging', 'woodcutting', /*'cheesesmithing', 'crafting', 'tailoring', 'cooking', 'brewing'*/].includes(actionType)) {
                const dropTable = actionDetail.dropTable;
                for (const dropItem of dropTable) {
                    const averageCount = dropItem.dropRate * (dropItem.minCount + dropItem.maxCount) / 2 * (1 + gatheringBuff);
                    const processedItemHrid = MWI_Toolkit_ActionDetailPlus.processableItemList[dropItem.itemHrid];
                    if (processedItemHrid && !ignoreProcessingTea) {
                        outputItems.push({ itemHrid: dropItem.itemHrid, count: averageCount * (1 - processingBuff), });
                        outputItems.push({ itemHrid: processedItemHrid, count: averageCount * (1 - processingBuff) / 2 / (1 - artisanBuff) + averageCount * processingBuff / 2, });
                    }
                    else {
                        outputItems.push({ itemHrid: dropItem.itemHrid, count: averageCount, });
                    }
                }
            }
            if ([/*'milking', 'foraging', 'woodcutting', 'cheesesmithing', 'crafting', 'tailoring',*/ 'cooking', 'brewing'].includes(actionType)) {
                for (const outputItem of outputItems) {
                    outputItem.count = outputItem.count * (1 + gourmetBuff);
                }
            }
            if ([/*'milking', 'foraging', 'woodcutting',*/ 'cheesesmithing', 'crafting', 'tailoring', 'cooking', 'brewing'].includes(actionType)) {
                for (const inputItem of inputItems) {
                    inputItem.count = inputItem.count * (1 - artisanBuff);
                }
            }
            return { upgradeItemHrid, inputItems, outputItems };
        }
        /**
         * 创建output数量栏,返回 [{component, input}]
         * @param itemHrid 物品的唯一标识符
         * @returns { component: HTMLDivElement; input: HTMLInputElement } | null
         */
        static createOutputItemComponent(itemHrid) {
            const origComponent = document.querySelector('[class^="SkillActionDetail_maxActionCountInput"]');
            if (!origComponent)
                return null;
            // 克隆外层div(不带子内容)
            const component = origComponent.cloneNode(false);
            const originalActionLabel = document.querySelector('[class^="SkillActionDetail_actionContainer"] [class^="SkillActionDetail_label"]');
            if (Object.values(MWI_Toolkit_ActionDetailPlus.processableItemList).includes(itemHrid)) {
                const tab = originalActionLabel.cloneNode(false);
                tab.style.width = window.getComputedStyle(originalActionLabel).width;
                tab.className = 'SkillActionDetail_tab';
                tab.textContent = '┗';
                component.appendChild(tab);
            }
            // 物品图标
            const itemIcon = document.createElement('div');
            itemIcon.style.width = window.getComputedStyle(originalActionLabel).width;
            itemIcon.style.height = window.getComputedStyle(originalActionLabel).height;
            itemIcon.style.marginRight = '2px';
            itemIcon.style.display = 'flex';
            itemIcon.style.alignItems = 'center';
            itemIcon.style.justifyContent = 'center';
            const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
            svg.setAttribute('width', '20px');
            svg.setAttribute('height', '20px');
            svg.style.display = 'block';
            const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
            use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', MWI_Toolkit_Utils.getIconHrefByItemHrid(itemHrid));
            svg.appendChild(use);
            itemIcon.appendChild(svg);
            component.appendChild(itemIcon);
            // 输入框
            const origInputWrap = origComponent.querySelector('[class^="SkillActionDetail_input"]');
            const inputWrap = origInputWrap.cloneNode(true);
            const origInput = origInputWrap.querySelector('input');
            const input = inputWrap.querySelector('input');
            input.addEventListener('focus', () => {
                setTimeout(() => {
                    input.select();
                }, 0);
            });
            input.addEventListener('keydown', (event) => {
                if (event.key === 'Enter') {
                    if (origInput) {
                        origInput.dispatchEvent(event);
                    }
                }
            });
            component.appendChild(inputWrap);
            if (!Object.values(MWI_Toolkit_ActionDetailPlus.processableItemList).includes(itemHrid)) {
                // 快捷填充按钮
                const btns = [
                    { val: 1000, txt: '1k' },
                    { val: 2000, txt: '2k' },
                    { val: 5000, txt: '5k' }
                ];
                const origButtons = origComponent.querySelectorAll('button');
                const buttonClass = origButtons.length > 0 ? origButtons[0].className : '';
                btns.forEach(({ val, txt }) => {
                    const btn = document.createElement('button');
                    btn.className = buttonClass;
                    btn.textContent = txt;
                    btn.addEventListener('click', () => {
                        input.value = val.toString();
                        input.dispatchEvent(new Event('input', { bubbles: true }));
                    });
                    component.appendChild(btn);
                });
            }
            return { component, input };
        }
        static getActionName() {
            const actionNameDiv = document.querySelector('[class^="SkillActionDetail_name"]');
            return actionNameDiv ? actionNameDiv.textContent : '';
        }
        static getActionHrid(actionName) {
            return MWI_Toolkit_I18n.getHridByName(actionName, 'actionNames');
        }
        static getActionDetail(actionHrid) {
            return MWI_Toolkit.initClientData?.actionDetailMap?.[`${actionHrid}`];
        }
        static getActionTypeDrinkSlots(actionType) {
            if (!actionType) {
                return [];
            }
            const drinkSlots = [];
            MWI_Toolkit.gameObject?.state?.actionTypeDrinkSlotsDict?.[`/action_types/${actionType}`].forEach(drink => {
                if (drink && drink.itemHrid) {
                    drinkSlots.push(drink.itemHrid);
                }
            });
            // 对三采添加对应的工匠茶数据用于计算加工数量
            const processActionType = { milking: 'cheesesmithing', foraging: 'tailoring', woodcutting: 'crafting' }[actionType] || null;
            if (processActionType) {
                const processDrinkSlots = MWI_Toolkit.gameObject?.state?.actionTypeDrinkSlotsDict?.[`/action_types/${processActionType}`];
                processDrinkSlots.forEach(drink => {
                    if (drink && drink.itemHrid == '/items/artisan_tea') {
                        drinkSlots.push(drink.itemHrid);
                    }
                });
            }
            return drinkSlots;
        }
        static getDrinkConcentration() {
            const enhancementLevel = MWI_Toolkit_ItemsMap.getMaxEnhancementLevel("/items/guzzling_pouch");
            if (enhancementLevel != -1) {
                return 1
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/guzzling_pouch`].equipmentDetail.noncombatStats.drinkConcentration
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/guzzling_pouch`].equipmentDetail.noncombatEnhancementBonuses.drinkConcentration
                        * MWI_Toolkit.initClientData?.enhancementLevelTotalBonusMultiplierTable[enhancementLevel];
            }
            return 1;
        }
        static getEquipmentGatheringBuff() {
            let equipmentGatheringBuff = 0;
            const philosophers_earrings_enhancementLevel = MWI_Toolkit_ItemsMap.getMaxEnhancementLevel("/items/philosophers_earrings");
            const earrings_of_gathering_enhancementLevel = MWI_Toolkit_ItemsMap.getMaxEnhancementLevel("/items/earrings_of_gathering");
            const philosophers_ring_enhancementLevel = MWI_Toolkit_ItemsMap.getMaxEnhancementLevel("/items/philosophers_ring");
            const ring_of_gathering_enhancementLevel = MWI_Toolkit_ItemsMap.getMaxEnhancementLevel("/items/ring_of_gathering");
            if (philosophers_earrings_enhancementLevel != -1) {
                equipmentGatheringBuff = equipmentGatheringBuff
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/philosophers_earrings`].equipmentDetail.noncombatStats.gatheringQuantity
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/philosophers_earrings`].equipmentDetail.noncombatEnhancementBonuses.gatheringQuantity
                        * MWI_Toolkit.initClientData?.enhancementLevelTotalBonusMultiplierTable[philosophers_earrings_enhancementLevel];
            }
            else if (earrings_of_gathering_enhancementLevel != -1) {
                equipmentGatheringBuff = equipmentGatheringBuff
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/earrings_of_gathering`].equipmentDetail.noncombatStats.gatheringQuantity
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/earrings_of_gathering`].equipmentDetail.noncombatEnhancementBonuses.gatheringQuantity
                        * MWI_Toolkit.initClientData?.enhancementLevelTotalBonusMultiplierTable[earrings_of_gathering_enhancementLevel];
            }
            if (philosophers_ring_enhancementLevel != -1) {
                equipmentGatheringBuff = equipmentGatheringBuff
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/philosophers_ring`].equipmentDetail.noncombatStats.gatheringQuantity
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/philosophers_ring`].equipmentDetail.noncombatEnhancementBonuses.gatheringQuantity
                        * MWI_Toolkit.initClientData?.enhancementLevelTotalBonusMultiplierTable[philosophers_ring_enhancementLevel];
            }
            else if (ring_of_gathering_enhancementLevel != -1) {
                equipmentGatheringBuff = equipmentGatheringBuff
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/ring_of_gathering`].equipmentDetail.noncombatStats.gatheringQuantity
                    + MWI_Toolkit.initClientData?.itemDetailMap?.[`/items/ring_of_gathering`].equipmentDetail.noncombatEnhancementBonuses.gatheringQuantity
                        * MWI_Toolkit.initClientData?.enhancementLevelTotalBonusMultiplierTable[ring_of_gathering_enhancementLevel];
            }
            return equipmentGatheringBuff;
        }
        static getCommunityGatheringBuff() {
            const communityBuffs = MWI_Toolkit.gameObject?.state?.communityBuffs || [];
            for (const buff of communityBuffs) {
                if (buff.hrid === "/community_buff_types/gathering_quantity" && !buff.isDone) {
                    return buff.level * 0.005 + 0.195;
                }
            }
            return 0;
        }
    }
    /**
     * 可加工的动作映射
     */
    MWI_Toolkit_ActionDetailPlus.processableActionList = {
        "/items/milk": "/actions/milking/cow",
        "/items/verdant_milk": "/actions/milking/verdant_cow",
        "/items/azure_milk": "/actions/milking/azure_cow",
        "/items/burble_milk": "/actions/milking/burble_cow",
        "/items/crimson_milk": "/actions/milking/crimson_cow",
        "/items/rainbow_milk": "/actions/milking/unicow",
        "/items/holy_milk": "/actions/milking/holy_cow",
        "/items/log": "/actions/woodcutting/tree",
        "/items/birch_log": "/actions/woodcutting/birch_tree",
        "/items/cedar_log": "/actions/woodcutting/cedar_tree",
        "/items/purpleheart_log": "/actions/woodcutting/purpleheart_tree",
        "/items/ginkgo_log": "/actions/woodcutting/ginkgo_tree",
        "/items/redwood_log": "/actions/woodcutting/redwood_tree",
        "/items/arcane_log": "/actions/woodcutting/arcane_tree",
        "/items/cotton": "/actions/foraging/cotton",
        "/items/flax": "/actions/foraging/flax",
        "/items/bamboo_branch": "/actions/foraging/bamboo_branch",
        "/items/cocoon": "/actions/foraging/cocoon",
        "/items/radiant_fiber": "/actions/foraging/radiant_fiber"
    };
    /**
     * 可加工的物品映射
     */
    MWI_Toolkit_ActionDetailPlus.processableItemList = {
        "/items/milk": "/items/cheese",
        "/items/verdant_milk": "/items/verdant_cheese",
        "/items/azure_milk": "/items/azure_cheese",
        "/items/burble_milk": "/items/burble_cheese",
        "/items/crimson_milk": "/items/crimson_cheese",
        "/items/rainbow_milk": "/items/rainbow_cheese",
        "/items/holy_milk": "/items/holy_cheese",
        "/items/log": "/items/lumber",
        "/items/birch_log": "/items/birch_lumber",
        "/items/cedar_log": "/items/cedar_lumber",
        "/items/purpleheart_log": "/items/purpleheart_lumber",
        "/items/ginkgo_log": "/items/ginkgo_lumber",
        "/items/redwood_log": "/items/redwood_lumber",
        "/items/arcane_log": "/items/arcane_lumber",
        "/items/cotton": "/items/cotton_fabric",
        "/items/flax": "/items/linen_fabric",
        "/items/bamboo_branch": "/items/bamboo_fabric",
        "/items/cocoon": "/items/silk_fabric",
        "/items/radiant_fiber": "/items/radiant_fabric"
    };
    //#endregion
    //#region Utils
    /**
     * 静态工具类
     */
    class MWI_Toolkit_Utils {
        /**
         * 格式化数字为字符串
         * @param num 要格式化的数字
         * @returns 格式化后的字符串
         */
        static formatNumber(num) {
            // 类型和有效性检查
            if (!Number.isFinite(num)) {
                return '0';
            }
            // 确保非负数
            const normalizedNum = Math.max(0, num);
            // 小于1000:保留1位小数,但如果小数为0则只显示整数
            if (normalizedNum <= 999) {
                const fixed = normalizedNum.toFixed(1);
                return fixed.endsWith('.0') ? Math.round(normalizedNum).toString() : fixed;
            }
            // 小于100,000:向上取整
            if (normalizedNum <= 99999) {
                return Math.ceil(normalizedNum).toString();
            }
            // 小于10,000,000:显示xxxK (100K~9999K)
            if (normalizedNum <= 9999999) {
                return `${Math.floor(normalizedNum / 1000)}K`;
            }
            // 小于10,000,000,000:显示xxxM (100M~9999M)
            if (normalizedNum <= 9999999999) {
                return `${Math.floor(normalizedNum / 1000000)}M`;
            }
            // 小于10,000,000,000,000:显示xxxB (100B~9999B)
            if (normalizedNum <= 9999999999999) {
                return `${Math.floor(normalizedNum / 1000000000)}B`;
            }
            // 更大的数值显示NaN
            return 'NaN';
        }
        /**
         * 获取物品排序索引
         * @param hrid 物品的唯一标识符
         * @returns 物品的排序索引
         */
        static getSortIndexByItemHrid(hrid) {
            return (MWI_Toolkit.initClientData?.itemDetailMap?.[hrid]?.sortIndex || 9999);
        }
        /**
         * 获取物品排序索引
         * @param hrid 物品的唯一标识符
         * @returns 物品的排序索引
         */
        static getSortIndexByHouseRoomHrid(hrid) {
            return (MWI_Toolkit.initClientData?.houseRoomDetailMap?.[hrid]?.sortIndex || 0) - 9999;
        }
        /**
         * 获取物品图标的链接
         * @param itemHrid 物品的唯一标识符
         * @returns 物品图标的链接
         */
        static getIconHrefByItemHrid(itemHrid) {
            return '/static/media/items_sprite.d4d08849.svg#' + (itemHrid.split('/').pop() || '');
        }
        /**
         * 获取技能图标的链接
         * @param skillHrid 技能的唯一标识符
         * @returns 技能图标的链接
         */
        static getIconHrefBySkillHrid(skillHrid) {
            return '/static/media/skills_sprite.3bb4d936.svg#' + (skillHrid.split('/').pop() || '');
        }
        /**
         * 获取房屋图标的链接
         * @param houseRoomHrid 房屋的唯一标识符
         * @returns 房屋图标的链接
         */
        static getIconHrefByHouseRoomHrid(houseRoomHrid) {
            return MWI_Toolkit_Utils.getIconHrefBySkillHrid(MWI_Toolkit.initClientData?.houseRoomDetailMap?.[houseRoomHrid]?.skillHrid || houseRoomHrid);
        }
        /**
         * 获取杂项图标的链接
         * @param hrid 杂项的唯一标识符
         * @returns 杂项图标的链接
         */
        static getIconHrefByMiscHrid(hrid) {
            return '/static/media/misc_sprite.6fa5e97c.svg#' + (hrid.split('/').pop() || '');
        }
        /**
         * 触发React输入框的change事件
         * 通过操作React内部的_valueTracker来触发React的事件系统
         * @param inputElem HTML输入元素
         */
        static reactInputTriggerHack(inputElem) {
            const lastValue = inputElem.value;
            const event = new Event("input", { bubbles: true });
            // 添加自定义标记
            event.simulated = true;
            // 访问React内部的value tracker
            const tracker = inputElem._valueTracker;
            if (tracker) {
                // 触发变更:设置为不同的值以触发React的change检测
                tracker.setValue(lastValue === '' ? ' ' : '');
            }
            inputElem.dispatchEvent(event);
        }
    }
    //#endregion
    //#region I18n
    /**
     * 国际化静态工具类实现
     * 提供游戏内物品和其他资源的多语言名称查询功能
     */
    class MWI_Toolkit_I18n {
        /**
         * 获取物品的本地化名称
         * @param itemHrid 物品的唯一标识符
         * @returns 本地化后的物品名称,如果找不到则返回原始HRID
         */
        static getItemName(itemHrid) {
            return MWI_Toolkit_I18n.getName(itemHrid, "itemNames");
        }
        /**
         * 获取资源的本地化名称(通用方法)
         * @param hrid 资源的唯一标识符
         * @param category 资源分类(houseRoomNames, actionNames, itemNames)
         * @returns 本地化后的名称,如果找不到则返回原始HRID
         */
        static getName(hrid, category) {
            if (!hrid || !category) {
                return hrid;
            }
            // 特例自定义itemCategory名称
            if (hrid === '/item_categories/house_rooms') {
                return MWI_Toolkit?.getGameLanguage() === 'zh' ? '房屋' : 'House';
            }
            if (hrid === '/item_categories/materials') {
                return MWI_Toolkit?.getGameLanguage() === 'zh' ? '材料' : 'Materials';
            }
            return MWI_Toolkit.gameObject?.props?.i18n?.options?.resources?.[MWI_Toolkit?.getGameLanguage()]?.translation?.[category]?.[hrid] || hrid;
        }
        /**
         * 根据物品名称反查HRID
         * @param itemName 物品的本地化名称
         * @returns 对应的物品HRID,如果找不到则返回null
         */
        static getItemHridByName(itemName) {
            return MWI_Toolkit_I18n.getHridByName(itemName, "itemNames");
        }
        /**
         * 根据名称反查HRID(通用方法)
         * @param name 资源的本地化名称
         * @param category 资源分类(houseRoomNames, actionNames, itemNames)
         * @returns 对应的HRID,如果找不到则返回null
         */
        static getHridByName(name, category) {
            if (!name || !category) {
                return null;
            }
            return Object.entries(MWI_Toolkit.gameObject?.props?.i18n?.options?.resources?.[MWI_Toolkit?.getGameLanguage()]?.translation?.[category] || {})
                .find(([, v]) => (v || '').toLowerCase() === name.toLowerCase().trim())?.[0] ?? null;
        }
    }
    //#endregion
    //#region ItemsMap
    /**
     * 物品映射管理类实现
     * 使用二级Map结构存储物品数据:itemHrid -> enhancementLevel -> count
     * 提供物品查询和事件监听功能
     */
    class MWI_Toolkit_ItemsMap {
        /**
         * 查询指定物品和强化等级的数量
         * @param itemHrid 物品的唯一标识符
         * @param enhancementLevel 强化等级,默认为0
         * @returns 物品数量,如果不存在则返回0
         */
        static getCount(itemHrid, enhancementLevel = 0) {
            return MWI_Toolkit_ItemsMap.map.get(itemHrid)?.get(enhancementLevel) ?? 0;
        }
        /**
         * 查询指定物品的最大强化等级
         * @param itemHrid 物品的唯一标识符
         * @returns 最大强化等级,如果物品不存在或所有数量为0则返回-1
         */
        static getMaxEnhancementLevel(itemHrid) {
            const m = MWI_Toolkit_ItemsMap.map.get(itemHrid);
            if (!m) {
                return -1;
            }
            let max = -1;
            for (const [level, count] of m) {
                if (count > 0 && level > max) {
                    max = level;
                }
            }
            return max;
        }
        /**
         * 更新物品数据
         * @param endCharacterItems 要更新的物品列表
         */
        static update(endCharacterItems) {
            if (!endCharacterItems) {
                return;
            }
            for (const item of endCharacterItems) {
                if (!MWI_Toolkit_ItemsMap.map.has(item.itemHrid)) {
                    MWI_Toolkit_ItemsMap.map.set(item.itemHrid, new Map());
                }
                MWI_Toolkit_ItemsMap.map.get(item.itemHrid).set(item.enhancementLevel, item.count);
            }
            MWI_Toolkit_ItemsMap.itemsUpdatedCallbacks.forEach(cb => {
                try {
                    cb(endCharacterItems);
                }
                catch (e) {
                    console.error('[MWI_Toolkit] Error in item updated callback:', e);
                }
            });
        }
        /**
         * 清空所有物品数据
         */
        static clear() {
            MWI_Toolkit_ItemsMap.map.clear();
        }
    }
    /** 物品数据映射表:itemHrid -> (enhancementLevel -> count) */
    MWI_Toolkit_ItemsMap.map = new Map();
    /** 物品更新事件的回调函数列表 */
    MWI_Toolkit_ItemsMap.itemsUpdatedCallbacks = [];
    //#endregion
    //#region MWI_Toolkit
    /**
     * MWI工具包主类
     * 提供游戏数据抓取、国际化、物品管理等核心功能
     * 使用单例模式确保全局只有一个实例
     */
    class MWI_Toolkit {
        static getGameLanguage() {
            return MWI_Toolkit.gameObject?.language || 'zh';
        }
        /**
         * 启动工具包
         * 等待游戏页面加载完成后进行初始化
         */
        static start() {
            MWI_Toolkit.setupWebSocketInterceptor();
            MWI_Toolkit.waitForElement('[class^="GamePage"]', () => {
                MWI_Toolkit.initialize();
            });
        }
        /**
         * 设置 WebSocket 消息拦截器
         * 通过劫持 MessageEvent.prototype.data 来拦截所有 WebSocket 消息
         */
        static setupWebSocketInterceptor() {
            const oriGet = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data")?.get;
            if (!oriGet) {
                return;
            }
            Object.defineProperty(MessageEvent.prototype, "data", {
                get: function () {
                    const socket = this.currentTarget;
                    // 只拦截游戏服务器的 WebSocket 消息
                    if (!(socket instanceof WebSocket) ||
                        (socket.url.indexOf("api.milkywayidle.com/ws") === -1 && socket.url.indexOf("api-test.milkywayidle.com/ws") === -1)) {
                        return oriGet.call(this);
                    }
                    const message = oriGet.call(this);
                    Object.defineProperty(this, "data", { value: message }); // 防止循环调用
                    MWI_Toolkit?.handleWebSocketMessage(message);
                    return message;
                }
            });
        }
        /**
         * 处理 WebSocket 消息
         * 解析消息并根据类型进行相应处理
         * @param message WebSocket 消息内容(JSON字符串)
         */
        static handleWebSocketMessage(message) {
            try {
                const obj = JSON.parse(message);
                // 类型守卫:检查是否为对象
                if (!obj || typeof obj !== 'object')
                    return;
                const msgObj = obj;
                // 处理角色初始化消息(使用双重断言)
                if (msgObj.type === "init_character_data" && Array.isArray(msgObj.characterItems)) {
                    MWI_Toolkit.handleInitCharacterData(obj);
                }
                // 处理物品变更消息(使用双重断言)
                else if (Array.isArray(msgObj.endCharacterItems)) {
                    MWI_Toolkit.handleEndCharacterItems(obj);
                }
            }
            catch {
                // 忽略解析错误(非JSON消息或其他错误)
            }
        }
        /**
         * 处理角色初始化数据
         * 当切换角色或刷新页面时会收到此消息
         * @param data 角色初始化数据
         */
        static handleInitCharacterData(data) {
            // 清空并初始化物品映射表
            MWI_Toolkit_ItemsMap.clear();
            MWI_Toolkit_ItemsMap.update(data.characterItems);
            if (!MWI_Toolkit.initialized) {
                return;
            }
            console.log("[MWI_Toolkit] 界面刷新");
            MWI_Toolkit_Calculator.initializeCalculatorUI();
            MWI_Toolkit.waitForElement('[class^="GamePage"]', () => {
                MWI_Toolkit.gameObject = MWI_Toolkit.getGameObject();
            });
        }
        /**
         * 处理物品变更数据
         * 当物品数量、强化等级等发生变化时会收到此消息
         * @param data 包含变更后物品数据的消息
         */
        static handleEndCharacterItems(data) {
            // 更新物品映射表
            MWI_Toolkit_ItemsMap.update(data.endCharacterItems);
        }
        /**
         * 等待指定的DOM元素出现
         * 使用 MutationObserver 监听DOM变化
         * @param callback 元素出现后执行的回调函数
         */
        static waitForElement(selector, callback) {
            const el = document.querySelector(selector);
            if (el) {
                // 元素已存在,直接执行回调
                callback();
                return;
            }
            // 元素不存在,监听DOM变化
            const observer = new MutationObserver(() => {
                const el = document.querySelector(selector);
                if (el) {
                    observer.disconnect();
                    callback();
                }
            });
            observer.observe(document.body, { childList: true, subtree: true });
        }
        /**
         * 初始化工具包
         * 获取游戏对象实例并设置初始化标志
         */
        static initialize() {
            MWI_Toolkit.gameObject = MWI_Toolkit.getGameObject();
            MWI_Toolkit.initClientData = MWI_Toolkit.getInitClientData();
            if (!MWI_Toolkit.gameObject || !MWI_Toolkit.initClientData) {
                console.error("[MWI_Toolkit] 初始化失败");
                return;
            }
            MWI_Toolkit.initialized = true;
            MWI_Toolkit_ActionDetailPlus.initialize();
            MWI_Toolkit_Calculator.initialize();
            console.log("[MWI_Toolkit] 已初始化");
            console.log(MWI_Toolkit.gameObject, MWI_Toolkit.initClientData);
        }
        /**
         * 从DOM元素获取React组件实例
         * 通过访问React内部的Fiber节点来获取组件实例
         * @returns React组件实例,如果未找到则返回null
         */
        static getGameObject() {
            // (e => e?.[Object.keys(e).find(k => k.startsWith('__reactFiber$'))]?.return?.stateNode)(document.querySelector('[class^="GamePage"]'))
            const gamePageElement = document.querySelector('[class^="GamePage"]');
            if (!gamePageElement)
                return null;
            // 查找React Fiber的key(格式:__reactFiber$xxx)
            const reactKey = Object.keys(gamePageElement).find(k => k.startsWith('__reactFiber$'));
            if (!reactKey)
                return null;
            // 通过Fiber节点获取组件实例
            const fiber = gamePageElement[reactKey];
            return fiber?.return?.stateNode || null;
        }
        /**
         * 从localStorage获取初始化客户端数据
         * 数据以压缩的UTF-16字符串形式存储
         * @returns 初始化客户端数据对象,如果未找到则返回null
         */
        static getInitClientData() {
            const compressedData = localStorage.getItem("initClientData");
            if (compressedData) {
                const decompressedData = LZString.decompressFromUTF16(compressedData);
                return JSON.parse(decompressedData);
            }
            return null;
        }
    }
    /** 初始化客户端数据(从localStorage获取) */
    MWI_Toolkit.initClientData = null;
    /** 游戏对象实例(从React组件获取) */
    MWI_Toolkit.gameObject = null;
    /** 是否已初始化 */
    MWI_Toolkit.initialized = false;
    //#endregion
    // 防止重复加载
    if (window.MWI_Toolkit_Started) {
        return;
    }
    window.MWI_Toolkit_Started = true;
    // 启动工具包
    MWI_Toolkit.start();
})();