银河奶牛放置-辅助增强

让你在使用插件的时候更方便?(what?)

// ==UserScript==
// @name         银河奶牛放置-辅助增强
// @namespace    https://github.com/HereIsYui
// @version      0.0.1
// @description  让你在使用插件的时候更方便?(what?)
// @author       Yui
// @match        https://www.milkywayidle.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=milkywayidle.com
// @license MIT
// ==/UserScript==

(function () {
    'use strict';
    var isInitFinished = false;
    var needItemEle;
    var buildNum = 0;
    /**
     * 监听带有模糊匹配class的元素出现
     * @param {string|RegExp} classPattern - 要匹配的class模式(字符串或正则表达式)
     * @param {Function} callback - 匹配到元素时的回调函数
     * @param {Object} [options] - 配置选项
     * @param {boolean} [options.checkExisting=true] - 是否检查已存在的元素
     * @param {boolean} [options.stopAfterFirstMatch=true] - 是否在第一次匹配后停止观察
     * @param {string} [options.matchMode='includes'] - 匹配模式: 'startsWith'|'includes'|'endsWith'|'regex'|'exact'
     * @param {boolean} [options.multiple=false] - 是否匹配多个元素
     * @returns {MutationObserver} 返回观察器实例以便手动控制
     */
    function observeElementByFuzzyClass(classPattern, callback, options = {}) {
        // 合并默认选项
        const {
            checkExisting = true,
            stopAfterFirstMatch = true,
            matchMode = 'includes',
            multiple = false,
            attributeFilter = ['class'],
            attributeOldValue = false,
            attributes = true,
            childList = true,
            subtree = true
        } = options;

        // 已匹配元素的集合(用于避免重复回调)
        const matchedElements = new Set();

        // 检查元素是否匹配条件的函数
        function isElementMatched(element) {
            if (!element.classList || element.classList.length === 0) return false;

            // 检查所有class是否符合条件
            for (const cls of element.classList) {
                if (matchClass(cls, classPattern, matchMode)) {
                    return true;
                }
            }
            return false;
        }

        // class匹配逻辑
        function matchClass(className, pattern, mode) {
            switch (mode) {
                case 'startsWith':
                    return className.startsWith(pattern);
                case 'includes':
                    return className.includes(pattern);
                case 'endsWith':
                    return className.endsWith(pattern);
                case 'regex':
                    return pattern.test(className);
                case 'exact':
                    return className === pattern;
                default:
                    return className.includes(pattern);
            }
        }

        // 处理匹配到的元素
        function handleMatchedElement(element) {
            if (matchedElements.has(element)) return false;

            matchedElements.add(element);
            callback(element);
            return true;
        }

        // 检查现有元素
        function checkExistingElements() {
            const allElements = document.querySelectorAll('*');
            let found = false;

            for (const element of allElements) {
                if (isElementMatched(element)) {
                    const handled = handleMatchedElement(element);
                    if (handled && stopAfterFirstMatch && !multiple) {
                        found = true;
                        break;
                    }
                }
            }

            return found;
        }

        // 首先检查现有元素
        if (checkExisting) {
            const foundExisting = checkExistingElements();
            if (foundExisting && stopAfterFirstMatch && !multiple) {
                return null;
            }
        }

        // 创建观察器实例
        const observer = new MutationObserver(function (mutations) {
            for (const mutation of mutations) {
                // 处理新增节点
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === 1) { // 元素节点
                        // 检查节点本身
                        if (isElementMatched(node)) {
                            handleMatchedElement(node);
                            if (stopAfterFirstMatch && !multiple) {
                                observer.disconnect();
                                return;
                            }
                        }

                        // 检查子节点
                        if (node.querySelectorAll) {
                            const children = node.querySelectorAll('*');
                            for (const child of children) {
                                if (isElementMatched(child)) {
                                    handleMatchedElement(child);
                                    if (stopAfterFirstMatch && !multiple) {
                                        observer.disconnect();
                                        return;
                                    }
                                }
                            }
                        }
                    }
                }

                // 处理class属性变化
                if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    if (isElementMatched(mutation.target)) {
                        handleMatchedElement(mutation.target);
                        if (stopAfterFirstMatch && !multiple) {
                            observer.disconnect();
                            return;
                        }
                    }
                }
            }

            // 补充全文档检查(防止遗漏)
            if (!stopAfterFirstMatch || multiple) {
                checkExistingElements();
            }
        });

        // 开始观察文档
        observer.observe(document.body, {
            childList,
            subtree,
            attributes,
            attributeFilter,
            attributeOldValue
        });

        return observer;
    }
    function observeElementByPartialId(partialId, callback, options = {}) {
        // 配置选项
        const {
            attributeFilter = ['id'],  // 只观察id属性变化
            attributeOldValue = false,
            attributes = true,         // 观察属性变化
            childList = true,          // 观察子节点变化
            subtree = true,            // 观察所有后代节点
            checkExisting = true,      // 是否检查已存在的元素
            matchMode = 'startsWith'   // 匹配模式:'startsWith'|'includes'|'endsWith'|'regex'
        } = options;

        // 检查元素是否已存在的函数
        function checkElement() {
            const elements = document.querySelectorAll('[id]');
            for (const element of elements) {
                if (matchesId(element.id, partialId, matchMode)) {
                    return element;
                }
            }
            return null;
        }

        // ID匹配函数
        function matchesId(id, partialId, mode) {
            switch (mode) {
                case 'startsWith':
                    return id.startsWith(partialId);
                case 'includes':
                    return id.includes(partialId);
                case 'endsWith':
                    return id.endsWith(partialId);
                case 'regex':
                    return new RegExp(partialId).test(id);
                default:
                    return id.startsWith(partialId);
            }
        }

        // 首先检查元素是否已经存在
        if (checkExisting) {
            const existingElement = checkElement();
            if (existingElement) {
                callback(existingElement);
                return null; // 返回null表示不需要观察
            }
        }

        // 创建观察器实例
        const observer = new MutationObserver(function (mutations) {
            // 检查每次DOM变化
            for (const mutation of mutations) {
                // 检查新增的节点
                for (const node of mutation.addedNodes) {
                    if (node.nodeType === 1) { // 元素节点
                        // 检查节点本身的ID
                        if (node.id && matchesId(node.id, partialId, matchMode)) {
                            observer.disconnect();
                            callback(node);
                            return;
                        }
                        // 检查节点的子节点
                        const matchedElement = node.querySelector(`[id]`);
                        if (matchedElement) {
                            const elements = node.querySelectorAll('[id]');
                            for (const element of elements) {
                                if (element.id && matchesId(element.id, partialId, matchMode)) {
                                    observer.disconnect();
                                    callback(element);
                                    return;
                                }
                            }
                        }
                    }
                }
                // 检查属性变化(如id被添加或修改)
                if (mutation.type === 'attributes' && mutation.attributeName === 'id') {
                    const element = mutation.target;
                    if (element.id && matchesId(element.id, partialId, matchMode)) {
                        observer.disconnect();
                        callback(element);
                        return;
                    }
                }
            }

            // 额外检查整个文档以防遗漏
            const matchedElement = checkElement();
            if (matchedElement) {
                observer.disconnect();
                callback(matchedElement);
            }
        });

        // 开始观察文档
        observer.observe(document.body, {
            childList,
            subtree,
            attributes,
            attributeFilter,
            attributeOldValue
        });

        return observer; // 返回观察器以便后续控制
    }

    // 监听数量变化
    document.getElementById('root').addEventListener('input', function (e) {
        if (e.target.matches('[class^="Input_input"] input')) {
            onInputValueChange(e.target.value);
            buildNum = e.target.value;
        }
    });

    // 监听面板弹出
    const modalObserver = observeElementByFuzzyClass('Modal_modalContainer', (el) => {
        // 数量input
        const inputItem = document.querySelector('[class^="Input_input"] input');

        // 监听插件数量显示
        const tillLevelNumberObserver = observeElementByPartialId('tillLevelNumber', (ele) => {
            ele.style.cursor = "pointer";
            ele.addEventListener('click', function () {
                const value = ele.innerText.split(" ")[0];
                reactInputTriggerHack(inputItem, value);
            });
        }, { stopAfterFirstMatch: false, multiple: true });

        const skillActionDetailObserver = observeElementByFuzzyClass('SkillActionDetail_itemRequirements', (ele) => {
            needItemEle = ele;
            ele.style.gridTemplateColumns = "auto min-content auto auto";
            onInputValueChange(0);
        }, { stopAfterFirstMatch: false, multiple: true });



    }, { stopAfterFirstMatch: false, multiple: true });
    function reactInputTriggerHack(inputElem, value) {
        let lastValue = inputElem.value;
        inputElem.value = value;
        let event = new Event("input", {
            bubbles: true
        });
        event.simulated = true;
        let tracker = inputElem._valueTracker;
        if (tracker) {
            tracker.setValue(lastValue);
        }
        inputElem.dispatchEvent(event);
    }


    function onInputValueChange(value) {
        console.log('动态input值变化:', value);
        let itemInfoArr = [];
        let needItemObj = needItemEle.children;
        if (needItemObj.length > 3 && needItemObj.length % 4 == 0 && needItemObj[3].innerText.startsWith('需要:')) {
            for (let i = 0; i < needItemObj.length; i++) {
                if (i % 4 == 0) {
                    itemInfoArr.push([needItemObj[i]]);
                } else {
                    itemInfoArr[itemInfoArr.length - 1].push(needItemObj[i]);
                }
            }
            itemInfoArr.forEach(element => {
                let num = parseInt(element[1].innerText.replace(/[^0-9]/g, ''), 10);
                if (isNaN(num)) {
                    num = 1;
                }
                console.log(num);
                element[3].innerHTML = `需要:${num * value}个`;
            });
        } else {
            for (let i = 0; i < needItemObj.length; i++) {
                if (i % 3 == 0) {
                    itemInfoArr.push([needItemObj[i]]);
                } else {
                    itemInfoArr[itemInfoArr.length - 1].push(needItemObj[i]);
                }
            }
            itemInfoArr.forEach(element => {
                let additem = document.createElement('span');
                let num = parseInt(element[1].innerText.replace(/[^0-9]/g, ''), 10);
                if (isNaN(num)) {
                    num = 1;
                }
                console.log(num);
                additem.innerHTML = `<span class="SkillActionDetail_itemRequirementCell__1F9JM SkillActionDetail_inventoryCount__tHmPD">需要:${num * value}个</span>`;
                needItemEle.insertBefore(additem, element[2].nextSibling);
            });
        }

    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址