您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
火龙果妙妙小工具,日利计算,每日利润计算,仓库价格统计,菜单栏技能信息
当前为
// ==UserScript== // @name 摸鱼放置妙妙小工具_v0.22 // @namespace http://tampermonkey.net/ // @version 0.22 // @description 火龙果妙妙小工具,日利计算,每日利润计算,仓库价格统计,菜单栏技能信息 // @author 火龙果 // @match **moyu-idle.com/* // @match *://*moyu-idle.com/* // @match *://www.moyu-idle.com/* // @license MIT // @icon https://www.google.com/s2/favicons?sz=64&domain=moyu-idle.com // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @run-at document-start // @require https://cdnjs.cloudflare.com/ajax/libs/pako/2.1.0/pako.min.js // ==/UserScript== (function () { 'use strict'; //有什么关于本脚本的意见或建议 1群内找火龙果 // 显示用户等级信息 let showUserLevel = true; // 显示物品价格 let showItemPrice = true; // 等待返回消息时长 设置长时间以防破财 毫秒 const waitForMsg = 30 * 1000; // socketIo模式 const socketIoMode = false; // ws调试模式开关 let WS_DEBUG_MODE = false; console.log(`[猫猫放置妙妙小工具] 已启动 v0.22`); // 物品价格 物品:价格 const cn_en = { "饱食度": "__satiety", "小猫咪": "__cat", "金币": "gold", "猫爪古钱币": "catPawCoin", "矿石": "stone", "煤炭": "coal", "沙子": "sand", "铁": "iron", "钢": "steel", "银矿": "silverOre", "银锭": "silverIngot", "秘银矿": "mithrilOre", "秘银锭": "mithrilIngot", "玻璃瓶": "glassBottles", "铁罐头": "ironCan", "鱼鳞矿": "fishscaleMineral", "绒毛岩": "fluffstone", "爪痕矿": "clawmarkOre", "魔晶石": "manacrystal", "猫眼石": "catEyeStone", "琥珀瞳石": "amberEyeStone", "鱼鳞合金": "fishscaleMineralIgnot", "暗影精铁": "shadowSteel", "星辰合金": "starforgedAlloy", "鸡蛋": "chickenEgg", "牛奶": "milk", "羊毛": "wool", "蚕丝": "silk", "羊绒布料": "cashmere", "丝绸布料": "silkFabric", "绒毛": "fluff", "绒毛布料": "fluffFabric", "斧头": "axe", "铁镐": "pickaxe", "采集戒指": "collectRing", "附魔采集戒指": "collectRing2", "哥布林匕首·改": "goblinDaggerPlus", "狼皮甲": "wolfPeltArmor", "骷髅盾·强化": "skeletonShieldPlus", "巨魔木棒·重型": "trollClubPlus", "巨蝎毒矛": "scorpionStingerSpear", "守护者核心护符": "guardianCoreAmulet", "月光守护者": "moonlightGuardianCoreAmulet", "龙鳞甲": "dragonScaleArmor", "羊毛衣": "woolCoat", "羊毛帽": "woolHat", "羊毛手套": "woolGloves", "羊毛裤": "woolPants", "铁甲衣": "ironCoat", "铁头盔": "ironHat", "铁护手": "ironGloves", "铁护腿": "ironPants", "钢甲衣": "steelCoat", "钢头盔": "steelHat", "钢护手": "steelGloves", "钢护腿": "steelPants", "银质剑": "silverSword", "银质匕首": "silverDagger", "银护甲": "silverCoat", "银头盔": "silverHat", "银护手": "silverGloves", "银护腿": "silverPants", "猫猫礼袋": "catGiftBag", "幸运猫盒": "luckyCatBox", "神秘罐头": "mysteryCan", "猫薄荷惊喜包": "catnipSurprise", "喵能量球": "meowEnergyBall", "梦羽袋": "dreamFeatherBag", "木剑": "woodSword", "毛毛衣": "catFurCoat", "毛毛帽": "catFurHat", "毛毛手套": "catFurGloves", "毛毛裤": "catFurPants", "采集手环": "collectingBracelet", "采矿工作服": "miningBelt", "园艺手套": "farmingGloves", "重型矿工手套": "heavyMinerGloves", "灵巧采集靴": "agileGatherBoots", "月光吊坠": "moonlightPendant", "测试资源": "testResource", "冰霜匕首": "frostDagger", "冰镐": "icePickaxe", "羊毛罩袍": "woolBurqa", "羊毛法师帽": "woolMageHat", "羊毛法师手套": "woolMageLongGloves", "羊毛法师裤": "woolMagePants", "羊毛紧身衣": "woolTightsCloth", "羊毛裹头巾": "woolDexHeadScarf", "羊毛绑带手套": "woolDexGloves", "羊毛紧身裤": "woolTightsPants", "木法杖": "woodStaff", "铁匕首": "ironDagger", "月光法杖": "moonlightStaff", "喵影法杖": "mewShadowStaff", "魔晶法杖": "manacrystalStaff", "时光猫眼法杖": "timeflowCatEyeStaff", "交织猫瞳杖": "intertwinedCatEyeStaff", "秘银头盔": "mithrilHat", "秘银护甲": "mithrilCoat", "秘银手套": "mithrilGloves", "秘银护腿": "mithrilPants", "群体护盾技能书": "groupShieldSkillBook", "穿针引线技能书": "threadingNeedleSkillBook", "自然馈赠技能书": "natureGiftSkillBook", "知识启迪技能书": "knowledgeInspirationSkillBook", "种瓜得瓜技能书": "sowMelonsReapMelonsSkillBook", "强化赋能技能书": "enhanceEmpowerSkillBook", "强化冲击技能书": "enhanceStrikeSkillBook", "超级大蘑菇": "hugeMushroom", "神秘浆果": "mysteriousBerry_1", "闪光岩": "flashStone", "彩虹鱼": "rainbowFish", "黑暗鱼": "darkFish", "胖胖鱼": "fatFish", "闪光鱼": "flashFish", "失败作": "failedFood", "闪光料理": "flashFood", "会跳舞的蛋糕": "dancingCake", "金蛋": "goldenEgg", "可爱的衣服": "cuteOutfit", "可爱的手环": "cuteBracelet", "可爱的帽子": "cuteHat", "可爱的围脖": "cuteScarf", "可爱的娃娃": "cuteDoll", "可爱的裙子": "cuteDress", "猫猫枪": "cuteGun", "猫猫剑": "cuteSword", "猫猫锤": "cuteHammer", "猫猫项链": "cuteIronBracelet", "猫猫猫": "cuteIronCat", "猫猫小铁盒": "cuteIronBox", "闪光铁剑": "shinyIronSword", "猫猫铃": "cuteIronBell", "猫猫盾": "cuteIronShield", "葡萄": "grape", "黑麦": "rye", "木材": "wood", "竹子": "bamboo", "蘑菇": "mushroom", "浆果": "berry", "蜂蜜": "honey", "草药": "herb", "晨露花": "dawnBlossom", "琥珀汁": "amberSap", "夜光苔": "luminousMoss", "风铃草": "windBellHerb", "云絮": "cloudCotton", "彩虹碎片": "rainbowShard", "自动喂食器": "autoFeeder", "猫抓板": "scratchingPost", "书桌": "studyDesk", "毛绒玩具": "cashmereToy", "舒适猫窝": "silkKittyNest", "遮光窗帘": "silkCurtain", "鱼": "fish", "鲑鱼": "salmon", "金枪鱼": "tuna", "翡翠金枪鱼": "jadeTuna", "余烬鳗": "emberEel", "月光虾": "moonlightShrimp", "水晶鲤": "crystalCarp", "木钓竿": "woodFishingRod", "竹钓竿": "bambooFishingRod", "竹抄网": "bambooDiddleNet", "竹制捕鱼笼": "bambooFishpot", "铁钓竿": "ironFishingRod", "铁抄网": "ironDiddleNet", "铁制捕鱼笼": "ironFishpot", "钓鱼帽": "fishingHat", "钓鱼专注帽": "focusedFishingCap", "远古鱼骨项链": "ancientFishboneNecklace", "钢制重锤": "steelHammer", "铁剑": "ironSword", "钢剑": "steelSword", "秘银剑": "mithrilSword", "秘银匕首": "mithrilDagger", "暗影精铁匕首": "shadowSteelDagger", "暗影精铁剑": "shadowSteelSword", "野草沙拉": "simpleSalad", "野果拼盘": "wildFruitMix", "鱼汤": "fishSoup", "浆果派": "berryPie", "蘑菇炖汤": "mushroomStew", "猫薄荷饼干": "catMint", "猫咪零食": "catSnack", "豪华猫粮": "luxuryCatFood", "鲜鱼刺身拼盘": "sashimiPlatter", "蛋奶布丁": "custardPudding", "浆果酒": "berryWine", "晨露精酿": "dawnBlossomWine", "铃语精酿": "windBellWine", "浆果奶昔": "milkManaShake", "铃语奶昔": "windBellMilkShake", "金枪鱼罐头": "cannedTuna", "风味虾仁罐头": "cannedShrimp", "彩虹鱼干罐头": "cannedRainbowFish", "神秘锦鲤罐头": "cannedMysticalKoi", "银项链": "silverNecklace", "银手链": "silverBracelet", "猫薄荷手链": "catPotionSilverBracelet", "铁锅": "ironPot", "铁铲": "ironShovel", "钢锅": "steelPot", "钢铲": "steelShovel", "铁锤": "ironMachinistHammer", "钢锤": "steelMachinistHammer", "酿造搅拌器": "fermentationStirrer", "裁缝剪刀": "tailorScissors", "针线包": "needleandThread", "采矿收纳背篓": "bambooMiningCatbasket", "秘银工匠锤": "mithrilMachinistHammer", "铁钳": "ironTongs", "彩虹手链": "rainbowBracelet", "彩虹项链": "rainbowNecklace", "竹质弓": "bambooBow", "毛毛裁缝服": "catTailorClothes", "毛毛裁缝手套": "catTailorGloves", "羊毛裁缝服": "woolTailorClothes", "羊毛裁缝手套": "woolTailorGloves", "毛毛可爱帽": "catFurCuteHat", "羊毛可爱帽": "woolCuteHat", "羊毛可爱手套": "woolCuteGloves", "羊毛工匠服": "woolArtisanOutfit", "丝质可爱帽": "silkCuteHat", "丝质可爱手套": "silkCuteGloves", "丝质工匠服": "silkArtisanOutfit", "丝质裁缝服": "silkTailorClothes", "丝质裁缝手套": "silkTailorGloves", "冰羽靴": "iceFeatherBoots", "云行靴": "cloudwalkerBoots", "雪狼皮披风": "snowWolfCloak", "云行斗篷": "cloudwalkerCloak", "诅咒香囊": "cursedSilkSachet", "厨师帽": "chefHat", "羊毛围裙": "woolChefApron", "羊毛隔热手套": "woolHeatResistantGloves", "羊毛探险背包": "woolExplorerCatpack", "虹运飘带": "luckRainbowRibbon", "丝质罩袍": "silkMageBurqa", "丝质法师帽": "silkMageHat", "丝质法师手套": "silkMageLongGloves", "丝质法师裤": "silkMagePants", "丝质法师披肩": "silkMageCloak", "丝质夜行衣": "silkTightsCloth", "丝质裹头巾": "silkDexHeadScarf", "丝质绑带手套": "silkDexGloves", "丝质宽松裤": "silkTightsPants", "丝质夜行斗篷": "silkDexCloak", "丝质战斗披风": "silkWarriorCloak", "丝质活力披肩": "silkVitalityCloak", "鱼鳞合金头盔": "fishscaleMineralHat", "鱼鳞合金盔甲": "fishscaleMineralCoat", "鱼鳞合金护手": "fishscaleMineralGloves", "鱼鳞合金护腿": "fishscaleMineralPants", "暗影精铁头盔": "shadowSteelHat", "暗影精铁盔甲": "shadowSteelCoat", "暗影精铁臂甲": "shadowSteelGloves", "暗影精铁腿甲": "shadowSteelPants", "提纯灵质": "purifiedEctoplasm", "纯净精华": "pureEssence", "治疗药水": "healingPotion", "魔法药水": "manaPotion", "魂灵之刃": "infusedShadowBlade", "纯净香囊": "puredSilkSachet", "魂灵守护者": "infusedGuardianCoreAmulet", "猫爪印章": "catPawStamp", "稀有猫鱼": "rareCatfish", "神秘锦鲤": "mysticalKoi", "藏宝图": "treasureMap", "猫爪化石": "catPawFossil", "猫雕像": "catStatue", "神秘铃铛": "mysteriousBell", "古代猫碗": "ancientCatBowl", "猫之卷轴": "catScroll", "猫咪文物碎片": "catAntiqueShard", "猫毛球": "catHairball", "招财猫护符": "luckyCatCharm", "猫薄荷宝石": "catnipGem", "远古鱼骨": "ancientFishBone", "胡须羽毛": "whiskerFeather", "月光铃铛": "moonlightBell", "贝壳": "shell", "神秘精华": "mysticalEssence", "猫薄荷药剂": "catPotion", "魔法卷轴": "magicScroll", "猫咪圣物": "catRelic", "祝福铃铛": "blessedBell", "悠闲平原探险地图": "plain_001_expedition_map", "幽暗森林探险地图": "forest_001_expedition_map", "黑石洞窟探险地图": "cave_001_expedition_map", "遗迹深处探险地图": "ruins_001_expedition_map", "极寒雪原探险地图": "snowfield_001_expedition_map", "猫影深渊探险地图": "cat_dungeon_001_expedition_map", "神圣猫咪神殿探险地图": "holy_cat_temple_001_expedition_map", "影爪巢穴探险地图": "shadow_paw_hideout_expedition_map", "星辉女帝试炼探险地图": "astralEmpressTrial_expedition_map", "\"游乐园\"探险地图": "amusement_park_expedition_map", "木浆": "woodPulp", "纸": "paper", "书": "book", "碳笔": "pencil", "力量经验": "experienceOfStrength", "敏捷经验": "experienceOfDexterity", "智力经验": "experienceOfIntelligence", "力量之书": "bookOfStrength", "敏捷之书": "bookOfDexterity", "智力之书": "bookOfIntelligence", "魔法书": "magicBook", "史莱姆凝胶": "slimeGel", "史莱姆核心": "slimeCore", "哥布林耳朵": "goblinEar", "哥布林匕首": "goblinDagger", "蝙蝠翅膀": "batWing", "蝙蝠牙": "batTooth", "狼牙": "wolfFang", "狼皮": "wolfPelt", "骷髅骨": "skeletonBone", "骷髅残盾": "skeletonShield", "毒孢子": "toxicSpore", "蘑菇怪帽": "mushroomCap", "分裂核心": "slimeDivideCore", "蝠影披风": "batShadownCape", "兽牙项链": "fangNecklace", "蜥蜴鳞片": "lizardScale", "蜥蜴尾巴": "lizardTail", "幽灵精华": "spiritEssence", "灵质": "ectoplasm", "巨魔兽皮": "trollHide", "巨魔木棒": "trollClub", "巨蝎毒针": "scorpionStinger", "巨蝎甲壳": "scorpionCarapace", "守护者核心": "guardianCore", "古代齿轮": "ancientGear", "熔岩之心": "lavaHeart", "龙鳞": "dragonScale", "剧毒匕首": "venomDagger", "余烬庇护": "emberAegis", "过载核心": "overloadGuardianCore", "冰霜凝胶": "iceGel", "霜之结晶": "frostCrystal", "雪狼皮": "snowWolfFur", "冰弹": "iceBomb", "冰蝙蝠翅膀": "iceBatWing", "雪兔皮": "snowRabbitFur", "霜之精华": "frostEssence", "巨兽獠牙": "snowBeastFang", "巨兽皮": "snowBeastHide", "霜之王冠": "frostCrown", "暗影猫皮": "shadowFur", "猫影宝石": "catShadowGem", "地牢钥匙": "dungeonKey", "铁爪护甲": "ironPawArmor", "幻影胡须": "phantomWhisker", "诅咒之翼": "curseWing", "猫偶核心": "golemCore", "巫术猫帽": "witchHat", "暗影法球": "shadowOrb", "深渊披风": "abyssalCloak", "猫祖王冠": "ancestorCrown", "影之刃": "shadowBlade", "星辉精华": "starEssence", "星辰碎片": "starShard", "陷阱零件": "trapParts", "星尘": "starDust", "星辉遗物": "starRelic", "星辰魔法书": "starDustMagicBook", "星辉王冠": "starCrown", "夜瞳宝石": "nightEyeGem", "剧毒皮毛": "toxicFur", "胡须护符": "whiskerCharm", "暗影披风": "shadowCape", "稀有利爪": "rareClaw", "烟雾弹": "smokeBall", "伏击吊坠": "stealthAmulet", "先机吊坠": "initiativeAmulet", "糖果炸弹": "candyBomb", "毛绒绒": "plushFur", "恶灵精华": "ghostEssence", "游行披风": "paradeCape", "女皇披风": "empressCloak", "“游乐园之王”": "loadOfamusementPark", "被封印的铃铛": "sealBell", "魔典残页": "tomeFragment", "魔法猫头鹰羽毛": "owlFeather", "记忆残页": "memoryPage", "黑暗结晶": "darkCrystal", "图书馆徽章": "libraryKingBadge", "知识冠冕": "knowledgeCrown", "噩梦监狱宝箱": "nightmarePrisonChest", "薄荷贵族": "sponsorPointResource_catnip_aristocrat", "战斗面板样式-战士喵": "sponsorPointResource_battleStyleSoldier", "斧头+1": "axe+1", "斧头+2": "axe+2", "斧头+3": "axe+3", "斧头+4": "axe+4", "斧头+5": "axe+5", "哥布林匕首·改+1": "goblinDaggerPlus+1", "哥布林匕首·改+2": "goblinDaggerPlus+2", "哥布林匕首·改+3": "goblinDaggerPlus+3", "哥布林匕首·改+4": "goblinDaggerPlus+4", "哥布林匕首·改+5": "goblinDaggerPlus+5", "哥布林匕首·改+6": "goblinDaggerPlus+6", "哥布林匕首·改+7": "goblinDaggerPlus+7", "哥布林匕首·改+8": "goblinDaggerPlus+8", "哥布林匕首·改+9": "goblinDaggerPlus+9", "哥布林匕首·改+10": "goblinDaggerPlus+10", "铁甲衣+1": "ironCoat+1", "铁甲衣+2": "ironCoat+2", "铁甲衣+3": "ironCoat+3", "铁甲衣+4": "ironCoat+4", "铁甲衣+5": "ironCoat+5", "铁甲衣+6": "ironCoat+6", "铁甲衣+7": "ironCoat+7", "铁甲衣+8": "ironCoat+8", "铁甲衣+9": "ironCoat+9", "铁甲衣+10": "ironCoat+10", "铁头盔+1": "ironHat+1", "铁头盔+2": "ironHat+2", "铁头盔+3": "ironHat+3", "铁头盔+4": "ironHat+4", "铁头盔+5": "ironHat+5", "铁头盔+6": "ironHat+6", "铁头盔+7": "ironHat+7", "铁头盔+8": "ironHat+8", "铁头盔+9": "ironHat+9", "铁头盔+10": "ironHat+10", "铁护手+1": "ironGloves+1", "铁护手+2": "ironGloves+2", "铁护手+3": "ironGloves+3", "铁护手+4": "ironGloves+4", "铁护手+5": "ironGloves+5", "铁护手+6": "ironGloves+6", "铁护手+7": "ironGloves+7", "铁护手+8": "ironGloves+8", "铁护手+9": "ironGloves+9", "铁护手+10": "ironGloves+10", "铁护腿+1": "ironPants+1", "铁护腿+2": "ironPants+2", "铁护腿+3": "ironPants+3", "铁护腿+4": "ironPants+4", "铁护腿+5": "ironPants+5", "铁护腿+6": "ironPants+6", "铁护腿+7": "ironPants+7", "铁护腿+8": "ironPants+8", "铁护腿+9": "ironPants+9", "铁护腿+10": "ironPants+10", "钢甲衣+1": "steelCoat+1", "钢甲衣+2": "steelCoat+2", "钢甲衣+3": "steelCoat+3", "钢甲衣+4": "steelCoat+4", "钢甲衣+5": "steelCoat+5", "钢甲衣+6": "steelCoat+6", "钢甲衣+7": "steelCoat+7", "钢甲衣+8": "steelCoat+8", "钢甲衣+9": "steelCoat+9", "钢甲衣+10": "steelCoat+10", "钢头盔+1": "steelHat+1", "钢头盔+2": "steelHat+2", "钢头盔+3": "steelHat+3", "钢头盔+4": "steelHat+4", "钢头盔+5": "steelHat+5", "钢头盔+6": "steelHat+6", "钢头盔+7": "steelHat+7", "钢头盔+8": "steelHat+8", "钢头盔+9": "steelHat+9", "钢头盔+10": "steelHat+10", "钢护手+1": "steelGloves+1", "钢护手+2": "steelGloves+2", "钢护手+3": "steelGloves+3", "钢护手+4": "steelGloves+4", "钢护手+5": "steelGloves+5", "钢护手+6": "steelGloves+6", "钢护手+7": "steelGloves+7", "钢护手+8": "steelGloves+8", "钢护手+9": "steelGloves+9", "钢护手+10": "steelGloves+10", "钢护腿+1": "steelPants+1", "钢护腿+2": "steelPants+2", "钢护腿+3": "steelPants+3", "钢护腿+4": "steelPants+4", "钢护腿+5": "steelPants+5", "钢护腿+6": "steelPants+6", "钢护腿+7": "steelPants+7", "钢护腿+8": "steelPants+8", "钢护腿+9": "steelPants+9", "钢护腿+10": "steelPants+10", "银质剑+1": "silverSword+1", "银质剑+2": "silverSword+2", "银质剑+3": "silverSword+3", "银质剑+4": "silverSword+4", "银质剑+5": "silverSword+5", "银质剑+6": "silverSword+6", "银质剑+7": "silverSword+7", "银质剑+8": "silverSword+8", "银质剑+9": "silverSword+9", "银质剑+10": "silverSword+10", "银质匕首+1": "silverDagger+1", "银质匕首+2": "silverDagger+2", "银质匕首+3": "silverDagger+3", "银质匕首+4": "silverDagger+4", "银质匕首+5": "silverDagger+5", "银质匕首+6": "silverDagger+6", "银质匕首+7": "silverDagger+7", "银质匕首+8": "silverDagger+8", "银质匕首+9": "silverDagger+9", "银质匕首+10": "silverDagger+10", "银护甲+1": "silverCoat+1", "银护甲+2": "silverCoat+2", "银护甲+3": "silverCoat+3", "银护甲+4": "silverCoat+4", "银护甲+5": "silverCoat+5", "银护甲+6": "silverCoat+6", "银护甲+7": "silverCoat+7", "银护甲+8": "silverCoat+8", "银护甲+9": "silverCoat+9", "银护甲+10": "silverCoat+10", "银头盔+1": "silverHat+1", "银头盔+2": "silverHat+2", "银头盔+3": "silverHat+3", "银头盔+4": "silverHat+4", "银头盔+5": "silverHat+5", "银头盔+6": "silverHat+6", "银头盔+7": "silverHat+7", "银头盔+8": "silverHat+8", "银头盔+9": "silverHat+9", "银头盔+10": "silverHat+10", "银护手+1": "silverGloves+1", "银护手+2": "silverGloves+2", "银护手+3": "silverGloves+3", "银护手+4": "silverGloves+4", "银护手+5": "silverGloves+5", "银护手+6": "silverGloves+6", "银护手+7": "silverGloves+7", "银护手+8": "silverGloves+8", "银护手+9": "silverGloves+9", "银护手+10": "silverGloves+10", "银护腿+1": "silverPants+1", "银护腿+2": "silverPants+2", "银护腿+3": "silverPants+3", "银护腿+4": "silverPants+4", "银护腿+5": "silverPants+5", "银护腿+6": "silverPants+6", "银护腿+7": "silverPants+7", "银护腿+8": "silverPants+8", "银护腿+9": "silverPants+9", "银护腿+10": "silverPants+10", "木剑+1": "woodSword+1", "木剑+2": "woodSword+2", "木剑+3": "woodSword+3", "木剑+4": "woodSword+4", "木剑+5": "woodSword+5", "采集手环+1": "collectingBracelet+1", "采集手环+2": "collectingBracelet+2", "采集手环+3": "collectingBracelet+3", "采集手环+4": "collectingBracelet+4", "采集手环+5": "collectingBracelet+5", "月光吊坠+1": "moonlightPendant+1", "月光吊坠+2": "moonlightPendant+2", "月光吊坠+3": "moonlightPendant+3", "月光吊坠+4": "moonlightPendant+4", "月光吊坠+5": "moonlightPendant+5", "冰霜匕首+1": "forestDagger+1", "冰霜匕首+2": "forestDagger+2", "冰霜匕首+3": "forestDagger+3", "冰霜匕首+4": "forestDagger+4", "冰霜匕首+5": "forestDagger+5", "冰镐+1": "icePickaxe+1", "冰镐+2": "icePickaxe+2", "冰镐+3": "icePickaxe+3", "冰镐+4": "icePickaxe+4", "冰镐+5": "icePickaxe+5", "羊毛罩袍+1": "woolBurqa+1", "羊毛罩袍+2": "woolBurqa+2", "羊毛罩袍+3": "woolBurqa+3", "羊毛罩袍+4": "woolBurqa+4", "羊毛罩袍+5": "woolBurqa+5", "羊毛法师帽+1": "woolMageHat+1", "羊毛法师帽+2": "woolMageHat+2", "羊毛法师帽+3": "woolMageHat+3", "羊毛法师帽+4": "woolMageHat+4", "羊毛法师帽+5": "woolMageHat+5", "羊毛法师手套+1": "woolMageLongGloves+1", "羊毛法师手套+2": "woolMageLongGloves+2", "羊毛法师手套+3": "woolMageLongGloves+3", "羊毛法师手套+4": "woolMageLongGloves+4", "羊毛法师手套+5": "woolMageLongGloves+5", "羊毛法师裤+1": "woolMagePants+1", "羊毛法师裤+2": "woolMagePants+2", "羊毛法师裤+3": "woolMagePants+3", "羊毛法师裤+4": "woolMagePants+4", "羊毛法师裤+5": "woolMagePants+5", "羊毛紧身衣+1": "woolTightsCloth+1", "羊毛紧身衣+2": "woolTightsCloth+2", "羊毛紧身衣+3": "woolTightsCloth+3", "羊毛紧身衣+4": "woolTightsCloth+4", "羊毛紧身衣+5": "woolTightsCloth+5", "羊毛裹头巾+1": "woolDexHeadScarf+1", "羊毛裹头巾+2": "woolDexHeadScarf+2", "羊毛裹头巾+3": "woolDexHeadScarf+3", "羊毛裹头巾+4": "woolDexHeadScarf+4", "羊毛裹头巾+5": "woolDexHeadScarf+5", "羊毛绑带手套+1": "woolDexGloves+1", "羊毛绑带手套+2": "woolDexGloves+2", "羊毛绑带手套+3": "woolDexGloves+3", "羊毛绑带手套+4": "woolDexGloves+4", "羊毛绑带手套+5": "woolDexGloves+5", "羊毛紧身裤+1": "woolTightsPants+1", "羊毛紧身裤+2": "woolTightsPants+2", "羊毛紧身裤+3": "woolTightsPants+3", "羊毛紧身裤+4": "woolTightsPants+4", "羊毛紧身裤+5": "woolTightsPants+5", "木法杖+1": "woodStaff+1", "木法杖+2": "woodStaff+2", "木法杖+3": "woodStaff+3", "木法杖+4": "woodStaff+4", "木法杖+5": "woodStaff+5", "木法杖+6": "woodStaff+6", "木法杖+7": "woodStaff+7", "木法杖+8": "woodStaff+8", "木法杖+9": "woodStaff+9", "木法杖+10": "woodStaff+10", "月光法杖+1": "moonlightStaff+1", "月光法杖+2": "moonlightStaff+2", "月光法杖+3": "moonlightStaff+3", "月光法杖+4": "moonlightStaff+4", "月光法杖+5": "moonlightStaff+5", "月光法杖+6": "moonlightStaff+6", "月光法杖+7": "moonlightStaff+7", "月光法杖+8": "moonlightStaff+8", "月光法杖+9": "moonlightStaff+9", "月光法杖+10": "moonlightStaff+10", "喵影法杖+1": "mewShadowStaff+1", "喵影法杖+2": "mewShadowStaff+2", "喵影法杖+3": "mewShadowStaff+3", "喵影法杖+4": "mewShadowStaff+4", "喵影法杖+5": "mewShadowStaff+5", "喵影法杖+6": "mewShadowStaff+6", "喵影法杖+7": "mewShadowStaff+7", "喵影法杖+8": "mewShadowStaff+8", "喵影法杖+9": "mewShadowStaff+9", "喵影法杖+10": "mewShadowStaff+10", "魔晶法杖+1": "manacrystalStaff+1", "魔晶法杖+2": "manacrystalStaff+2", "魔晶法杖+3": "manacrystalStaff+3", "魔晶法杖+4": "manacrystalStaff+4", "魔晶法杖+5": "manacrystalStaff+5", "魔晶法杖+6": "manacrystalStaff+6", "魔晶法杖+7": "manacrystalStaff+7", "魔晶法杖+8": "manacrystalStaff+8", "魔晶法杖+9": "manacrystalStaff+9", "魔晶法杖+10": "manacrystalStaff+10", "时光猫眼法杖+1": "timeflowCatEyeStaff+1", "时光猫眼法杖+2": "timeflowCatEyeStaff+2", "时光猫眼法杖+3": "timeflowCatEyeStaff+3", "时光猫眼法杖+4": "timeflowCatEyeStaff+4", "时光猫眼法杖+5": "timeflowCatEyeStaff+5", "时光猫眼法杖+6": "timeflowCatEyeStaff+6", "时光猫眼法杖+7": "timeflowCatEyeStaff+7", "时光猫眼法杖+8": "timeflowCatEyeStaff+8", "时光猫眼法杖+9": "timeflowCatEyeStaff+9", "时光猫眼法杖+10": "timeflowCatEyeStaff+10", "交织猫瞳杖+1": "intertwinedCatEyeStaff+1", "交织猫瞳杖+2": "intertwinedCatEyeStaff+2", "交织猫瞳杖+3": "intertwinedCatEyeStaff+3", "交织猫瞳杖+4": "intertwinedCatEyeStaff+4", "交织猫瞳杖+5": "intertwinedCatEyeStaff+5", "交织猫瞳杖+6": "intertwinedCatEyeStaff+6", "交织猫瞳杖+7": "intertwinedCatEyeStaff+7", "交织猫瞳杖+8": "intertwinedCatEyeStaff+8", "交织猫瞳杖+9": "intertwinedCatEyeStaff+9", "交织猫瞳杖+10": "intertwinedCatEyeStaff+10", "秘银头盔+1": "mithrilHat+1", "秘银头盔+2": "mithrilHat+2", "秘银头盔+3": "mithrilHat+3", "秘银头盔+4": "mithrilHat+4", "秘银头盔+5": "mithrilHat+5", "秘银头盔+6": "mithrilHat+6", "秘银头盔+7": "mithrilHat+7", "秘银头盔+8": "mithrilHat+8", "秘银头盔+9": "mithrilHat+9", "秘银头盔+10": "mithrilHat+10", "秘银护甲+1": "mithrilCoat+1", "秘银护甲+2": "mithrilCoat+2", "秘银护甲+3": "mithrilCoat+3", "秘银护甲+4": "mithrilCoat+4", "秘银护甲+5": "mithrilCoat+5", "秘银护甲+6": "mithrilCoat+6", "秘银护甲+7": "mithrilCoat+7", "秘银护甲+8": "mithrilCoat+8", "秘银护甲+9": "mithrilCoat+9", "秘银护甲+10": "mithrilCoat+10", "秘银手套+1": "mithrilGloves+1", "秘银手套+2": "mithrilGloves+2", "秘银手套+3": "mithrilGloves+3", "秘银手套+4": "mithrilGloves+4", "秘银手套+5": "mithrilGloves+5", "秘银手套+6": "mithrilGloves+6", "秘银手套+7": "mithrilGloves+7", "秘银手套+8": "mithrilGloves+8", "秘银手套+9": "mithrilGloves+9", "秘银手套+10": "mithrilGloves+10", "秘银护腿+1": "mithrilPants+1", "秘银护腿+2": "mithrilPants+2", "秘银护腿+3": "mithrilPants+3", "秘银护腿+4": "mithrilPants+4", "秘银护腿+5": "mithrilPants+5", "秘银护腿+6": "mithrilPants+6", "秘银护腿+7": "mithrilPants+7", "秘银护腿+8": "mithrilPants+8", "秘银护腿+9": "mithrilPants+9", "秘银护腿+10": "mithrilPants+10", "铁钓竿+1": "ironFishingRod+1", "铁钓竿+2": "ironFishingRod+2", "铁钓竿+3": "ironFishingRod+3", "铁钓竿+4": "ironFishingRod+4", "铁钓竿+5": "ironFishingRod+5", "铁抄网+1": "ironDiddleNet+1", "铁抄网+2": "ironDiddleNet+2", "铁抄网+3": "ironDiddleNet+3", "铁抄网+4": "ironDiddleNet+4", "铁抄网+5": "ironDiddleNet+5", "铁制捕鱼笼+1": "ironFishpot+1", "铁制捕鱼笼+2": "ironFishpot+2", "铁制捕鱼笼+3": "ironFishpot+3", "铁制捕鱼笼+4": "ironFishpot+4", "铁制捕鱼笼+5": "ironFishpot+5", "钓鱼帽+1": "fishingHat+1", "钓鱼帽+2": "fishingHat+2", "钓鱼帽+3": "fishingHat+3", "钓鱼帽+4": "fishingHat+4", "钓鱼帽+5": "fishingHat+5", "远古鱼骨项链+1": "ancientFishboneNecklace+1", "远古鱼骨项链+2": "ancientFishboneNecklace+2", "远古鱼骨项链+3": "ancientFishboneNecklace+3", "远古鱼骨项链+4": "ancientFishboneNecklace+4", "远古鱼骨项链+5": "ancientFishboneNecklace+5", "钢制重锤+1": "steelHammer+1", "钢制重锤+2": "steelHammer+2", "钢制重锤+3": "steelHammer+3", "钢制重锤+4": "steelHammer+4", "钢制重锤+5": "steelHammer+5", "钢制重锤+6": "steelHammer+6", "钢制重锤+7": "steelHammer+7", "钢制重锤+8": "steelHammer+8", "钢制重锤+9": "steelHammer+9", "钢制重锤+10": "steelHammer+10", "铁剑+1": "ironSword+1", "铁剑+2": "ironSword+2", "铁剑+3": "ironSword+3", "铁剑+4": "ironSword+4", "铁剑+5": "ironSword+5", "铁剑+6": "ironSword+6", "铁剑+7": "ironSword+7", "铁剑+8": "ironSword+8", "铁剑+9": "ironSword+9", "铁剑+10": "ironSword+10", "钢剑+1": "steelSword+1", "钢剑+2": "steelSword+2", "钢剑+3": "steelSword+3", "钢剑+4": "steelSword+4", "钢剑+5": "steelSword+5", "钢剑+6": "steelSword+6", "钢剑+7": "steelSword+7", "钢剑+8": "steelSword+8", "钢剑+9": "steelSword+9", "钢剑+10": "steelSword+10", "秘银剑+1": "mithrilSword+1", "秘银剑+2": "mithrilSword+2", "秘银剑+3": "mithrilSword+3", "秘银剑+4": "mithrilSword+4", "秘银剑+5": "mithrilSword+5", "秘银剑+6": "mithrilSword+6", "秘银剑+7": "mithrilSword+7", "秘银剑+8": "mithrilSword+8", "秘银剑+9": "mithrilSword+9", "秘银剑+10": "mithrilSword+10", "秘银匕首+1": "mithrilDagger+1", "秘银匕首+2": "mithrilDagger+2", "秘银匕首+3": "mithrilDagger+3", "秘银匕首+4": "mithrilDagger+4", "秘银匕首+5": "mithrilDagger+5", "秘银匕首+6": "mithrilDagger+6", "秘银匕首+7": "mithrilDagger+7", "秘银匕首+8": "mithrilDagger+8", "秘银匕首+9": "mithrilDagger+9", "秘银匕首+10": "mithrilDagger+10", "暗影精铁匕首+1": "shadowSteelDagger+1", "暗影精铁匕首+2": "shadowSteelDagger+2", "暗影精铁匕首+3": "shadowSteelDagger+3", "暗影精铁匕首+4": "shadowSteelDagger+4", "暗影精铁匕首+5": "shadowSteelDagger+5", "暗影精铁匕首+6": "shadowSteelDagger+6", "暗影精铁匕首+7": "shadowSteelDagger+7", "暗影精铁匕首+8": "shadowSteelDagger+8", "暗影精铁匕首+9": "shadowSteelDagger+9", "暗影精铁匕首+10": "shadowSteelDagger+10", "暗影精铁剑+1": "shadowSteelSword+1", "暗影精铁剑+2": "shadowSteelSword+2", "暗影精铁剑+3": "shadowSteelSword+3", "暗影精铁剑+4": "shadowSteelSword+4", "暗影精铁剑+5": "shadowSteelSword+5", "暗影精铁剑+6": "shadowSteelSword+6", "暗影精铁剑+7": "shadowSteelSword+7", "暗影精铁剑+8": "shadowSteelSword+8", "暗影精铁剑+9": "shadowSteelSword+9", "暗影精铁剑+10": "shadowSteelSword+10", "猫薄荷手链+1": "catPotionSilverBracelet+1", "猫薄荷手链+2": "catPotionSilverBracelet+2", "猫薄荷手链+3": "catPotionSilverBracelet+3", "猫薄荷手链+4": "catPotionSilverBracelet+4", "猫薄荷手链+5": "catPotionSilverBracelet+5", "铁锅+1": "ironPot+1", "铁锅+2": "ironPot+2", "铁锅+3": "ironPot+3", "铁锅+4": "ironPot+4", "铁锅+5": "ironPot+5", "铁铲+1": "ironShovel+1", "铁铲+2": "ironShovel+2", "铁铲+3": "ironShovel+3", "铁铲+4": "ironShovel+4", "铁铲+5": "ironShovel+5", "钢锅+1": "steelPot+1", "钢锅+2": "steelPot+2", "钢锅+3": "steelPot+3", "钢锅+4": "steelPot+4", "钢锅+5": "steelPot+5", "钢铲+1": "steelShovel+1", "钢铲+2": "steelShovel+2", "钢铲+3": "steelShovel+3", "钢铲+4": "steelShovel+4", "钢铲+5": "steelShovel+5", "铁锤+1": "ironMachinistHammer+1", "铁锤+2": "ironMachinistHammer+2", "铁锤+3": "ironMachinistHammer+3", "铁锤+4": "ironMachinistHammer+4", "铁锤+5": "ironMachinistHammer+5", "钢锤+1": "steelMachinistHammer+1", "钢锤+2": "steelMachinistHammer+2", "钢锤+3": "steelMachinistHammer+3", "钢锤+4": "steelMachinistHammer+4", "钢锤+5": "steelMachinistHammer+5", "酿造搅拌器+1": "fermentationStirrer+1", "酿造搅拌器+2": "fermentationStirrer+2", "酿造搅拌器+3": "fermentationStirrer+3", "酿造搅拌器+4": "fermentationStirrer+4", "酿造搅拌器+5": "fermentationStirrer+5", "裁缝剪刀+1": "tailorScissors+1", "裁缝剪刀+2": "tailorScissors+2", "裁缝剪刀+3": "tailorScissors+3", "裁缝剪刀+4": "tailorScissors+4", "裁缝剪刀+5": "tailorScissors+5", "针线包+1": "needleandThread+1", "针线包+2": "needleandThread+2", "针线包+3": "needleandThread+3", "针线包+4": "needleandThread+4", "针线包+5": "needleandThread+5", "采矿收纳背篓+1": "bambooMiningCatbasket+1", "采矿收纳背篓+2": "bambooMiningCatbasket+2", "采矿收纳背篓+3": "bambooMiningCatbasket+3", "采矿收纳背篓+4": "bambooMiningCatbasket+4", "采矿收纳背篓+5": "bambooMiningCatbasket+5", "秘银工匠锤+1": "mithrilMachinistHammer+1", "秘银工匠锤+2": "mithrilMachinistHammer+2", "秘银工匠锤+3": "mithrilMachinistHammer+3", "秘银工匠锤+4": "mithrilMachinistHammer+4", "秘银工匠锤+5": "mithrilMachinistHammer+5", "铁钳+1": "ironTongs+1", "铁钳+2": "ironTongs+2", "铁钳+3": "ironTongs+3", "铁钳+4": "ironTongs+4", "铁钳+5": "ironTongs+5", "彩虹手链+1": "rainbowBracelet+1", "彩虹手链+2": "rainbowBracelet+2", "彩虹手链+3": "rainbowBracelet+3", "彩虹手链+4": "rainbowBracelet+4", "彩虹手链+5": "rainbowBracelet+5", "彩虹项链+1": "rainbowNecklace+1", "彩虹项链+2": "rainbowNecklace+2", "彩虹项链+3": "rainbowNecklace+3", "彩虹项链+4": "rainbowNecklace+4", "彩虹项链+5": "rainbowNecklace+5", "竹质弓+1": "bambooBow+1", "竹质弓+2": "bambooBow+2", "竹质弓+3": "bambooBow+3", "竹质弓+4": "bambooBow+4", "竹质弓+5": "bambooBow+5", "竹质弓+6": "bambooBow+6", "竹质弓+7": "bambooBow+7", "竹质弓+8": "bambooBow+8", "竹质弓+9": "bambooBow+9", "竹质弓+10": "bambooBow+10", "羊毛裁缝服+1": "woolTailorClothes+1", "羊毛裁缝服+2": "woolTailorClothes+2", "羊毛裁缝服+3": "woolTailorClothes+3", "羊毛裁缝服+4": "woolTailorClothes+4", "羊毛裁缝服+5": "woolTailorClothes+5", "羊毛裁缝手套+1": "woolTailorGloves+1", "羊毛裁缝手套+2": "woolTailorGloves+2", "羊毛裁缝手套+3": "woolTailorGloves+3", "羊毛裁缝手套+4": "woolTailorGloves+4", "羊毛裁缝手套+5": "woolTailorGloves+5", "毛毛可爱帽+1": "catFurCuteHat+1", "毛毛可爱帽+2": "catFurCuteHat+2", "毛毛可爱帽+3": "catFurCuteHat+3", "毛毛可爱帽+4": "catFurCuteHat+4", "毛毛可爱帽+5": "catFurCuteHat+5", "羊毛可爱帽+1": "woolCuteHat+1", "羊毛可爱帽+2": "woolCuteHat+2", "羊毛可爱帽+3": "woolCuteHat+3", "羊毛可爱帽+4": "woolCuteHat+4", "羊毛可爱帽+5": "woolCuteHat+5", "羊毛可爱手套+1": "woolCuteGloves+1", "羊毛可爱手套+2": "woolCuteGloves+2", "羊毛可爱手套+3": "woolCuteGloves+3", "羊毛可爱手套+4": "woolCuteGloves+4", "羊毛可爱手套+5": "woolCuteGloves+5", "羊毛工匠服+1": "woolArtisanOutfit+1", "羊毛工匠服+2": "woolArtisanOutfit+2", "羊毛工匠服+3": "woolArtisanOutfit+3", "羊毛工匠服+4": "woolArtisanOutfit+4", "羊毛工匠服+5": "woolArtisanOutfit+5", "丝质可爱帽+1": "silkCuteHat+1", "丝质可爱帽+2": "silkCuteHat+2", "丝质可爱帽+3": "silkCuteHat+3", "丝质可爱帽+4": "silkCuteHat+4", "丝质可爱帽+5": "silkCuteHat+5", "丝质可爱手套+1": "silkCuteGloves+1", "丝质可爱手套+2": "silkCuteGloves+2", "丝质可爱手套+3": "silkCuteGloves+3", "丝质可爱手套+4": "silkCuteGloves+4", "丝质可爱手套+5": "silkCuteGloves+5", "丝质工匠服+1": "silkArtisanOutfit+1", "丝质工匠服+2": "silkArtisanOutfit+2", "丝质工匠服+3": "silkArtisanOutfit+3", "丝质工匠服+4": "silkArtisanOutfit+4", "丝质工匠服+5": "silkArtisanOutfit+5", "丝质裁缝服+1": "silkTailorClothes+1", "丝质裁缝服+2": "silkTailorClothes+2", "丝质裁缝服+3": "silkTailorClothes+3", "丝质裁缝服+4": "silkTailorClothes+4", "丝质裁缝服+5": "silkTailorClothes+5", "丝质裁缝手套+1": "silkTailorGloves+1", "丝质裁缝手套+2": "silkTailorGloves+2", "丝质裁缝手套+3": "silkTailorGloves+3", "丝质裁缝手套+4": "silkTailorGloves+4", "丝质裁缝手套+5": "silkTailorGloves+5", "冰羽靴+1": "iceFeatherBoots+1", "冰羽靴+2": "iceFeatherBoots+2", "冰羽靴+3": "iceFeatherBoots+3", "冰羽靴+4": "iceFeatherBoots+4", "冰羽靴+5": "iceFeatherBoots+5", "云行靴+1": "cloudwalkerBoots+1", "云行靴+2": "cloudwalkerBoots+2", "云行靴+3": "cloudwalkerBoots+3", "云行靴+4": "cloudwalkerBoots+4", "云行靴+5": "cloudwalkerBoots+5", "雪狼皮披风+1": "snowWolfCloak+1", "雪狼皮披风+2": "snowWolfCloak+2", "雪狼皮披风+3": "snowWolfCloak+3", "雪狼皮披风+4": "snowWolfCloak+4", "雪狼皮披风+5": "snowWolfCloak+5", "云行斗篷+1": "cloudwalkerCloak+1", "云行斗篷+2": "cloudwalkerCloak+2", "云行斗篷+3": "cloudwalkerCloak+3", "云行斗篷+4": "cloudwalkerCloak+4", "云行斗篷+5": "cloudwalkerCloak+5", "羊毛围裙+1": "woolChefApron+1", "羊毛围裙+2": "woolChefApron+2", "羊毛围裙+3": "woolChefApron+3", "羊毛围裙+4": "woolChefApron+4", "羊毛围裙+5": "woolChefApron+5", "羊毛隔热手套+1": "woolHeatResistantGloves+1", "羊毛隔热手套+2": "woolHeatResistantGloves+2", "羊毛隔热手套+3": "woolHeatResistantGloves+3", "羊毛隔热手套+4": "woolHeatResistantGloves+4", "羊毛隔热手套+5": "woolHeatResistantGloves+5", "羊毛探险背包+1": "woolExplorerCatpack+1", "羊毛探险背包+2": "woolExplorerCatpack+2", "羊毛探险背包+3": "woolExplorerCatpack+3", "羊毛探险背包+4": "woolExplorerCatpack+4", "羊毛探险背包+5": "woolExplorerCatpack+5", "虹运飘带+1": "luckRainbowRibbon+1", "虹运飘带+2": "luckRainbowRibbon+2", "虹运飘带+3": "luckRainbowRibbon+3", "虹运飘带+4": "luckRainbowRibbon+4", "虹运飘带+5": "luckRainbowRibbon+5", "丝质罩袍+1": "silkMageBurqa+1", "丝质罩袍+2": "silkMageBurqa+2", "丝质罩袍+3": "silkMageBurqa+3", "丝质罩袍+4": "silkMageBurqa+4", "丝质罩袍+5": "silkMageBurqa+5", "丝质法师帽+1": "silkMageHat+1", "丝质法师帽+2": "silkMageHat+2", "丝质法师帽+3": "silkMageHat+3", "丝质法师帽+4": "silkMageHat+4", "丝质法师帽+5": "silkMageHat+5", "丝质法师手套+1": "silkMageLongGloves+1", "丝质法师手套+2": "silkMageLongGloves+2", "丝质法师手套+3": "silkMageLongGloves+3", "丝质法师手套+4": "silkMageLongGloves+4", "丝质法师手套+5": "silkMageLongGloves+5", "丝质法师裤+1": "silkMagePants+1", "丝质法师裤+2": "silkMagePants+2", "丝质法师裤+3": "silkMagePants+3", "丝质法师裤+4": "silkMagePants+4", "丝质法师裤+5": "silkMagePants+5", "丝质法师披肩+1": "silkMageCloak+1", "丝质法师披肩+2": "silkMageCloak+2", "丝质法师披肩+3": "silkMageCloak+3", "丝质法师披肩+4": "silkMageCloak+4", "丝质法师披肩+5": "silkMageCloak+5", "丝质夜行衣+1": "silkTightsCloth+1", "丝质夜行衣+2": "silkTightsCloth+2", "丝质夜行衣+3": "silkTightsCloth+3", "丝质夜行衣+4": "silkTightsCloth+4", "丝质夜行衣+5": "silkTightsCloth+5", "丝质裹头巾+1": "silkDexHeadScarf+1", "丝质裹头巾+2": "silkDexHeadScarf+2", "丝质裹头巾+3": "silkDexHeadScarf+3", "丝质裹头巾+4": "silkDexHeadScarf+4", "丝质裹头巾+5": "silkDexHeadScarf+5", "丝质绑带手套+1": "silkDexGloves+1", "丝质绑带手套+2": "silkDexGloves+2", "丝质绑带手套+3": "silkDexGloves+3", "丝质绑带手套+4": "silkDexGloves+4", "丝质绑带手套+5": "silkDexGloves+5", "丝质宽松裤+1": "silkTightsPants+1", "丝质宽松裤+2": "silkTightsPants+2", "丝质宽松裤+3": "silkTightsPants+3", "丝质宽松裤+4": "silkTightsPants+4", "丝质宽松裤+5": "silkTightsPants+5", "丝质夜行斗篷+1": "silkDexCloak+1", "丝质夜行斗篷+2": "silkDexCloak+2", "丝质夜行斗篷+3": "silkDexCloak+3", "丝质夜行斗篷+4": "silkDexCloak+4", "丝质夜行斗篷+5": "silkDexCloak+5", "丝质战斗披风+1": "silkWarriorCloak+1", "丝质战斗披风+2": "silkWarriorCloak+2", "丝质战斗披风+3": "silkWarriorCloak+3", "丝质战斗披风+4": "silkWarriorCloak+4", "丝质战斗披风+5": "silkWarriorCloak+5", "丝质活力披肩+1": "silkVitalityCloak+1", "丝质活力披肩+2": "silkVitalityCloak+2", "丝质活力披肩+3": "silkVitalityCloak+3", "丝质活力披肩+4": "silkVitalityCloak+4", "丝质活力披肩+5": "silkVitalityCloak+5", "鱼鳞合金头盔+1": "fishscaleMineralHat+1", "鱼鳞合金头盔+2": "fishscaleMineralHat+2", "鱼鳞合金头盔+3": "fishscaleMineralHat+3", "鱼鳞合金头盔+4": "fishscaleMineralHat+4", "鱼鳞合金头盔+5": "fishscaleMineralHat+5", "鱼鳞合金头盔+6": "fishscaleMineralHat+6", "鱼鳞合金头盔+7": "fishscaleMineralHat+7", "鱼鳞合金头盔+8": "fishscaleMineralHat+8", "鱼鳞合金头盔+9": "fishscaleMineralHat+9", "鱼鳞合金头盔+10": "fishscaleMineralHat+10", "鱼鳞合金盔甲+1": "fishscaleMineralCoat+1", "鱼鳞合金盔甲+2": "fishscaleMineralCoat+2", "鱼鳞合金盔甲+3": "fishscaleMineralCoat+3", "鱼鳞合金盔甲+4": "fishscaleMineralCoat+4", "鱼鳞合金盔甲+5": "fishscaleMineralCoat+5", "鱼鳞合金盔甲+6": "fishscaleMineralCoat+6", "鱼鳞合金盔甲+7": "fishscaleMineralCoat+7", "鱼鳞合金盔甲+8": "fishscaleMineralCoat+8", "鱼鳞合金盔甲+9": "fishscaleMineralCoat+9", "鱼鳞合金盔甲+10": "fishscaleMineralCoat+10", "鱼鳞合金护手+1": "fishscaleMineralGloves+1", "鱼鳞合金护手+2": "fishscaleMineralGloves+2", "鱼鳞合金护手+3": "fishscaleMineralGloves+3", "鱼鳞合金护手+4": "fishscaleMineralGloves+4", "鱼鳞合金护手+5": "fishscaleMineralGloves+5", "鱼鳞合金护手+6": "fishscaleMineralGloves+6", "鱼鳞合金护手+7": "fishscaleMineralGloves+7", "鱼鳞合金护手+8": "fishscaleMineralGloves+8", "鱼鳞合金护手+9": "fishscaleMineralGloves+9", "鱼鳞合金护手+10": "fishscaleMineralGloves+10", "鱼鳞合金护腿+1": "fishscaleMineralPants+1", "鱼鳞合金护腿+2": "fishscaleMineralPants+2", "鱼鳞合金护腿+3": "fishscaleMineralPants+3", "鱼鳞合金护腿+4": "fishscaleMineralPants+4", "鱼鳞合金护腿+5": "fishscaleMineralPants+5", "鱼鳞合金护腿+6": "fishscaleMineralPants+6", "鱼鳞合金护腿+7": "fishscaleMineralPants+7", "鱼鳞合金护腿+8": "fishscaleMineralPants+8", "鱼鳞合金护腿+9": "fishscaleMineralPants+9", "鱼鳞合金护腿+10": "fishscaleMineralPants+10", "暗影精铁头盔+1": "shadowSteelHat+1", "暗影精铁头盔+2": "shadowSteelHat+2", "暗影精铁头盔+3": "shadowSteelHat+3", "暗影精铁头盔+4": "shadowSteelHat+4", "暗影精铁头盔+5": "shadowSteelHat+5", "暗影精铁头盔+6": "shadowSteelHat+6", "暗影精铁头盔+7": "shadowSteelHat+7", "暗影精铁头盔+8": "shadowSteelHat+8", "暗影精铁头盔+9": "shadowSteelHat+9", "暗影精铁头盔+10": "shadowSteelHat+10", "暗影精铁盔甲+1": "shadowSteelCoat+1", "暗影精铁盔甲+2": "shadowSteelCoat+2", "暗影精铁盔甲+3": "shadowSteelCoat+3", "暗影精铁盔甲+4": "shadowSteelCoat+4", "暗影精铁盔甲+5": "shadowSteelCoat+5", "暗影精铁盔甲+6": "shadowSteelCoat+6", "暗影精铁盔甲+7": "shadowSteelCoat+7", "暗影精铁盔甲+8": "shadowSteelCoat+8", "暗影精铁盔甲+9": "shadowSteelCoat+9", "暗影精铁盔甲+10": "shadowSteelCoat+10", "暗影精铁臂甲+1": "shadowSteelGloves+1", "暗影精铁臂甲+2": "shadowSteelGloves+2", "暗影精铁臂甲+3": "shadowSteelGloves+3", "暗影精铁臂甲+4": "shadowSteelGloves+4", "暗影精铁臂甲+5": "shadowSteelGloves+5", "暗影精铁臂甲+6": "shadowSteelGloves+6", "暗影精铁臂甲+7": "shadowSteelGloves+7", "暗影精铁臂甲+8": "shadowSteelGloves+8", "暗影精铁臂甲+9": "shadowSteelGloves+9", "暗影精铁臂甲+10": "shadowSteelGloves+10", "暗影精铁腿甲+1": "shadowSteelPants+1", "暗影精铁腿甲+2": "shadowSteelPants+2", "暗影精铁腿甲+3": "shadowSteelPants+3", "暗影精铁腿甲+4": "shadowSteelPants+4", "暗影精铁腿甲+5": "shadowSteelPants+5", "暗影精铁腿甲+6": "shadowSteelPants+6", "暗影精铁腿甲+7": "shadowSteelPants+7", "暗影精铁腿甲+8": "shadowSteelPants+8", "暗影精铁腿甲+9": "shadowSteelPants+9", "暗影精铁腿甲+10": "shadowSteelPants+10", "魔法书+1": "magicBook+1", "魔法书+2": "magicBook+2", "魔法书+3": "magicBook+3", "魔法书+4": "magicBook+4", "魔法书+5": "magicBook+5", "兽牙项链+1": "fangNecklace+1", "兽牙项链+2": "fangNecklace+2", "兽牙项链+3": "fangNecklace+3", "兽牙项链+4": "fangNecklace+4", "兽牙项链+5": "fangNecklace+5", "余烬庇护+1": "emberAegis+1", "余烬庇护+2": "emberAegis+2", "余烬庇护+3": "emberAegis+3", "余烬庇护+4": "emberAegis+4", "余烬庇护+5": "emberAegis+5", "过载核心+1": "overloadGuardianCore+1", "过载核心+2": "overloadGuardianCore+2", "过载核心+3": "overloadGuardianCore+3", "过载核心+4": "overloadGuardianCore+4", "过载核心+5": "overloadGuardianCore+5", "霜之王冠+1": "frostCrown+1", "霜之王冠+2": "frostCrown+2", "霜之王冠+3": "frostCrown+3", "霜之王冠+4": "frostCrown+4", "“极寒雪原之王”": "frostCrown+5", "猫祖王冠+1": "ancestorCrown+1", "猫祖王冠+2": "ancestorCrown+2", "猫祖王冠+3": "ancestorCrown+3", "猫祖王冠+4": "ancestorCrown+4", "“深渊之主”": "ancestorCrown+5", "星辰魔法书+1": "starDustMagicBook+1", "星辰魔法书+2": "starDustMagicBook+2", "星辰魔法书+3": "starDustMagicBook+3", "星辰魔法书+4": "starDustMagicBook+4", "星辰魔法书+5": "starDustMagicBook+5", "星辉王冠+1": "starCrown+1", "星辉王冠+2": "starCrown+2", "星辉王冠+3": "starCrown+3", "星辉王冠+4": "starCrown+4", "“星界主冠”": "starCrown+5", "“游乐园之王”+1": "loadOfamusementPark+1", "“游乐园之王”+2": "loadOfamusementPark+2", "“游乐园之王”+3": "loadOfamusementPark+3", "“游乐园之王”+4": "loadOfamusementPark+4", "“游乐园传奇”": "loadOfamusementPark+5", '自然馈赠': 'natureGiftSkillBook', '穿针引线': 'threadingNeedleSkillBook', '知识启迪': 'knowledgeInspirationSkillBook', '种瓜得瓜': 'sowMelonsReapMelonsSkillBook', '强化赋能': 'enhanceEmpowerSkillBook', '强化冲击': 'enhanceStrikeSkillBook', '普通攻击': 'baseAttackSkillBook', '骨盾': 'boneShieldSkillBook', '腐蚀吐息': 'corrosiveBreathSkillBook', '召唤浆果鸟': 'summonBerryBirdSkillBook', '基础治疗': 'baseHealSkillBook', '中毒': 'poisonSkillBook', '自我疗愈': 'selfHealSkillBook', '横扫': 'sweepSkillBook', '基础群体治疗': 'baseGroupHealSkillBook', '重击': 'powerStrikeSkillBook', '守护者激光': 'guardianLaserSkillBook', '熔岩吐息': 'lavaBreathSkillBook', '龙之咆哮': 'dragonRoarSkillBook', '双重打击': 'doubleStrikeSkillBook', '弱点打击': 'lowestHpStrikeSkillBook', '爆炸射击': 'explosiveShotSkillBook', '冻结': 'freezeSkillBook', '冰弹': 'iceBombSkillBook', '吸血': 'lifeDrainSkillBook', '咆哮': 'roarSkillBook', '暴风雪': 'blizzardSkillBook', '铁壁': 'ironWallSkillBook', '诅咒': 'curseSkillBook', '暗影爆发': 'shadowBurstSkillBook', '群体诅咒': 'groupCurseSkillBook', '神圣之光': 'holyLightSkillBook', '祝福': 'blessSkillBook', '复活': 'reviveSkillBook', '群体再生': 'groupRegenSkillBook', '星辉结界': 'astralBarrierSkillBook', '星辉冲击': 'astralBlastSkillBook', '群体沉默': 'groupSilenceSkillBook', '自我修复': 'selfRepairSkillBook', '驱散': 'cleanseSkillBook', '彗星打击': 'cometStrikeSkillBook', '破甲': 'armorBreakSkillBook', '星辰陷阱': 'starTrapSkillBook', '星辉终极裁决': 'emperorCatFinale_forAstralEmpressBossSkillBook', '星辉风暴': 'astralStormSkillBook', '群体护盾': 'groupShieldSkillBook', '潜行': 'sneakSkillBook', '偷袭': 'ambushSkillBook', '毒爪': 'poisonClawSkillBook', '暗影步': 'shadowStepSkillBook', '沉默打击': 'silenceStrikeSkillBook', '静默烟雾弹': 'slientSmokeScreenSkillBook', '镜像影分身': 'mirrorImageSkillBook', '绝影连杀': 'shadowAssassinUltSkillBook', '偷天换日': 'stardustMouseSwapSkillBook', '眩晕旋转': 'dizzySpinSkillBook', '失控加速': 'carouselOverdriveSkillBook', '糖果爆裂': 'candyBombSkillBook', '恶作剧烟雾': 'prankSmokeSkillBook', '嘲讽': 'mercenaryTauntSkillBook', '毛绒嘲讽': 'plushTauntSkillBook', '星光治愈': 'starlightSanctuarySkillBook', '鬼影冲锋': 'ghostlyStrikeSkillBook', '狂欢号角': 'paradeHornSkillBook', '小丑召集令': 'clownSummonSkillBook', '猫王庇护': 'kingAegisSkillBook', '封印魔法': 'sealMagicSkillBook', '驱逐': 'banishSkillBook', '束缚': 'bindSkillBook', '识破魔法': 'detectMagicSkillBook', '惩戒': 'punishSkillBook', '扰乱': 'confuseSkillBook', '禁忌魔法': 'forbiddenMagicSkillBook', '禁魔审判': 'ultimateLibraryJudgementSkillBook', '锁链鞭打': 'chainWhipSkillBook', '恐惧': 'fearInductionSkillBook', '灵魂吸取': 'soulDrainSkillBook', '恶魔狂怒': 'demonicRageSkillBook', '幽灵利爪': 'spectralClawSkillBook', '哀嚎怨声': 'hauntingWailSkillBook', '复仇一击': 'vengeanceStrikeSkillBook', '绝望光环': 'despairAuraSkillBook', '幽灵突击': 'phantomStrikeSkillBook', '精神崩溃': 'mentalBreakSkillBook', '痛苦放大': 'painAmplifierSkillBook', '酷刑程序': 'tortureProtocolSkillBook', '机械钳制': 'mechanicalGripSkillBook', '暗影腐蚀': 'shadowCorruptionSkillBook', '噩梦重击': 'nightmareSlamSkillBook', '末日咆哮': 'apocalypticRoarSkillBook', '监狱统治': 'prisonDominationSkillBook', '黑暗仪式': 'darkRitualSkillBook' } let marketPrices = GM_getValue('marketPrices', {}); unsafeWindow.marketPrices = marketPrices; unsafeWindow.itemCnEn = cn_en initMarketPrices(); async function initMarketPrices() { // API 请求配置 const apiUrl = 'https://www.moyu-idle.com/api/game/market/price'; const data = await httpGet(apiUrl); console.log('获取市场价格成功,更新时间:', new Date(data.lastUpdateTime).toLocaleString()) const newMarketPrices = data.items newMarketPrices["gold"] = { sellOrders: { itemId: "gold", minPrice: 1, minPriceCount: 1 }, buyOrders: { itemId: "gold", maxPrice: 1, maxPriceCount: 1 } } newMarketPrices["__satiety"] = { sellOrders: { itemId: "__satiety", minPrice: 5, minPriceCount: 1 }, buyOrders: { itemId: "__satiety", maxPrice: 5, maxPriceCount: 1 } } for (const [id, item] of Object.entries(newMarketPrices)) { if (id) { if (!item['sellOrders']) { item['sellOrders'] = { minPrice: 0, minPriceCount: 0 } } if (!item['buyOrders']) { item['buyOrders'] = { maxPrice: 0, maxPriceCount: 0 } } marketPrices[id] = item; } } GM_setValue('marketPrices', marketPrices); } // 使用 Promise 封装 GM_xmlhttpRequest function httpGet(url) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: url, headers: { "Content-Type": "application/json" }, onload: function (response) { if (response.status === 200) { try { const data = JSON.parse(response.responseText); if (data.code === 200) { resolve(data.data); // 数据 } else { reject(new Error("业务错误: " + data.message)); } } catch (error) { reject(new Error("解析响应失败: " + error.message)); } } else { reject(new Error("请求失败,状态码: " + response.status)); } }, onerror: function (error) { reject(new Error("网络错误: " + error)); } }); }); } function addDailyTable(dialog) { if (!dialog) { return; } // 横杠 const borderElement = dialog.querySelector('.border-t.border-gray-200.dark\\:border-gray-600.my-3'); const oldDailyStatsTable = document.querySelector('#daily-stats-table') if (oldDailyStatsTable) { oldDailyStatsTable.remove() } // 3. 提取耗时(修复querySelector) const timeLabel = findElementByText(dialog, '耗时:', 'span'); const timeCard = timeLabel?.closest('.p-2.bg-gray-100.dark\\:bg-gray-700.rounded.mb-2'); if (!timeCard) { return; } // 4. 耗时转换(保持不变) const timeTextRaw = timeCard.querySelector('.bg-blue-100')?.textContent || ''; const actualTimeText = timeTextRaw.match(/^(.*?)\(基础/)?.[1]?.trim() || ''; const costTime = convertTimeToSeconds(actualTimeText); // 提取需求(避免重复解析) const demands = []; const demandLabels = findElementsByText(dialog, '需求:', 'span'); demandLabels.forEach(label => { const demandCard = label.closest('.p-2.bg-gray-100.dark\\:bg-gray-700.rounded.mb-2'); // 精准选择需求项元素(只选择最内层的span) const demandItems = demandCard?.querySelectorAll('div.flex.items-center.rounded.text-sm.white-space-nowrap > span.inline-block.px-2.py-1.rounded.text-sm'); demandItems?.forEach(item => { const text = item.textContent.trim(); // 尝试匹配"名称: 数量"格式 const resourceMatch = text.match(/(.+?)\s*[::]\s*(\d+)\s*(?:\(([^)]*)\))?/); if (resourceMatch) { demands.push({ type: 'resource', name: removeEmoji(resourceMatch[1].trim()).trim(), amount: parseInt(resourceMatch[2]) }); } }); }); // 提取获得 const gainLabel = findElementByText(dialog, '获得:', 'span'); const gainCard = gainLabel?.closest('.p-2.bg-gray-100.dark\\:bg-gray-700.rounded.mb-2'); const gainItems = gainCard?.querySelectorAll('.bg-blue-100'); const gains = []; gainItems?.forEach(item => { const text = item.textContent.trim(); const nameMatch = text.match(/(.+?)\s*[::]/)?.[1]?.trim(); const probMatch = text.match(/(\d+\.?\d*)%/)?.[1] || '100'; let min, max; const rangeMatch = text.match(/(\d+)\s*[~-]\s*(\d+)/); if (rangeMatch) { // 处理范围情况(如 "1~3") min = parseInt(rangeMatch[1]); max = parseInt(rangeMatch[2]); } else { // 处理单个数字情况(如 "1") const singleMatch = text.match(/(\d+)/); if (singleMatch) { min = max = parseInt(singleMatch[1]); } else { // 默认值(防止NaN) min = max = 1; } } const probability = parseFloat(probMatch) / 100; if (nameMatch && !isNaN(min) && !isNaN(max) && !isNaN(probability)) { gains.push({ name: removeEmoji(nameMatch).trim(), range: [min, max], probability }); } }); // 7. 计算每日产量和消耗量(保持不变) const dailyTimes = Math.floor(86400 / costTime); const dailyOutput = gains.map(gain => { const avgPerAmount = (gain.range[0] + gain.range[1]) / 2; const avgAmount = avgPerAmount * gain.probability; return { name: gain.name, amount: avgAmount, total: Math.round(dailyTimes * avgAmount) }; }); const dailyConsume = demands.map(demand => { return { name: demand.name, amount: demand.amount, total: demand.amount * dailyTimes } }); // 创建展示区 const displayHtml = createDisplayHtml(borderElement, dailyConsume, dailyOutput); const levelUpTimesSpan = document.getElementById('levelUpTimesSpan') levelUpTimesSpan.innerText = ` 0 次[0 天]` const expPerLabel = findElementByText(dialog, '提升:', 'span'); if (expPerLabel) { //flex flex-wrap gap-2 ml-10 w-full const expLabel = expPerLabel.parentNode.children[1] const expLabelInnerText = expLabel.innerText.trim(); if (expLabelInnerText && expLabelInnerText.includes('经验')) { const expLabelInfos = expLabelInnerText.replace(' ', '').split(':'); const expName = removeEmoji(expLabelInfos[0]); const exp = parseInt(expLabelInfos[1].replace('经验', ''), 0); const levelUpInput = document.getElementById('levelUpInput') const expInfo = expInfoMap[skillEnCn[expName] || ''] if (expInfo) { // 技能升级提示 levelUpInput.dataset.expName = expName; levelUpInput.dataset.exp = exp; levelUpInput.value = expInfo.level levelUpInput.addEventListener('change', function () { const value = this.value const level = expInfo.level if (value < 0 || value > levelExp.length) { this.value = level return } let totalNeedExp = levelExp[String(level + 1)] - expInfo.currentExp for (let i = level + 2; i <= value; i++) { totalNeedExp += parseInt(levelExp[String(i)]) } const doTimes = totalNeedExp / exp levelUpTimesSpan.innerText = ` ${doTimes.toFixed(2)} 次[${formatSeconds(doTimes * costTime)}]` }); } } } } //秒转 天 时 分 秒 function formatSeconds(seconds) { // 处理无效输入 if (typeof seconds !== 'number' || isNaN(seconds) || seconds < 0) { return "0秒"; } // 计算各单位值 const days = Math.floor(seconds / 86400); // 1天 = 86400秒 const hours = Math.floor((seconds % 86400) / 3600); // 1小时 = 3600秒 const minutes = Math.floor((seconds % 3600) / 60); // 1分钟 = 60秒 const remainingSeconds = Math.floor(seconds % 60); // 存储非零单位 const timeParts = []; if (days > 0) timeParts.push(`${days}天`); if (hours > 0) timeParts.push(`${hours}时`); if (minutes > 0) timeParts.push(`${minutes}分`); if (remainingSeconds > 0) timeParts.push(`${remainingSeconds}秒`); // 处理所有单位都为0的情况(输入为0时) if (timeParts.length === 0) { return "0秒"; } // 拼接结果 return timeParts.join(''); } function convertTimeToSeconds(timeText) { let totalSeconds = 0; // 匹配“时”(1时=3600秒) const hourMatch = timeText.match(/(\d+\.?\d*)\s*[时h]/); if (hourMatch) { totalSeconds += parseFloat(hourMatch[1]) * 3600; timeText = timeText.replace(hourMatch[0], ''); // 移除已匹配的部分 } // 匹配“分”(1分=60秒) const minuteMatch = timeText.match(/(\d+\.?\d*)\s*[分m]/); if (minuteMatch) { totalSeconds += parseFloat(minuteMatch[1]) * 60; timeText = timeText.replace(minuteMatch[0], ''); // 移除已匹配的部分 } // 匹配“秒”(直接累加) const secondMatch = timeText.match(/(\d+\.?\d*)\s*[秒s]/); if (secondMatch) { totalSeconds += parseFloat(secondMatch[1]); } return totalSeconds; } /** * 查找包含指定文本的元素 * @param {Element} parent 父元素 * @param {string} text 要匹配的文本 * @param {string} tag 目标元素标签(如 'span') * @returns {Element[]} 匹配的元素数组 */ function findElementsByText(parent, text, tag = '*') { const result = []; const elements = parent.getElementsByTagName(tag); for (const el of elements) { if (el.textContent.trim().includes(text.trim())) { result.push(el); } } return result; } // 工具函数:查找包含指定文本的单个元素 function findElementByText(parent, text, tag = '*') { const elements = parent.getElementsByTagName(tag); for (const el of elements) { if (el.textContent.trim().includes(text.trim())) { return el; } } return null; } GM_addStyle(` .item-refresh-btn { cursor: pointer; font-size: 18px; transition: all 0.2s ease; user-select: none; } .item-refresh-btn:active { transform: scale(0.9); opacity: 0.6; filter: brightness(0.7); } .item-refresh-btn:hover { transform: rotate(15deg); } `); // 核心函数:使用dailyConsume和dailyOutput创建展示区HTML function createDisplayHtml(borderElement, dailyConsume, dailyOutput) { // 单个物品的材料价格 let sellUnitPrice = 0; let buyUnitPrice = 0; // 计算原料总价值 const materialRows = dailyConsume.map(item => { const price = marketPrices[cn_en[item.name]] || { sellOrders: { minPrice: 0 }, buyOrders: { maxPrice: 0 } }; const sellValue = item.total * price.sellOrders.minPrice; // 总挂价价值 const buyValue = item.total * price.buyOrders.maxPrice; // 总填价价值 sellUnitPrice += item.amount * price.sellOrders.minPrice; buyUnitPrice += item.amount * price.buyOrders.maxPrice; return { ...item, price, sellValue, buyValue }; }); // 计算产品总价值 const productRows = dailyOutput.map(item => { const price = marketPrices[cn_en[item.name]] || { sellOrders: { minPrice: 0 }, buyOrders: { maxPrice: 0 } }; const sellValue = item.total * price.sellOrders?.minPrice; // 总挂价价值 const buyValue = item.total * price.buyOrders?.maxPrice; // 总填价价值 return { ...item, price, sellValue, buyValue }; }); // 计算总计 const totalMaterialSell = materialRows.reduce((sum, item) => sum + item.sellValue, 0); const totalMaterialBuy = materialRows.reduce((sum, item) => sum + item.buyValue, 0); const totalProductSell = productRows.reduce((sum, item) => sum + item.sellValue, 0); const totalProductBuy = productRows.reduce((sum, item) => sum + item.buyValue, 0); const cutTex = 0.97 // 计算利润 const profit1 = totalProductSell * cutTex - totalMaterialBuy; // 产品挂价 - 原料填价 const profit2 = totalProductBuy * cutTex - totalMaterialSell; // 产品填价 - 原料挂价 // 生成原料行HTML const materialHtml = materialRows.map(item => ` <tr> <td class="border px-2 py-1 text-sm">${item.name}<span class="item-refresh-btn text-sm" data-itemname="${cn_en[item.name]}">↺</span></td> <td class="border px-2 py-1 text-sm text-right">${item.total}</td> <td class="border px-2 py-1 text-sm text-right ${item.price.sellOrders.minPrice == 0 ? 'text-red-600' : ''}">${formatLargeNumber(item.price.sellOrders.minPrice)}</td> <td class="border px-2 py-1 text-sm text-right">${formatLargeNumber(item.sellValue)}</td> <td class="border px-2 py-1 text-sm text-right ${item.price.buyOrders.maxPrice == 0 ? 'text-red-600' : ''}">${formatLargeNumber(item.price.buyOrders.maxPrice)}</td> <td class="border px-2 py-1 text-sm text-right">${formatLargeNumber(item.buyValue)}</td> </tr> `).join(''); // 生成产品行HTML const productHtml = productRows.map(item => ` <tr> <td class="border px-2 py-1 text-sm">${item.name}<span class="item-refresh-btn text-sm" data-itemname="${cn_en[item.name]}">↺</span></td> <td class="border px-2 py-1 text-sm text-right">${item.total}</td> <td class="border px-2 py-1 text-sm text-right ${item.price.sellOrders.minPrice == 0 ? 'text-red-600' : ''}">${formatLargeNumber(item.price.sellOrders.minPrice)}</td> <td class="border px-2 py-1 text-sm text-right">${formatLargeNumber(item.sellValue)}</td> <td class="border px-2 py-1 text-sm text-right ${item.price.buyOrders.maxPrice == 0 ? 'text-red-600' : ''}">${formatLargeNumber(item.price.buyOrders.maxPrice)}</td> <td class="border px-2 py-1 text-sm text-right">${formatLargeNumber(item.buyValue)}</td> </tr> `).join(''); // 技能升级提示 const displayHtml = ` <div id="daily-stats-table" class="my-4 p-3 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700"> <!-- 插入样式代码 --> <style> /* 表格边框统一改为浅灰色 */ #daily-stats-table table { border-collapse: collapse; } #daily-stats-table th, #daily-stats-table td { border-color: #e5e7eb !important; } @media (prefers-color-scheme: dark) { #daily-stats-table th, #daily-stats-table td { border-color: #374151 !important; } } #daily-stats-table thead tr { border-bottom: 1px solid #e5e7eb !important; } @media (prefers-color-scheme: dark) { #daily-stats-table thead tr { border-bottom-color: #374151 !important; } } </style> <h4 class="text-sm font-medium text-gray-800 dark:text-gray-200 mb-2">每日产量/消耗价值表</h4> <!-- 原料消耗部分 --> <div class="mb-4"> <h5 class="text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">消耗</h5> <table class="min-w-full text-sm"> <thead> <tr class="bg-gray-50 dark:bg-gray-700"> <th class="border px-2 py-1 text-left" style="min-width: 45px;">原料</th> <th class="border px-2 py-1 text-center">日消</th> <th class="border px-2 py-1 text-center">挂</th> <th class="border px-2 py-1 text-center">总挂</th> <th class="border px-2 py-1 text-center">填</th> <th class="border px-2 py-1 text-center">总填</th> </tr> </thead> <tbody>${materialHtml}</tbody> <tfoot class="bg-gray-50 dark:bg-gray-700 font-medium"> <tr> <td class="border px-2 py-1 text-left" style="min-width: 45px;">总计</td> <td class="border px-2 py-1 text-center">-</td> <td class="border px-2 py-1 text-center">${formatLargeNumber(sellUnitPrice)}</td> <td class="border px-2 py-1 text-center">${formatLargeNumber(totalMaterialSell)}</td> <td class="border px-2 py-1 text-center">${formatLargeNumber(buyUnitPrice)}</td> <td class="border px-2 py-1 text-center">${formatLargeNumber(totalMaterialBuy)}</td> </tr> </tfoot> </table> </div> <!-- 产品产出部分 --> <div class="mb-4"> <h5 class="text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">产出</h5> <table class="min-w-full text-sm"> <thead> <tr class="bg-gray-50 dark:bg-gray-700"> <th class="border px-2 py-1 text-left" style="min-width: 45px;">产品</th> <th class="border px-2 py-1 text-center">日产</th> <th class="border px-2 py-1 text-center">挂</th> <th class="border px-2 py-1 text-center">总挂</th> <th class="border px-2 py-1 text-center">填</th> <th class="border px-2 py-1 text-center">总填</th> </tr> </thead> <tbody>${productHtml}</tbody> <tfoot class="bg-gray-50 dark:bg-gray-700 font-medium"> <tr> <td class="border px-2 py-1 text-left" style="min-width: 45px;">总计</td> <td class="border px-2 py-1 text-center">-</td> <td class="border px-2 py-1 text-center">-</td> <td class="border px-2 py-1 text-center">${formatLargeNumber(totalProductSell)}</td> <td class="border px-2 py-1 text-center">-</td> <td class="border px-2 py-1 text-center">${formatLargeNumber(totalProductBuy)}</td> </tr> </tfoot> </table> </div> <!-- 利润计算部分 --> <div class="p-2 bg-gray-50 dark:bg-gray-700 rounded-lg"> <h5 class="text-xs font-medium text-gray-600 dark:text-gray-400 mb-2">每日利润分析</h5> <div class="grid grid-cols-2 gap-2 text-sm"> <div class="flex justify-between"> <span class="text-gray-600 dark:text-gray-400">挂填:</span> <span class="${profit1 >= 0 ? 'text-green-600' : 'text-red-600'}"> ${profit1 >= 0 ? '+' : ''}${formatLargeNumber(profit1)} </span> </div> <div class="flex justify-between"> <span class="text-gray-600 dark:text-gray-400">填挂:</span> <span class="${profit2 >= 0 ? 'text-green-600' : 'text-red-600'}"> ${profit2 >= 0 ? '+' : ''}${formatLargeNumber(profit2)} </span> </div> </div> </div> <div class="p-2 bg-gray-50 rounded-lg"> 到 <input type="number" id="levelUpInput" value="100" min="0" max="102" step="1" style="width: 40px;"> 级还需做 <span id="levelUpTimesSpan">0 次[0 天]</span> </div> </div> `; // 6. 插入到指定位置 borderElement.insertAdjacentHTML('afterend', displayHtml); document.querySelectorAll('.item-refresh-btn.text-sm').forEach(btn => { btn.addEventListener('click', async function () { sendGetItemPriceMessage(this.dataset.itemname) wsRespondMsgStatus.wait = true const res = await waitTaskListCallback() if (res) { setTimeout(() => { document.getElementById("daily-stats-table").remove() createDisplayHtml(borderElement, dailyConsume, dailyOutput) }, 200) } }); }); } async function sleep(time) { await new Promise(resolve => setTimeout(resolve, time)); } function removeEmoji(text) { if (!text) return ''; // 更全面的emoji匹配正则,包括变体选择器 const emojiRegex = /(?:[\u2700-\u27BF]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff]|[\uFE00-\uFE0F])/g; return text?.replace(emojiRegex, '') || ''; } // 物品价格 物品:价格 function monitorMarketMessage(data) { if (!socketIoMode) return //newMarket:getUnifiedTransactionList:success const event = data?.event if (event === "newMarket:getUnifiedTransactionList:success") { updateMarketPrices(data.data.data) } else if (showUserLevel && event.includes("dispatchCharacterStatusInfo")) { const userExpInfo = data.data?.data menusAddUserExpInfo(userExpInfo) } else if (event.includes("dispatchTaskQueueToClient")) { tryUpdateSatietyShow(data.data?.data) } } let updateMarketPricesing = false; function updateMarketPrices(marketList) { if (updateMarketPricesing) return; updateMarketPricesing = true; const marketItem = { itemId: "", sellOrders: { minPrice: 0 }, buyOrders: { maxPrice: 0 } } for (let marketListElement of marketList) { if (!marketItem.itemId) { marketItem.itemId = marketListElement.sellResourceId ? marketListElement.sellResourceId : marketListElement.requireResourceId if (!marketItem.itemId) { continue; } } if (marketListElement.costResourceId === "gold" && marketListElement.type === "sell") { if (marketItem.itemId === marketListElement.sellResourceId && (marketItem.sellOrders.minPrice === 0 || marketItem.sellOrders.minPrice > marketListElement.costPerUnit)) { //卖 marketItem.sellOrders = { minPrice: marketListElement.costPerUnit, minPriceCount: marketListElement.sellResourceCount - marketListElement.selledResourceCount } } } else if (marketListElement.payResourceId === "gold" && marketListElement.type === "buy") { if (marketItem.itemId === marketListElement.requireResourceId && (marketItem.buyOrders.maxPrice === 0 || marketItem.buyOrders.maxPrice < marketListElement.payPerUnit)) { //买 marketItem.buyOrders = { maxPrice: marketListElement.payPerUnit, maxPriceCount: marketListElement.requireResourceCount - marketListElement.doneResourceCount } } } } if (marketItem.itemId) { marketPrices[marketItem.itemId] = marketItem GM_setValue("marketPrices", marketPrices) } updateMarketPricesing = false; } // 菜单栏 添加经验信息============================================================ //升级经验 const levelExp = { '1': '0', '2': '20', '3': '45', '4': '80', '5': '125', '6': '180', '7': '245', '8': '320', '9': '405', '10': '500', '11': '605', '12': '720', '13': '845', '14': '980', '15': '1125', '16': '1280', '17': '1445', '18': '1620', '19': '1805', '20': '2000', '21': '2205', '22': '2420', '23': '2645', '24': '2880', '25': '3125', '26': '3380', '27': '3645', '28': '3920', '29': '4205', '30': '4500', '31': '4805', '32': '5760', '33': '6825', '34': '8000', '35': '9285', '36': '10680', '37': '12185', '38': '13800', '39': '15525', '40': '17360', '41': '19305', '42': '21360', '43': '23525', '44': '25800', '45': '28185', '46': '30680', '47': '33285', '48': '36000', '49': '38825', '50': '41760', '51': '44805', '52': '52869', '53': '62386', '54': '73616', '55': '86866', '56': '102502', '57': '120953', '58': '142725', '59': '168415', '60': '198730', '61': '234502', '62': '276712', '63': '326520', '64': '385294', '65': '454647', '66': '536483', '67': '633050', '68': '747000', '69': '881460', '70': '1040122', '71': '1227344', '72': '1448267', '73': '1708955', '74': '2016566', '75': '2379549', '76': '2807867', '77': '3313284', '78': '3909675', '79': '4613416', '80': '5443831', '81': '6423721', '82': '7579991', '83': '8944389', '84': '10554379', '85': '12454168', '86': '14695918', '87': '17341183', '88': '20462597', '89': '24145864', '90': '28492120', '91': '33620701', '92': '39672428', '93': '46813465', '94': '55239888', '95': '65183068', '96': '76916021', '97': '90760905', '98': '107097867', '99': '126375484', '100': '149123071', '101': '175965224', '102': '175965224' } const menusEnCn = { "强化": "enhance", "战斗": "battle", "采集": 'collecting', "钓鱼": 'fishing', '照料家禽': 'farmingAnimal', '畜牧': 'farmingAnimal', '采矿': 'mining', "烹饪": 'cooking', "制造": 'manufacturing', '锻造': 'forging', '缝制': 'sewing', '炼金': 'mysterious', '探索': 'exploring' } const skillEnCn = { "攻击": "attacking", "战斗": "battle", "采集": "collecting", "烹饪": "cooking", "防御": "defencing", "敏捷": "dexterity", "强化": "enhance", "探索": "exploring", "畜牧": "farmingAnimal", "种植": "farmingPlant", "钓鱼": "fishing", "锻造": "forging", "智力": "intelligence", "学识": "knowledge", "幸运": "luck", "制造": "manufacturing", "挖掘": "mining", "神秘": "mysterious", "缝纫": "sewing", "耐力": "stamina", "力量": "strength", "交易": "trading" } let expInfoMap; let menusAddUserExpInfoing = false; function menusAddUserExpInfo(userExpInfo) { if (menusAddUserExpInfoing) return; menusAddUserExpInfoing = true; expInfoMap = userExpInfo // 尝试通过特定类名查找 const menubars = document.querySelectorAll('.el-menu-item.cute-menu-item'); for (let menubar of menubars) { const menubarText = (menubar.querySelector('.menu-text')?.innerText || '').trim(); if (menubarText === '照料家禽') { menubar.querySelector('.menu-text').innerText = '畜牧' } const menuName = menusEnCn[menubarText] if (menuName) { const menuExp = userExpInfo[menuName] //往左移动 menubar.style.paddingLeft = '8px' // 3. 创建等级标签并插入到图标左侧 const id = `${menuName}-level` let levelBadge = document.getElementById(id) if (!levelBadge) { levelBadge = document.createElement('span'); levelBadge.id = `${menuName}-level` // 调整等级标签样式(减小宽度和内边距) levelBadge.className = 'inline-block mr-0 px-0 py-0.5 text-xs rounded-sm'; levelBadge.style.minWidth = '2.3em'; // 强制最小宽度为两个字符 levelBadge.style.textAlign = 'center'; // 文本居中 // 找到图标元素并插入等级标签 const iconElement = menubar.querySelector('.el-icon.menu-icon'); if (iconElement) { iconElement.parentNode.appendChild(levelBadge); } } levelBadge.textContent = menuExp?.level || 0; // 4. 创建进度条容器并插入到按钮底部 const progressId = `${menuName}-progress` let progressContainer = document.getElementById(progressId) if (!progressContainer) { progressContainer = document.createElement('div'); progressContainer.id = `${menuName}-progress`; progressContainer.className = 'absolute bottom-0 left-10% right-10% h-0.5 bg-gray-300 dark:bg-gray-600'; //'absolute bottom-0 left-10% right-10% h-0.5 bg-gray-300 dark:bg-gray-600'; progressContainer.style.width = '75%'; menubar.appendChild(progressContainer); } // 7. 进度条背景 const progressBgId = `${menuName}-progress-bg` let progressBg = document.getElementById(progressBgId) if (!progressBg) { progressBg = document.createElement('div'); progressBg.id = progressBgId; progressBg.className = 'w-full h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden'; progressContainer.appendChild(progressBg); } // 8. 进度条填充部分 const progressFillId = `${menuName}-progress-fill` let progressFill = document.getElementById(progressFillId) if (!progressFill) { progressFill = document.createElement('div'); progressFill.id = progressFillId; progressFill.className = 'h-full bg-blue-400 transition-all duration-300'; progressBg.appendChild(progressFill); } const progressPercent = (menuExp.currentExp / (levelExp[menuExp.level + 1] || 99999999)) * 100; progressFill.style.width = `${Math.min(100, progressPercent)}%`; // 7. 调整菜单项样式,为进度条腾出空间 // menubar.style.paddingBottom = '8px'; // menubar.style.position = 'relative'; } } menusAddUserExpInfoing = false; } /** * 将大数字格式化为人性化显示(k/m/b) * @param {number} num - 要格式化的数字 * @param {number} [decimalPlaces=1] - 保留的小数位数 * @returns {string} 格式化后的字符串(如 "100.0k", "100.0m", "100.0b") */ function formatLargeNumber(num, decimalPlaces = 1) { // 处理非数字或0的情况 if (isNaN(num) || num === 0) return '0'; // 定义单位和对应的量级 const units = [ { unit: 'b', value: 1e9 }, // 十亿 { unit: 'm', value: 1e6 }, // 百万 { unit: 'k', value: 1e3 } // 千 ]; // 遍历单位找到合适的量级 for (const { unit, value } of units) { if (Math.abs(num) >= value) { // 计算数值并保留指定小数位数 const formattedNum = (num / value).toFixed(decimalPlaces); return `${formattedNum}${unit}`; } } // 小于1k的数字直接返回(可根据需要添加整数处理) return num.toFixed(decimalPlaces); } /** * 将带单位的数值字符串转换为实际数值 * @param {string} valueStr - 带单位的数值字符串,如 "32.0K"、"1.5M" * @returns {number} - 转换后的实际数值 */ function parseUnitValue(valueStr) { // 定义单位映射表(k: 千, m: 百万, b: 十亿, 以此类推) const unitMap = { 'b': 1e9, // 10^9 'm': 1e6, // 10^6 'k': 1e3, // 10^3 '': 1 // 无单位,基数为1 }; // 正则表达式:匹配数字部分和单位部分 const regex = /^(\d+(?:\.\d+)?)\s*([bkm]?)$/i; const match = valueStr.trim().match(regex); if (!match) { return 0; } // 提取数字和单位 const number = parseFloat(match[1]); const unit = match[2].toLowerCase(); // 转换为实际数值 return number * unitMap[unit]; } window.monitorMarketMessage = monitorMarketMessage function dailyNodeObserver() { // 1. 日利节点 // 选择要观察的目标节点(这里选择body) const targetNode = document.body; // 创建观察器实例 const observer = new MutationObserver(mutationsList => { // 检查body是否有目标class if (document.body.classList.contains('el-popup-parent--hidden')) { // 查找可见的el-overlay元素 const visibleOverlay = document.querySelector('div.el-overlay:not([style*="display: none"])'); if (visibleOverlay && visibleOverlay.parentElement === document.body) { // 在这里执行你需要的操作 addDailyTable(visibleOverlay) } } }); // 配置观察选项 const config = { attributes: true, // 监听属性变化 attributeFilter: ['class'], // 只监听class属性 childList: true, // 监听子节点变化 subtree: false // 不监听所有后代节点 }; // 开始观察 observer.observe(targetNode, config); } // 日利完成 开始仓库相关======================================================================================================= let showSellPrice = true; // 仓库内容配置 const warehouseConfig = { // 左侧菜单中“仓库”选项的选择器 warehouseMenuSelector: '.el-menu-item:has(.iconify.i-material-symbols\\:warehouse-outline-rounded)', // 内容容器(仓库页面内容的父容器) contentWrapper: '.content-wrapper', // 仓库内容面板(仓库页面的核心容器) warehousePane: '#pane-full', // 物品卡片基础类 itemCard: '.item-card.relative', // 物品名称选择器(用于获取物品名称) itemNameSelector: '.absolute.text-center.left-0.-bottom-5.5.text-xs' }; // 仓库内容状态管理:避免重复监听和处理 let warehouseState = { isInWarehouse: false, // 是否在仓库页面 menuObserver: null, // 监听仓库菜单点击的观察者 itemObserver: null, // 监听物品卡片的观察者 itemHoverObserver: null // 监听物品卡片悬停的观察者 }; /** * 第一步:监听仓库菜单点击,启动仓库监听逻辑 */ function watchWarehouseEntry() { // 查找仓库菜单元素 const warehouseMenu = document.querySelector(warehouseConfig.warehouseMenuSelector); if (warehouseMenu) { // 直接监听菜单点击事件 warehouseMenu.addEventListener('click', onWarehouseEnter); } else { setTimeout(watchWarehouseEntry, 1000); } //面板折叠 iconify i-material-symbols:expand-content-rounded const collapseMenu = document.querySelector('.iconify.i-material-symbols\\:collapse-content-rounded'); if (collapseMenu) { collapseMenu.parentNode.parentNode.addEventListener('click', function () { stopWarehouseListening() setTimeout(watchWarehouseEntry, 1000); }); } const expandMenu = document.querySelector('.iconify.i-material-symbols\\:expand-content-rounded'); if (expandMenu) { expandMenu.parentNode.parentNode.addEventListener('click', function () { stopWarehouseListening() setTimeout(watchWarehouseEntry, 1000); }); } } /** * 进入仓库页面后执行的逻辑 */ function onWarehouseEnter() { if (warehouseState.isInWarehouse) { return; } warehouseState.isInWarehouse = true; // 等待仓库内容加载(给页面渲染留时间) setTimeout(() => { // 监听是否离开仓库页面 watchWarehouseExit(); try { startWarehouseContentListener(); } catch (e) { console.error('物品价格渲染失败', e); } try { itemHoverNodeObserver(); } catch (e) { console.error('物品hover渲染失败', e); } }, 100); } /** * 第二步:监听仓库内容容器,等待仓库面板出现 */ function startWarehouseContentListener() { const contentWrapper = document.querySelector(warehouseConfig.contentWrapper); if (!contentWrapper) { console.error('未找到仓库内容容器'); return; } const warehousePane = document.querySelector(warehouseConfig.warehousePane) // 初始扫描已存在的物品卡片 scanAndProcessItems(warehousePane); // 启动物品卡片监听(监听新增和刷新) watchWarehouseItems(warehousePane); } /** * 第三步:监听仓库面板内的物品卡片变化 * @param {HTMLElement} warehousePane - 仓库面板元素 */ function watchWarehouseItems(warehousePane) { warehouseState.itemObserver = new MutationObserver((mutations) => { mutations.forEach(mutation => { // 处理新增物品卡片 if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { // 新增节点本身是物品卡片 if (node.matches(warehouseConfig.itemCard)) { processItemCard(node); } // 新增节点的后代中包含物品卡片 node.querySelectorAll(warehouseConfig.itemCard).forEach(processItemCard); } }); } }); }); // 只监听仓库面板内的必要变化 warehouseState.itemObserver.observe(warehousePane.querySelector('.flex.flex-wrap.gap-x-6.gap-8.pb-8'), { childList: true, subtree: true, // 监听后代(物品卡片在面板内部) attributes: true, attributeFilter: ['class'], // 只关注影响显示的属性 attributeOldValue: false }); } /** * 扫描并处理容器内所有未处理的物品卡片 * @param {HTMLElement} container - 容器元素 */ function scanAndProcessItems(container) { container.querySelectorAll(warehouseConfig.itemCard).forEach(processItemCard); //计算总价 warehouseTotalPrice() } let warehouseTotalPriceUpdate = false; function warehouseTotalPrice() { if (warehouseTotalPriceUpdate) return; warehouseTotalPriceUpdate = true; const itemCardPrices = document.querySelectorAll('.item-card-price') let sellTotal = 0 let buyTotal = 0 const jumpItem = [] const typePriceMap = {} itemCardPrices.forEach(itemCardPrice => { const priceinfo = itemCardPrice.dataset.price const name = itemCardPrice.dataset.name const type = itemCardPrice.dataset.type if (!priceinfo) { return } const prices = priceinfo.split('/') const sell = parseInt(prices[0], 0) const buy = parseInt(prices[1], 0) if (!jumpItem.includes(name)) { //跳过处理过的 sellTotal += sell buyTotal += buy jumpItem.push(name) } //大类计价 let typePrice = typePriceMap[type] if (!typePrice) { typePrice = { sell: 0, buy: 0 } typePriceMap[type] = typePrice } typePrice.sell += sell typePrice.buy += buy }); const sellTotalStr = formatLargeNumber(sellTotal) const buyTotalStr = formatLargeNumber(buyTotal) // 定位输入框容器 const inputContainer = document.querySelector('.el-input.w-full.md\\:w-20'); if (!inputContainer) return; // 缩短输入框宽度 inputContainer.style.width = '40%'; // 可根据需要调整 // 创建"总资产"显示区域 const assetsContainerId = 'assets-container'; let assetsContainer = document.getElementById(assetsContainerId) if (!assetsContainer) { assetsContainer = document.createElement('div'); assetsContainer.className = 'ml-2 flex items-center justify-center px-3 py-1 bg-gray-100 dark:bg-gray-800 rounded-md cursor-help relative'; assetsContainer.innerHTML = ` <span class="text-sm font-medium">总资产: 0/0</span> <button class="el-button el-button--mini ml-2" style="padding: 2px 8px; font-size: 12px;">挂价</button> <button class="el-button el-button--mini ml-1" style="padding: 2px 8px; font-size: 12px;">填价</button> `; assetsContainer.id = 'assets-container' // 调整总资产容器样式阻止换行+灵活占宽 assetsContainer.style.cssText += `white-space: nowrap; flex: 1; min-width: 0; `; // 添加到页面 inputContainer.parentNode.appendChild(assetsContainer); // 绑定按钮点击事件 const priceButton = assetsContainer.querySelector('button:first-of-type'); const fillButton = assetsContainer.querySelector('button:last-of-type'); if (!showItemPrice) showSellPrice = null; priceButton.addEventListener('click', () => { if (showSellPrice === null || showSellPrice === false) { showSellPrice = true; showItemPrice = true; document.querySelector(warehouseConfig.warehousePane).querySelectorAll(warehouseConfig.itemCard).forEach(processItemCard); } }); fillButton.addEventListener('click', () => { if (!showSellPrice === null || showSellPrice === true) { showSellPrice = false; showItemPrice = true; document.querySelector(warehouseConfig.warehousePane).querySelectorAll(warehouseConfig.itemCard).forEach(processItemCard); } }); } assetsContainer.querySelector('.text-sm.font-medium').innerText = `总资产: ${sellTotalStr}/${buyTotalStr}`; document.querySelectorAll('.w-full.font-bold.text-lg').forEach(cardTitle => { const title = cardTitle.innerText.trim() const typePrice = typePriceMap[title] if (typePrice) { // 创建要添加的小字元素 let smallText = document.getElementById('type-Price-' + title) if (!smallText) { smallText = document.createElement('div'); smallText.style.cssText = ` display: inline-block; font-size: 0.7em; font-weight: normal; color: #666; vertical-align: middle; `; // 获取目标元素的父容器(用于插入同级元素) cardTitle.parentNode.insertBefore(smallText, cardTitle.nextSibling); } smallText.textContent = `${formatLargeNumber(typePrice.sell)}/${formatLargeNumber(typePrice.buy)}`; } }); warehouseTotalPriceUpdate = false; } function processItemCard(itemCard) { //console.log('处理物品卡片', itemCard); //跳过金币 const itemNum = parseUnitValue(itemCard.children[1].innerText) const itemCnName = itemCard.children[2].innerText.trim() let itemEnName if (itemCnName.endsWith('技能书')) { itemEnName = cn_en[itemCnName.replace('技能书', '')] } else { itemEnName = cn_en[itemCnName] } if (!itemEnName) { console.log(`未找到 ${itemCnName} 的英文名称`) return } const itemPrice = marketPrices[itemEnName] || { sellOrders: { minPrice: 0 }, buyOrders: { maxPrice: 0 } }; //获取类型标签 let typeNode; if (itemCard.parentNode.classList && itemCard.parentNode.classList.length > 0) { typeNode = itemCard.parentNode.parentNode.children[0] } else { typeNode = itemCard.parentNode.parentNode.parentNode.children[0] } let type = '' if (typeNode) { type = typeNode.innerText.trim() } // 创建新的数字元素 let id = 'item-card-' + type + "-" + itemCnName let numberElement = document.getElementById(id) if (!numberElement) { numberElement = document.createElement('div'); numberElement.id = id // 将新元素添加到卡片中 itemCard.appendChild(numberElement); // 设置与现有数字相同的样式类 numberElement.className = 'flex justify-start items-start text-sm text-yellow-600 dark:text-cyan-600 absolute w-16 h-16 left-1 top-1 break-all text-left drop-shadow-sm item-card-price'; } // 设置文本内容 const sellTotal = itemNum * itemPrice.sellOrders.minPrice || 0; const buyTotal = itemNum * itemPrice.buyOrders.maxPrice || 0; numberElement.textContent = showSellPrice ? formatLargeNumber(sellTotal) : formatLargeNumber(buyTotal); numberElement.dataset.price = sellTotal + "/" + buyTotal numberElement.dataset.name = itemCnName numberElement.dataset.type = type numberElement.style.display = showItemPrice ? "block" : 'none' } function itemHoverNodeObserver() { let targetNode = null; // 物品hover节点 document.querySelectorAll('[id^="el-popper-container-"]').forEach(element => { if (/^el-popper-container-\d+$/.test(element.id)) { targetNode = element; return; } }); if (!targetNode) { console.log('未找到匹配的hover元素'); } // 创建观察器实例,只监听 targetNode 内部的变化 warehouseState.itemHoverObserver = new MutationObserver(mutationsList => { for (const mutation of mutationsList) { if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { addPriceInfo(node); } }); } } }); // 配置观察选项 const config = { childList: true, // 监听子节点添加/移除 attributes: false, // 监听属性变化 subtree: false, //attributeFilter: ['style'], // 只监听class属性 }; // 开始观察 warehouseState.itemHoverObserver.observe(targetNode, config); } // 在指定节点下查找目标div并添加价格信息 function addPriceInfo(parentNode) { // 查找目标div元素 const targetDiv = parentNode.querySelector('div.el-divider.el-divider--horizontal.my-2\\!'); if (targetDiv) { const text = parentNode.querySelectorAll('.font-bold.text-base.mb-1')[0].innerText.trim() // 创建价格信息元素 const id = 'price-info-' + text; let priceDiv = document.getElementById(id) if (!priceDiv) { //oldInfo.remove() priceDiv = document.createElement('div'); // 设置样式类(使用Tailwind CSS类) priceDiv.className = 'text-sm text-gray-600 dark:text-gray-400 mb-2'; priceDiv.id = id; // 将价格元素插入到目标div之后 targetDiv.parentNode.insertBefore(priceDiv, targetDiv.nextSibling); } // 设置文本内容 const itemNum = parseUnitValue(getPreviousSiblingText(text)) const itemPrice = marketPrices[cn_en[text]] || { sellOrders: { minPrice: 0 }, buyOrders: { maxPrice: 0 } }; const totalSell = itemNum * itemPrice.sellOrders.minPrice priceDiv.textContent = `价格:${formatLargeNumber(itemPrice.sellOrders.minPrice)}/${formatLargeNumber(itemPrice.buyOrders.maxPrice)} (${formatLargeNumber(totalSell, 1)}/${formatLargeNumber(itemNum * itemPrice.buyOrders.maxPrice, 1)})`; } } // 函数:获取指定文本的div的上一个同级div的文本 function getPreviousSiblingText(targetText) { // 1. 查找页面中所有符合样式的div const allDivs = document.querySelectorAll( 'div[class*="absolute"][class*="text-center"][class*="left-0"][class*="-bottom-5.5"][class*="text-xs"][class*="w-16"][class*="text-gray-600"][class*="dark:text-gray-200"]' ); // 2. 遍历div,找到文本内容匹配的目标元素 let targetDiv = null; for (const div of allDivs) { if (div.textContent.trim() === targetText) { targetDiv = div; break; // 找到第一个匹配的即可 } } if (!targetDiv) { console.log(`未找到文本为"${targetText}"的div元素`); return 0; } const prevDiv = getPrevDivNode(targetDiv) if (!prevDiv) { console.log(`目标div没有同级上一个div元素`); return 0; } // 4. 返回上一个div的文本内容 const prevText = prevDiv.textContent.trim(); return prevText; } // 同级上一个div function getPrevDivNode(node) { // 3. 获取上一个同级div元素(只找div类型的同级元素) let prevDiv = node.previousElementSibling; // 循环查找上一个同级,直到找到div或无同级元素 while (prevDiv && prevDiv.tagName !== 'DIV') { prevDiv = prevDiv.previousElementSibling; } return prevDiv; } /** * 监听是否离开仓库页面(停止所有监听) */ function watchWarehouseExit() { // 监听仓库菜单是否失去激活状态(离开仓库时) warehouseState.menuObserver = new MutationObserver(() => { const warehouseMenu = document.querySelector(warehouseConfig.warehouseMenuSelector); // 仓库菜单不再激活,视为离开仓库 if (warehouseMenu && !warehouseMenu.classList.contains('is-active')) { stopWarehouseListening(); } else if (!warehouseMenu) { stopWarehouseListening(); } }); // 监听菜单的类名变化(检测激活状态) const menuContainer = document.querySelector('.el-menu'); if (menuContainer) { warehouseState.menuObserver.observe(menuContainer, { childList: false, subtree: true, attributes: true, attributeFilter: ['class'] }); } } /** * 离开仓库页面时,停止所有监听并清理状态 */ function stopWarehouseListening() { if (!warehouseState.isInWarehouse) return; warehouseState.isInWarehouse = false; // 断开所有观察者 if (warehouseState.menuObserver) warehouseState.menuObserver.disconnect(); if (warehouseState.itemObserver) warehouseState.itemObserver.disconnect(); if (warehouseState.itemHoverObserver) warehouseState.itemHoverObserver.disconnect(); } // 仓库相关结束 ==================================================================================================== // 聊天图片========================================================================================================= function createPicUpdateUI() { // 添加样式 GM_addStyle(` .moyu-upload-container { bottom: 20px; right: 20px; cursor: move; } .moyu-upload-btn { background-color: #4CAF50; color: white; border: none; padding: 10px 15px; border-radius: 5px; cursor: pointer; font-size: 14px; transition: all 0.3s; box-shadow: 0 2px 5px rgba(0,0,0,0.2); } .moyu-upload-btn:hover { background-color: #45a049; transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.2); } .moyu-upload-panel { display: none; position: fixed; z-index: 99999; bottom: 80px; right: 0; width: 320px; background: white; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.2); padding: 15px; cursor: default; } .moyu-upload-panel.show { display: block; animation: fadeIn 0.3s; } .moyu-paste-hint { margin-bottom: 15px; font-size: 14px; color: #555; text-align: center; padding: 10px; background: #f8f9fa; border-radius: 5px; } .moyu-preview-container { position: relative; margin: 10px 0; display: none; } .moyu-preview { max-width: 100%; max-height: 200px; display: block; margin: 0 auto; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } .moyu-result { margin-top: 15px; padding: 12px; background: #f8f9fa; border-radius: 5px; word-break: break-all; font-size: 13px; display: none; border: 1px solid #e0e0e0; } .moyu-copy-btn { background-color: #2196F3; color: white; border: none; padding: 8px 15px; border-radius: 5px; cursor: pointer; margin-top: 12px; font-size: 13px; width: 100%; transition: all 0.2s; } .moyu-copy-btn:hover { background-color: #0b7dda; transform: translateY(-1px); } .moyu-status { margin: 12px 0; font-size: 13px; color: #666; text-align: center; min-height: 20px; } .moyu-close-btn { position: absolute; top: 8px; right: 8px; background: #f44336; color: white; border: none; width: 24px; height: 24px; border-radius: 50%; font-size: 14px; cursor: pointer; display: flex; align-items: center; justify-content: center; opacity: 0.8; transition: opacity 0.2s; } .moyu-close-btn:hover { opacity: 1; } .moyu-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding-bottom: 10px; border-bottom: 1px solid #eee; } .moyu-title { font-weight: bold; color: #333; } .moyu-drag-handle { width: 100%; height: 30px; position: absolute; top: 0; left: 0; cursor: move; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .moyu-progress { width: 100%; height: 4px; background: #e0e0e0; border-radius: 2px; margin: 10px 0; overflow: hidden; display: none; } .moyu-progress-bar { height: 100%; background: #4CAF50; width: 0%; transition: width 0.3s; } `); // 创建UI元素 const container = document.createElement('div'); container.className = 'moyu-upload-container'; const uploadBtn = document.createElement('button'); uploadBtn.className = 'moyu-upload-btn'; uploadBtn.textContent = '截图上传'; const panel = document.createElement('div'); panel.className = 'moyu-upload-panel'; const header = document.createElement('div'); header.className = 'moyu-header'; const title = document.createElement('div'); title.className = 'moyu-title'; title.textContent = '截图上传助手'; const closeBtn = document.createElement('button'); closeBtn.className = 'moyu-close-btn'; closeBtn.innerHTML = '×'; closeBtn.title = '关闭'; const pasteHint = document.createElement('div'); pasteHint.className = 'moyu-paste-hint'; pasteHint.textContent = '截图后按 Ctrl+V 粘贴图片'; const previewContainer = document.createElement('div'); previewContainer.className = 'moyu-preview-container'; const preview = document.createElement('img'); preview.className = 'moyu-preview'; const progress = document.createElement('div'); progress.className = 'moyu-progress'; const progressBar = document.createElement('div'); progressBar.className = 'moyu-progress-bar'; progress.appendChild(progressBar); const status = document.createElement('div'); status.className = 'moyu-status'; const result = document.createElement('div'); result.className = 'moyu-result'; const copyBtn = document.createElement('button'); copyBtn.className = 'moyu-copy-btn'; copyBtn.textContent = '复制图片链接'; // 组装UI header.appendChild(title); header.appendChild(closeBtn); panel.appendChild(header); panel.appendChild(pasteHint); previewContainer.appendChild(preview); panel.appendChild(previewContainer); panel.appendChild(progress); panel.appendChild(status); panel.appendChild(result); panel.appendChild(copyBtn); container.appendChild(uploadBtn); container.appendChild(panel); // 事件处理 uploadBtn.addEventListener('click', () => { panel.classList.toggle('show'); if (panel.classList.contains('show')) { panel.focus(); result.textContent = ''; result.style.display = 'none'; status.textContent = ''; preview.src = ''; previewContainer.style.display = 'none'; } }); closeBtn.addEventListener('click', () => { panel.classList.remove('show'); }); copyBtn.addEventListener('click', () => { if (result.textContent) { GM_setClipboard(result.textContent); //showNotification('复制成功', '图片链接已复制到剪贴板'); } }); // 粘贴事件处理 panel.addEventListener('paste', async (e) => { panel.classList.add('show'); const items = e.clipboardData.items; let imageFound = false; for (let i = 0; i < items.length; i++) { if (items[i].type.indexOf('image') !== -1) { imageFound = true; const blob = items[i].getAsFile(); // 显示预览 const reader = new FileReader(); reader.onload = (e) => { preview.src = e.target.result; previewContainer.style.display = 'block'; }; reader.readAsDataURL(blob); status.textContent = '正在上传截图...'; result.style.display = 'none'; progress.style.display = 'block'; progressBar.style.width = '30%'; try { const formData = new FormData(); formData.append('image', blob); formData.append('outputFormat', 'auto'); const xhr = new XMLHttpRequest(); xhr.open('POST', 'https://img.scdn.io/api/v1.php', true); xhr.upload.onprogress = (e) => { if (e.lengthComputable) { const percent = Math.round((e.loaded / e.total) * 100); progressBar.style.width = percent + '%'; } }; xhr.onload = () => { if (xhr.status === 200) { const data = JSON.parse(xhr.responseText); if (data.success) { const imgUrl = `[${data.url}]`; result.textContent = imgUrl; result.style.display = 'block'; status.textContent = '上传成功!'; progressBar.style.width = '100%'; setTimeout(() => { progress.style.display = 'none'; }, 500); } else { status.textContent = '上传失败: ' + (data.message || '未知错误'); progress.style.display = 'none'; } } else { status.textContent = '上传出错: 服务器返回状态 ' + xhr.status; progress.style.display = 'none'; } }; xhr.onerror = () => { status.textContent = '上传出错: 网络错误'; progress.style.display = 'none'; }; xhr.send(formData); } catch (error) { console.error('上传错误:', error); status.textContent = '上传出错: ' + error.message; progress.style.display = 'none'; } break; } } if (!imageFound) { status.textContent = '剪贴板中没有找到图片'; setTimeout(() => { status.textContent = ''; }, 2000); } }); // 使面板可聚焦 panel.tabIndex = -1; // // 显示通知 // function showNotification(title, text) { // GM_notification({ // title: title, // text: text, // timeout: 2000, // silent: true // }); // } return container } function chatPicTool() { const chatBtn = document.querySelector('.cute-chat-button.fixed\\!.z-50.bottom-6.right-6.md\\:bottom-8.md\\:right-8') if (!chatBtn) { setTimeout(() => { chatPicTool() }, 500); return } chatBtn.addEventListener('click', function () { setTimeout(() => { const chatInput = document.querySelector('.el-input.el-input--large.flex-1') let picUpdateContainer = document.getElementById('picUpdateContainer') if (chatInput && !picUpdateContainer && !chatInput.dataset?.processed) { chatInput.dataset.processed = true picUpdateContainer = createPicUpdateUI() picUpdateContainer.id = 'picUpdateContainer' chatInput.parentNode.appendChild(picUpdateContainer, chatInput.nextSibling); } }, 500); }); } function satietyShowTool() { const mainBar = document.querySelector('.el-icon.menu-icon') if (!mainBar) { setTimeout(() => { satietyShowTool() }, 500); return } mainBar.parentNode.addEventListener('click', function () { tryUpdateSatietyShowCount = 0 setTimeout(updateSatietyShow, 500); }); tryUpdateSatietyShowCount = 0 setTimeout(updateSatietyShow, 500); } let tryUpdateSatietyShowCount = 0 function tryUpdateSatietyShow(data) { tryUpdateSatietyShowCount = 0 setTimeout(() => updateSatietyShow(data), 500); } let tryUpdateSatietyShowing = false function updateSatietyShow(data) { if (tryUpdateSatietyShowing) { return } tryUpdateSatietyShowing = true tryUpdateSatietyShowCount++ const userTaskCadrsNode = document.querySelector('.bg-gradient-to-br.from-white') if (!userTaskCadrsNode) { if (tryUpdateSatietyShowCount < 10) { setTimeout(updateSatietyShow, 500); } tryUpdateSatietyShowing = false return } const totalSatietyShow = userTaskCadrsNode.querySelector('.min-w-0.flex-1 > .text-sm.font-semibold.text-red-600.dark\\:text-red-400'); if (!totalSatietyShow) { if (tryUpdateSatietyShowCount < 10) { setTimeout(updateSatietyShow, 500); } tryUpdateSatietyShowing = false return } let totalSatiety = totalSatietyShow.innerText?.trim()?.split('/')[1] if (!totalSatiety) { if (tryUpdateSatietyShowCount < 10) { setTimeout(updateSatietyShow, 500); } tryUpdateSatietyShowing = false return } const taskCards = userTaskCadrsNode.querySelectorAll('.group.relative.overflow-hidden.rounded-lg.border.transition-all.duration-300') let firstUseOut = true let lastEndTime = new Date() for (let i = 0; i < taskCards.length; i++) { const taskCard = taskCards[i]; const taskInfo = data[i] || { actionId: "", createTime: 0, currentRepeat: 0, hasDeductFirstTaskResource: false, lastSubtaskDoneTime: 0, pastTimeAboutLastSubtask: 0, repeatCount: 0 } const satietyShow = taskCard.querySelector('.flex.items-center.space-x-2.text-xs.text-gray-500'); const satietyNode = satietyShow.childNodes[0] const satiety = parseInt(removeEmoji(satietyNode.textContent?.trim()), 0) //剩余饱食 const remaining = totalSatiety totalSatiety -= satiety const useOut = totalSatiety <= 0 const appendDiv = document.getElementById('totalSatiety-' + i) let originaltime; if (appendDiv) { originaltime = appendDiv.dataset.originaltime appendDiv.remove() } else { originaltime = satietyShow.childNodes[1].innerText } satietyNode.insertAdjacentHTML('afterend', `<span id='totalSatiety-${i}' data-originaltime="${originaltime}" class="text-xs text-gray-500 ${useOut ? 'text-red-400' : ''} ">(剩余 ${totalSatiety})</span>`) if (useOut) { if (firstUseOut) { firstUseOut = false const doTimes = taskInfo.repeatCount - taskInfo.currentRepeat satietyShow.childNodes[2].innerText = calculateAdjustedTime(originaltime, lastEndTime, remaining / satiety) } else { satietyShow.childNodes[2].innerText = '-----------------------' } } //结束时间 lastEndTime = originaltime } tryUpdateSatietyShowCount = 0 tryUpdateSatietyShowing = false } /** * 计算两个时间差值的60%并加到初始时间上 * @param {string} time1 - 带⏰的结束时间字符串 * @param {string} time2 - 带⏰的开始时间字符串 * @returns {string} 计算后的时间字符串(带⏰) */ function calculateAdjustedTime(time1, time2, percentage) { try { // 解析时间字符串为Date对象 const date1 = new Date(removeEmoji(time1)); const date2 = new Date(removeEmoji(time2)); // 计算时间差(毫秒)并转换为秒 const timeDiffMs = date1 - date2; const timeDiffSeconds = timeDiffMs / 1000; // 计算差值的60%(秒) const adjustmentSeconds = timeDiffSeconds * percentage; // 计算调整后的时间(毫秒) const adjustedTimeMs = date2.getTime() + adjustmentSeconds * 1000; // 格式化结果为指定字符串格式 const adjustedDate = new Date(adjustedTimeMs); const year = adjustedDate.getFullYear(); const month = String(adjustedDate.getMonth() + 1).padStart(2, '0'); const day = String(adjustedDate.getDate()).padStart(2, '0'); const hours = String(adjustedDate.getHours()).padStart(2, '0'); const minutes = String(adjustedDate.getMinutes()).padStart(2, '0'); const seconds = String(adjustedDate.getSeconds()).padStart(2, '0'); return `⏰ ${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; } catch (error) { console.error('时间计算出错:', error); return ''; } } // ws ================================================================================= // ================================================================================= // == 核心:WebSocket 拦截器 (原型链拦截) // ================================================================================= // 全局WebSocket实例引用 let currentSocket = null; let userInfo = null; let wsRespondMsgStatus = { titel: '', wait: false, //是否等待 netx: false //是否下一条消息 }; const wsRespondFuns = { 'dispatchCharacterStatusInfo': menusAddUserExpInfo, 'dispatchTaskQueueToClient': tryUpdateSatietyShow, 'newMarket:getUnifiedTransactionList:success': updateMarketPrices }; function initWs() { console.log('妙妙工具 初始化WebSocket...'); const wsProto = WebSocket.prototype; // 存储所有活跃连接 const activeSockets = new Set(); // 判断当前对象是否为真正的WebSocket实例 function isRealWebSocket(obj) { // 双重校验:类型和构造函数,避免原型链污染导致的误判 return obj instanceof WebSocket && obj.constructor === WebSocket && !activeSockets.has(obj); // 避免重复处理; } // 1. 拦截构造函数(关键新增) const OriginalWebSocket = window.WebSocket; unsafeWindow.WebSocket = function (...args) { const ws = new OriginalWebSocket(...args); activeSockets.add(ws); setupSocketCleanup(ws); // 设置清理钩子 return ws; }; // 2. 连接清理函数 function setupSocketCleanup(ws) { const originalClose = ws.close; ws.close = function (...args) { activeSockets.delete(ws); return originalClose.apply(this, args); }; ws.addEventListener('close', () => { activeSockets.delete(ws); currentSocket = null; }); } // 3. 页面刷新时的清理(新增) unsafeWindow.addEventListener('beforeunload', () => { for (let ws of activeSockets) { try { ws.close(1000, 'page reload'); } catch (e) { } } }); // 1. 拦截 send 方法 const originalSend = wsProto.send; wsProto.send = function (data) { if (!isRealWebSocket(this)) { return originalSend.apply(this, arguments); // 非WebSocket实例直接放行 } currentSocket = this; handleSendMessage(data); return originalSend.apply(this, arguments); }; // 2. 拦截 onmessage let onmessageDescriptor = Object.getOwnPropertyDescriptor(wsProto, 'onmessage'); if (!onmessageDescriptor || typeof onmessageDescriptor.set !== 'function') { const onmessageStore = new WeakMap(); onmessageDescriptor = { get() { return onmessageStore.get(this); }, set(callback) { onmessageStore.set(this, callback); } }; } Object.defineProperty(wsProto, 'onmessage', { ...onmessageDescriptor, set: function (callback) { if (!isRealWebSocket(this)) { return onmessageDescriptor.set.call(this, callback); // 非WebSocket实例直接放行 } const ws = this; currentSocket = ws; const wrapped = (event) => { handleReceivedMessage(event.data, ws); if (typeof callback === 'function') { callback.call(ws, event); } }; onmessageDescriptor.set.call(this, wrapped); } }); // 3. 拦截 addEventListener const originalAddEventListener = wsProto.addEventListener; wsProto.addEventListener = function (type, listener, options) { if (!isRealWebSocket(this)) { return originalAddEventListener.call(this, type, listener, options); // 非WebSocket实例直接放行 } if (type === 'message') { const ws = this; currentSocket = ws; const wrappedListener = (event) => { handleReceivedMessage(event.data, ws); listener.call(ws, event); }; return originalAddEventListener.call(this, type, wrappedListener, options); } return originalAddEventListener.call(this, type, listener, options); }; console.log('妙妙工具 WebSocket拦截初始化完成'); } // —— 消息处理核心函数 —— /** * 处理发送的WebSocket消息 * @param {string|ArrayBuffer} data - 发送的消息数据 */ function handleSendMessage(data) { if (WS_DEBUG_MODE) { console.log('%c[WS发送]', 'color: #03A9F4; font-weight: bold;', data); } if (!userInfo) { userInfo = getUserInfo(data); } // 可在此处添加发送消息的自定义处理逻辑 } // —— 解析用户数据 —— function getUserInfo(data) { try { if (typeof data === 'string' && data.length > 2) { const payload = JSON.parse(data.substring(2, data.length)); if (payload[1] && payload[1]['user'] && payload[1]['user']['name']) { return payload[1]['user']; } } } catch (e) { // 解析失败,忽略 } return null; } /** * 处理接收的WebSocket消息 * @param {string|ArrayBuffer} messageData - 接收的消息数据 * @param {WebSocket} ws - WebSocket实例 */ function handleReceivedMessage(messageData, ws) { if (messageData instanceof ArrayBuffer) { try { // 检测压缩格式并解压 const format = detectCompression(messageData); const text = pako.inflate(new Uint8Array(messageData), { to: 'string' }); let parsed; let isJson = false; try { parsed = JSON.parse(text); isJson = true; } catch { parsed = text; } if (WS_DEBUG_MODE) { console.log('%c[WS 已发送]', 'color: #2196F3; font-weight: bold;', `(已压缩 ${format} ${isJson ? 'json' : ''})`, parsed); } // 可在此处添加接收消息的自定义处理逻辑 // 例如:解析特定消息类型、触发自定义事件等 if (wsRespondMsgStatus.netx) { wsRespondMsgStatus.netx = false; wsRespondMsgStatus.wait = false; const fun = wsRespondFuns[wsRespondMsgStatus.titel] if (fun && typeof fun === 'function') { fun(parsed.data) } wsRespondMsgStatus.titel = '' } } catch (err) { if (WS_DEBUG_MODE) { console.error('%c[WS错误]', 'color: #f44336;', '消息解压失败:', err); } } } else { // 文本消息直接打印 if (WS_DEBUG_MODE) { console.log('%c[WS接收]', 'color: #4CAF50; font-weight: bold;', '(文本消息)', messageData); } let listIndex = messageData.indexOf('[') let mapIndex = messageData.indexOf('{') messageData = messageData.substring(listIndex > mapIndex ? mapIndex : listIndex) try { const payload = JSON.parse(messageData); if (wsRespondFuns[payload[0]]) { wsRespondMsgStatus.wait = true; wsRespondMsgStatus.titel = payload[0]; wsRespondMsgStatus.netx = true } } catch (e) { // } } } /** * 检测数据压缩格式 * @param {ArrayBuffer} buf - 二进制数据 * @returns {string} 压缩格式 ('gzip'|'zlib'|'deflate') */ function detectCompression(buf) { const b = new Uint8Array(buf); if (b.length < 2) return 'deflate'; if (b[0] === 0x1f && b[1] === 0x8b) return 'gzip'; if (b[0] === 0x78 && (((b[0] << 8) | b[1]) % 31) === 0) return 'zlib'; return 'deflate'; } // —— 自定义发送消息接口 —— // 等待任务列表返回 async function waitTaskListCallback() { const now = Date.now(); while (Date.now() - now < waitForMsg && wsRespondMsgStatus.wait) { await sleep(100); } if (wsRespondMsgStatus.wait) { wsRespondMsgStatus.wait = false; wsRespondMsgStatus.netx = false; return false; } wsRespondMsgStatus.wait = false; wsRespondMsgStatus.netx = false; return true }; // 刷新物品价格 function sendGetItemPriceMessage(itemName) { if (!itemName) { return; } console.log('妙妙工具 发送刷新物品价格消息', itemName) const msg = `42["newMarket:getUnifiedTransactionList",{"user":${JSON.stringify(userInfo)},"data":{"resourceId":"${itemName}"}}]` sendCustomWsMessage(msg) } // —— 自定义发送消息接口 —— /** * 发送自定义WebSocket消息 * @param {string|object} data - 要发送的消息数据(对象会自动转为JSON字符串) * @param {string} [type='custom'] - 消息类型标识 * @returns {boolean} 是否发送成功 */ function sendCustomWsMessage(message) { if (!currentSocket || currentSocket.readyState !== WebSocket.OPEN) { console.error('%c[WS发送失败]', 'color: #f44336;', 'WebSocket未连接或已关闭'); return false; } try { currentSocket.send(message); //console.log('%c[自定义发送]', 'color: #FF9800; font-weight: bold;', message); return true; } catch (error) { console.error('%c[自定义发送失败]', 'color: #f44336;', error); return false; } }; initWs() window.addEventListener('load', function () { // 延迟创建以确保页面完全加载 setTimeout(() => { // 1. 日利节点 dailyNodeObserver() // 2. 仓库点击展示价格 watchWarehouseEntry() // 3. 聊天图片 chatPicTool() // 4.饱食度 使用socket触发 //satietyShowTool() }, 1200); }); })(); window.addEventListener("moyu-socket-event", (e) => { monitorMarketMessage(e.detail); });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址