IdleTools

一键吃药|一键点亮|一键改造|一键合符文|一键血白

// ==UserScript==
// @name         IdleTools
// @version      0.8.6
// @description  一键吃药|一键点亮|一键改造|一键合符文|一键血白
// @author       奶牛
// @match        https://www.idleinfinity.cn/Equipment/Query?*
// @match        https://www.idleinfinity.cn/Map/Detail?*
// @match        https://www.idleinfinity.cn/Equipment/Query?*
// @match        https://www.idleinfinity.cn/Equipment/Reform?*
// @match        https://www.idleinfinity.cn/Equipment/Material?*
// @grant        none
// @license MIT
// @namespace https://greasyfork.org/users/1411581
// ==/UserScript==
(function () {
    getLibrary().then(data => {
        // console.log(data);
        addScriptToHead(data);
        async function asyncLanuch() {
            onLaunch();
        }
        asyncLanuch();
    }).catch((_url, xhr, status, error) => {
        alert('从(' + _url + ')获取数据失败!请确认重载', function () { location.reload(); });
    });
})();

function onLaunch() {
    //存储角色状态的key值
    const charStatus = "charStatus";
    //一键吃药记录的物品id
    const sanMedKey = "sanMedcineIds";

    const isClickOnline = "isClickOnline";

    //改造需要匹配的词条
    const reformKeyArr = "reformKeyArr";
    //改造白名单
    const reformWhiteList = [["血红", "转换"], ["雄黄", "转换"], ["血红", "白热"], ["雄黄", "白热"], ["雷云风暴", "陨石"], ["支配", "陨石"], ["冰封球", "陨石"]]
    //升级符文保留数量默认表
    const storedCompandDefault = {
        "夏-13#": 200,
        "多尔-14#": 200,
        "蓝姆-20#": 100,
        "普尔-21#": 1000,
        "乌姆-22#": 1000,
        "马尔-23#": 1000,
        "伊司特-24#": 1000,
        "古尔-25#": 1000,
        "伐克斯-26#": 1000,
        "欧姆-27#": 1000,
        "罗-28#": 1000,
        "瑟-29#": 1000,
        "贝-30#": 1000,
        "乔-31#": 1000,
        "查姆-32#": 1000,
        "萨德-33#": 1000,
    }
    class Idle {
        constructor() {

            this.cids = this.getCharacters();
            this.initCidStatus();
            this.initCurrentChar();
            this.loadPlugin();
        }

        cids = [];
        //当前用户
        currentId = 0;


        //获取所有账号
        getCharacters() {
            let all = [];
            $(".dropdown-menu.char-switch li[data-id]").each((index, item) => {
                let id = $(item).attr("data-id");
                all.push(id);
            });
            return all;
        }
        initCurrentChar() {
            let localtion = $("a:contains('消息')")[0].href;//消息中有当前id
            let url = new URL(localtion);
            let urlParams = new URLSearchParams(url.search);
            let id = urlParams.get("id");
            this.currentId = id;
            //在地图页面修正离线状态,其他页面每次刷新初始化都是在线状态 
            if (window.location.href.indexOf("Map/Detail") > -1) {
                var btns = $('a:contains("离线挂机")');
                var localObj = JSON.parse(localStorage.getItem(charStatus));
                if (btns.length == 0) {

                    localObj[id].isOnline = true;
                }
                else {
                    localObj[id].isOnline = false;
                }
                saveMergeStatus(localObj, charStatus);
            }

        }

        //初始化一些角色相关的对象
        initCidStatus() {
            var map = {};
            this.cids.forEach((item, index) => {
                var obj = {};
                obj[item] = { isOnline: true, }
                saveMergeStatus(obj, charStatus);
            });
        }


        online(callback) {
            setTimeout(() => {
                $.ajax({
                    type: "POST", // 或者 "GET",根据实际情况选择
                    url: "BattleGuaji",
                    data: $("form").serialize(),
                    success: function (response) {
                        if (callback) callback();
                        location.reload();
                    }
                });
            }, 1000)

        }

        switchCharacter(id) {
            if (!!!id) return;
            setTimeout(() => {
                location.href = `https://www.idleinfinity.cn/Map/Detail?id=${id}`;
            }, 1000)

        }
        //开始循环点亮
        onlineLoop() {
            let isStart = localStorage.getItem(isClickOnline);
            if (!!!isStart) return;//没有点击启动则不开始自动点亮
            var localObj = JSON.parse(localStorage.getItem(charStatus));
            for (let id in localObj) {
                let item = localObj[id];
                if (this.currentId == id) {
                    if (!item.isOnline) {
                        this.online(() => {
                            var cIndex = this.cids.indexOf(this.currentId);
                            this.switchCharacter(this.cids[++cIndex]);
                        });
                    }
                    else {
                        var cIndex = this.cids.indexOf(this.currentId);
                        this.switchCharacter(this.cids[++cIndex]);
                    }

                }
            }
            if (this.currentId == this.cids[this.cids.length - 1]) {
                localStorage.removeItem(isClickOnline);
            }
        }




        loadReformPlugin() {
            if (location.href.indexOf("Equipment/Reform") == -1) {
                localStorage.removeItem(reformKeyArr);
                return;
            }
            var container = $(".panel-heading:eq(1)");
            var span1 = $("<span>", {
                text: "目标词条1:"
            });
            var input1 = $("<input>", {
                type: "text",
                placeholder: "输入匹配词条",
                style: "color:#000",
                id: "txtTarget1"
            })
            var input2 = $("<input>", {
                type: "text",
                placeholder: "输入匹配词条",
                style: "color:#000",
                id: "txtTarget2"
            })


            container.append(span1)
            container.append(input1)
            var span2 = $("<span>", {
                text: "目标词条2:",

            });
            container.append(span2)
            container.append(input2)

            var span3 = $("<span>", {
                text: "改造公式:"
            });
            var opt = $("<select>", {
                id: "optType",
            })
            // 添加option元素
            var options = [
                { text: '蓝装+14#', value: '30' },
                { text: '蓝装+13#', value: '20' },
                { text: '蓝装+12#', value: '10' },
                { text: '蓝装+绿|钻宝石', value: '11' },
                { text: '蓝装+21#', value: '26' },
                { text: '套装+23#', value: '16' },
                { text: '套装+21#', value: '17' },
                { text: '稀有+22#', value: '27' },



            ];
            //需要一个保留清单 洗出值钱的其他东西保留

            $.each(options, function (i, option) {
                opt.append($('<option></option>').text(option.text).attr('value', option.value));
            });
            container.append(span3);
            container.append(opt);

            var btn = $('<button>', {
                'class': 'btn btn-default btn-xs dropdown-toggle',
                'text': '开始改造',
                'style': "margin-left:20px",
                'id': "btnReform",
                click: () => {
                    var t1 = $("#txtTarget1").val();
                    var t2 = $("#txtTarget2").val();
                    var optType = $("#optType").val();
                    var arr = this.saveAffixToArr([t1, t2, optType]);
                    saveMergeStatus(arr, reformKeyArr);
                    this.reformAuto();
                }
            });
            container.append(btn);
            this.reformAuto();

        }

        reform(type, callback) {
            $("#form input[name='type']").val(type);
            $.ajax({
                type: "POST", // 或者 "GET",根据实际情况选择
                url: "EquipReform",
                data: $("form").serialize(),
                success: function (response) {
                    if (callback) {
                        callback();
                    }
                    else {
                        location.reload();
                    }
                }
            });

        }
        reformAuto() {

            var localStr = localStorage.getItem(reformKeyArr);
            if (!!!localStr) return;//去掉本地存储就停止
            var arr = JSON.parse(localStr);
            $("#txtTarget1").val(arr[0]);
            $("#txtTarget2").val(arr[1]);
            $("#optType").val(arr[2]);
            let affix = this.getAffix();
            if (!!affix) {
                $("#affix").val(affix);
                this.setAffixCheckbox(affix);
            }
            //检测一下是否匹配
            var text = $(".equip")[0].innerText;
            if (text.indexOf(arr[0]) > -1 && text.indexOf(arr[1]) > -1) {
                localStorage.removeItem(reformKeyArr);
                confirm("出现了!", function () {

                });
                return;
            }
            if (this.checkWhiteList(text)) {
                localStorage.removeItem(reformKeyArr);
                confirm("出现了白名单物品!", function () {

                });
                return;
            }
            setTimeout(() => {
                this.reform(arr[2]);
            }, 1500)


        }
        checkWhiteList(text) {
            for (let i = 0; i < reformWhiteList.length; i++) {
                var isMatch = true;//满足一组条件才算命中
                for (let j = 0; j < reformWhiteList[i].length; j++) {
                    var condition = reformWhiteList[i][j];
                    if (text.indexOf(condition) == -1) {

                        isMatch = false;
                        break;
                    }
                }
                if (isMatch) {
                    return true;
                }
            }
            return false;
        }
        getAffix() {
            var arr = JSON.parse(localStorage.getItem(reformKeyArr));
            var affixArr = arr.splice(3);
            if (affixArr.length == 0) return "";
            return affixArr.join(",");
        }

        //勾选选中的
        setAffixCheckbox(affixStr) {
            var arr = affixStr.split(",");
            arr.forEach((item, index) => {
                var fillter = `.affix-select[data-name='${item}']`
                $(fillter).prop('checked', true);
            })
        }
        //保存勾选框
        saveAffixToArr(arr) {

            $(".affix-select").each((index, item) => {
                var isChecked = $(item).prop("checked");
                if (isChecked) {
                    arr.push($(item).attr("data-name"));
                }
            })
            return arr;
        }
        //改造返回储藏箱
        reformBackToBag() {
            $("a:contains('返回')")[0].click();
        }




        loadPlugin() {
            //自动吃药
            loadSanPlugin();
            //电量
            loadOnlinePlugin();
            //自动改造
            this.loadReformPlugin();
            loadStorePlugin();
        }

    }

    let _idle = new Idle();
    _idle.onlineLoop();



    //载入吃药插件
    function loadSanPlugin() {
        var equipArr = [];//所有装备的id;
        var sanRestoreMap = {};//回复药水所处在数组中的index
        $(".equip-box .equip-name .unique[data-id]").each(function (index, item) {
            var name = $(this)[0].innerText;
            if (name.indexOf("药水") > -1) {
                sanRestoreMap[index] = item;
            }

        })
        if (countProperties(sanRestoreMap) > 0) {
            var btn = $('<button>', {
                'class': 'btn btn-default btn-xs dropdown-toggle',
                'text': '一键吃药',
                'id': "btnSanRestore"
            });
            var numInput = $('<input>', {
                'style': "width:120px;line-height:18px;",
                'placeholder': '请填写要吃的数量',
                'id': 'sanNumTxt'
            });
            $(".panel-heading:eq(2) .pull-right").append(btn);
            $(".panel-heading:eq(2) .pull-right").append(numInput);
        }
        $(".equip-box .equip-use[data-id]").each(function (index, item) {

            let id = $(item).attr("data-id");
            equipArr.push(id);
        });

        useSan();//缓存中计数吃药
        $("#btnSanRestore").on("click", function () {
            var count = 0;
            var sanMedcineIds = [];
            var num = $("#sanNumTxt").val() * 1;
            if (Number.isNaN(num) || num <= 0) {
                alert("请填写正确的数量");
                return;
            }
            for (let key in sanRestoreMap) {

                if (count < num) {
                    sanMedcineIds.push(equipArr[key]);
                }

                count++;
            }
            localStorage.setItem(sanMedKey, sanMedcineIds);
            useSan();
        });

        //自动吃掉本地存储sanMedcineIds里面的药
        function useSan() {
            let medcine = localStorage.getItem(sanMedKey);
            if (medcine == null) return;
            let arr = medcine.split(',');
            if (!!!arr[0]) return;
            use(arr[0], function () {
                arr.splice(0, 1);
                localStorage.setItem(sanMedKey, arr);
            });
        }

    }

    //载入上线脚本
    function loadOnlinePlugin() {
        var btns = $('a:contains("离线挂机")');
        if (btns.length == 0) {
            return;
        }
        var container = $(".panel-inverse .panel-footer .pull-right:first");
        var btn = $('<button>', {
            'class': 'btn btn-default btn-xs dropdown-toggle',
            'text': '一键点亮',
            'id': "btnOnline"
        });
        container.append(btn);

        $("#btnOnline").on("click", function () {
            saveMergeStatus(true, isClickOnline);

            _idle.switchCharacter(_idle.cids[0]);//从第一个角色开始
        });

    }



    //使用道具
    function use(eid, callback) {
        $.ajax({
            url: "EquipUse",
            type: "post",
            data: {
                cid: $("#cid").val(),
                eid: eid,
                __RequestVerificationToken: $("[name='__RequestVerificationToken']").val()
            },
            dataType: "html",
            success: function (result) {
                callback();
                location.reload();
            },
            error: function (request, state, ex) {
                console.log(result)
            }
        });
    }

    function countProperties(obj) {
        let count = 0;
        for (let prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                count++;
            }
        }
        return count;
    }


    //#region 符文插件

    //载入符文插件
    function loadStorePlugin() {
        if (location.href.indexOf("Equipment/Material") == -1) {
            return;
        }

        var compandMode = false;
        var autoCompandMode = false;
        var storedRuneCounts = {}; // 存储每个符文项的数量
        var storedCompandCounts = {}; // 合成每个符文项的保留数量

        function showChange() {
            var lastCompandRuneId = parseInt(localStorage.getItem('lastCompandRuneId'));
            //刷新页面前正在运行一键升级符文逻辑,且符文检查没有运行完
            if (!lastCompandRuneId.isNaN && lastCompandRuneId >= 0 && lastCompandRuneId < 33) {
                autoCompandMode = true;
            }

            console.log("上次自动升级符文id:" + lastCompandRuneId + "----是否进入自动升级模式:" + autoCompandMode);
            //一键升级模式
            if (autoCompandMode) {
                var curCompandRuneId = lastCompandRuneId + 1;
                $('.col-xs-12.col-sm-4.col-md-3.equip-container').each(function () {
                    var runeName = $(this).find('p:first .equip-name .artifact:nth-child(2)').text().trim(); // 获取符文名称的第二个 span
                    var runeCount = parseInt($(this).find('p:first .artifact').last().text().trim()); // 获取符文数量

                    var storedCompandCounts = JSON.parse(localStorage.getItem('storedCompandCounts'));

                    var storedCount = storedCompandCounts[runeName];
                    if (storedCount.isNaN || storedCount == undefined)
                        storedCount = 0;
                    var regexResult = runeName.match(/-(\d+)#/);
                    var count = 0;
                    if (runeCount > storedCount) {
                        count = runeCount - storedCount;
                        count = count - count % 2;
                    }

                    if (regexResult[1] == curCompandRuneId) {
                        localStorage.setItem('lastCompandRuneId', regexResult[1]);
                        if (count > 1) {
                            //升级符文消息
                            compandStore(regexResult[1], count);
                        }
                        else {
                            showChange();
                        }
                        // return;
                    }
                });
                compandMode = true;
            }

            //设置升级保留数量模式
            if (compandMode) {
                // localStorage.setItem('storedCompandCounts', JSON.stringify(""));
                //默认保留数量
                var storedCompandCounts = JSON.parse(localStorage.getItem('storedCompandCounts')) || storedCompandDefault;
                $('.panel-heading:contains("符文") .rasdsky').remove();

                var confirmButton = $('<a class="btn btn-xs btn-default" id="confirmButton">确认</a>');
                var cancleButton = $('<a class="btn btn-xs btn-default" id="cancleButton">退出</a>');

                // 将按钮放入一个 div 中,并添加到 panel-heading 中
                var buttonContainer = $('<div class="pull-right rasdsky"></div>');
                buttonContainer.append(confirmButton);
                buttonContainer.append(cancleButton);

                $('.panel-heading:contains("符文")').append(buttonContainer);
                confirmButton.click(function () {
                    $('.col-xs-12.col-sm-4.col-md-3.equip-container').each(function () {
                        var runeName = $(this).find('p:first .equip-name .artifact:nth-child(2)').text().trim(); // 获取符文名称的第二个 span
                        var runeCount = parseInt($(this).find('p:first .artifact').last().text().trim()); // 获取符文数量

                        var _inputElement = $(this).find('.rasdsky-input:first');
                        var cnt = parseInt(_inputElement.val());
                        if (storedCompandCounts.hasOwnProperty(runeName)) {
                            if (!cnt.isNaN && cnt != undefined) {
                                storedCompandCounts[runeName] = cnt;
                            }
                        }
                        else {
                            storedCompandCounts[runeName] = 0;
                        }
                        // var storedCount = storedCompandCounts[runeName];
                        // var regexResult = runeName.match(/-(\d+)#/);
                        // if (runeCount > storedCount) {
                        //     var count = runeCount - storedCount;
                        //     count = count - count % 2;
                        //     compandStore(regexResult[1], count);
                        // }
                    });
                    localStorage.setItem('storedCompandCounts', JSON.stringify(storedCompandCounts)); // 存储到 localStorage 

                    //进入一键升级模式
                    autoCompandMode = true;
                    localStorage.setItem('lastCompandRuneId', 0);
                    showChange();
                });
                cancleButton.click(function () {
                    compandMode = false;
                    autoCompandMode = false;
                    showChange();
                });

                $('.col-xs-12.col-sm-4.col-md-3.equip-container').each(function () {
                    var runeName = $(this).find('p:first .equip-name .artifact:nth-child(2)').text().trim(); // 获取符文名称的第二个 span

                    var retainCount = 0;
                    if (storedCompandCounts.hasOwnProperty(runeName)) {
                        retainCount = storedCompandCounts[runeName];
                        if (retainCount == undefined || retainCount.isNaN)
                            retainCount = 0;
                    }
                    $(this).find('.rasdsky').remove();

                    var t = ($('<span>').text('  保留:').css('color', 'grey'));

                    var inputElement = $('<input class="rasdsky-input">').css({
                        "color": "grey",
                        "width": 120,
                        "height": 21,
                    });
                    inputElement.val(retainCount);
                    var p = $('<p class="rasdsky">');
                    p.append(t);
                    p.append(inputElement);

                    $(this).append(p)

                });
            }
            //查看变动数量模式
            else {

                $('.panel-heading:contains("符文") .rasdsky').remove();
                var storedRuneCounts = JSON.parse(localStorage.getItem('storedRuneCounts')) || {};
                console.log(storedRuneCounts);
                var storedTime = localStorage.getItem('storedTime');

                // 将按钮放入一个 div 中,并添加到 panel-heading 中
                var buttonContainer2 = $('<div class="pull-right rasdsky"></div>');

                // 创建展示存储时间的元素
                var timeDiv = $('<div class="pull-left rasdsky"></div>');
                var timeElement = $('<p>').text('存储时间: ' + storedTime);
                timeDiv.append(timeElement);
                // 创建存储符文数量的按钮
                var saveButton = $('<a class="btn btn-xs btn-default" id="saveButton">存储</a>');
                // 创建升级符文的按钮
                var compandButton = $('<a class="pull-right btn btn-xs btn-default" id="compandButton">升级</a>');

                buttonContainer2.append(timeDiv);
                buttonContainer2.append(saveButton);
                buttonContainer2.append(compandButton);

                $('.panel-heading:contains("符文")').append(buttonContainer2);

                saveButton.click(function () {
                    var storedRuneCounts = {};

                    $('.col-xs-12.col-sm-4.col-md-3.equip-container').each(function () {

                        var runeName = $(this).find('p:first .equip-name .artifact:nth-child(2)').text().trim(); // 获取符文名称的第二个 span

                        var runeCount = parseInt($(this).find('p:first .artifact').last().text().trim()); // 获取符文数量
                        // 检查解析是否成功,如果是 NaN 或者数量小于等于 20 则跳过不存储
                        var regexResult = runeName.match(/-(\d+)#/);
                        if (regexResult && parseInt(regexResult[1]) >= 1) {
                            // 检查解析是否成功,如果是 NaN 则设为 0
                            if (isNaN(runeCount)) {
                                runeCount = 0;
                            }
                            storedRuneCounts[runeName] = runeCount; // 存储符文数量
                        }
                    });

                    var currentTime = new Date().toLocaleString(); // 获取当前时间
                    localStorage.setItem('storedRuneCounts', JSON.stringify(storedRuneCounts)); // 存储到 localStorage
                    localStorage.setItem('storedTime', currentTime); // 存储时间到 localStorage
                    alert("已存储数据", function () { });
                });

                compandButton.click(function () {
                    compandMode = true;
                    showChange();
                });

                $('.col-xs-12.col-sm-4.col-md-3.equip-container').each(function () {

                    var $pElement = $(this).find('p:first'); // 获取当前容器下的第一个 <p> 元素

                    var runeName = $(this).find('p:first .equip-name .artifact:nth-child(2)').text().trim(); // 获取符文名称的第二个 span

                    var currentRuneCount = parseInt($(this).find('p:first .artifact').last().text().trim()); // 获取符文数量

                    if (storedRuneCounts.hasOwnProperty(runeName)) {
                        var storedCount = storedRuneCounts[runeName];
                        var changeCount = currentRuneCount - storedCount; // 计算数量变动
                        if (changeCount !== undefined) {
                            var changeText = '  (' + storedCount + ' -> ' + currentRuneCount + ')'; // 根据变动数量生成对应文本

                            $(this).find('.rasdsky').remove();
                            // 将变动数量拼接到符文信息的最后,并为 <p> 标签添加对应的样式
                            $(this).find('p:first .artifact:last').append($('<span class="rasdsky">').text(changeText).css('color', (changeCount > 0) ? 'red' : (changeCount < 0) ? 'green' : 'white')); // 为 <p> 标签添加颜色样式);)
                        }
                    }
                });
            }
        }
        showChange();

        // function compandStore(rune, count) {
        //     var t = 1500;
        //     POST_Message("RuneUpgrade", MERGE_Form({
        //         rune: rune,
        //         count: count,
        //     }), "html", t, function (result) {
        //         compandMode = true;
        //         // location.reload();
        //     }, function (request, state, ex) {
        //         // console.log(result)
        //     })
        // }
        function compandStore(rune, count) {
            var data = MERGE_Form({
                rune: rune,
                count: count
            });
            POST_Message("RuneUpgrade", data, "html", 2000)
                .then(r => {
                    compandMode = true;
                    location.reload();
                })
                .catch(r => { console.log(r) });
        }
    }

    //#endregion

    /***************一键血白**********************/
    const autoXuebaiType = "autoXuebaiType";
    loadAutoXuebai();//在储藏箱执行
    reformXuebai();//在改造页执行
    //加载一键血白
    function loadAutoXuebai() {
        if (location.href.indexOf("Equipment/Query") == -1) {
            return;
        }
        var targetEquip = [];//回复药水所处在数组中的index
        $(".equip-box .equip-name").each(function (index, item) {
            var name = $(this)[0].innerText;
            if (name == "【白热的珠宝】" || name == "【血红之珠宝】" || name == "【雄黄之珠宝】") {
                targetEquip.push(item);
            }

        })
        $(".equip-bag .equip-name").each(function (index, item) {
            var name = $(this)[0].innerText;
            if (name == "【白热的珠宝】" || name == "【血红之珠宝】" || name == "【雄黄之珠宝】") {
                targetEquip.push(item);
            }

        })
        if (targetEquip.length > 0) {
            var btn = $('<button>', {
                'class': 'btn btn-default btn-xs dropdown-toggle',
                'text': '一键血白',
                'id': "btnXuebai"
            });
            $(".panel-heading:eq(2) .pull-right").append(btn);
        }
        else {
            localStorage.removeItem(autoXuebaiType);
        }
        $("#btnXuebai").on("click", function () {
            saveMergeStatus(20, autoXuebaiType);
            var btn = $(targetEquip[0]).parent().find(".equip-reform");
            btn[0].click();
        });
        if (targetEquip.length > 0 && localStorage.getItem(autoXuebaiType)) {
            var btn = $(targetEquip[0]).parent().find(".equip-reform");
            btn[0].click();
        }
    }

    function reformXuebai() {
        if (location.href.indexOf("Equipment/Reform") == -1) {
            return;
        }
        var type = localStorage.getItem(autoXuebaiType);
        if (type) {
            setTimeout(() => {
                _idle.reform(type, function () {
                    _idle.reformBackToBag();
                });
            }, 1500)


        }

    }

    /***************一键血白end**********************/
}

function deepMerge(target, ...sources) {
    for (let source of sources) {
        for (let key in source) {
            if (source.hasOwnProperty(key)) {
                if (typeof target[key] === 'object' && typeof source[key] === 'object') {
                    deepMerge(target[key], source[key]);
                } else {
                    target[key] = source[key];
                }
            }
        }
    }
    return target;
}
//保存对象到本地缓存,有则合并,无则直接新增
function saveMergeStatus(obj, key) {
    var localObj = localStorage.getItem(key);
    localObj = JSON.parse(localObj);
    if (!!!localObj) {
        var str = JSON.stringify(obj);
        localStorage.setItem(key, str);
    }
    else {

        var t = deepMerge(localObj, obj);
        var saveStr = JSON.stringify(t);
        localStorage.setItem(key, saveStr);
    }
}

//#region  INIT 
function addScriptToHead(src) {
    const script = document.createElement('script');
    script.text = src;
    document.head.appendChild(script);
    console.log(document.head);
}

function getLibrary(_timeout = 5000) {
    return new Promise((resolve, reject) => {
        const _url = "https://raw.githubusercontent.com/GbaFun/IdleinfinityTools/refs/heads/main/IdleUtils.js"
        $.ajax({
            url: _url,
            timeout: _timeout,
            dataType: 'text',
            success: function (data) {
                // console.log(data);
                resolve(data);
            },
            error: function (xhr, status, error) {
                // 请求失败时的操作
                // console.log('从(' + _url + ')获取JS脚本失败!');
                reject(_url, xhr, status, error);
            }
        });
    });
}

//#endregion