mooket

银河奶牛历史价格(包含强化物品)history(enhancement included) price for milkywayidle

  1. // ==UserScript==
  2. // @name mooket
  3. // @namespace http://tampermonkey.net/
  4. // @version 20250621.1.0
  5. // @description 银河奶牛历史价格(包含强化物品)history(enhancement included) price for milkywayidle
  6. // @author IOMisaka
  7. // @match https://www.milkywayidle.com/*
  8. // @icon https://www.milkywayidle.com/favicon.svg
  9. // @grant none
  10. // @require https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js
  11. // @require https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0/dist/chartjs-adapter-date-fns.bundle.min.js
  12. // @require https://cdn.jsdelivr.net/npm/chartjs-plugin-crosshair@2.0.0/dist/chartjs-plugin-crosshair.min.js
  13. // @run-at document-start
  14. // @license MIT
  15. // ==/UserScript==
  16.  
  17. (function () {
  18. 'use strict';
  19. let injectSpace = "mwi";//use window.mwi to access the injected object
  20. if (window[injectSpace]) return;//已经注入
  21. //优先注册(不可用)ob
  22. new MutationObserver((mutationsList, obs) => {
  23. mutationsList.forEach((mutationRecord) => {
  24. for (const node of mutationRecord.addedNodes) {
  25. if (node.src) {
  26. console.log(node.src);
  27. if (node.src.search(/.*main\..*\.chunk.js/) === 0) {
  28. console.info("patching:" + node.src)
  29. obs.disconnect();
  30. patchScript(node);
  31. }
  32. }
  33. }
  34. });
  35. }).observe(document, { childList: true, subtree: true });
  36. let mwi = {//供外部调用的接口
  37. //由于脚本加载问题,注入有可能失败
  38. //修改了hookCallback,添加了回调前和回调后处理
  39. version: "0.6.0",//版本号,未改动原有接口只更新最后一个版本号,更改了接口会更改次版本号,主版本暂时不更新,等稳定之后再考虑主版本号更新
  40. MWICoreInitialized: false,//是否初始化完成,完成会还会通过window发送一个自定义事件 MWICoreInitialized
  41. game: null,//注入游戏对象,可以直接访问游戏中的大量数据和方法以及消息事件等
  42. lang: null,//语言翻译, 例如中文物品lang.zh.translation.itemNames['/items/coin']
  43. buffCalculator: null,//注入buff计算对象buffCalculator.mergeBuffs()合并buffs,计算加成效果等
  44. alchemyCalculator: null,//注入炼金计算对象
  45.  
  46. //////非注入接口,保证可以使用的功能//////
  47. ///需要等待加载完成才能使用
  48.  
  49. coreMarket: null,//coreMarket.marketData 格式{"/items/apple_yogurt:0":{ask,bid,time}}
  50. initCharacterData: null,
  51. initClientData: null,
  52. get character() { return this.game?.state?.character || this.initCharacterData?.character },
  53.  
  54. ///不需要等待加载的
  55.  
  56. isZh: true,//是否中文
  57. /* marketJson兼容接口 */
  58. get marketJsonOld() {
  59. return this.coreMarket && new Proxy(this.coreMarket, {
  60. get(coreMarket, prop) {
  61. if (prop === "market") {
  62. return new Proxy(coreMarket, {
  63. get(coreMarket, itemHridOrName) {
  64. return coreMarket.getItemPrice(itemHridOrName);
  65. }
  66. });
  67. }
  68. return null;
  69. }
  70.  
  71. });
  72. },
  73. get marketJson() {
  74. return mwi.coreMarket && new Proxy({}, {
  75. get(_, marketData) {
  76. if (marketData === "marketData")
  77. return new Proxy({}, {
  78. get(_, itemHridOrName) {
  79. return new Proxy({}, {
  80. get(_, itemLevel) {
  81. return new Proxy({}, {
  82. get(_, objProp) {
  83. switch (objProp) {
  84. case "a": {
  85. return mwi.coreMarket?.getItemPrice(itemHridOrName, itemLevel)?.ask;
  86. }
  87. case "b": {
  88. return mwi.coreMarket?.getItemPrice(itemHridOrName, itemLevel)?.bid;
  89. }
  90. case "time": {
  91. return mwi.coreMarket?.getItemPrice(itemHridOrName, itemLevel)?.time;
  92. }
  93. }
  94. return -1;
  95. }
  96. })
  97. }
  98. })
  99. }
  100. })
  101. }
  102. })
  103. },
  104.  
  105. itemNameToHridDict: null,//物品名称反查表
  106.  
  107.  
  108. ensureItemHrid: function (itemHridOrName) {
  109. let itemHrid = this.itemNameToHridDict[itemHridOrName];
  110. if (itemHrid) return itemHrid;
  111. if (itemHridOrName?.startsWith("/items/")) return itemHridOrName;
  112. return null;
  113. },//各种名字转itemHrid,找不到返回原itemHrid或者null
  114. getItemDetail: function (itemHrid) {
  115. return this.initClientData?.itemDetailMap && this.initClientData.itemDetailMap[itemHrid];
  116. },
  117. hookMessage: hookMessage,//hook 游戏websocket消息 例如聊天消息mwi.hookMessage("chat_message_received",obj=>{console.log(obj)})
  118. hookCallback: hookCallback,//hook回调,可以hook游戏处理事件调用前后,方便做统计处理? 例如聊天消息mwi.hookCallback("handleMessageChatMessageReceived",obj=>{console.log("before")},obj=>{console.log("after")})
  119. fetchWithTimeout: fetchWithTimeout,//带超时的fetch
  120. };
  121. window[injectSpace] = mwi;
  122.  
  123. mwi.initClientData = JSON.parse(localStorage.getItem("initClientData") || "{}");
  124. mwi.isZh = localStorage.getItem("i18nextLng")?.startsWith("zh");
  125.  
  126. const originalSetItem = localStorage.setItem;
  127. localStorage.setItem = function (key, value) {
  128. const event = new Event('localStorageChanged');
  129. event.key = key;
  130. event.newValue = value;
  131. event.oldValue = localStorage.getItem(key);
  132. originalSetItem.apply(this, arguments);
  133. dispatchEvent(event);
  134.  
  135. };
  136.  
  137. addEventListener('localStorageChanged', function (event) {
  138. if (event.key === "i18nextLng") {
  139. console.log(`i18nextLng changed: ${event.key} = ${event.newValue}`);
  140. mwi.isZh = event.newValue?.startsWith("zh");
  141. dispatchEvent(new Event("MWILangChanged"));
  142. }
  143. });
  144. async function patchScript(node) {
  145. try {
  146. const scriptUrl = node.src;
  147. node.remove();
  148. const response = await fetch(scriptUrl);
  149. if (!response.ok) throw new Error(`Failed to fetch script: ${response.status}`);
  150.  
  151. let sourceCode = await response.text();
  152.  
  153. // Define injection points as configurable patterns
  154. const injectionPoints = [
  155. {
  156. pattern: "Ca.a.use",
  157. replacement: `window.${injectSpace}.lang=Oa;Ca.a.use`,
  158. description: "注入语言翻译对象"
  159. },
  160. {
  161. pattern: "this.sendPing=",
  162. replacement: `window.${injectSpace}.game=this,this.sendPing=`,
  163. description: "注入游戏对象"
  164.  
  165. },
  166. {
  167. pattern: "var Q=W;",
  168. replacement: `window.${injectSpace}.buffCalculator=W;var Q=W;`,
  169. description: "注入buff计算对象"
  170. },
  171. {
  172. pattern: "class Rn",
  173. replacement: `window.${injectSpace}.alchemyCalculator=Ln;class Rn`,
  174. description: "注入炼金计算对象"
  175. }
  176. ];
  177.  
  178. injectionPoints.forEach(({ pattern, replacement, description }) => {
  179. if (sourceCode.includes(pattern)) {
  180. sourceCode = sourceCode.replace(pattern, replacement);
  181. console.info(`MWICore injecting: ${description}`);
  182. } else {
  183. console.warn(`MWICore injecting failed: ${description}`);
  184. }
  185. });
  186.  
  187. const newNode = document.createElement('script');
  188. newNode.textContent = sourceCode;
  189. document.body.appendChild(newNode);
  190. console.info('MWICore patched successfully.')
  191. } catch (error) {
  192. console.error('MWICore patching failed:', error);
  193. }
  194. }
  195.  
  196.  
  197. function hookWS() {
  198. const dataProperty = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
  199. const oriGet = dataProperty.get;
  200. dataProperty.get = hookedGet;
  201. Object.defineProperty(MessageEvent.prototype, "data", dataProperty);
  202.  
  203. function hookedGet() {
  204. const socket = this.currentTarget;
  205. if (!(socket instanceof WebSocket)) {
  206. return oriGet.call(this);
  207. }
  208. if (socket.url.indexOf("api.milkywayidle.com/ws") <= -1) {
  209. return oriGet.call(this);
  210. }
  211. const message = oriGet.call(this);
  212. Object.defineProperty(this, "data", { value: message }); // Anti-loop
  213.  
  214. try {
  215. let obj = JSON.parse(message);
  216. if (obj?.type) {
  217. if (obj.type === "init_character_data") {
  218. mwi.initCharacterData = obj;
  219. } else if (obj.type === "init_client_data") {
  220. mwi.initClientData = obj;
  221. }
  222.  
  223. dispatchEvent(new CustomEvent("MWI_" + obj.type, { detail: obj }));
  224. }
  225. } catch { console.error("dispatch error."); }
  226.  
  227. return message;
  228. }
  229. }
  230. hookWS();
  231. /**
  232. * Hook游戏消息在处理之前,随时可用
  233. * @param {string} message.type 消息类型,ws钩子,必定可用,仅在游戏处理之前调用beforeFunc
  234. * @param {Function} beforeFunc 前处理函数
  235. */
  236. function hookMessage(messageType, beforeFunc) {
  237. if (messageType && beforeFunc) {
  238. //游戏websocket消息hook
  239. addEventListener("MWI_" + messageType, (e) => beforeFunc(e.detail));
  240. } else {
  241. console.warn("messageType or beforeFunc is missing");
  242. }
  243. }
  244. /**
  245. * Hook游戏回调函数,仅在游戏注入成功时可用,会调用beforeFunc和afterFunc
  246. * @param {string} callbackProp 游戏处理回调函数名mwi.game.handleMessage*,仅当注入成功时可用,会调用beforeFunc和afterFunc
  247. * @param {Function} beforeFunc 前处理函数
  248. * @param {Function} afterFunc 后处理函数
  249. */
  250. function hookCallback(callbackProp, beforeFunc, afterFunc) {
  251. if (callbackProp && mwi?.game) {//优先使用游戏回调hook
  252. const targetObj = mwi.game;
  253. const originalCallback = targetObj[callbackProp];
  254.  
  255. if (!originalCallback || !targetObj) {
  256. throw new Error(`Callback ${callbackProp} does not exist`);
  257. }
  258.  
  259. targetObj[callbackProp] = function (...args) {
  260. // 前处理
  261. try {
  262. if (beforeFunc) beforeFunc(...args);
  263. } catch { }
  264. // 原始回调函数调用
  265. const result = originalCallback.apply(this, args);
  266. // 后处理
  267. try {
  268. if (afterFunc) afterFunc(result, ...args);
  269. } catch { }
  270. return result;
  271. };
  272.  
  273. // 返回取消Hook的方法
  274. return () => {
  275. targetObj[callbackProp] = originalCallback;
  276. };
  277. } else {
  278. console.warn("hookCallback error");
  279. }
  280. }
  281. /**
  282. * 带超时功能的fetch封装
  283. * @param {string} url - 请求URL
  284. * @param {object} options - fetch选项
  285. * @param {number} timeout - 超时时间(毫秒),默认10秒
  286. * @returns {Promise} - 返回fetch的Promise
  287. */
  288. function fetchWithTimeout(url, options = {}, timeout = 10000) {
  289. // 创建AbortController实例
  290. const controller = new AbortController();
  291. const { signal } = controller;
  292.  
  293. // 设置超时计时器
  294. const timeoutId = setTimeout(() => {
  295. controller.abort(new Error(`请求超时: ${timeout}ms`));
  296. }, timeout);
  297.  
  298. // 合并选项,添加signal
  299. const fetchOptions = {
  300. ...options,
  301. signal
  302. };
  303.  
  304. // 发起fetch请求
  305. return fetch(url, fetchOptions)
  306. .then(response => {
  307. // 清除超时计时器
  308. clearTimeout(timeoutId);
  309.  
  310. if (!response.ok) {
  311. throw new Error(`HTTP错误! 状态码: ${response.status}`);
  312. }
  313. return response;
  314. })
  315. .catch(error => {
  316. // 清除超时计时器
  317. clearTimeout(timeoutId);
  318.  
  319. // 如果是中止错误,重新抛出超时错误
  320. if (error.name === 'AbortError') {
  321. throw new Error(`请求超时: ${timeout}ms`);
  322. }
  323. throw error;
  324. });
  325. }
  326. function staticInit() {
  327. /*静态初始化,手动提取的游戏数据*/
  328. mwi.lang = {
  329. en: {
  330. translation: {
  331. ...{
  332. itemNames: {
  333. '/items/coin': 'Coin',
  334. '/items/task_token': 'Task Token',
  335. '/items/chimerical_token': 'Chimerical Token',
  336. '/items/sinister_token': 'Sinister Token',
  337. '/items/enchanted_token': 'Enchanted Token',
  338. '/items/pirate_token': 'Pirate Token',
  339. '/items/cowbell': 'Cowbell',
  340. '/items/bag_of_10_cowbells': 'Bag Of 10 Cowbells',
  341. '/items/purples_gift': 'Purple\'s Gift',
  342. '/items/small_meteorite_cache': 'Small Meteorite Cache',
  343. '/items/medium_meteorite_cache': 'Medium Meteorite Cache',
  344. '/items/large_meteorite_cache': 'Large Meteorite Cache',
  345. '/items/small_artisans_crate': 'Small Artisan\'s Crate',
  346. '/items/medium_artisans_crate': 'Medium Artisan\'s Crate',
  347. '/items/large_artisans_crate': 'Large Artisan\'s Crate',
  348. '/items/small_treasure_chest': 'Small Treasure Chest',
  349. '/items/medium_treasure_chest': 'Medium Treasure Chest',
  350. '/items/large_treasure_chest': 'Large Treasure Chest',
  351. '/items/chimerical_chest': 'Chimerical Chest',
  352. '/items/sinister_chest': 'Sinister Chest',
  353. '/items/enchanted_chest': 'Enchanted Chest',
  354. '/items/pirate_chest': 'Pirate Chest',
  355. '/items/blue_key_fragment': 'Blue Key Fragment',
  356. '/items/green_key_fragment': 'Green Key Fragment',
  357. '/items/purple_key_fragment': 'Purple Key Fragment',
  358. '/items/white_key_fragment': 'White Key Fragment',
  359. '/items/orange_key_fragment': 'Orange Key Fragment',
  360. '/items/brown_key_fragment': 'Brown Key Fragment',
  361. '/items/stone_key_fragment': 'Stone Key Fragment',
  362. '/items/dark_key_fragment': 'Dark Key Fragment',
  363. '/items/burning_key_fragment': 'Burning Key Fragment',
  364. '/items/chimerical_entry_key': 'Chimerical Entry Key',
  365. '/items/chimerical_chest_key': 'Chimerical Chest Key',
  366. '/items/sinister_entry_key': 'Sinister Entry Key',
  367. '/items/sinister_chest_key': 'Sinister Chest Key',
  368. '/items/enchanted_entry_key': 'Enchanted Entry Key',
  369. '/items/enchanted_chest_key': 'Enchanted Chest Key',
  370. '/items/pirate_entry_key': 'Pirate Entry Key',
  371. '/items/pirate_chest_key': 'Pirate Chest Key',
  372. '/items/donut': 'Donut',
  373. '/items/blueberry_donut': 'Blueberry Donut',
  374. '/items/blackberry_donut': 'Blackberry Donut',
  375. '/items/strawberry_donut': 'Strawberry Donut',
  376. '/items/mooberry_donut': 'Mooberry Donut',
  377. '/items/marsberry_donut': 'Marsberry Donut',
  378. '/items/spaceberry_donut': 'Spaceberry Donut',
  379. '/items/cupcake': 'Cupcake',
  380. '/items/blueberry_cake': 'Blueberry Cake',
  381. '/items/blackberry_cake': 'Blackberry Cake',
  382. '/items/strawberry_cake': 'Strawberry Cake',
  383. '/items/mooberry_cake': 'Mooberry Cake',
  384. '/items/marsberry_cake': 'Marsberry Cake',
  385. '/items/spaceberry_cake': 'Spaceberry Cake',
  386. '/items/gummy': 'Gummy',
  387. '/items/apple_gummy': 'Apple Gummy',
  388. '/items/orange_gummy': 'Orange Gummy',
  389. '/items/plum_gummy': 'Plum Gummy',
  390. '/items/peach_gummy': 'Peach Gummy',
  391. '/items/dragon_fruit_gummy': 'Dragon Fruit Gummy',
  392. '/items/star_fruit_gummy': 'Star Fruit Gummy',
  393. '/items/yogurt': 'Yogurt',
  394. '/items/apple_yogurt': 'Apple Yogurt',
  395. '/items/orange_yogurt': 'Orange Yogurt',
  396. '/items/plum_yogurt': 'Plum Yogurt',
  397. '/items/peach_yogurt': 'Peach Yogurt',
  398. '/items/dragon_fruit_yogurt': 'Dragon Fruit Yogurt',
  399. '/items/star_fruit_yogurt': 'Star Fruit Yogurt',
  400. '/items/milking_tea': 'Milking Tea',
  401. '/items/foraging_tea': 'Foraging Tea',
  402. '/items/woodcutting_tea': 'Woodcutting Tea',
  403. '/items/cooking_tea': 'Cooking Tea',
  404. '/items/brewing_tea': 'Brewing Tea',
  405. '/items/alchemy_tea': 'Alchemy Tea',
  406. '/items/enhancing_tea': 'Enhancing Tea',
  407. '/items/cheesesmithing_tea': 'Cheesesmithing Tea',
  408. '/items/crafting_tea': 'Crafting Tea',
  409. '/items/tailoring_tea': 'Tailoring Tea',
  410. '/items/super_milking_tea': 'Super Milking Tea',
  411. '/items/super_foraging_tea': 'Super Foraging Tea',
  412. '/items/super_woodcutting_tea': 'Super Woodcutting Tea',
  413. '/items/super_cooking_tea': 'Super Cooking Tea',
  414. '/items/super_brewing_tea': 'Super Brewing Tea',
  415. '/items/super_alchemy_tea': 'Super Alchemy Tea',
  416. '/items/super_enhancing_tea': 'Super Enhancing Tea',
  417. '/items/super_cheesesmithing_tea': 'Super Cheesesmithing Tea',
  418. '/items/super_crafting_tea': 'Super Crafting Tea',
  419. '/items/super_tailoring_tea': 'Super Tailoring Tea',
  420. '/items/ultra_milking_tea': 'Ultra Milking Tea',
  421. '/items/ultra_foraging_tea': 'Ultra Foraging Tea',
  422. '/items/ultra_woodcutting_tea': 'Ultra Woodcutting Tea',
  423. '/items/ultra_cooking_tea': 'Ultra Cooking Tea',
  424. '/items/ultra_brewing_tea': 'Ultra Brewing Tea',
  425. '/items/ultra_alchemy_tea': 'Ultra Alchemy Tea',
  426. '/items/ultra_enhancing_tea': 'Ultra Enhancing Tea',
  427. '/items/ultra_cheesesmithing_tea': 'Ultra Cheesesmithing Tea',
  428. '/items/ultra_crafting_tea': 'Ultra Crafting Tea',
  429. '/items/ultra_tailoring_tea': 'Ultra Tailoring Tea',
  430. '/items/gathering_tea': 'Gathering Tea',
  431. '/items/gourmet_tea': 'Gourmet Tea',
  432. '/items/wisdom_tea': 'Wisdom Tea',
  433. '/items/processing_tea': 'Processing Tea',
  434. '/items/efficiency_tea': 'Efficiency Tea',
  435. '/items/artisan_tea': 'Artisan Tea',
  436. '/items/catalytic_tea': 'Catalytic Tea',
  437. '/items/blessed_tea': 'Blessed Tea',
  438. '/items/stamina_coffee': 'Stamina Coffee',
  439. '/items/intelligence_coffee': 'Intelligence Coffee',
  440. '/items/defense_coffee': 'Defense Coffee',
  441. '/items/attack_coffee': 'Attack Coffee',
  442. '/items/power_coffee': 'Power Coffee',
  443. '/items/ranged_coffee': 'Ranged Coffee',
  444. '/items/magic_coffee': 'Magic Coffee',
  445. '/items/super_stamina_coffee': 'Super Stamina Coffee',
  446. '/items/super_intelligence_coffee': 'Super Intelligence Coffee',
  447. '/items/super_defense_coffee': 'Super Defense Coffee',
  448. '/items/super_attack_coffee': 'Super Attack Coffee',
  449. '/items/super_power_coffee': 'Super Power Coffee',
  450. '/items/super_ranged_coffee': 'Super Ranged Coffee',
  451. '/items/super_magic_coffee': 'Super Magic Coffee',
  452. '/items/ultra_stamina_coffee': 'Ultra Stamina Coffee',
  453. '/items/ultra_intelligence_coffee': 'Ultra Intelligence Coffee',
  454. '/items/ultra_defense_coffee': 'Ultra Defense Coffee',
  455. '/items/ultra_attack_coffee': 'Ultra Attack Coffee',
  456. '/items/ultra_power_coffee': 'Ultra Power Coffee',
  457. '/items/ultra_ranged_coffee': 'Ultra Ranged Coffee',
  458. '/items/ultra_magic_coffee': 'Ultra Magic Coffee',
  459. '/items/wisdom_coffee': 'Wisdom Coffee',
  460. '/items/lucky_coffee': 'Lucky Coffee',
  461. '/items/swiftness_coffee': 'Swiftness Coffee',
  462. '/items/channeling_coffee': 'Channeling Coffee',
  463. '/items/critical_coffee': 'Critical Coffee',
  464. '/items/poke': 'Poke',
  465. '/items/impale': 'Impale',
  466. '/items/puncture': 'Puncture',
  467. '/items/penetrating_strike': 'Penetrating Strike',
  468. '/items/scratch': 'Scratch',
  469. '/items/cleave': 'Cleave',
  470. '/items/maim': 'Maim',
  471. '/items/crippling_slash': 'Crippling Slash',
  472. '/items/smack': 'Smack',
  473. '/items/sweep': 'Sweep',
  474. '/items/stunning_blow': 'Stunning Blow',
  475. '/items/fracturing_impact': 'Fracturing Impact',
  476. '/items/shield_bash': 'Shield Bash',
  477. '/items/quick_shot': 'Quick Shot',
  478. '/items/aqua_arrow': 'Aqua Arrow',
  479. '/items/flame_arrow': 'Flame Arrow',
  480. '/items/rain_of_arrows': 'Rain Of Arrows',
  481. '/items/silencing_shot': 'Silencing Shot',
  482. '/items/steady_shot': 'Steady Shot',
  483. '/items/pestilent_shot': 'Pestilent Shot',
  484. '/items/penetrating_shot': 'Penetrating Shot',
  485. '/items/water_strike': 'Water Strike',
  486. '/items/ice_spear': 'Ice Spear',
  487. '/items/frost_surge': 'Frost Surge',
  488. '/items/mana_spring': 'Mana Spring',
  489. '/items/entangle': 'Entangle',
  490. '/items/toxic_pollen': 'Toxic Pollen',
  491. '/items/natures_veil': 'Nature\'s Veil',
  492. '/items/life_drain': 'Life Drain',
  493. '/items/fireball': 'Fireball',
  494. '/items/flame_blast': 'Flame Blast',
  495. '/items/firestorm': 'Firestorm',
  496. '/items/smoke_burst': 'Smoke Burst',
  497. '/items/minor_heal': 'Minor Heal',
  498. '/items/heal': 'Heal',
  499. '/items/quick_aid': 'Quick Aid',
  500. '/items/rejuvenate': 'Rejuvenate',
  501. '/items/taunt': 'Taunt',
  502. '/items/provoke': 'Provoke',
  503. '/items/toughness': 'Toughness',
  504. '/items/elusiveness': 'Elusiveness',
  505. '/items/precision': 'Precision',
  506. '/items/berserk': 'Berserk',
  507. '/items/elemental_affinity': 'Elemental Affinity',
  508. '/items/frenzy': 'Frenzy',
  509. '/items/spike_shell': 'Spike Shell',
  510. '/items/arcane_reflection': 'Arcane Reflection',
  511. '/items/vampirism': 'Vampirism',
  512. '/items/revive': 'Revive',
  513. '/items/insanity': 'Insanity',
  514. '/items/invincible': 'Invincible',
  515. '/items/fierce_aura': 'Fierce Aura',
  516. '/items/aqua_aura': 'Aqua Aura',
  517. '/items/sylvan_aura': 'Sylvan Aura',
  518. '/items/flame_aura': 'Flame Aura',
  519. '/items/speed_aura': 'Speed Aura',
  520. '/items/critical_aura': 'Critical Aura',
  521. '/items/gobo_stabber': 'Gobo Stabber',
  522. '/items/gobo_slasher': 'Gobo Slasher',
  523. '/items/gobo_smasher': 'Gobo Smasher',
  524. '/items/spiked_bulwark': 'Spiked Bulwark',
  525. '/items/werewolf_slasher': 'Werewolf Slasher',
  526. '/items/griffin_bulwark': 'Griffin Bulwark',
  527. '/items/gobo_shooter': 'Gobo Shooter',
  528. '/items/vampiric_bow': 'Vampiric Bow',
  529. '/items/cursed_bow': 'Cursed Bow',
  530. '/items/gobo_boomstick': 'Gobo Boomstick',
  531. '/items/cheese_bulwark': 'Cheese Bulwark',
  532. '/items/verdant_bulwark': 'Verdant Bulwark',
  533. '/items/azure_bulwark': 'Azure Bulwark',
  534. '/items/burble_bulwark': 'Burble Bulwark',
  535. '/items/crimson_bulwark': 'Crimson Bulwark',
  536. '/items/rainbow_bulwark': 'Rainbow Bulwark',
  537. '/items/holy_bulwark': 'Holy Bulwark',
  538. '/items/wooden_bow': 'Wooden Bow',
  539. '/items/birch_bow': 'Birch Bow',
  540. '/items/cedar_bow': 'Cedar Bow',
  541. '/items/purpleheart_bow': 'Purpleheart Bow',
  542. '/items/ginkgo_bow': 'Ginkgo Bow',
  543. '/items/redwood_bow': 'Redwood Bow',
  544. '/items/arcane_bow': 'Arcane Bow',
  545. '/items/stalactite_spear': 'Stalactite Spear',
  546. '/items/granite_bludgeon': 'Granite Bludgeon',
  547. '/items/furious_spear': 'Furious Spear',
  548. '/items/regal_sword': 'Regal Sword',
  549. '/items/chaotic_flail': 'Chaotic Flail',
  550. '/items/soul_hunter_crossbow': 'Soul Hunter Crossbow',
  551. '/items/sundering_crossbow': 'Sundering Crossbow',
  552. '/items/frost_staff': 'Frost Staff',
  553. '/items/infernal_battlestaff': 'Infernal Battlestaff',
  554. '/items/jackalope_staff': 'Jackalope Staff',
  555. '/items/rippling_trident': 'Rippling Trident',
  556. '/items/blooming_trident': 'Blooming Trident',
  557. '/items/blazing_trident': 'Blazing Trident',
  558. '/items/cheese_sword': 'Cheese Sword',
  559. '/items/verdant_sword': 'Verdant Sword',
  560. '/items/azure_sword': 'Azure Sword',
  561. '/items/burble_sword': 'Burble Sword',
  562. '/items/crimson_sword': 'Crimson Sword',
  563. '/items/rainbow_sword': 'Rainbow Sword',
  564. '/items/holy_sword': 'Holy Sword',
  565. '/items/cheese_spear': 'Cheese Spear',
  566. '/items/verdant_spear': 'Verdant Spear',
  567. '/items/azure_spear': 'Azure Spear',
  568. '/items/burble_spear': 'Burble Spear',
  569. '/items/crimson_spear': 'Crimson Spear',
  570. '/items/rainbow_spear': 'Rainbow Spear',
  571. '/items/holy_spear': 'Holy Spear',
  572. '/items/cheese_mace': 'Cheese Mace',
  573. '/items/verdant_mace': 'Verdant Mace',
  574. '/items/azure_mace': 'Azure Mace',
  575. '/items/burble_mace': 'Burble Mace',
  576. '/items/crimson_mace': 'Crimson Mace',
  577. '/items/rainbow_mace': 'Rainbow Mace',
  578. '/items/holy_mace': 'Holy Mace',
  579. '/items/wooden_crossbow': 'Wooden Crossbow',
  580. '/items/birch_crossbow': 'Birch Crossbow',
  581. '/items/cedar_crossbow': 'Cedar Crossbow',
  582. '/items/purpleheart_crossbow': 'Purpleheart Crossbow',
  583. '/items/ginkgo_crossbow': 'Ginkgo Crossbow',
  584. '/items/redwood_crossbow': 'Redwood Crossbow',
  585. '/items/arcane_crossbow': 'Arcane Crossbow',
  586. '/items/wooden_water_staff': 'Wooden Water Staff',
  587. '/items/birch_water_staff': 'Birch Water Staff',
  588. '/items/cedar_water_staff': 'Cedar Water Staff',
  589. '/items/purpleheart_water_staff': 'Purpleheart Water Staff',
  590. '/items/ginkgo_water_staff': 'Ginkgo Water Staff',
  591. '/items/redwood_water_staff': 'Redwood Water Staff',
  592. '/items/arcane_water_staff': 'Arcane Water Staff',
  593. '/items/wooden_nature_staff': 'Wooden Nature Staff',
  594. '/items/birch_nature_staff': 'Birch Nature Staff',
  595. '/items/cedar_nature_staff': 'Cedar Nature Staff',
  596. '/items/purpleheart_nature_staff': 'Purpleheart Nature Staff',
  597. '/items/ginkgo_nature_staff': 'Ginkgo Nature Staff',
  598. '/items/redwood_nature_staff': 'Redwood Nature Staff',
  599. '/items/arcane_nature_staff': 'Arcane Nature Staff',
  600. '/items/wooden_fire_staff': 'Wooden Fire Staff',
  601. '/items/birch_fire_staff': 'Birch Fire Staff',
  602. '/items/cedar_fire_staff': 'Cedar Fire Staff',
  603. '/items/purpleheart_fire_staff': 'Purpleheart Fire Staff',
  604. '/items/ginkgo_fire_staff': 'Ginkgo Fire Staff',
  605. '/items/redwood_fire_staff': 'Redwood Fire Staff',
  606. '/items/arcane_fire_staff': 'Arcane Fire Staff',
  607. '/items/eye_watch': 'Eye Watch',
  608. '/items/snake_fang_dirk': 'Snake Fang Dirk',
  609. '/items/vision_shield': 'Vision Shield',
  610. '/items/gobo_defender': 'Gobo Defender',
  611. '/items/vampire_fang_dirk': 'Vampire Fang Dirk',
  612. '/items/knights_aegis': 'Knight\'s Aegis',
  613. '/items/treant_shield': 'Treant Shield',
  614. '/items/manticore_shield': 'Manticore Shield',
  615. '/items/tome_of_healing': 'Tome Of Healing',
  616. '/items/tome_of_the_elements': 'Tome Of The Elements',
  617. '/items/watchful_relic': 'Watchful Relic',
  618. '/items/bishops_codex': 'Bishop\'s Codex',
  619. '/items/cheese_buckler': 'Cheese Buckler',
  620. '/items/verdant_buckler': 'Verdant Buckler',
  621. '/items/azure_buckler': 'Azure Buckler',
  622. '/items/burble_buckler': 'Burble Buckler',
  623. '/items/crimson_buckler': 'Crimson Buckler',
  624. '/items/rainbow_buckler': 'Rainbow Buckler',
  625. '/items/holy_buckler': 'Holy Buckler',
  626. '/items/wooden_shield': 'Wooden Shield',
  627. '/items/birch_shield': 'Birch Shield',
  628. '/items/cedar_shield': 'Cedar Shield',
  629. '/items/purpleheart_shield': 'Purpleheart Shield',
  630. '/items/ginkgo_shield': 'Ginkgo Shield',
  631. '/items/redwood_shield': 'Redwood Shield',
  632. '/items/arcane_shield': 'Arcane Shield',
  633. '/items/sinister_cape': 'Sinister Cape',
  634. '/items/chimerical_quiver': 'Chimerical Quiver',
  635. '/items/enchanted_cloak': 'Enchanted Cloak',
  636. '/items/red_culinary_hat': 'Red Culinary Hat',
  637. '/items/snail_shell_helmet': 'Snail Shell Helmet',
  638. '/items/vision_helmet': 'Vision Helmet',
  639. '/items/fluffy_red_hat': 'Fluffy Red Hat',
  640. '/items/corsair_helmet': 'Corsair Helmet',
  641. '/items/acrobatic_hood': 'Acrobatic Hood',
  642. '/items/magicians_hat': 'Magician\'s Hat',
  643. '/items/cheese_helmet': 'Cheese Helmet',
  644. '/items/verdant_helmet': 'Verdant Helmet',
  645. '/items/azure_helmet': 'Azure Helmet',
  646. '/items/burble_helmet': 'Burble Helmet',
  647. '/items/crimson_helmet': 'Crimson Helmet',
  648. '/items/rainbow_helmet': 'Rainbow Helmet',
  649. '/items/holy_helmet': 'Holy Helmet',
  650. '/items/rough_hood': 'Rough Hood',
  651. '/items/reptile_hood': 'Reptile Hood',
  652. '/items/gobo_hood': 'Gobo Hood',
  653. '/items/beast_hood': 'Beast Hood',
  654. '/items/umbral_hood': 'Umbral Hood',
  655. '/items/cotton_hat': 'Cotton Hat',
  656. '/items/linen_hat': 'Linen Hat',
  657. '/items/bamboo_hat': 'Bamboo Hat',
  658. '/items/silk_hat': 'Silk Hat',
  659. '/items/radiant_hat': 'Radiant Hat',
  660. '/items/dairyhands_top': 'Dairyhand\'s Top',
  661. '/items/foragers_top': 'Forager\'s Top',
  662. '/items/lumberjacks_top': 'Lumberjack\'s Top',
  663. '/items/cheesemakers_top': 'Cheesemaker\'s Top',
  664. '/items/crafters_top': 'Crafter\'s Top',
  665. '/items/tailors_top': 'Tailor\'s Top',
  666. '/items/chefs_top': 'Chef\'s Top',
  667. '/items/brewers_top': 'Brewer\'s Top',
  668. '/items/alchemists_top': 'Alchemist\'s Top',
  669. '/items/enhancers_top': 'Enhancer\'s Top',
  670. '/items/gator_vest': 'Gator Vest',
  671. '/items/turtle_shell_body': 'Turtle Shell Body',
  672. '/items/colossus_plate_body': 'Colossus Plate Body',
  673. '/items/demonic_plate_body': 'Demonic Plate Body',
  674. '/items/anchorbound_plate_body': 'Anchorbound Plate Body',
  675. '/items/maelstrom_plate_body': 'Maelstrom Plate Body',
  676. '/items/marine_tunic': 'Marine Tunic',
  677. '/items/revenant_tunic': 'Revenant Tunic',
  678. '/items/griffin_tunic': 'Griffin Tunic',
  679. '/items/kraken_tunic': 'Kraken Tunic',
  680. '/items/icy_robe_top': 'Icy Robe Top',
  681. '/items/flaming_robe_top': 'Flaming Robe Top',
  682. '/items/luna_robe_top': 'Luna Robe Top',
  683. '/items/royal_water_robe_top': 'Royal Water Robe Top',
  684. '/items/royal_nature_robe_top': 'Royal Nature Robe Top',
  685. '/items/royal_fire_robe_top': 'Royal Fire Robe Top',
  686. '/items/cheese_plate_body': 'Cheese Plate Body',
  687. '/items/verdant_plate_body': 'Verdant Plate Body',
  688. '/items/azure_plate_body': 'Azure Plate Body',
  689. '/items/burble_plate_body': 'Burble Plate Body',
  690. '/items/crimson_plate_body': 'Crimson Plate Body',
  691. '/items/rainbow_plate_body': 'Rainbow Plate Body',
  692. '/items/holy_plate_body': 'Holy Plate Body',
  693. '/items/rough_tunic': 'Rough Tunic',
  694. '/items/reptile_tunic': 'Reptile Tunic',
  695. '/items/gobo_tunic': 'Gobo Tunic',
  696. '/items/beast_tunic': 'Beast Tunic',
  697. '/items/umbral_tunic': 'Umbral Tunic',
  698. '/items/cotton_robe_top': 'Cotton Robe Top',
  699. '/items/linen_robe_top': 'Linen Robe Top',
  700. '/items/bamboo_robe_top': 'Bamboo Robe Top',
  701. '/items/silk_robe_top': 'Silk Robe Top',
  702. '/items/radiant_robe_top': 'Radiant Robe Top',
  703. '/items/dairyhands_bottoms': 'Dairyhand\'s Bottoms',
  704. '/items/foragers_bottoms': 'Forager\'s Bottoms',
  705. '/items/lumberjacks_bottoms': 'Lumberjack\'s Bottoms',
  706. '/items/cheesemakers_bottoms': 'Cheesemaker\'s Bottoms',
  707. '/items/crafters_bottoms': 'Crafter\'s Bottoms',
  708. '/items/tailors_bottoms': 'Tailor\'s Bottoms',
  709. '/items/chefs_bottoms': 'Chef\'s Bottoms',
  710. '/items/brewers_bottoms': 'Brewer\'s Bottoms',
  711. '/items/alchemists_bottoms': 'Alchemist\'s Bottoms',
  712. '/items/enhancers_bottoms': 'Enhancer\'s Bottoms',
  713. '/items/turtle_shell_legs': 'Turtle Shell Legs',
  714. '/items/colossus_plate_legs': 'Colossus Plate Legs',
  715. '/items/demonic_plate_legs': 'Demonic Plate Legs',
  716. '/items/anchorbound_plate_legs': 'Anchorbound Plate Legs',
  717. '/items/maelstrom_plate_legs': 'Maelstrom Plate Legs',
  718. '/items/marine_chaps': 'Marine Chaps',
  719. '/items/revenant_chaps': 'Revenant Chaps',
  720. '/items/griffin_chaps': 'Griffin Chaps',
  721. '/items/kraken_chaps': 'Kraken Chaps',
  722. '/items/icy_robe_bottoms': 'Icy Robe Bottoms',
  723. '/items/flaming_robe_bottoms': 'Flaming Robe Bottoms',
  724. '/items/luna_robe_bottoms': 'Luna Robe Bottoms',
  725. '/items/royal_water_robe_bottoms': 'Royal Water Robe Bottoms',
  726. '/items/royal_nature_robe_bottoms': 'Royal Nature Robe Bottoms',
  727. '/items/royal_fire_robe_bottoms': 'Royal Fire Robe Bottoms',
  728. '/items/cheese_plate_legs': 'Cheese Plate Legs',
  729. '/items/verdant_plate_legs': 'Verdant Plate Legs',
  730. '/items/azure_plate_legs': 'Azure Plate Legs',
  731. '/items/burble_plate_legs': 'Burble Plate Legs',
  732. '/items/crimson_plate_legs': 'Crimson Plate Legs',
  733. '/items/rainbow_plate_legs': 'Rainbow Plate Legs',
  734. '/items/holy_plate_legs': 'Holy Plate Legs',
  735. '/items/rough_chaps': 'Rough Chaps',
  736. '/items/reptile_chaps': 'Reptile Chaps',
  737. '/items/gobo_chaps': 'Gobo Chaps',
  738. '/items/beast_chaps': 'Beast Chaps',
  739. '/items/umbral_chaps': 'Umbral Chaps',
  740. '/items/cotton_robe_bottoms': 'Cotton Robe Bottoms',
  741. '/items/linen_robe_bottoms': 'Linen Robe Bottoms',
  742. '/items/bamboo_robe_bottoms': 'Bamboo Robe Bottoms',
  743. '/items/silk_robe_bottoms': 'Silk Robe Bottoms',
  744. '/items/radiant_robe_bottoms': 'Radiant Robe Bottoms',
  745. '/items/enchanted_gloves': 'Enchanted Gloves',
  746. '/items/pincer_gloves': 'Pincer Gloves',
  747. '/items/panda_gloves': 'Panda Gloves',
  748. '/items/magnetic_gloves': 'Magnetic Gloves',
  749. '/items/dodocamel_gauntlets': 'Dodocamel Gauntlets',
  750. '/items/sighted_bracers': 'Sighted Bracers',
  751. '/items/marksman_bracers': 'Marksman Bracers',
  752. '/items/chrono_gloves': 'Chrono Gloves',
  753. '/items/cheese_gauntlets': 'Cheese Gauntlets',
  754. '/items/verdant_gauntlets': 'Verdant Gauntlets',
  755. '/items/azure_gauntlets': 'Azure Gauntlets',
  756. '/items/burble_gauntlets': 'Burble Gauntlets',
  757. '/items/crimson_gauntlets': 'Crimson Gauntlets',
  758. '/items/rainbow_gauntlets': 'Rainbow Gauntlets',
  759. '/items/holy_gauntlets': 'Holy Gauntlets',
  760. '/items/rough_bracers': 'Rough Bracers',
  761. '/items/reptile_bracers': 'Reptile Bracers',
  762. '/items/gobo_bracers': 'Gobo Bracers',
  763. '/items/beast_bracers': 'Beast Bracers',
  764. '/items/umbral_bracers': 'Umbral Bracers',
  765. '/items/cotton_gloves': 'Cotton Gloves',
  766. '/items/linen_gloves': 'Linen Gloves',
  767. '/items/bamboo_gloves': 'Bamboo Gloves',
  768. '/items/silk_gloves': 'Silk Gloves',
  769. '/items/radiant_gloves': 'Radiant Gloves',
  770. '/items/collectors_boots': 'Collector\'s Boots',
  771. '/items/shoebill_shoes': 'Shoebill Shoes',
  772. '/items/black_bear_shoes': 'Black Bear Shoes',
  773. '/items/grizzly_bear_shoes': 'Grizzly Bear Shoes',
  774. '/items/polar_bear_shoes': 'Polar Bear Shoes',
  775. '/items/centaur_boots': 'Centaur Boots',
  776. '/items/sorcerer_boots': 'Sorcerer Boots',
  777. '/items/cheese_boots': 'Cheese Boots',
  778. '/items/verdant_boots': 'Verdant Boots',
  779. '/items/azure_boots': 'Azure Boots',
  780. '/items/burble_boots': 'Burble Boots',
  781. '/items/crimson_boots': 'Crimson Boots',
  782. '/items/rainbow_boots': 'Rainbow Boots',
  783. '/items/holy_boots': 'Holy Boots',
  784. '/items/rough_boots': 'Rough Boots',
  785. '/items/reptile_boots': 'Reptile Boots',
  786. '/items/gobo_boots': 'Gobo Boots',
  787. '/items/beast_boots': 'Beast Boots',
  788. '/items/umbral_boots': 'Umbral Boots',
  789. '/items/cotton_boots': 'Cotton Boots',
  790. '/items/linen_boots': 'Linen Boots',
  791. '/items/bamboo_boots': 'Bamboo Boots',
  792. '/items/silk_boots': 'Silk Boots',
  793. '/items/radiant_boots': 'Radiant Boots',
  794. '/items/small_pouch': 'Small Pouch',
  795. '/items/medium_pouch': 'Medium Pouch',
  796. '/items/large_pouch': 'Large Pouch',
  797. '/items/giant_pouch': 'Giant Pouch',
  798. '/items/gluttonous_pouch': 'Gluttonous Pouch',
  799. '/items/guzzling_pouch': 'Guzzling Pouch',
  800. '/items/necklace_of_efficiency': 'Necklace Of Efficiency',
  801. '/items/fighter_necklace': 'Fighter Necklace',
  802. '/items/ranger_necklace': 'Ranger Necklace',
  803. '/items/wizard_necklace': 'Wizard Necklace',
  804. '/items/necklace_of_wisdom': 'Necklace Of Wisdom',
  805. '/items/necklace_of_speed': 'Necklace Of Speed',
  806. '/items/philosophers_necklace': 'Philosopher\'s Necklace',
  807. '/items/earrings_of_gathering': 'Earrings Of Gathering',
  808. '/items/earrings_of_essence_find': 'Earrings Of Essence Find',
  809. '/items/earrings_of_armor': 'Earrings Of Armor',
  810. '/items/earrings_of_regeneration': 'Earrings Of Regeneration',
  811. '/items/earrings_of_resistance': 'Earrings Of Resistance',
  812. '/items/earrings_of_rare_find': 'Earrings Of Rare Find',
  813. '/items/earrings_of_critical_strike': 'Earrings Of Critical Strike',
  814. '/items/philosophers_earrings': 'Philosopher\'s Earrings',
  815. '/items/ring_of_gathering': 'Ring Of Gathering',
  816. '/items/ring_of_essence_find': 'Ring Of Essence Find',
  817. '/items/ring_of_armor': 'Ring Of Armor',
  818. '/items/ring_of_regeneration': 'Ring Of Regeneration',
  819. '/items/ring_of_resistance': 'Ring Of Resistance',
  820. '/items/ring_of_rare_find': 'Ring Of Rare Find',
  821. '/items/ring_of_critical_strike': 'Ring Of Critical Strike',
  822. '/items/philosophers_ring': 'Philosopher\'s Ring',
  823. '/items/basic_task_badge': 'Basic Task Badge',
  824. '/items/advanced_task_badge': 'Advanced Task Badge',
  825. '/items/expert_task_badge': 'Expert Task Badge',
  826. '/items/celestial_brush': 'Celestial Brush',
  827. '/items/cheese_brush': 'Cheese Brush',
  828. '/items/verdant_brush': 'Verdant Brush',
  829. '/items/azure_brush': 'Azure Brush',
  830. '/items/burble_brush': 'Burble Brush',
  831. '/items/crimson_brush': 'Crimson Brush',
  832. '/items/rainbow_brush': 'Rainbow Brush',
  833. '/items/holy_brush': 'Holy Brush',
  834. '/items/celestial_shears': 'Celestial Shears',
  835. '/items/cheese_shears': 'Cheese Shears',
  836. '/items/verdant_shears': 'Verdant Shears',
  837. '/items/azure_shears': 'Azure Shears',
  838. '/items/burble_shears': 'Burble Shears',
  839. '/items/crimson_shears': 'Crimson Shears',
  840. '/items/rainbow_shears': 'Rainbow Shears',
  841. '/items/holy_shears': 'Holy Shears',
  842. '/items/celestial_hatchet': 'Celestial Hatchet',
  843. '/items/cheese_hatchet': 'Cheese Hatchet',
  844. '/items/verdant_hatchet': 'Verdant Hatchet',
  845. '/items/azure_hatchet': 'Azure Hatchet',
  846. '/items/burble_hatchet': 'Burble Hatchet',
  847. '/items/crimson_hatchet': 'Crimson Hatchet',
  848. '/items/rainbow_hatchet': 'Rainbow Hatchet',
  849. '/items/holy_hatchet': 'Holy Hatchet',
  850. '/items/celestial_hammer': 'Celestial Hammer',
  851. '/items/cheese_hammer': 'Cheese Hammer',
  852. '/items/verdant_hammer': 'Verdant Hammer',
  853. '/items/azure_hammer': 'Azure Hammer',
  854. '/items/burble_hammer': 'Burble Hammer',
  855. '/items/crimson_hammer': 'Crimson Hammer',
  856. '/items/rainbow_hammer': 'Rainbow Hammer',
  857. '/items/holy_hammer': 'Holy Hammer',
  858. '/items/celestial_chisel': 'Celestial Chisel',
  859. '/items/cheese_chisel': 'Cheese Chisel',
  860. '/items/verdant_chisel': 'Verdant Chisel',
  861. '/items/azure_chisel': 'Azure Chisel',
  862. '/items/burble_chisel': 'Burble Chisel',
  863. '/items/crimson_chisel': 'Crimson Chisel',
  864. '/items/rainbow_chisel': 'Rainbow Chisel',
  865. '/items/holy_chisel': 'Holy Chisel',
  866. '/items/celestial_needle': 'Celestial Needle',
  867. '/items/cheese_needle': 'Cheese Needle',
  868. '/items/verdant_needle': 'Verdant Needle',
  869. '/items/azure_needle': 'Azure Needle',
  870. '/items/burble_needle': 'Burble Needle',
  871. '/items/crimson_needle': 'Crimson Needle',
  872. '/items/rainbow_needle': 'Rainbow Needle',
  873. '/items/holy_needle': 'Holy Needle',
  874. '/items/celestial_spatula': 'Celestial Spatula',
  875. '/items/cheese_spatula': 'Cheese Spatula',
  876. '/items/verdant_spatula': 'Verdant Spatula',
  877. '/items/azure_spatula': 'Azure Spatula',
  878. '/items/burble_spatula': 'Burble Spatula',
  879. '/items/crimson_spatula': 'Crimson Spatula',
  880. '/items/rainbow_spatula': 'Rainbow Spatula',
  881. '/items/holy_spatula': 'Holy Spatula',
  882. '/items/celestial_pot': 'Celestial Pot',
  883. '/items/cheese_pot': 'Cheese Pot',
  884. '/items/verdant_pot': 'Verdant Pot',
  885. '/items/azure_pot': 'Azure Pot',
  886. '/items/burble_pot': 'Burble Pot',
  887. '/items/crimson_pot': 'Crimson Pot',
  888. '/items/rainbow_pot': 'Rainbow Pot',
  889. '/items/holy_pot': 'Holy Pot',
  890. '/items/celestial_alembic': 'Celestial Alembic',
  891. '/items/cheese_alembic': 'Cheese Alembic',
  892. '/items/verdant_alembic': 'Verdant Alembic',
  893. '/items/azure_alembic': 'Azure Alembic',
  894. '/items/burble_alembic': 'Burble Alembic',
  895. '/items/crimson_alembic': 'Crimson Alembic',
  896. '/items/rainbow_alembic': 'Rainbow Alembic',
  897. '/items/holy_alembic': 'Holy Alembic',
  898. '/items/celestial_enhancer': 'Celestial Enhancer',
  899. '/items/cheese_enhancer': 'Cheese Enhancer',
  900. '/items/verdant_enhancer': 'Verdant Enhancer',
  901. '/items/azure_enhancer': 'Azure Enhancer',
  902. '/items/burble_enhancer': 'Burble Enhancer',
  903. '/items/crimson_enhancer': 'Crimson Enhancer',
  904. '/items/rainbow_enhancer': 'Rainbow Enhancer',
  905. '/items/holy_enhancer': 'Holy Enhancer',
  906. '/items/milk': 'Milk',
  907. '/items/verdant_milk': 'Verdant Milk',
  908. '/items/azure_milk': 'Azure Milk',
  909. '/items/burble_milk': 'Burble Milk',
  910. '/items/crimson_milk': 'Crimson Milk',
  911. '/items/rainbow_milk': 'Rainbow Milk',
  912. '/items/holy_milk': 'Holy Milk',
  913. '/items/cheese': 'Cheese',
  914. '/items/verdant_cheese': 'Verdant Cheese',
  915. '/items/azure_cheese': 'Azure Cheese',
  916. '/items/burble_cheese': 'Burble Cheese',
  917. '/items/crimson_cheese': 'Crimson Cheese',
  918. '/items/rainbow_cheese': 'Rainbow Cheese',
  919. '/items/holy_cheese': 'Holy Cheese',
  920. '/items/log': 'Log',
  921. '/items/birch_log': 'Birch Log',
  922. '/items/cedar_log': 'Cedar Log',
  923. '/items/purpleheart_log': 'Purpleheart Log',
  924. '/items/ginkgo_log': 'Ginkgo Log',
  925. '/items/redwood_log': 'Redwood Log',
  926. '/items/arcane_log': 'Arcane Log',
  927. '/items/lumber': 'Lumber',
  928. '/items/birch_lumber': 'Birch Lumber',
  929. '/items/cedar_lumber': 'Cedar Lumber',
  930. '/items/purpleheart_lumber': 'Purpleheart Lumber',
  931. '/items/ginkgo_lumber': 'Ginkgo Lumber',
  932. '/items/redwood_lumber': 'Redwood Lumber',
  933. '/items/arcane_lumber': 'Arcane Lumber',
  934. '/items/rough_hide': 'Rough Hide',
  935. '/items/reptile_hide': 'Reptile Hide',
  936. '/items/gobo_hide': 'Gobo Hide',
  937. '/items/beast_hide': 'Beast Hide',
  938. '/items/umbral_hide': 'Umbral Hide',
  939. '/items/rough_leather': 'Rough Leather',
  940. '/items/reptile_leather': 'Reptile Leather',
  941. '/items/gobo_leather': 'Gobo Leather',
  942. '/items/beast_leather': 'Beast Leather',
  943. '/items/umbral_leather': 'Umbral Leather',
  944. '/items/cotton': 'Cotton',
  945. '/items/flax': 'Flax',
  946. '/items/bamboo_branch': 'Bamboo Branch',
  947. '/items/cocoon': 'Cocoon',
  948. '/items/radiant_fiber': 'Radiant Fiber',
  949. '/items/cotton_fabric': 'Cotton Fabric',
  950. '/items/linen_fabric': 'Linen Fabric',
  951. '/items/bamboo_fabric': 'Bamboo Fabric',
  952. '/items/silk_fabric': 'Silk Fabric',
  953. '/items/radiant_fabric': 'Radiant Fabric',
  954. '/items/egg': 'Egg',
  955. '/items/wheat': 'Wheat',
  956. '/items/sugar': 'Sugar',
  957. '/items/blueberry': 'Blueberry',
  958. '/items/blackberry': 'Blackberry',
  959. '/items/strawberry': 'Strawberry',
  960. '/items/mooberry': 'Mooberry',
  961. '/items/marsberry': 'Marsberry',
  962. '/items/spaceberry': 'Spaceberry',
  963. '/items/apple': 'Apple',
  964. '/items/orange': 'Orange',
  965. '/items/plum': 'Plum',
  966. '/items/peach': 'Peach',
  967. '/items/dragon_fruit': 'Dragon Fruit',
  968. '/items/star_fruit': 'Star Fruit',
  969. '/items/arabica_coffee_bean': 'Arabica Coffee Bean',
  970. '/items/robusta_coffee_bean': 'Robusta Coffee Bean',
  971. '/items/liberica_coffee_bean': 'Liberica Coffee Bean',
  972. '/items/excelsa_coffee_bean': 'Excelsa Coffee Bean',
  973. '/items/fieriosa_coffee_bean': 'Fieriosa Coffee Bean',
  974. '/items/spacia_coffee_bean': 'Spacia Coffee Bean',
  975. '/items/green_tea_leaf': 'Green Tea Leaf',
  976. '/items/black_tea_leaf': 'Black Tea Leaf',
  977. '/items/burble_tea_leaf': 'Burble Tea Leaf',
  978. '/items/moolong_tea_leaf': 'Moolong Tea Leaf',
  979. '/items/red_tea_leaf': 'Red Tea Leaf',
  980. '/items/emp_tea_leaf': 'Emp Tea Leaf',
  981. '/items/catalyst_of_coinification': 'Catalyst Of Coinification',
  982. '/items/catalyst_of_decomposition': 'Catalyst Of Decomposition',
  983. '/items/catalyst_of_transmutation': 'Catalyst Of Transmutation',
  984. '/items/prime_catalyst': 'Prime Catalyst',
  985. '/items/snake_fang': 'Snake Fang',
  986. '/items/shoebill_feather': 'Shoebill Feather',
  987. '/items/snail_shell': 'Snail Shell',
  988. '/items/crab_pincer': 'Crab Pincer',
  989. '/items/turtle_shell': 'Turtle Shell',
  990. '/items/marine_scale': 'Marine Scale',
  991. '/items/treant_bark': 'Treant Bark',
  992. '/items/centaur_hoof': 'Centaur Hoof',
  993. '/items/luna_wing': 'Luna Wing',
  994. '/items/gobo_rag': 'Gobo Rag',
  995. '/items/goggles': 'Goggles',
  996. '/items/magnifying_glass': 'Magnifying Glass',
  997. '/items/eye_of_the_watcher': 'Eye Of The Watcher',
  998. '/items/icy_cloth': 'Icy Cloth',
  999. '/items/flaming_cloth': 'Flaming Cloth',
  1000. '/items/sorcerers_sole': 'Sorcerer\'s Sole',
  1001. '/items/chrono_sphere': 'Chrono Sphere',
  1002. '/items/frost_sphere': 'Frost Sphere',
  1003. '/items/panda_fluff': 'Panda Fluff',
  1004. '/items/black_bear_fluff': 'Black Bear Fluff',
  1005. '/items/grizzly_bear_fluff': 'Grizzly Bear Fluff',
  1006. '/items/polar_bear_fluff': 'Polar Bear Fluff',
  1007. '/items/red_panda_fluff': 'Red Panda Fluff',
  1008. '/items/magnet': 'Magnet',
  1009. '/items/stalactite_shard': 'Stalactite Shard',
  1010. '/items/living_granite': 'Living Granite',
  1011. '/items/colossus_core': 'Colossus Core',
  1012. '/items/vampire_fang': 'Vampire Fang',
  1013. '/items/werewolf_claw': 'Werewolf Claw',
  1014. '/items/revenant_anima': 'Revenant Anima',
  1015. '/items/soul_fragment': 'Soul Fragment',
  1016. '/items/infernal_ember': 'Infernal Ember',
  1017. '/items/demonic_core': 'Demonic Core',
  1018. '/items/griffin_leather': 'Griffin Leather',
  1019. '/items/manticore_sting': 'Manticore Sting',
  1020. '/items/jackalope_antler': 'Jackalope Antler',
  1021. '/items/dodocamel_plume': 'Dodocamel Plume',
  1022. '/items/griffin_talon': 'Griffin Talon',
  1023. '/items/acrobats_ribbon': 'Acrobat\'s Ribbon',
  1024. '/items/magicians_cloth': 'Magician\'s Cloth',
  1025. '/items/chaotic_chain': 'Chaotic Chain',
  1026. '/items/cursed_ball': 'Cursed Ball',
  1027. '/items/royal_cloth': 'Royal Cloth',
  1028. '/items/knights_ingot': 'Knight\'s Ingot',
  1029. '/items/bishops_scroll': 'Bishop\'s Scroll',
  1030. '/items/regal_jewel': 'Regal Jewel',
  1031. '/items/sundering_jewel': 'Sundering Jewel',
  1032. '/items/marksman_brooch': 'Marksman Brooch',
  1033. '/items/corsair_crest': 'Corsair Crest',
  1034. '/items/damaged_anchor': 'Damaged Anchor',
  1035. '/items/maelstrom_plating': 'Maelstrom Plating',
  1036. '/items/kraken_leather': 'Kraken Leather',
  1037. '/items/kraken_fang': 'Kraken Fang',
  1038. '/items/butter_of_proficiency': 'Butter Of Proficiency',
  1039. '/items/thread_of_expertise': 'Thread Of Expertise',
  1040. '/items/branch_of_insight': 'Branch Of Insight',
  1041. '/items/gluttonous_energy': 'Gluttonous Energy',
  1042. '/items/guzzling_energy': 'Guzzling Energy',
  1043. '/items/milking_essence': 'Milking Essence',
  1044. '/items/foraging_essence': 'Foraging Essence',
  1045. '/items/woodcutting_essence': 'Woodcutting Essence',
  1046. '/items/cheesesmithing_essence': 'Cheesesmithing Essence',
  1047. '/items/crafting_essence': 'Crafting Essence',
  1048. '/items/tailoring_essence': 'Tailoring Essence',
  1049. '/items/cooking_essence': 'Cooking Essence',
  1050. '/items/brewing_essence': 'Brewing Essence',
  1051. '/items/alchemy_essence': 'Alchemy Essence',
  1052. '/items/enhancing_essence': 'Enhancing Essence',
  1053. '/items/swamp_essence': 'Swamp Essence',
  1054. '/items/aqua_essence': 'Aqua Essence',
  1055. '/items/jungle_essence': 'Jungle Essence',
  1056. '/items/gobo_essence': 'Gobo Essence',
  1057. '/items/eyessence': 'Eyessence',
  1058. '/items/sorcerer_essence': 'Sorcerer Essence',
  1059. '/items/bear_essence': 'Bear Essence',
  1060. '/items/golem_essence': 'Golem Essence',
  1061. '/items/twilight_essence': 'Twilight Essence',
  1062. '/items/abyssal_essence': 'Abyssal Essence',
  1063. '/items/chimerical_essence': 'Chimerical Essence',
  1064. '/items/sinister_essence': 'Sinister Essence',
  1065. '/items/enchanted_essence': 'Enchanted Essence',
  1066. '/items/pirate_essence': 'Pirate Essence',
  1067. '/items/task_crystal': 'Task Crystal',
  1068. '/items/star_fragment': 'Star Fragment',
  1069. '/items/pearl': 'Pearl',
  1070. '/items/amber': 'Amber',
  1071. '/items/garnet': 'Garnet',
  1072. '/items/jade': 'Jade',
  1073. '/items/amethyst': 'Amethyst',
  1074. '/items/moonstone': 'Moonstone',
  1075. '/items/sunstone': 'Sunstone',
  1076. '/items/philosophers_stone': 'Philosopher\'s Stone',
  1077. '/items/crushed_pearl': 'Crushed Pearl',
  1078. '/items/crushed_amber': 'Crushed Amber',
  1079. '/items/crushed_garnet': 'Crushed Garnet',
  1080. '/items/crushed_jade': 'Crushed Jade',
  1081. '/items/crushed_amethyst': 'Crushed Amethyst',
  1082. '/items/crushed_moonstone': 'Crushed Moonstone',
  1083. '/items/crushed_sunstone': 'Crushed Sunstone',
  1084. '/items/crushed_philosophers_stone': 'Crushed Philosopher\'s Stone',
  1085. '/items/shard_of_protection': 'Shard Of Protection',
  1086. '/items/mirror_of_protection': 'Mirror Of Protection'
  1087. },
  1088. }
  1089. }
  1090. },
  1091. zh: {
  1092. translation: {
  1093. ...{
  1094. itemNames: {
  1095. '/items/coin': '金币',
  1096. '/items/task_token': '任务代币',
  1097. '/items/chimerical_token': '奇幻代币',
  1098. '/items/sinister_token': '阴森代币',
  1099. '/items/enchanted_token': '秘法代币',
  1100. '/items/pirate_token': '海盗代币',
  1101. '/items/cowbell': '牛铃',
  1102. '/items/bag_of_10_cowbells': '牛铃袋 (10个)',
  1103. '/items/purples_gift': '小紫牛的礼物',
  1104. '/items/small_meteorite_cache': '小陨石舱',
  1105. '/items/medium_meteorite_cache': '中陨石舱',
  1106. '/items/large_meteorite_cache': '大陨石舱',
  1107. '/items/small_artisans_crate': '小工匠匣',
  1108. '/items/medium_artisans_crate': '中工匠匣',
  1109. '/items/large_artisans_crate': '大工匠匣',
  1110. '/items/small_treasure_chest': '小宝箱',
  1111. '/items/medium_treasure_chest': '中宝箱',
  1112. '/items/large_treasure_chest': '大宝箱',
  1113. '/items/chimerical_chest': '奇幻宝箱',
  1114. '/items/sinister_chest': '阴森宝箱',
  1115. '/items/enchanted_chest': '秘法宝箱',
  1116. '/items/pirate_chest': '海盗宝箱',
  1117. '/items/blue_key_fragment': '蓝色钥匙碎片',
  1118. '/items/green_key_fragment': '绿色钥匙碎片',
  1119. '/items/purple_key_fragment': '紫色钥匙碎片',
  1120. '/items/white_key_fragment': '白色钥匙碎片',
  1121. '/items/orange_key_fragment': '橙色钥匙碎片',
  1122. '/items/brown_key_fragment': '棕色钥匙碎片',
  1123. '/items/stone_key_fragment': '石头钥匙碎片',
  1124. '/items/dark_key_fragment': '黑暗钥匙碎片',
  1125. '/items/burning_key_fragment': '燃烧钥匙碎片',
  1126. '/items/chimerical_entry_key': '奇幻钥匙',
  1127. '/items/chimerical_chest_key': '奇幻宝箱钥匙',
  1128. '/items/sinister_entry_key': '阴森钥匙',
  1129. '/items/sinister_chest_key': '阴森宝箱钥匙',
  1130. '/items/enchanted_entry_key': '秘法钥匙',
  1131. '/items/enchanted_chest_key': '秘法宝箱钥匙',
  1132. '/items/pirate_entry_key': '海盗钥匙',
  1133. '/items/pirate_chest_key': '海盗宝箱钥匙',
  1134. '/items/donut': '甜甜圈',
  1135. '/items/blueberry_donut': '蓝莓甜甜圈',
  1136. '/items/blackberry_donut': '黑莓甜甜圈',
  1137. '/items/strawberry_donut': '草莓甜甜圈',
  1138. '/items/mooberry_donut': '哞莓甜甜圈',
  1139. '/items/marsberry_donut': '火星莓甜甜圈',
  1140. '/items/spaceberry_donut': '太空莓甜甜圈',
  1141. '/items/cupcake': '纸杯蛋糕',
  1142. '/items/blueberry_cake': '蓝莓蛋糕',
  1143. '/items/blackberry_cake': '黑莓蛋糕',
  1144. '/items/strawberry_cake': '草莓蛋糕',
  1145. '/items/mooberry_cake': '哞莓蛋糕',
  1146. '/items/marsberry_cake': '火星莓蛋糕',
  1147. '/items/spaceberry_cake': '太空莓蛋糕',
  1148. '/items/gummy': '软糖',
  1149. '/items/apple_gummy': '苹果软糖',
  1150. '/items/orange_gummy': '橙子软糖',
  1151. '/items/plum_gummy': '李子软糖',
  1152. '/items/peach_gummy': '桃子软糖',
  1153. '/items/dragon_fruit_gummy': '火龙果软糖',
  1154. '/items/star_fruit_gummy': '杨桃软糖',
  1155. '/items/yogurt': '酸奶',
  1156. '/items/apple_yogurt': '苹果酸奶',
  1157. '/items/orange_yogurt': '橙子酸奶',
  1158. '/items/plum_yogurt': '李子酸奶',
  1159. '/items/peach_yogurt': '桃子酸奶',
  1160. '/items/dragon_fruit_yogurt': '火龙果酸奶',
  1161. '/items/star_fruit_yogurt': '杨桃酸奶',
  1162. '/items/milking_tea': '挤奶茶',
  1163. '/items/foraging_tea': '采摘茶',
  1164. '/items/woodcutting_tea': '伐木茶',
  1165. '/items/cooking_tea': '烹饪茶',
  1166. '/items/brewing_tea': '冲泡茶',
  1167. '/items/alchemy_tea': '炼金茶',
  1168. '/items/enhancing_tea': '强化茶',
  1169. '/items/cheesesmithing_tea': '奶酪锻造茶',
  1170. '/items/crafting_tea': '制作茶',
  1171. '/items/tailoring_tea': '缝纫茶',
  1172. '/items/super_milking_tea': '超级挤奶茶',
  1173. '/items/super_foraging_tea': '超级采摘茶',
  1174. '/items/super_woodcutting_tea': '超级伐木茶',
  1175. '/items/super_cooking_tea': '超级烹饪茶',
  1176. '/items/super_brewing_tea': '超级冲泡茶',
  1177. '/items/super_alchemy_tea': '超级炼金茶',
  1178. '/items/super_enhancing_tea': '超级强化茶',
  1179. '/items/super_cheesesmithing_tea': '超级奶酪锻造茶',
  1180. '/items/super_crafting_tea': '超级制作茶',
  1181. '/items/super_tailoring_tea': '超级缝纫茶',
  1182. '/items/ultra_milking_tea': '究极挤奶茶',
  1183. '/items/ultra_foraging_tea': '究极采摘茶',
  1184. '/items/ultra_woodcutting_tea': '究极伐木茶',
  1185. '/items/ultra_cooking_tea': '究极烹饪茶',
  1186. '/items/ultra_brewing_tea': '究极冲泡茶',
  1187. '/items/ultra_alchemy_tea': '究极炼金茶',
  1188. '/items/ultra_enhancing_tea': '究极强化茶',
  1189. '/items/ultra_cheesesmithing_tea': '究极奶酪锻造茶',
  1190. '/items/ultra_crafting_tea': '究极制作茶',
  1191. '/items/ultra_tailoring_tea': '究极缝纫茶',
  1192. '/items/gathering_tea': '采集茶',
  1193. '/items/gourmet_tea': '美食茶',
  1194. '/items/wisdom_tea': '经验茶',
  1195. '/items/processing_tea': '加工茶',
  1196. '/items/efficiency_tea': '效率茶',
  1197. '/items/artisan_tea': '工匠茶',
  1198. '/items/catalytic_tea': '催化茶',
  1199. '/items/blessed_tea': '福气茶',
  1200. '/items/stamina_coffee': '耐力咖啡',
  1201. '/items/intelligence_coffee': '智力咖啡',
  1202. '/items/defense_coffee': '防御咖啡',
  1203. '/items/attack_coffee': '攻击咖啡',
  1204. '/items/power_coffee': '力量咖啡',
  1205. '/items/ranged_coffee': '远程咖啡',
  1206. '/items/magic_coffee': '魔法咖啡',
  1207. '/items/super_stamina_coffee': '超级耐力咖啡',
  1208. '/items/super_intelligence_coffee': '超级智力咖啡',
  1209. '/items/super_defense_coffee': '超级防御咖啡',
  1210. '/items/super_attack_coffee': '超级攻击咖啡',
  1211. '/items/super_power_coffee': '超级力量咖啡',
  1212. '/items/super_ranged_coffee': '超级远程咖啡',
  1213. '/items/super_magic_coffee': '超级魔法咖啡',
  1214. '/items/ultra_stamina_coffee': '究极耐力咖啡',
  1215. '/items/ultra_intelligence_coffee': '究极智力咖啡',
  1216. '/items/ultra_defense_coffee': '究极防御咖啡',
  1217. '/items/ultra_attack_coffee': '究极攻击咖啡',
  1218. '/items/ultra_power_coffee': '究极力量咖啡',
  1219. '/items/ultra_ranged_coffee': '究极远程咖啡',
  1220. '/items/ultra_magic_coffee': '究极魔法咖啡',
  1221. '/items/wisdom_coffee': '经验咖啡',
  1222. '/items/lucky_coffee': '幸运咖啡',
  1223. '/items/swiftness_coffee': '迅捷咖啡',
  1224. '/items/channeling_coffee': '吟唱咖啡',
  1225. '/items/critical_coffee': '暴击咖啡',
  1226. '/items/poke': '破胆之刺',
  1227. '/items/impale': '透骨之刺',
  1228. '/items/puncture': '破甲之刺',
  1229. '/items/penetrating_strike': '贯心之刺',
  1230. '/items/scratch': '爪影斩',
  1231. '/items/cleave': '分裂斩',
  1232. '/items/maim': '血刃斩',
  1233. '/items/crippling_slash': '致残斩',
  1234. '/items/smack': '重碾',
  1235. '/items/sweep': '重扫',
  1236. '/items/stunning_blow': '重锤',
  1237. '/items/fracturing_impact': '碎裂冲击',
  1238. '/items/shield_bash': '盾击',
  1239. '/items/quick_shot': '快速射击',
  1240. '/items/aqua_arrow': '流水箭',
  1241. '/items/flame_arrow': '烈焰箭',
  1242. '/items/rain_of_arrows': '箭雨',
  1243. '/items/silencing_shot': '沉默之箭',
  1244. '/items/steady_shot': '稳定射击',
  1245. '/items/pestilent_shot': '疫病射击',
  1246. '/items/penetrating_shot': '贯穿射击',
  1247. '/items/water_strike': '流水冲击',
  1248. '/items/ice_spear': '冰枪术',
  1249. '/items/frost_surge': '冰霜爆裂',
  1250. '/items/mana_spring': '法力喷泉',
  1251. '/items/entangle': '缠绕',
  1252. '/items/toxic_pollen': '剧毒粉尘',
  1253. '/items/natures_veil': '自然菌幕',
  1254. '/items/life_drain': '生命吸取',
  1255. '/items/fireball': '火球',
  1256. '/items/flame_blast': '熔岩爆裂',
  1257. '/items/firestorm': '火焰风暴',
  1258. '/items/smoke_burst': '烟爆灭影',
  1259. '/items/minor_heal': '初级自愈术',
  1260. '/items/heal': '自愈术',
  1261. '/items/quick_aid': '快速治疗术',
  1262. '/items/rejuvenate': '群体治疗术',
  1263. '/items/taunt': '嘲讽',
  1264. '/items/provoke': '挑衅',
  1265. '/items/toughness': '坚韧',
  1266. '/items/elusiveness': '闪避',
  1267. '/items/precision': '精确',
  1268. '/items/berserk': '狂暴',
  1269. '/items/elemental_affinity': '元素增幅',
  1270. '/items/frenzy': '狂速',
  1271. '/items/spike_shell': '尖刺防护',
  1272. '/items/arcane_reflection': '奥术反射',
  1273. '/items/vampirism': '吸血',
  1274. '/items/revive': '复活',
  1275. '/items/insanity': '疯狂',
  1276. '/items/invincible': '无敌',
  1277. '/items/fierce_aura': '物理光环',
  1278. '/items/aqua_aura': '流水光环',
  1279. '/items/sylvan_aura': '自然光环',
  1280. '/items/flame_aura': '火焰光环',
  1281. '/items/speed_aura': '速度光环',
  1282. '/items/critical_aura': '暴击光环',
  1283. '/items/gobo_stabber': '哥布林长剑',
  1284. '/items/gobo_slasher': '哥布林关刀',
  1285. '/items/gobo_smasher': '哥布林狼牙棒',
  1286. '/items/spiked_bulwark': '尖刺重盾',
  1287. '/items/werewolf_slasher': '狼人关刀',
  1288. '/items/griffin_bulwark': '狮鹫重盾',
  1289. '/items/gobo_shooter': '哥布林弹弓',
  1290. '/items/vampiric_bow': '吸血弓',
  1291. '/items/cursed_bow': '咒怨之弓',
  1292. '/items/gobo_boomstick': '哥布林火棍',
  1293. '/items/cheese_bulwark': '奶酪重盾',
  1294. '/items/verdant_bulwark': '翠绿重盾',
  1295. '/items/azure_bulwark': '蔚蓝重盾',
  1296. '/items/burble_bulwark': '深紫重盾',
  1297. '/items/crimson_bulwark': '绛红重盾',
  1298. '/items/rainbow_bulwark': '彩虹重盾',
  1299. '/items/holy_bulwark': '神圣重盾',
  1300. '/items/wooden_bow': '木弓',
  1301. '/items/birch_bow': '桦木弓',
  1302. '/items/cedar_bow': '雪松弓',
  1303. '/items/purpleheart_bow': '紫心弓',
  1304. '/items/ginkgo_bow': '银杏弓',
  1305. '/items/redwood_bow': '红杉弓',
  1306. '/items/arcane_bow': '神秘弓',
  1307. '/items/stalactite_spear': '石钟长枪',
  1308. '/items/granite_bludgeon': '花岗岩大棒',
  1309. '/items/furious_spear': '狂怒长枪',
  1310. '/items/regal_sword': '君王之剑',
  1311. '/items/chaotic_flail': '混沌连枷',
  1312. '/items/soul_hunter_crossbow': '灵魂猎手弩',
  1313. '/items/sundering_crossbow': '裂空之弩',
  1314. '/items/frost_staff': '冰霜法杖',
  1315. '/items/infernal_battlestaff': '炼狱法杖',
  1316. '/items/jackalope_staff': '鹿角兔之杖',
  1317. '/items/rippling_trident': '涟漪三叉戟',
  1318. '/items/blooming_trident': '绽放三叉戟',
  1319. '/items/blazing_trident': '炽焰三叉戟',
  1320. '/items/cheese_sword': '奶酪剑',
  1321. '/items/verdant_sword': '翠绿剑',
  1322. '/items/azure_sword': '蔚蓝剑',
  1323. '/items/burble_sword': '深紫剑',
  1324. '/items/crimson_sword': '绛红剑',
  1325. '/items/rainbow_sword': '彩虹剑',
  1326. '/items/holy_sword': '神圣剑',
  1327. '/items/cheese_spear': '奶酪长枪',
  1328. '/items/verdant_spear': '翠绿长枪',
  1329. '/items/azure_spear': '蔚蓝长枪',
  1330. '/items/burble_spear': '深紫长枪',
  1331. '/items/crimson_spear': '绛红长枪',
  1332. '/items/rainbow_spear': '彩虹长枪',
  1333. '/items/holy_spear': '神圣长枪',
  1334. '/items/cheese_mace': '奶酪钉头锤',
  1335. '/items/verdant_mace': '翠绿钉头锤',
  1336. '/items/azure_mace': '蔚蓝钉头锤',
  1337. '/items/burble_mace': '深紫钉头锤',
  1338. '/items/crimson_mace': '绛红钉头锤',
  1339. '/items/rainbow_mace': '彩虹钉头锤',
  1340. '/items/holy_mace': '神圣钉头锤',
  1341. '/items/wooden_crossbow': '木弩',
  1342. '/items/birch_crossbow': '桦木弩',
  1343. '/items/cedar_crossbow': '雪松弩',
  1344. '/items/purpleheart_crossbow': '紫心弩',
  1345. '/items/ginkgo_crossbow': '银杏弩',
  1346. '/items/redwood_crossbow': '红杉弩',
  1347. '/items/arcane_crossbow': '神秘弩',
  1348. '/items/wooden_water_staff': '木制水法杖',
  1349. '/items/birch_water_staff': '桦木水法杖',
  1350. '/items/cedar_water_staff': '雪松水法杖',
  1351. '/items/purpleheart_water_staff': '紫心水法杖',
  1352. '/items/ginkgo_water_staff': '银杏水法杖',
  1353. '/items/redwood_water_staff': '红杉水法杖',
  1354. '/items/arcane_water_staff': '神秘水法杖',
  1355. '/items/wooden_nature_staff': '木制自然法杖',
  1356. '/items/birch_nature_staff': '桦木自然法杖',
  1357. '/items/cedar_nature_staff': '雪松自然法杖',
  1358. '/items/purpleheart_nature_staff': '紫心自然法杖',
  1359. '/items/ginkgo_nature_staff': '银杏自然法杖',
  1360. '/items/redwood_nature_staff': '红杉自然法杖',
  1361. '/items/arcane_nature_staff': '神秘自然法杖',
  1362. '/items/wooden_fire_staff': '木制火法杖',
  1363. '/items/birch_fire_staff': '桦木火法杖',
  1364. '/items/cedar_fire_staff': '雪松火法杖',
  1365. '/items/purpleheart_fire_staff': '紫心火法杖',
  1366. '/items/ginkgo_fire_staff': '银杏火法杖',
  1367. '/items/redwood_fire_staff': '红杉火法杖',
  1368. '/items/arcane_fire_staff': '神秘火法杖',
  1369. '/items/eye_watch': '掌上监工',
  1370. '/items/snake_fang_dirk': '蛇牙短剑',
  1371. '/items/vision_shield': '视觉盾',
  1372. '/items/gobo_defender': '哥布林防御者',
  1373. '/items/vampire_fang_dirk': '吸血鬼短剑',
  1374. '/items/knights_aegis': '骑士盾',
  1375. '/items/treant_shield': '树人盾',
  1376. '/items/manticore_shield': '蝎狮盾',
  1377. '/items/tome_of_healing': '治疗之书',
  1378. '/items/tome_of_the_elements': '元素之书',
  1379. '/items/watchful_relic': '警戒遗物',
  1380. '/items/bishops_codex': '主教法典',
  1381. '/items/cheese_buckler': '奶酪圆盾',
  1382. '/items/verdant_buckler': '翠绿圆盾',
  1383. '/items/azure_buckler': '蔚蓝圆盾',
  1384. '/items/burble_buckler': '深紫圆盾',
  1385. '/items/crimson_buckler': '绛红圆盾',
  1386. '/items/rainbow_buckler': '彩虹圆盾',
  1387. '/items/holy_buckler': '神圣圆盾',
  1388. '/items/wooden_shield': '木盾',
  1389. '/items/birch_shield': '桦木盾',
  1390. '/items/cedar_shield': '雪松盾',
  1391. '/items/purpleheart_shield': '紫心盾',
  1392. '/items/ginkgo_shield': '银杏盾',
  1393. '/items/redwood_shield': '红杉盾',
  1394. '/items/arcane_shield': '神秘盾',
  1395. '/items/sinister_cape': '阴森斗篷',
  1396. '/items/chimerical_quiver': '奇幻箭袋',
  1397. '/items/enchanted_cloak': '秘法披风',
  1398. '/items/red_culinary_hat': '红色厨师帽',
  1399. '/items/snail_shell_helmet': '蜗牛壳头盔',
  1400. '/items/vision_helmet': '视觉头盔',
  1401. '/items/fluffy_red_hat': '蓬松红帽子',
  1402. '/items/corsair_helmet': '掠夺者头盔',
  1403. '/items/acrobatic_hood': '杂技师兜帽',
  1404. '/items/magicians_hat': '魔术师帽',
  1405. '/items/cheese_helmet': '奶酪头盔',
  1406. '/items/verdant_helmet': '翠绿头盔',
  1407. '/items/azure_helmet': '蔚蓝头盔',
  1408. '/items/burble_helmet': '深紫头盔',
  1409. '/items/crimson_helmet': '绛红头盔',
  1410. '/items/rainbow_helmet': '彩虹头盔',
  1411. '/items/holy_helmet': '神圣头盔',
  1412. '/items/rough_hood': '粗糙兜帽',
  1413. '/items/reptile_hood': '爬行动物兜帽',
  1414. '/items/gobo_hood': '哥布林兜帽',
  1415. '/items/beast_hood': '野兽兜帽',
  1416. '/items/umbral_hood': '暗影兜帽',
  1417. '/items/cotton_hat': '棉帽',
  1418. '/items/linen_hat': '亚麻帽',
  1419. '/items/bamboo_hat': '竹帽',
  1420. '/items/silk_hat': '丝帽',
  1421. '/items/radiant_hat': '光辉帽',
  1422. '/items/dairyhands_top': '挤奶工上衣',
  1423. '/items/foragers_top': '采摘者上衣',
  1424. '/items/lumberjacks_top': '伐木工上衣',
  1425. '/items/cheesemakers_top': '奶酪师上衣',
  1426. '/items/crafters_top': '工匠上衣',
  1427. '/items/tailors_top': '裁缝上衣',
  1428. '/items/chefs_top': '厨师上衣',
  1429. '/items/brewers_top': '饮品师上衣',
  1430. '/items/alchemists_top': '炼金师上衣',
  1431. '/items/enhancers_top': '强化师上衣',
  1432. '/items/gator_vest': '鳄鱼马甲',
  1433. '/items/turtle_shell_body': '龟壳胸甲',
  1434. '/items/colossus_plate_body': '巨像胸甲',
  1435. '/items/demonic_plate_body': '恶魔胸甲',
  1436. '/items/anchorbound_plate_body': '锚定胸甲',
  1437. '/items/maelstrom_plate_body': '怒涛胸甲',
  1438. '/items/marine_tunic': '海洋皮衣',
  1439. '/items/revenant_tunic': '亡灵皮衣',
  1440. '/items/griffin_tunic': '狮鹫皮衣',
  1441. '/items/kraken_tunic': '克拉肯皮衣',
  1442. '/items/icy_robe_top': '冰霜袍服',
  1443. '/items/flaming_robe_top': '烈焰袍服',
  1444. '/items/luna_robe_top': '月神袍服',
  1445. '/items/royal_water_robe_top': '皇家水系袍服',
  1446. '/items/royal_nature_robe_top': '皇家自然系袍服',
  1447. '/items/royal_fire_robe_top': '皇家火系袍服',
  1448. '/items/cheese_plate_body': '奶酪胸甲',
  1449. '/items/verdant_plate_body': '翠绿胸甲',
  1450. '/items/azure_plate_body': '蔚蓝胸甲',
  1451. '/items/burble_plate_body': '深紫胸甲',
  1452. '/items/crimson_plate_body': '绛红胸甲',
  1453. '/items/rainbow_plate_body': '彩虹胸甲',
  1454. '/items/holy_plate_body': '神圣胸甲',
  1455. '/items/rough_tunic': '粗糙皮衣',
  1456. '/items/reptile_tunic': '爬行动物皮衣',
  1457. '/items/gobo_tunic': '哥布林皮衣',
  1458. '/items/beast_tunic': '野兽皮衣',
  1459. '/items/umbral_tunic': '暗影皮衣',
  1460. '/items/cotton_robe_top': '棉布袍服',
  1461. '/items/linen_robe_top': '亚麻袍服',
  1462. '/items/bamboo_robe_top': '竹袍服',
  1463. '/items/silk_robe_top': '丝绸袍服',
  1464. '/items/radiant_robe_top': '光辉袍服',
  1465. '/items/dairyhands_bottoms': '挤奶工下装',
  1466. '/items/foragers_bottoms': '采摘者下装',
  1467. '/items/lumberjacks_bottoms': '伐木工下装',
  1468. '/items/cheesemakers_bottoms': '奶酪师下装',
  1469. '/items/crafters_bottoms': '工匠下装',
  1470. '/items/tailors_bottoms': '裁缝下装',
  1471. '/items/chefs_bottoms': '厨师下装',
  1472. '/items/brewers_bottoms': '饮品师下装',
  1473. '/items/alchemists_bottoms': '炼金师下装',
  1474. '/items/enhancers_bottoms': '强化师下装',
  1475. '/items/turtle_shell_legs': '龟壳腿甲',
  1476. '/items/colossus_plate_legs': '巨像腿甲',
  1477. '/items/demonic_plate_legs': '恶魔腿甲',
  1478. '/items/anchorbound_plate_legs': '锚定腿甲',
  1479. '/items/maelstrom_plate_legs': '怒涛腿甲',
  1480. '/items/marine_chaps': '航海皮裤',
  1481. '/items/revenant_chaps': '亡灵皮裤',
  1482. '/items/griffin_chaps': '狮鹫皮裤',
  1483. '/items/kraken_chaps': '克拉肯皮裤',
  1484. '/items/icy_robe_bottoms': '冰霜袍裙',
  1485. '/items/flaming_robe_bottoms': '烈焰袍裙',
  1486. '/items/luna_robe_bottoms': '月神袍裙',
  1487. '/items/royal_water_robe_bottoms': '皇家水系袍裙',
  1488. '/items/royal_nature_robe_bottoms': '皇家自然系袍裙',
  1489. '/items/royal_fire_robe_bottoms': '皇家火系袍裙',
  1490. '/items/cheese_plate_legs': '奶酪腿甲',
  1491. '/items/verdant_plate_legs': '翠绿腿甲',
  1492. '/items/azure_plate_legs': '蔚蓝腿甲',
  1493. '/items/burble_plate_legs': '深紫腿甲',
  1494. '/items/crimson_plate_legs': '绛红腿甲',
  1495. '/items/rainbow_plate_legs': '彩虹腿甲',
  1496. '/items/holy_plate_legs': '神圣腿甲',
  1497. '/items/rough_chaps': '粗糙皮裤',
  1498. '/items/reptile_chaps': '爬行动物皮裤',
  1499. '/items/gobo_chaps': '哥布林皮裤',
  1500. '/items/beast_chaps': '野兽皮裤',
  1501. '/items/umbral_chaps': '暗影皮裤',
  1502. '/items/cotton_robe_bottoms': '棉袍裙',
  1503. '/items/linen_robe_bottoms': '亚麻袍裙',
  1504. '/items/bamboo_robe_bottoms': '竹袍裙',
  1505. '/items/silk_robe_bottoms': '丝绸袍裙',
  1506. '/items/radiant_robe_bottoms': '光辉袍裙',
  1507. '/items/enchanted_gloves': '附魔手套',
  1508. '/items/pincer_gloves': '蟹钳手套',
  1509. '/items/panda_gloves': '熊猫手套',
  1510. '/items/magnetic_gloves': '磁力手套',
  1511. '/items/dodocamel_gauntlets': '渡渡驼护手',
  1512. '/items/sighted_bracers': '瞄准护腕',
  1513. '/items/marksman_bracers': '神射护腕',
  1514. '/items/chrono_gloves': '时空手套',
  1515. '/items/cheese_gauntlets': '奶酪护手',
  1516. '/items/verdant_gauntlets': '翠绿护手',
  1517. '/items/azure_gauntlets': '蔚蓝护手',
  1518. '/items/burble_gauntlets': '深紫护手',
  1519. '/items/crimson_gauntlets': '绛红护手',
  1520. '/items/rainbow_gauntlets': '彩虹护手',
  1521. '/items/holy_gauntlets': '神圣护手',
  1522. '/items/rough_bracers': '粗糙护腕',
  1523. '/items/reptile_bracers': '爬行动物护腕',
  1524. '/items/gobo_bracers': '哥布林护腕',
  1525. '/items/beast_bracers': '野兽护腕',
  1526. '/items/umbral_bracers': '暗影护腕',
  1527. '/items/cotton_gloves': '棉手套',
  1528. '/items/linen_gloves': '亚麻手套',
  1529. '/items/bamboo_gloves': '竹手套',
  1530. '/items/silk_gloves': '丝手套',
  1531. '/items/radiant_gloves': '光辉手套',
  1532. '/items/collectors_boots': '收藏家靴',
  1533. '/items/shoebill_shoes': '鲸头鹳鞋',
  1534. '/items/black_bear_shoes': '黑熊鞋',
  1535. '/items/grizzly_bear_shoes': '棕熊鞋',
  1536. '/items/polar_bear_shoes': '北极熊鞋',
  1537. '/items/centaur_boots': '半人马靴',
  1538. '/items/sorcerer_boots': '巫师靴',
  1539. '/items/cheese_boots': '奶酪靴',
  1540. '/items/verdant_boots': '翠绿靴',
  1541. '/items/azure_boots': '蔚蓝靴',
  1542. '/items/burble_boots': '深紫靴',
  1543. '/items/crimson_boots': '绛红靴',
  1544. '/items/rainbow_boots': '彩虹靴',
  1545. '/items/holy_boots': '神圣靴',
  1546. '/items/rough_boots': '粗糙靴',
  1547. '/items/reptile_boots': '爬行动物靴',
  1548. '/items/gobo_boots': '哥布林靴',
  1549. '/items/beast_boots': '野兽靴',
  1550. '/items/umbral_boots': '暗影靴',
  1551. '/items/cotton_boots': '棉靴',
  1552. '/items/linen_boots': '亚麻靴',
  1553. '/items/bamboo_boots': '竹靴',
  1554. '/items/silk_boots': '丝靴',
  1555. '/items/radiant_boots': '光辉靴',
  1556. '/items/small_pouch': '小袋子',
  1557. '/items/medium_pouch': '中袋子',
  1558. '/items/large_pouch': '大袋子',
  1559. '/items/giant_pouch': '巨大袋子',
  1560. '/items/gluttonous_pouch': '贪食之袋',
  1561. '/items/guzzling_pouch': '暴饮之囊',
  1562. '/items/necklace_of_efficiency': '效率项链',
  1563. '/items/fighter_necklace': '战士项链',
  1564. '/items/ranger_necklace': '射手项链',
  1565. '/items/wizard_necklace': '巫师项链',
  1566. '/items/necklace_of_wisdom': '经验项链',
  1567. '/items/necklace_of_speed': '速度项链',
  1568. '/items/philosophers_necklace': '贤者项链',
  1569. '/items/earrings_of_gathering': '采集耳环',
  1570. '/items/earrings_of_essence_find': '精华发现耳环',
  1571. '/items/earrings_of_armor': '护甲耳环',
  1572. '/items/earrings_of_regeneration': '恢复耳环',
  1573. '/items/earrings_of_resistance': '抗性耳环',
  1574. '/items/earrings_of_rare_find': '稀有发现耳环',
  1575. '/items/earrings_of_critical_strike': '暴击耳环',
  1576. '/items/philosophers_earrings': '贤者耳环',
  1577. '/items/ring_of_gathering': '采集戒指',
  1578. '/items/ring_of_essence_find': '精华发现戒指',
  1579. '/items/ring_of_armor': '护甲戒指',
  1580. '/items/ring_of_regeneration': '恢复戒指',
  1581. '/items/ring_of_resistance': '抗性戒指',
  1582. '/items/ring_of_rare_find': '稀有发现戒指',
  1583. '/items/ring_of_critical_strike': '暴击戒指',
  1584. '/items/philosophers_ring': '贤者戒指',
  1585. '/items/basic_task_badge': '基础任务徽章',
  1586. '/items/advanced_task_badge': '高级任务徽章',
  1587. '/items/expert_task_badge': '专家任务徽章',
  1588. '/items/celestial_brush': '星空刷子',
  1589. '/items/cheese_brush': '奶酪刷子',
  1590. '/items/verdant_brush': '翠绿刷子',
  1591. '/items/azure_brush': '蔚蓝刷子',
  1592. '/items/burble_brush': '深紫刷子',
  1593. '/items/crimson_brush': '绛红刷子',
  1594. '/items/rainbow_brush': '彩虹刷子',
  1595. '/items/holy_brush': '神圣刷子',
  1596. '/items/celestial_shears': '星空剪刀',
  1597. '/items/cheese_shears': '奶酪剪刀',
  1598. '/items/verdant_shears': '翠绿剪刀',
  1599. '/items/azure_shears': '蔚蓝剪刀',
  1600. '/items/burble_shears': '深紫剪刀',
  1601. '/items/crimson_shears': '绛红剪刀',
  1602. '/items/rainbow_shears': '彩虹剪刀',
  1603. '/items/holy_shears': '神圣剪刀',
  1604. '/items/celestial_hatchet': '星空斧头',
  1605. '/items/cheese_hatchet': '奶酪斧头',
  1606. '/items/verdant_hatchet': '翠绿斧头',
  1607. '/items/azure_hatchet': '蔚蓝斧头',
  1608. '/items/burble_hatchet': '深紫斧头',
  1609. '/items/crimson_hatchet': '绛红斧头',
  1610. '/items/rainbow_hatchet': '彩虹斧头',
  1611. '/items/holy_hatchet': '神圣斧头',
  1612. '/items/celestial_hammer': '星空锤子',
  1613. '/items/cheese_hammer': '奶酪锤子',
  1614. '/items/verdant_hammer': '翠绿锤子',
  1615. '/items/azure_hammer': '蔚蓝锤子',
  1616. '/items/burble_hammer': '深紫锤子',
  1617. '/items/crimson_hammer': '绛红锤子',
  1618. '/items/rainbow_hammer': '彩虹锤子',
  1619. '/items/holy_hammer': '神圣锤子',
  1620. '/items/celestial_chisel': '星空凿子',
  1621. '/items/cheese_chisel': '奶酪凿子',
  1622. '/items/verdant_chisel': '翠绿凿子',
  1623. '/items/azure_chisel': '蔚蓝凿子',
  1624. '/items/burble_chisel': '深紫凿子',
  1625. '/items/crimson_chisel': '绛红凿子',
  1626. '/items/rainbow_chisel': '彩虹凿子',
  1627. '/items/holy_chisel': '神圣凿子',
  1628. '/items/celestial_needle': '星空针',
  1629. '/items/cheese_needle': '奶酪针',
  1630. '/items/verdant_needle': '翠绿针',
  1631. '/items/azure_needle': '蔚蓝针',
  1632. '/items/burble_needle': '深紫针',
  1633. '/items/crimson_needle': '绛红针',
  1634. '/items/rainbow_needle': '彩虹针',
  1635. '/items/holy_needle': '神圣针',
  1636. '/items/celestial_spatula': '星空锅铲',
  1637. '/items/cheese_spatula': '奶酪锅铲',
  1638. '/items/verdant_spatula': '翠绿锅铲',
  1639. '/items/azure_spatula': '蔚蓝锅铲',
  1640. '/items/burble_spatula': '深紫锅铲',
  1641. '/items/crimson_spatula': '绛红锅铲',
  1642. '/items/rainbow_spatula': '彩虹锅铲',
  1643. '/items/holy_spatula': '神圣锅铲',
  1644. '/items/celestial_pot': '星空壶',
  1645. '/items/cheese_pot': '奶酪壶',
  1646. '/items/verdant_pot': '翠绿壶',
  1647. '/items/azure_pot': '蔚蓝壶',
  1648. '/items/burble_pot': '深紫壶',
  1649. '/items/crimson_pot': '绛红壶',
  1650. '/items/rainbow_pot': '彩虹壶',
  1651. '/items/holy_pot': '神圣壶',
  1652. '/items/celestial_alembic': '星空蒸馏器',
  1653. '/items/cheese_alembic': '奶酪蒸馏器',
  1654. '/items/verdant_alembic': '翠绿蒸馏器',
  1655. '/items/azure_alembic': '蔚蓝蒸馏器',
  1656. '/items/burble_alembic': '深紫蒸馏器',
  1657. '/items/crimson_alembic': '绛红蒸馏器',
  1658. '/items/rainbow_alembic': '彩虹蒸馏器',
  1659. '/items/holy_alembic': '神圣蒸馏器',
  1660. '/items/celestial_enhancer': '星空强化器',
  1661. '/items/cheese_enhancer': '奶酪强化器',
  1662. '/items/verdant_enhancer': '翠绿强化器',
  1663. '/items/azure_enhancer': '蔚蓝强化器',
  1664. '/items/burble_enhancer': '深紫强化器',
  1665. '/items/crimson_enhancer': '绛红强化器',
  1666. '/items/rainbow_enhancer': '彩虹强化器',
  1667. '/items/holy_enhancer': '神圣强化器',
  1668. '/items/milk': '牛奶',
  1669. '/items/verdant_milk': '翠绿牛奶',
  1670. '/items/azure_milk': '蔚蓝牛奶',
  1671. '/items/burble_milk': '深紫牛奶',
  1672. '/items/crimson_milk': '绛红牛奶',
  1673. '/items/rainbow_milk': '彩虹牛奶',
  1674. '/items/holy_milk': '神圣牛奶',
  1675. '/items/cheese': '奶酪',
  1676. '/items/verdant_cheese': '翠绿奶酪',
  1677. '/items/azure_cheese': '蔚蓝奶酪',
  1678. '/items/burble_cheese': '深紫奶酪',
  1679. '/items/crimson_cheese': '绛红奶酪',
  1680. '/items/rainbow_cheese': '彩虹奶酪',
  1681. '/items/holy_cheese': '神圣奶酪',
  1682. '/items/log': '原木',
  1683. '/items/birch_log': '白桦原木',
  1684. '/items/cedar_log': '雪松原木',
  1685. '/items/purpleheart_log': '紫心原木',
  1686. '/items/ginkgo_log': '银杏原木',
  1687. '/items/redwood_log': '红杉原木',
  1688. '/items/arcane_log': '神秘原木',
  1689. '/items/lumber': '木板',
  1690. '/items/birch_lumber': '白桦木板',
  1691. '/items/cedar_lumber': '雪松木板',
  1692. '/items/purpleheart_lumber': '紫心木板',
  1693. '/items/ginkgo_lumber': '银杏木板',
  1694. '/items/redwood_lumber': '红杉木板',
  1695. '/items/arcane_lumber': '神秘木板',
  1696. '/items/rough_hide': '粗糙兽皮',
  1697. '/items/reptile_hide': '爬行动物皮',
  1698. '/items/gobo_hide': '哥布林皮',
  1699. '/items/beast_hide': '野兽皮',
  1700. '/items/umbral_hide': '暗影皮',
  1701. '/items/rough_leather': '粗糙皮革',
  1702. '/items/reptile_leather': '爬行动物皮革',
  1703. '/items/gobo_leather': '哥布林皮革',
  1704. '/items/beast_leather': '野兽皮革',
  1705. '/items/umbral_leather': '暗影皮革',
  1706. '/items/cotton': '棉花',
  1707. '/items/flax': '亚麻',
  1708. '/items/bamboo_branch': '竹子',
  1709. '/items/cocoon': '蚕茧',
  1710. '/items/radiant_fiber': '光辉纤维',
  1711. '/items/cotton_fabric': '棉花布料',
  1712. '/items/linen_fabric': '亚麻布料',
  1713. '/items/bamboo_fabric': '竹子布料',
  1714. '/items/silk_fabric': '丝绸',
  1715. '/items/radiant_fabric': '光辉布料',
  1716. '/items/egg': '鸡蛋',
  1717. '/items/wheat': '小麦',
  1718. '/items/sugar': '糖',
  1719. '/items/blueberry': '蓝莓',
  1720. '/items/blackberry': '黑莓',
  1721. '/items/strawberry': '草莓',
  1722. '/items/mooberry': '哞莓',
  1723. '/items/marsberry': '火星莓',
  1724. '/items/spaceberry': '太空莓',
  1725. '/items/apple': '苹果',
  1726. '/items/orange': '橙子',
  1727. '/items/plum': '李子',
  1728. '/items/peach': '桃子',
  1729. '/items/dragon_fruit': '火龙果',
  1730. '/items/star_fruit': '杨桃',
  1731. '/items/arabica_coffee_bean': '低级咖啡豆',
  1732. '/items/robusta_coffee_bean': '中级咖啡豆',
  1733. '/items/liberica_coffee_bean': '高级咖啡豆',
  1734. '/items/excelsa_coffee_bean': '特级咖啡豆',
  1735. '/items/fieriosa_coffee_bean': '火山咖啡豆',
  1736. '/items/spacia_coffee_bean': '太空咖啡豆',
  1737. '/items/green_tea_leaf': '绿茶叶',
  1738. '/items/black_tea_leaf': '黑茶叶',
  1739. '/items/burble_tea_leaf': '紫茶叶',
  1740. '/items/moolong_tea_leaf': '哞龙茶叶',
  1741. '/items/red_tea_leaf': '红茶叶',
  1742. '/items/emp_tea_leaf': '虚空茶叶',
  1743. '/items/catalyst_of_coinification': '点金催化剂',
  1744. '/items/catalyst_of_decomposition': '分解催化剂',
  1745. '/items/catalyst_of_transmutation': '转化催化剂',
  1746. '/items/prime_catalyst': '至高催化剂',
  1747. '/items/snake_fang': '蛇牙',
  1748. '/items/shoebill_feather': '鲸头鹳羽毛',
  1749. '/items/snail_shell': '蜗牛壳',
  1750. '/items/crab_pincer': '蟹钳',
  1751. '/items/turtle_shell': '乌龟壳',
  1752. '/items/marine_scale': '海洋鳞片',
  1753. '/items/treant_bark': '树皮',
  1754. '/items/centaur_hoof': '半人马蹄',
  1755. '/items/luna_wing': '月神翼',
  1756. '/items/gobo_rag': '哥布林抹布',
  1757. '/items/goggles': '护目镜',
  1758. '/items/magnifying_glass': '放大镜',
  1759. '/items/eye_of_the_watcher': '观察者之眼',
  1760. '/items/icy_cloth': '冰霜织物',
  1761. '/items/flaming_cloth': '烈焰织物',
  1762. '/items/sorcerers_sole': '魔法师鞋底',
  1763. '/items/chrono_sphere': '时空球',
  1764. '/items/frost_sphere': '冰霜球',
  1765. '/items/panda_fluff': '熊猫绒',
  1766. '/items/black_bear_fluff': '黑熊绒',
  1767. '/items/grizzly_bear_fluff': '棕熊绒',
  1768. '/items/polar_bear_fluff': '北极熊绒',
  1769. '/items/red_panda_fluff': '小熊猫绒',
  1770. '/items/magnet': '磁铁',
  1771. '/items/stalactite_shard': '钟乳石碎片',
  1772. '/items/living_granite': '花岗岩',
  1773. '/items/colossus_core': '巨像核心',
  1774. '/items/vampire_fang': '吸血鬼之牙',
  1775. '/items/werewolf_claw': '狼人之爪',
  1776. '/items/revenant_anima': '亡者之魂',
  1777. '/items/soul_fragment': '灵魂碎片',
  1778. '/items/infernal_ember': '地狱余烬',
  1779. '/items/demonic_core': '恶魔核心',
  1780. '/items/griffin_leather': '狮鹫之皮',
  1781. '/items/manticore_sting': '蝎狮之刺',
  1782. '/items/jackalope_antler': '鹿角兔之角',
  1783. '/items/dodocamel_plume': '渡渡驼之翎',
  1784. '/items/griffin_talon': '狮鹫之爪',
  1785. '/items/acrobats_ribbon': '杂技师彩带',
  1786. '/items/magicians_cloth': '魔术师织物',
  1787. '/items/chaotic_chain': '混沌锁链',
  1788. '/items/cursed_ball': '诅咒之球',
  1789. '/items/royal_cloth': '皇家织物',
  1790. '/items/knights_ingot': '骑士之锭',
  1791. '/items/bishops_scroll': '主教卷轴',
  1792. '/items/regal_jewel': '君王宝石',
  1793. '/items/sundering_jewel': '裂空宝石',
  1794. '/items/marksman_brooch': '神射胸针',
  1795. '/items/corsair_crest': '掠夺者徽章',
  1796. '/items/damaged_anchor': '破损船锚',
  1797. '/items/maelstrom_plating': '怒涛甲片',
  1798. '/items/kraken_leather': '克拉肯皮革',
  1799. '/items/kraken_fang': '克拉肯之牙',
  1800. '/items/butter_of_proficiency': '精通之油',
  1801. '/items/thread_of_expertise': '专精之线',
  1802. '/items/branch_of_insight': '洞察之枝',
  1803. '/items/gluttonous_energy': '贪食能量',
  1804. '/items/guzzling_energy': '暴饮能量',
  1805. '/items/milking_essence': '挤奶精华',
  1806. '/items/foraging_essence': '采摘精华',
  1807. '/items/woodcutting_essence': '伐木精华',
  1808. '/items/cheesesmithing_essence': '奶酪锻造精华',
  1809. '/items/crafting_essence': '制作精华',
  1810. '/items/tailoring_essence': '缝纫精华',
  1811. '/items/cooking_essence': '烹饪精华',
  1812. '/items/brewing_essence': '冲泡精华',
  1813. '/items/alchemy_essence': '炼金精华',
  1814. '/items/enhancing_essence': '强化精华',
  1815. '/items/swamp_essence': '沼泽精华',
  1816. '/items/aqua_essence': '海洋精华',
  1817. '/items/jungle_essence': '丛林精华',
  1818. '/items/gobo_essence': '哥布林精华',
  1819. '/items/eyessence': '眼精华',
  1820. '/items/sorcerer_essence': '法师精华',
  1821. '/items/bear_essence': '熊熊精华',
  1822. '/items/golem_essence': '魔像精华',
  1823. '/items/twilight_essence': '暮光精华',
  1824. '/items/abyssal_essence': '地狱精华',
  1825. '/items/chimerical_essence': '奇幻精华',
  1826. '/items/sinister_essence': '阴森精华',
  1827. '/items/enchanted_essence': '秘法精华',
  1828. '/items/pirate_essence': '海盗精华',
  1829. '/items/task_crystal': '任务水晶',
  1830. '/items/star_fragment': '星光碎片',
  1831. '/items/pearl': '珍珠',
  1832. '/items/amber': '琥珀',
  1833. '/items/garnet': '石榴石',
  1834. '/items/jade': '翡翠',
  1835. '/items/amethyst': '紫水晶',
  1836. '/items/moonstone': '月亮石',
  1837. '/items/sunstone': '太阳石',
  1838. '/items/philosophers_stone': '贤者之石',
  1839. '/items/crushed_pearl': '珍珠碎片',
  1840. '/items/crushed_amber': '琥珀碎片',
  1841. '/items/crushed_garnet': '石榴石碎片',
  1842. '/items/crushed_jade': '翡翠碎片',
  1843. '/items/crushed_amethyst': '紫水晶碎片',
  1844. '/items/crushed_moonstone': '月亮石碎片',
  1845. '/items/crushed_sunstone': '太阳石碎片',
  1846. '/items/crushed_philosophers_stone': '贤者之石碎片',
  1847. '/items/shard_of_protection': '保护碎片',
  1848. '/items/mirror_of_protection': '保护之镜'
  1849. }
  1850. }
  1851. }
  1852. }
  1853. };
  1854. mwi.itemNameToHridDict = {};
  1855. Object.entries(mwi.lang.en.translation.itemNames).forEach(([k, v]) => { mwi.itemNameToHridDict[v] = k });
  1856. Object.entries(mwi.lang.zh.translation.itemNames).forEach(([k, v]) => { mwi.itemNameToHridDict[v] = k });
  1857. }
  1858. function injectedInit() {
  1859. /*注入成功,使用游戏数据*/
  1860. mwi.itemNameToHridDict = {};
  1861. Object.entries(mwi.lang.en.translation.itemNames).forEach(([k, v]) => { mwi.itemNameToHridDict[v] = k });
  1862. Object.entries(mwi.lang.zh.translation.itemNames).forEach(([k, v]) => { mwi.itemNameToHridDict[v] = k });
  1863.  
  1864. mwi.MWICoreInitialized = true;
  1865. mwi.game.updateNotifications("info", mwi.isZh ? "mooket加载成功" : "mooket ready");
  1866. window.dispatchEvent(new CustomEvent("MWICoreInitialized"));
  1867. console.info("MWICoreInitialized");
  1868. }
  1869. staticInit();
  1870. new Promise(resolve => {
  1871. let count = 0;
  1872. const interval = setInterval(() => {
  1873. count++;
  1874. if (count > 30) {
  1875. console.warn("injecting failed,部分功能可能受到影响,可以尝试刷新页面或者关闭网页重开(Steam用户请忽略)");
  1876. clearInterval(interval)
  1877. }//最多等待30秒
  1878. if (mwi.game && mwi.lang && mwi?.game?.state?.character?.gameMode) {//等待必须组件加载完毕后再初始化
  1879. clearInterval(interval);
  1880. resolve();
  1881. }
  1882. }, 1000);
  1883. }).then(() => {
  1884. injectedInit();
  1885. });
  1886.  
  1887. class ReconnectWebSocket {
  1888. constructor(url, options = {}) {
  1889. this.url = url; // WebSocket 服务器地址
  1890. this.reconnectInterval = options.reconnectInterval || 10000; // 重连间隔(默认 5 秒)
  1891. this.heartbeatInterval = options.heartbeatInterval || 60000; // 心跳间隔(默认 60 秒)
  1892. this.maxReconnectAttempts = options.maxReconnectAttempts || 9999999; // 最大重连次数
  1893. this.reconnectAttempts = 0; // 当前重连次数
  1894. this.ws = null; // WebSocket 实例
  1895. this.heartbeatTimer = null; // 心跳定时器
  1896. this.isManualClose = false; // 是否手动关闭连接
  1897.  
  1898. // 绑定事件处理器
  1899. this.onOpen = options.onOpen || (() => { });
  1900. this.onMessage = options.onMessage || (() => { });
  1901. this.onClose = options.onClose || (() => { });
  1902. this.onError = options.onError || (() => { });
  1903.  
  1904. this.connect();
  1905. }
  1906.  
  1907. // 连接 WebSocket
  1908. connect() {
  1909. this.ws = new WebSocket(this.url);
  1910.  
  1911. // WebSocket 打开事件
  1912. this.ws.onopen = () => {
  1913. console.info('WebMooket connected');
  1914. this.reconnectAttempts = 0; // 重置重连次数
  1915. this.startHeartbeat(); // 启动心跳
  1916. this.onOpen();
  1917. };
  1918.  
  1919. // WebSocket 消息事件
  1920. this.ws.onmessage = (event) => {
  1921. this.onMessage(event.data);
  1922. };
  1923.  
  1924. // WebSocket 关闭事件
  1925. this.ws.onclose = () => {
  1926. console.warn('WebMooket disconnected');
  1927. this.stopHeartbeat(); // 停止心跳
  1928. this.onClose();
  1929.  
  1930. if (!this.isManualClose) {
  1931. this.reconnect();
  1932. }
  1933. };
  1934.  
  1935. // WebSocket 错误事件
  1936. this.ws.onerror = (error) => {
  1937. console.error('WebMooket error:', error);
  1938. this.onError(error);
  1939. };
  1940. }
  1941.  
  1942. // 启动心跳
  1943. startHeartbeat() {
  1944. this.heartbeatTimer = setInterval(() => {
  1945. if (this.ws.readyState === WebSocket.OPEN) {
  1946. //this.ws.send("ping");
  1947. }
  1948. }, this.heartbeatInterval);
  1949. }
  1950.  
  1951. // 停止心跳
  1952. stopHeartbeat() {
  1953. if (this.heartbeatTimer) {
  1954. clearInterval(this.heartbeatTimer);
  1955. this.heartbeatTimer = null;
  1956. }
  1957. }
  1958.  
  1959. // 自动重连
  1960. reconnect() {
  1961. if (this.reconnectAttempts < this.maxReconnectAttempts) {
  1962. console.info(`Reconnecting in ${this.reconnectInterval / 1000} seconds...`);
  1963. setTimeout(() => {
  1964. this.reconnectAttempts++;
  1965. this.connect();
  1966. }, this.reconnectInterval);
  1967. } else {
  1968. console.error('Max reconnection attempts reached');
  1969. }
  1970. }
  1971. warnTimer = null; // 警告定时器
  1972.  
  1973.  
  1974. // 发送消息
  1975. send(data) {
  1976. if (this.ws.readyState === WebSocket.OPEN) {
  1977. this.ws.send(data);
  1978. } else {
  1979. clearTimeout(this.warnTimer);
  1980. this.warnTimer = setTimeout(() => {
  1981. console.warn('WebMooket is not open');
  1982. }, 1000);
  1983. }
  1984. }
  1985.  
  1986. // 手动关闭连接
  1987. close() {
  1988. this.isManualClose = true;
  1989. this.ws.close();
  1990. }
  1991. }
  1992. /*实时市场模块*/
  1993. const HOST = "https://mooket.qi-e.top";
  1994. const MWIAPI_URL = "https://mooket.qi-e.top/market/api.json";
  1995.  
  1996. class CoreMarket {
  1997. marketData = {};//市场数据,带强化等级,存储格式{"/items/apple_yogurt:0":{ask,bid,time}}
  1998. fetchTimeDict = {};//记录上次API请求时间,防止频繁请求
  1999. ttl = 300;//缓存时间,单位秒
  2000. trade_ws = null;
  2001. subItems = [];
  2002. constructor() {
  2003. //core data
  2004. let marketDataStr = localStorage.getItem("MWICore_marketData") || "{}";
  2005. this.marketData = JSON.parse(marketDataStr);
  2006.  
  2007. //mwiapi data
  2008. let mwiapiJsonStr = localStorage.getItem("MWIAPI_JSON_NEW");
  2009. let mwiapiObj = null;
  2010. if (mwiapiJsonStr) {
  2011. mwiapiObj = JSON.parse(mwiapiJsonStr);
  2012. this.mergeMWIData(mwiapiObj);
  2013. }
  2014. if (!mwiapiObj || Date.now() / 1000 - mwiapiObj.timestamp > 600) {//超过10分才更新
  2015. fetch(MWIAPI_URL).then(res => {
  2016. res.text().then(mwiapiJsonStr => {
  2017. mwiapiObj = JSON.parse(mwiapiJsonStr);
  2018. this.mergeMWIData(mwiapiObj);
  2019. //更新本地缓存数据
  2020. localStorage.setItem("MWIAPI_JSON_NEW", mwiapiJsonStr);//更新本地缓存数据
  2021. console.info("MWIAPI_JSON updated:", new Date(mwiapiObj.timestamp * 1000).toLocaleString());
  2022. })
  2023. }).catch(err => { console.warn("MWIAPI_JSON update failed,using localdata"); });
  2024. }
  2025. //市场数据更新
  2026. hookMessage("market_item_order_books_updated", obj => this.handleMessageMarketItemOrderBooksUpdated(obj, true));
  2027. hookMessage("init_character_data", (msg) => {
  2028. if (msg.character.gameMode === "standard") {//标准模式才连接ws服务器,铁牛模式不连接ws服务器)
  2029. if (!this.trade_ws) {
  2030. this.trade_ws = new ReconnectWebSocket(`${HOST}/market/ws`);
  2031. this.trade_ws.onOpen = () => this.onWebsocketConnected();
  2032. this.trade_ws.onMessage = (data) => {
  2033. if (data === "ping") { return; }//心跳包,忽略
  2034. let obj = JSON.parse(data);
  2035. if (obj && obj.type === "market_item_order_books_updated") {
  2036. this.handleMessageMarketItemOrderBooksUpdated(obj, false);//收到市场服务器数据,不上传
  2037. } else if (obj && obj.type === "ItemPrice") {
  2038. this.processItemPrice(obj);
  2039. } else {
  2040. console.warn("unknown message:", data);
  2041. }
  2042. }
  2043. }
  2044. } else {
  2045. this.trade_ws?.disconnect();//断开连接
  2046. this.trade_ws = null;
  2047. }
  2048. });
  2049. setInterval(() => { this.save(); }, 1000 * 600);//十分钟保存一次
  2050. }
  2051. handleMessageMarketItemOrderBooksUpdated(obj, upload = false) {
  2052. //更新本地,游戏数据不带时间戳,市场服务器数据带时间戳
  2053. let timestamp = obj.time || parseInt(Date.now() / 1000);
  2054. let itemHrid = obj.marketItemOrderBooks.itemHrid;
  2055. obj.marketItemOrderBooks?.orderBooks?.forEach((item, enhancementLevel) => {
  2056. let bid = item.bids?.length > 0 ? item.bids[0].price : -1;
  2057. let ask = item.asks?.length > 0 ? item.asks[0].price : -1;
  2058. this.updateItem(itemHrid + ":" + enhancementLevel, { bid: bid, ask: ask, time: timestamp });
  2059. });
  2060. obj.time = timestamp;//添加时间戳
  2061. //上报数据
  2062. if (!upload) return;//不走上报逻辑,只在收到游戏服务器数据时上报
  2063.  
  2064. if (this.trade_ws) {//标准模式走ws
  2065. this.trade_ws.send(JSON.stringify(obj));//ws上报
  2066. } else {//铁牛上报
  2067. fetchWithTimeout(`${HOST}/market/upload/order`, {
  2068. method: "POST",
  2069. headers: {
  2070. "Content-Type": "application/json"
  2071. },
  2072. body: JSON.stringify(obj)
  2073. });
  2074. }
  2075. }
  2076. onWebsocketConnected() {
  2077. if (this.subItems?.length > 0) {//订阅物品列表
  2078. this.trade_ws?.send(JSON.stringify({ type: "SubscribeItems", items: this.subItems }));
  2079. }
  2080. }
  2081. subscribeItems(itemHridList) {//订阅物品列表,只在游戏服务器上报
  2082. this.subItems = itemHridList;
  2083. this.trade_ws?.send(JSON.stringify({ type: "SubscribeItems", items: itemHridList }));
  2084. }
  2085. /**
  2086. * 合并MWIAPI数据,只包含0级物品
  2087. *
  2088. * @param obj 包含市场数据的对象
  2089. */
  2090. mergeMWIData(obj) {
  2091. Object.entries(obj.marketData).forEach(([itemName, priceDict]) => {
  2092. let itemHrid = mwi.ensureItemHrid(itemName);
  2093. if (itemHrid) {
  2094. Object.entries(priceDict).forEach(([enhancementLevel, price]) => {
  2095. this.updateItem(itemHrid + ":" + enhancementLevel, { bid: price.b, ask: price.a, time: obj.timestamp }, false);//本地更新
  2096. });
  2097. }
  2098. });
  2099. this.save();
  2100. }
  2101. mergeCoreDataBeforeSave() {
  2102. let obj = JSON.parse(localStorage.getItem("MWICore_marketData") || "{}");
  2103. Object.entries(obj).forEach(([itemHridLevel, priceObj]) => {
  2104. this.updateItem(itemHridLevel, priceObj, false);//本地更新
  2105. });
  2106. //不保存,只合并
  2107. }
  2108. save() {//保存到localStorage
  2109. if (mwi.character?.gameMode !== "standard") return;//非标准模式不保存
  2110. this.mergeCoreDataBeforeSave();//从其他角色合并保存的数据
  2111. localStorage.setItem("MWICore_marketData", JSON.stringify(this.marketData));
  2112. }
  2113.  
  2114. /**
  2115. * 部分特殊物品的价格
  2116. * 例如金币固定1,牛铃固定为牛铃袋/10的价格
  2117. * @param {string} itemHrid - 物品hrid
  2118. * @returns {Price|null} - 返回对应商品的价格对象,如果没有则null
  2119. */
  2120. getSpecialPrice(itemHrid) {
  2121. switch (itemHrid) {
  2122. case "/items/coin":
  2123. return { bid: 1, ask: 1, time: Date.now() / 1000 };
  2124. case "/items/cowbell": {
  2125. let cowbells = this.getItemPrice("/items/bag_of_10_cowbells");
  2126. return cowbells && { bid: cowbells.bid / 10, ask: cowbells.ask / 10, time: cowbells.time };
  2127. }
  2128. case "/items/bag_of_10_cowbells": return null;//走普通get,这里返回空
  2129. case "/items/task_crystal": {//固定点金收益5000,这里计算可能有bug
  2130. return { bid: 5000, ask: 5000, time: Date.now() / 1000 }
  2131. }
  2132. default: {
  2133. let itemDetail = mwi.getItemDetail(itemHrid);
  2134. if (itemDetail?.categoryHrid === "/item_categories/loot") {//宝箱陨石
  2135. let totalAsk = 0;
  2136. let totalBid = 0;
  2137. let minTime = Date.now() / 1000;
  2138. this.getOpenableItems(itemHrid)?.forEach(openItem => {
  2139. let price = this.getItemPrice(openItem.itemHrid);
  2140. if (price) minTime = Math.min(minTime, price.time);
  2141. totalAsk += (price?.ask || 0) * openItem.count;//可以算平均价格
  2142. totalBid += (price?.bid || 0) * openItem.count;
  2143. });
  2144. return { bid: totalBid, ask: totalAsk, time: minTime };
  2145. }
  2146.  
  2147. if (mwi.character?.gameMode !== "standard") {//其他物品都按点金分解价值
  2148. return { ask: itemDetail.sellPrice * 5 * 0.7, bid: itemDetail.sellPrice * 5 * 0.7, time: Date.now() / 1000 };//铁牛模式显示物品价值使用点金价格*几率
  2149. }
  2150.  
  2151. return null;
  2152. }
  2153. }
  2154. }
  2155. getOpenableItems(itemHrid) {
  2156. let items = [];
  2157. for (let openItem of mwi.initClientData.openableLootDropMap[itemHrid]) {
  2158. if (openItem.itemHrid === "/items/purples_gift") continue;//防止循环
  2159. items.push({
  2160. itemHrid: openItem.itemHrid,
  2161. count: (openItem.minCount + openItem.maxCount) / 2 * openItem.dropRate
  2162. });
  2163. }
  2164. return items;
  2165. }
  2166. /**
  2167. * 获取商品的价格
  2168. *
  2169. * @param {string} itemHridOrName 商品HRID或名称
  2170. * @param {number} [enhancementLevel=0] 装备强化等级,普通商品默认为0
  2171. * @param {boolean} [peek=false] 是否只查看本地数据,不请求服务器数据
  2172. * @returns {number|null} 返回商品的价格,如果商品不存在或无法获取价格则返回null
  2173. */
  2174. getItemPrice(itemHridOrName, enhancementLevel = 0, peek = false) {
  2175. if (itemHridOrName?.includes(":")) {//兼容单名称,例如"itemHrid:enhancementLevel"
  2176. let arr = itemHridOrName.split(":");
  2177. itemHridOrName = arr[0];
  2178. enhancementLevel = parseInt(arr[1]);
  2179. }
  2180. let itemHrid = mwi.ensureItemHrid(itemHridOrName);
  2181. if (!itemHrid) return null;
  2182. let specialPrice = this.getSpecialPrice(itemHrid);
  2183. if (specialPrice) return specialPrice;
  2184. let itemHridLevel = itemHrid + ":" + enhancementLevel;
  2185.  
  2186. let priceObj = this.marketData[itemHridLevel];
  2187. if (peek) return priceObj;
  2188.  
  2189. if (Date.now() / 1000 - this.fetchTimeDict[itemHridLevel] < this.ttl) return priceObj;//1分钟内直接返回本地数据,防止频繁请求服务器
  2190. this.fetchTimeDict[itemHridLevel] = Date.now() / 1000;
  2191. this.trade_ws?.send(JSON.stringify({ type: "GetItemPrice", name: itemHrid, level: enhancementLevel }));
  2192. return priceObj;
  2193. }
  2194. processItemPrice(resObj) {
  2195. let itemHridLevel = resObj.name + ":" + resObj.level;
  2196. let priceObj = { bid: resObj.bid, ask: resObj.ask, time: resObj.time };
  2197. if (resObj.ttl) this.ttl = resObj.ttl;//更新ttl
  2198. this.updateItem(itemHridLevel, priceObj);
  2199. }
  2200. updateItem(itemHridLevel, priceObj, isFetch = true) {
  2201. let localItem = this.marketData[itemHridLevel];
  2202. if (isFetch) this.fetchTimeDict[itemHridLevel] = Date.now() / 1000;//fetch时间戳
  2203. if (!localItem || localItem.time < priceObj.time || localItem.time>Date.now() / 1000) {//服务器数据更新则更新本地数据
  2204.  
  2205. let risePercent = 0;
  2206. if (localItem) {
  2207. let oriPrice = (localItem.ask + localItem.bid);
  2208. let newPrice = (priceObj.ask + priceObj.bid);
  2209. if (oriPrice != 0) risePercent = newPrice / oriPrice - 1;
  2210. }
  2211. this.marketData[itemHridLevel] = { rise: risePercent, ask: priceObj.ask, bid: priceObj.bid, time: priceObj.time };//更新本地数据
  2212. dispatchEvent(new CustomEvent("MWICoreItemPriceUpdated", { detail: { priceObj: priceObj, itemHridLevel: itemHridLevel } }));//触发事件
  2213. }
  2214. }
  2215. resetRise() {
  2216. Object.entries(this.marketData).forEach(([k, v]) => {
  2217. v.rise = 0;
  2218. });
  2219. }
  2220. save() {
  2221. localStorage.setItem("MWICore_marketData", JSON.stringify(this.marketData));
  2222. }
  2223. }
  2224. mwi.coreMarket = new CoreMarket();
  2225. /*历史数据模块*/
  2226. function mooket() {
  2227.  
  2228. mwi.hookMessage("market_listings_updated", obj => {
  2229. obj.endMarketListings.forEach(order => {
  2230. if (order.filledQuantity == 0) return;//没有成交的订单不记录
  2231. let key = order.itemHrid + ":" + order.enhancementLevel;
  2232.  
  2233. let tradeItem = trade_history[key] || {}
  2234. if (order.isSell) {
  2235. tradeItem.sell = order.price;
  2236. } else {
  2237. tradeItem.buy = order.price;
  2238. }
  2239. trade_history[key] = tradeItem;
  2240. });
  2241. if (mwi.character?.gameMode === "standard") {//只记录标准模式的数据,因为铁牛不能交易
  2242. localStorage.setItem("mooket_trade_history", JSON.stringify(trade_history));//保存挂单数据
  2243. }
  2244. });
  2245.  
  2246.  
  2247.  
  2248. let curDay = 1;
  2249. let curHridName = null;
  2250. let curLevel = 0;
  2251. let curShowItemName = null;
  2252.  
  2253. let delayItemHridName = null;
  2254. let delayItemLevel = 0;
  2255.  
  2256. let chartWidth = 500;
  2257. let chartHeight = 280
  2258.  
  2259. let configStr = localStorage.getItem("mooket_config");
  2260. let config = configStr ? JSON.parse(configStr) : { "dayIndex": 0, "visible": true, "filter": { "bid": true, "ask": true, "mean": true }, "favo": {} };
  2261. config.favo = config.favo || {};
  2262. curDay = config.day;//读取设置
  2263.  
  2264. let trade_history = JSON.parse(localStorage.getItem("mooket_trade_history") || "{}");
  2265. function trade_history_migrate() {
  2266. if (config?.version > 1) return;
  2267. //把trade_history的key从itemHrid_enhancementLevel改为itemHrid:enhancementLevel
  2268. let new_trade_history = {};
  2269. for (let oldKey in trade_history) {
  2270. if (/_(\d+)/.test(oldKey)) {
  2271. let newKey = oldKey.replace(/_(\d+)/, ":$1");
  2272. new_trade_history[newKey] = trade_history[oldKey];
  2273. } else {
  2274.  
  2275. }
  2276. }
  2277. localStorage.setItem("mooket_trade_history", JSON.stringify(new_trade_history));//保存挂单数据
  2278. trade_history = new_trade_history;
  2279. config.version = 1.1;
  2280. }
  2281. trade_history_migrate();
  2282.  
  2283. window.onresize = function () {
  2284. checkSize();
  2285. };
  2286. function checkSize() {
  2287. if (window.innerWidth < window.innerHeight) {//竖屏,强制设置
  2288. config.w = chartWidth = window.innerWidth * 0.8;
  2289. config.h = chartHeight = chartWidth * 0.6;
  2290. } else {
  2291. chartWidth = 400;
  2292. chartHeight = 250;
  2293. }
  2294. }
  2295. checkSize();
  2296.  
  2297. // 创建容器元素并设置样式和位置
  2298. const container = document.createElement('div');
  2299. //container.style.border = "1px solid #ccc"; //边框样式
  2300. container.style.border = "1px solid #90a6eb"; //边框样式
  2301. container.style.backgroundColor = "#282844";
  2302. container.style.position = "fixed";
  2303. container.style.zIndex = 10000;
  2304. container.style.top = `${Math.max(0, Math.min(config.y || 0, window.innerHeight - 50))}px`; //距离顶部位置
  2305. container.style.left = `${Math.max(0, Math.min(config.x || 0, window.innerWidth - 50))}px`; //距离左侧位置
  2306. container.style.width = `${Math.max(0, Math.min(config.w || chartWidth, window.innerWidth))}px`; //容器宽度
  2307. container.style.height = `${Math.max(0, Math.min(config.h || chartHeight, window.innerHeight))}px`; //容器高度
  2308. container.style.resize = "both";
  2309. container.style.overflow = "auto";
  2310. container.style.display = "none";
  2311. container.style.flexDirection = "column";
  2312. container.style.flex = "1";
  2313. container.style.minHeight = "35px";
  2314. container.style.minWidth = "112px";
  2315. container.style.maxWidth = window.clientWidth;
  2316. container.style.userSelect = "none";
  2317.  
  2318. let mouseDragging = false;
  2319. let touchDragging = false;
  2320. let offsetX, offsetY;
  2321.  
  2322. let resizeEndTimer = null;
  2323. container.addEventListener("resize", () => {
  2324. if (resizeEndTimer) clearTimeout(resizeEndTimer);
  2325. resizeEndTimer = setTimeout(save_config, 1000);
  2326. });
  2327. container.addEventListener("mousedown", function (e) {
  2328. if (mouseDragging || touchDragging) return;
  2329. const rect = container.getBoundingClientRect();
  2330. if (container.style.resize === "both" && (e.clientX > rect.right - 10 && e.clientY > rect.bottom - 10)) return;
  2331. mouseDragging = true;
  2332. offsetX = e.clientX - container.offsetLeft;
  2333. offsetY = e.clientY - container.offsetTop;
  2334. });
  2335.  
  2336. document.addEventListener("mousemove", function (e) {
  2337. if (mouseDragging) {
  2338. var newX = e.clientX - offsetX;
  2339. var newY = e.clientY - offsetY;
  2340.  
  2341. if (newX < 0) newX = 0;
  2342. if (newY < 0) newY = 0;
  2343. if (newX > window.innerWidth - container.offsetWidth) newX = window.innerWidth - container.offsetWidth;
  2344. if (newY > window.innerHeight - container.offsetHeight) newY = window.innerHeight - container.offsetHeight;
  2345.  
  2346. container.style.left = newX + "px";
  2347. container.style.top = newY + "px";
  2348. }
  2349. });
  2350.  
  2351. document.addEventListener("mouseup", function () {
  2352. if (mouseDragging) {
  2353. mouseDragging = false;
  2354. save_config();
  2355. }
  2356. });
  2357.  
  2358. container.addEventListener("touchstart", function (e) {
  2359. if (mouseDragging || touchDragging) return;
  2360. const rect = container.getBoundingClientRect();
  2361. let touch = e.touches[0];
  2362. if (container.style.resize === "both" && (e.clientX > rect.right - 10 && e.clientY > rect.bottom - 10)) return;
  2363. touchDragging = true;
  2364. offsetX = touch.clientX - container.offsetLeft;
  2365. offsetY = touch.clientY - container.offsetTop;
  2366. });
  2367.  
  2368. document.addEventListener("touchmove", function (e) {
  2369. if (touchDragging) {
  2370. let touch = e.touches[0];
  2371. var newX = touch.clientX - offsetX;
  2372. var newY = touch.clientY - offsetY;
  2373.  
  2374. if (newX < 0) newX = 0;
  2375. if (newY < 0) newY = 0;
  2376. if (newX > window.innerWidth - container.offsetWidth) newX = window.innerWidth - container.offsetWidth;
  2377. if (newY > window.innerHeight - container.offsetHeight) newY = window.innerHeight - container.offsetHeight;
  2378.  
  2379. container.style.left = newX + "px";
  2380. container.style.top = newY + "px";
  2381. }
  2382. });
  2383.  
  2384. document.addEventListener("touchend", function () {
  2385. if (touchDragging) {
  2386. touchDragging = false;
  2387. save_config();
  2388. }
  2389. });
  2390. document.body.appendChild(container);
  2391.  
  2392. const ctx = document.createElement('canvas');
  2393. ctx.id = "mooket_chart";
  2394. container.appendChild(ctx);
  2395.  
  2396.  
  2397.  
  2398. // 创建下拉菜单并设置样式和位置
  2399. let uiContainer = document.createElement('div');
  2400. uiContainer.style.position = 'absolute';
  2401. uiContainer.style.top = '5px';
  2402. uiContainer.style.right = '16px';
  2403. uiContainer.style.fontSize = '14px';
  2404.  
  2405. //wrapper.style.backgroundColor = '#fff';
  2406. uiContainer.style.flexShrink = 0;
  2407. container.appendChild(uiContainer);
  2408.  
  2409. const days = [1, 3, 7, 14, 30, 90, 180];
  2410. curDay = days[config.dayIndex];
  2411.  
  2412. let select = document.createElement('select');
  2413. select.style.cursor = 'pointer';
  2414. select.style.verticalAlign = 'middle';
  2415. select.onchange = function () {
  2416. config.dayIndex = this.selectedIndex;
  2417. if (curHridName) requestItemPrice(curHridName, this.value, curLevel);
  2418. save_config();
  2419. };
  2420.  
  2421. for (let i = 0; i < days.length; i++) {
  2422. let option = document.createElement('option');
  2423. option.value = days[i];
  2424. if (i === config.dayIndex) option.selected = true;
  2425. select.appendChild(option);
  2426. }
  2427. updateMoodays();
  2428. function updateMoodays() {
  2429. for (let i = 0; i < select.options.length; i++) {
  2430. select.options[i].text = days[i] + (mwi.isZh ? "天" : "d");
  2431. }
  2432. }
  2433.  
  2434. uiContainer.appendChild(select);
  2435.  
  2436. //添加一个radio用于设置自动隐藏显示
  2437. let btn_auto = document.createElement('input');
  2438. btn_auto.type = 'checkbox';
  2439. btn_auto.style.cursor = 'pointer';
  2440. btn_auto.style.verticalAlign = 'middle';
  2441. btn_auto.title = mwi.isZh ? "在市场外隐藏" : "hide when out of marketplace";
  2442. btn_auto.checked = config.autoHide;
  2443. btn_auto.id = "mooket_autoHide";
  2444.  
  2445. btn_auto.onchange = function () {
  2446. config.autoHide = this.checked;
  2447. save_config();
  2448. }
  2449. uiContainer.appendChild(btn_auto);
  2450. let label_auto = document.createElement('label');
  2451. label_auto.htmlFor = btn_auto.id;
  2452. label_auto.style.cursor = 'pointer';
  2453. label_auto.style.color = 'white';
  2454. label_auto.style.marginLeft = '5px';
  2455. label_auto.textContent = mwi.isZh ? "自动隐藏" : "Auto Hide";
  2456. uiContainer.appendChild(label_auto);
  2457.  
  2458. // 创建一个容器元素并设置样式和位置
  2459. const leftContainer = document.createElement('div');
  2460. leftContainer.style.padding = '2px'
  2461. leftContainer.style.display = 'flex';
  2462. leftContainer.style.flexDirection = 'row';
  2463. leftContainer.style.alignItems = 'center'
  2464. container.appendChild(leftContainer);
  2465.  
  2466. //添加一个btn隐藏canvas和wrapper
  2467. let btn_close = document.createElement('input');
  2468. btn_close.type = 'button';
  2469. btn_close.classList.add('Button_button__1Fe9z')
  2470. btn_close.value = '📈隐藏';
  2471. btn_close.style.margin = 0;
  2472. btn_close.style.cursor = 'pointer';
  2473.  
  2474. leftContainer.appendChild(btn_close);
  2475.  
  2476. //添加一个按钮切换simpleInfo和fullInfo
  2477.  
  2478. let btn_switch = document.createElement('input');
  2479. btn_switch.type = 'button';
  2480. btn_switch.value = "👁";
  2481. btn_switch.title = mwi.isZh ? "切换显示模式" : "Detail level";
  2482. btn_switch.style.cursor = 'pointer';
  2483. btn_switch.style.padding = "0 3px";
  2484. btn_switch.style.fontSize = "16px";
  2485.  
  2486. btn_switch.onclick = function () {
  2487. const modeCycle = {
  2488. icon: "iconPercent",
  2489. iconPercent: "iconPrice",
  2490. iconPrice: "iconFull",
  2491. iconFull: "normalPercent",
  2492. normalPercent: "normalPrice",
  2493. normalPrice: "normalFull",
  2494. normalFull: "full",
  2495. full: "none",
  2496. none: "icon",
  2497. };
  2498.  
  2499. const target = uiContainer.style.display === "none" ? "favoModeOff" : "favoModeOn";
  2500. config[target] = modeCycle[config[target]] || "icon";
  2501. updateFavo();
  2502. container.style.width = "min-content";
  2503. container.style.height = "min-content";
  2504. save_config();
  2505. };
  2506. leftContainer.appendChild(btn_switch);
  2507.  
  2508.  
  2509. let btn_relayout = document.createElement('input');
  2510. btn_relayout.type = 'checkbox';
  2511. btn_relayout.title = mwi.isZh ? "固定精简面板大小" : "Keep minibox size";
  2512. btn_relayout.checked = config.keepsize;
  2513. btn_relayout.onchange = function () {
  2514. config.keepsize = this.checked;
  2515. save_config();
  2516. };
  2517. leftContainer.appendChild(btn_relayout);
  2518. //自选
  2519. let favoContainer = document.createElement('div');
  2520. favoContainer.style.fontSize = '15px';
  2521. favoContainer.style.maxWidth = "100%";
  2522. favoContainer.style.display = 'flex';
  2523. favoContainer.style.flexWrap = 'wrap'
  2524. favoContainer.style.position = 'absolute';
  2525. favoContainer.style.top = '35px';
  2526. favoContainer.style.lineHeight = "15px";
  2527. favoContainer.style.overflow = 'auto';
  2528. favoContainer.title = "📈🖱❌";
  2529.  
  2530. container.appendChild(favoContainer);
  2531.  
  2532. function sendFavo() {
  2533. if (mwi.character?.gameMode !== "standard") return;
  2534. let items = new Set();
  2535. Object.entries(config.favo || {}).forEach(([itemHridLevel, data]) => {
  2536. items.add(itemHridLevel.split(":")[0]);
  2537. });
  2538. //if(items.size > 10)mwi.game?.updateNotifications("info",mwi.isZh?"当前的自选物品种类已超过10个,服务器仅会自动推送前10个物品的最新价格":"");
  2539. mwi.coreMarket.subscribeItems(Array.from(items));
  2540. updateFavo();
  2541. }
  2542. function addFavo(itemHridLevel) {
  2543. if (mwi.character?.gameMode !== "standard") return;
  2544. let priceObj = mwi.coreMarket.getItemPrice(itemHridLevel);
  2545. config.favo[itemHridLevel] = { ask: priceObj.ask, bid: priceObj.bid, time: priceObj.time };
  2546. save_config();
  2547. sendFavo();
  2548. }
  2549. function removeFavo(itemHridLevel) {
  2550. if (mwi.character?.gameMode !== "standard") return;
  2551. delete config.favo[itemHridLevel];
  2552. save_config();
  2553. sendFavo();
  2554. }
  2555. function updateFavo() {
  2556. if (mwi.character?.gameMode !== "standard") {
  2557. favoContainer.style.display = 'none';
  2558. return;
  2559. }
  2560. favoContainer.style.display = 'flex';
  2561. //在favoContainer中添加config.favo dict中 key对应的元素,或者删除不存在的
  2562. let items = Object.keys(config.favo);
  2563. for (let i = 0; i < favoContainer.children.length; i++) {
  2564. if (!items.includes(favoContainer.children[i].id)) {
  2565. favoContainer.removeChild(favoContainer.children[i]);
  2566. }
  2567. }
  2568. for (let itemHridLevel of items) {
  2569. let favoItemDiv = document.getElementById(itemHridLevel);
  2570.  
  2571. let oldPrice = config.favo[itemHridLevel];
  2572. let newPrice = mwi.coreMarket.getItemPrice(itemHridLevel);
  2573.  
  2574. oldPrice.ask = oldPrice?.ask > 0 ? oldPrice.ask : newPrice?.ask;//如果旧价格没有ask,就用新价格的ask代替
  2575. oldPrice.bid = oldPrice?.bid > 0 ? oldPrice.bid : newPrice?.bid;//如果旧价格没有bid,就用新价格的bid代替
  2576.  
  2577.  
  2578. let priceDelta = {
  2579. ask: newPrice?.ask > 0 ? showNumber(newPrice.ask) : "-",
  2580. bid: newPrice?.bid > 0 ? showNumber(newPrice.bid) : "-",
  2581. askRise: (oldPrice?.ask > 0 && newPrice?.ask > 0) ? (100 * (newPrice.ask - oldPrice.ask) / oldPrice.ask).toFixed(1) : 0,
  2582. bidRise: (oldPrice?.bid > 0 && newPrice?.bid > 0) ? (100 * (newPrice.bid - oldPrice.bid) / oldPrice.bid).toFixed(1) : 0,
  2583. };
  2584. let [itemHrid, level] = itemHridLevel.split(":");
  2585. let iconName = itemHrid.split("/")[2];
  2586. let itemName = mwi.isZh ? mwi.lang.zh.translation.itemNames[itemHrid] : mwi.lang.en.translation.itemNames[itemHrid];
  2587.  
  2588.  
  2589. if (!favoItemDiv) {
  2590. favoItemDiv = document.createElement('div');
  2591. //div.style.border = '1px solid #90a6eb';
  2592. favoItemDiv.style.color = 'white';
  2593. favoItemDiv.style.whiteSpace = 'nowrap';
  2594. favoItemDiv.style.cursor = 'pointer';
  2595. favoItemDiv.onclick = function () {
  2596. let [itemHrid, level] = itemHridLevel.split(":")
  2597. if (uiContainer.style.display === 'none') {
  2598. delayItemHridName = itemHrid;
  2599. delayItemLevel = parseInt(level);
  2600. } else {
  2601. requestItemPrice(itemHrid, curDay, level);
  2602. }
  2603. mwi.game?.handleGoToMarketplace(itemHrid, parseInt(level));//打开市场
  2604. //toggleShow(true);
  2605. };
  2606. favoItemDiv.oncontextmenu = (event) => { event.preventDefault(); removeFavo(itemHridLevel); };
  2607. favoItemDiv.id = itemHridLevel;
  2608. favoContainer.appendChild(favoItemDiv);
  2609. }
  2610. //鼠标如果在div范围内就显示fullinfo
  2611. let favoMode = uiContainer.style.display === 'none' ? config.favoModeOff : config.favoModeOn;
  2612. let title = `${itemName}${level > 0 ? `(+${level})` : ""} ${priceDelta.ask} ${priceDelta.askRise > 0 ? "+" : ""}${priceDelta.askRise}% ${new Date((newPrice?.time || 0) * 1000).toLocaleString()}`;
  2613. switch (favoMode) {
  2614. case "none":
  2615. favoItemDiv.innerHTML = "";
  2616. break;
  2617. case "full":
  2618. favoItemDiv.innerHTML = `
  2619. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2620. <svg width="15px" height="15px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2621. <span>${itemName}${level > 0 ? `(+${level})` : ""}</span>
  2622. <span style="color:${priceDelta.askRise == 0 ? "white" : priceDelta.askRise > 0 ? "red" : "lime"}">${priceDelta.ask}</span>
  2623. <span style="color:white;background-color:${priceDelta.askRise == 0 ? "black" : priceDelta.askRise > 0 ? "brown" : "green"}">${priceDelta.askRise > 0 ? "+" : ""}${priceDelta.askRise}%</span>
  2624. <span style="color:${priceDelta.bidRise == 0 ? "white" : priceDelta.bidRise > 0 ? "red" : "lime"}">${priceDelta.bid}</span>
  2625. <span style="color:white;background-color:${priceDelta.bidRise == 0 ? "black" : priceDelta.bidRise > 0 ? "brown" : "green"}">${priceDelta.bidRise > 0 ? "+" : ""}${priceDelta.bidRise}%</span>
  2626. </div>
  2627. `;
  2628. break;
  2629. case "iconPercent":
  2630. favoItemDiv.innerHTML = `
  2631. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2632. <svg width="15px" height="15px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2633. <span style="color:white;background-color:${priceDelta.askRise == 0 ? "transparent" : priceDelta.askRise > 0 ? "brown" : "green"}">${priceDelta.askRise == 0 ? "" : priceDelta.askRise > 0 ? "+" + priceDelta.askRise + "%" : priceDelta.askRise + "%"}</span>
  2634. </div>
  2635. `;
  2636. break;
  2637. case "iconPrice":
  2638. favoItemDiv.innerHTML = `
  2639. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2640. <svg width="15px" height="15px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2641. <span style="color:${priceDelta.askRise == 0 ? "white" : priceDelta.askRise > 0 ? "red" : "lime"}">${priceDelta.ask}</span>
  2642. </div>
  2643. `;
  2644. break;
  2645. case "iconFull":
  2646. favoItemDiv.innerHTML = `
  2647. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2648. <svg width="15px" height="15px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2649. <span style="color:${priceDelta.askRise == 0 ? "white" : priceDelta.askRise > 0 ? "red" : "lime"}">${priceDelta.ask}</span>
  2650. <span style="color:white;background-color:${priceDelta.askRise == 0 ? "black" : priceDelta.askRise > 0 ? "brown" : "green"}">${priceDelta.askRise > 0 ? "+" : ""}${priceDelta.askRise}%</span>
  2651. </div>
  2652. `;
  2653. break;
  2654. case "normalPercent":
  2655. favoItemDiv.innerHTML = `
  2656. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2657. <svg width="15px" height="15px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2658. <span>${itemName}${level > 0 ? `(+${level})` : ""}</span>
  2659. <span style="color:white;background-color:${priceDelta.askRise == 0 ? "transparent" : priceDelta.askRise > 0 ? "brown" : "green"}">${priceDelta.askRise == 0 ? "" : priceDelta.askRise > 0 ? "+" + priceDelta.askRise + "%" : priceDelta.askRise + "%"}</span>
  2660. </div>
  2661. `;
  2662. break;
  2663. case "normalPrice":
  2664. favoItemDiv.innerHTML = `
  2665. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2666. <svg width="15px" height="15px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2667. <span>${itemName}${level > 0 ? `(+${level})` : ""}</span>
  2668. <span style="color:${priceDelta.askRise == 0 ? "white" : priceDelta.askRise > 0 ? "red" : "lime"}">${priceDelta.ask}</span>
  2669. </div>
  2670. `;
  2671. break;
  2672. case "normalFull":
  2673. favoItemDiv.innerHTML = `
  2674. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2675. <svg width="15px" height="15px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2676. <span>${itemName}${level > 0 ? `(+${level})` : ""}</span>
  2677. <span style="color:${priceDelta.askRise == 0 ? "white" : priceDelta.askRise > 0 ? "red" : "lime"}">${priceDelta.ask}</span>
  2678. <span style="color:white;background-color:${priceDelta.askRise == 0 ? "black" : priceDelta.askRise > 0 ? "brown" : "green"}">${priceDelta.askRise > 0 ? "+" : ""}${priceDelta.askRise}%</span>
  2679. </div>
  2680. `;
  2681. break;
  2682. default://icon
  2683. favoItemDiv.innerHTML = `
  2684. <div title="${title}" style="display:inline-block;border:1px solid #98a7e9;">
  2685. <svg width="20px" height="20px" style="display:inline-block"><use href="/static/media/items_sprite.6d12eb9d.svg#${iconName}"></use></svg>
  2686. </div>
  2687. `;
  2688. }
  2689. }
  2690. }
  2691.  
  2692. sendFavo();//初始化自选
  2693. addEventListener('MWICoreItemPriceUpdated', updateFavo);
  2694. addEventListener("MWILangChanged", () => {
  2695. updateMoodays();
  2696. updateFavo();
  2697. btn_switch.title = mwi.isZh ? "显示模式" : "Detail Level";
  2698. btn_auto.title = mwi.isZh ? "在市场外隐藏" : "Hide out of marketplace";
  2699. label_auto.textContent = mwi.isZh ? "自动隐藏" : "AutoHide";
  2700. if (uiContainer.style.display === 'none') {
  2701. btn_close.value = mwi.isZh ? "📈显示" : "Show";
  2702. } else {
  2703. btn_close.value = mwi.isZh ? "📈隐藏" : "Hide";
  2704. }
  2705.  
  2706. });
  2707. btn_close.onclick = toggle;
  2708. function toggle() {
  2709.  
  2710. if (uiContainer.style.display === 'none') {//展开
  2711. uiContainer.style.display = ctx.style.display = 'block';
  2712.  
  2713. btn_close.value = '📈' + (mwi.isZh ? "隐藏" : "Hide");
  2714. leftContainer.style.position = 'absolute'
  2715. leftContainer.style.top = '1px';
  2716. leftContainer.style.left = '1px';
  2717. container.style.width = config.w + "px";
  2718. container.style.height = config.h + "px";
  2719. container.style.minHeight = "150px";
  2720. container.style.minWidth = "200px";
  2721.  
  2722. config.visible = true;
  2723. favoContainer.style.top = "35px";
  2724. favoContainer.style.right = 0;
  2725. favoContainer.style.left = null;
  2726. favoContainer.style.position = 'absolute';
  2727.  
  2728. requestItemPrice(delayItemHridName, curDay, delayItemLevel);
  2729. updateFavo();
  2730. save_config();
  2731. } else {//隐藏
  2732. uiContainer.style.display = ctx.style.display = 'none';
  2733.  
  2734. container.style.width = config.minWidth + "px";
  2735. container.style.height = config.minHeight + "px";
  2736. container.style.minHeight = "min-content";
  2737. container.style.minWidth = "112px";
  2738.  
  2739. if (!config.keepsize) {
  2740. container.style.width = "min-content";
  2741. container.style.height = "min-content";
  2742. }
  2743.  
  2744. btn_close.value = '📈' + (mwi.isZh ? "显示" : "Show");
  2745. leftContainer.style.position = 'relative'
  2746. leftContainer.style.top = 0;
  2747. leftContainer.style.left = 0;
  2748. favoContainer.style.top = 0;
  2749. favoContainer.style.left = 0;
  2750. favoContainer.style.right = null;
  2751. favoContainer.style.position = 'relative';
  2752. config.visible = false;
  2753.  
  2754. updateFavo();
  2755. save_config();
  2756. }
  2757. };
  2758. function toggleShow(show = true) {
  2759. if ((uiContainer.style.display !== 'none') !== show) {
  2760. toggle()
  2761. }
  2762. }
  2763. let chart = new Chart(ctx, {
  2764. type: 'line',
  2765. data: {
  2766. labels: [],
  2767. datasets: []
  2768. },
  2769. options: {
  2770. onClick: save_config,
  2771. responsive: true,
  2772. maintainAspectRatio: false,
  2773. pointRadius: 0,
  2774. pointHitRadius: 20,
  2775. scales: {
  2776. x: {
  2777. type: 'time',
  2778. time: {
  2779. displayFormats: {
  2780. hour: 'HH:mm',
  2781. day: 'MM/dd'
  2782. }
  2783. },
  2784. title: {
  2785. display: false
  2786. },
  2787. grid: {
  2788. color: "rgba(255,255,255,0.2)"
  2789. },
  2790. ticks: {
  2791. color: "#e7e7e7"
  2792. }
  2793. },
  2794. y: {
  2795. beginAtZero: false,
  2796. title: {
  2797. display: false,
  2798. color: "white",
  2799. },
  2800. grid: {
  2801. color: "rgba(255,255,255,0.2)",
  2802. },
  2803. ticks: {
  2804. color: "#e7e7e7",
  2805. // 自定义刻度标签格式化
  2806. callback: showNumber
  2807. }
  2808. }
  2809. },
  2810. plugins: {
  2811. tooltip: { mode: 'index', intersect: false, bodyColor: "#e7e7e7", titleColor: "#e7e7e7" },
  2812. crosshair: {
  2813. line: { color: '#AAAAAA', width: 1 },
  2814. zoom: { enabled: false }
  2815. },
  2816. title: {
  2817. display: true,
  2818. text: "",
  2819. color: "#e7e7e7",
  2820. font: {
  2821. size: 15,
  2822. weight: 'bold',
  2823. }
  2824. },
  2825. legend: {
  2826. display: true,
  2827. labels: {
  2828. color: "#e7e7e7"
  2829. }
  2830. },
  2831. }
  2832. }
  2833. });
  2834.  
  2835. function requestItemPrice(itemHridName, day = 1, level = 0) {
  2836. if (!itemHridName) return;
  2837. if (curHridName === itemHridName && curLevel == level && curDay == day) return;//防止重复请求
  2838.  
  2839. delayItemHridName = curHridName = itemHridName;
  2840. delayItemLevel = curLevel = level;
  2841. curDay = day;
  2842.  
  2843. curShowItemName = mwi.isZh ? mwi.lang.zh.translation.itemNames[itemHridName] : mwi.lang.en.translation.itemNames[itemHridName];
  2844. curShowItemName += curLevel > 0 ? `(+${curLevel})` : "";
  2845.  
  2846. let time = day * 3600 * 24;
  2847.  
  2848. const params = new URLSearchParams();
  2849. params.append("name", curHridName);
  2850. params.append("level", curLevel);
  2851. params.append("time", time);
  2852. fetch(`${HOST}/market/item/history?${params}`).then(res => {
  2853. res.json().then(data => updateChart(data, curDay));
  2854. }).catch(err => console.error("请求历史价格失败", err));
  2855.  
  2856. }
  2857.  
  2858. function formatTime(timestamp, range) {
  2859. const date = new Date(timestamp * 1000);
  2860. const pad = n => n.toString().padStart(2, '0');
  2861.  
  2862. // 获取各时间组件
  2863. const hours = pad(date.getHours());
  2864. const minutes = pad(date.getMinutes());
  2865. const day = pad(date.getDate());
  2866. const month = pad(date.getMonth() + 1);
  2867. const shortYear = date.getFullYear().toString().slice(-2);
  2868.  
  2869. // 根据时间范围选择格式
  2870. switch (parseInt(range)) {
  2871. case 1: // 1天:只显示时间
  2872. return `${hours}:${minutes}`;
  2873.  
  2874. case 3: // 3天:日+时段
  2875. return `${hours}:${minutes}`;
  2876.  
  2877. case 7: // 7天:月/日 + 时段
  2878. return `${day}.${hours}`;
  2879. case 14: // 14天:月/日 + 时段
  2880. return `${day}.${hours}`;
  2881. case 30: // 30天:月/日
  2882. return `${month}/${day}`;
  2883.  
  2884. default: // 180天:年/月
  2885. return `${shortYear}/${month}`;
  2886. }
  2887. }
  2888.  
  2889. function showNumber(num) {
  2890. if (isNaN(num)) return num;
  2891. if (num === 0) return "0"; // 单独处理0的情况
  2892.  
  2893. const absNum = Math.abs(num);
  2894.  
  2895. //num保留一位小数
  2896. if (num < 1) return num.toFixed(2);
  2897.  
  2898. return absNum >= 1e10 ? `${(num / 1e9).toFixed(1)}B` :
  2899. absNum >= 1e7 ? `${(num / 1e6).toFixed(1)}M` :
  2900. absNum >= 1e5 ? `${Math.floor(num / 1e3)}K` :
  2901. `${Math.floor(num)}`;
  2902. }
  2903. //data={'bid':[{time:1,price:1}],'ask':[{time:1,price:1}]}
  2904. function updateChart(data, day) {
  2905. //字段名差异
  2906. data.bid = data.bid || data.bids
  2907. data.ask = data.ask || data.asks;
  2908. //过滤异常元素
  2909. for (let i = data.bid.length - 1; i >= 0; i--) {
  2910. if (data.bid[i].price < 0 && data.ask[i].price < 0) {//都小于0,认为是异常数据,直接删除
  2911. data.bid.splice(i, 1);
  2912. data.ask.splice(i, 1);
  2913. } else {//小于0则设置为0
  2914. data.bid[i].price = Math.max(0, data.bid[i].price);
  2915. data.ask[i].price = Math.max(0, data.ask[i].price);
  2916. }
  2917. }
  2918.  
  2919. //timestamp转日期时间
  2920. //根据day输出不同的时间表示,<3天显示时分,<=7天显示日时,<=30天显示月日,>30天显示年月
  2921.  
  2922. const labels = data.bid.map(x => new Date(x.time * 1000));
  2923. chart.data.labels = labels;
  2924.  
  2925. let sma = [];
  2926. let sma_size = 6;
  2927. let sma_window = [];
  2928. for (let i = 0; i < data.bid.length; i++) {
  2929. sma_window.push((data.bid[i].price + data.ask[i].price) / 2);
  2930. if (sma_window.length > sma_size) sma_window.shift();
  2931. sma.push(sma_window.reduce((a, b) => a + b, 0) / sma_window.length);
  2932. }
  2933. chart.options.plugins.title.text = curShowItemName;
  2934. chart.data.datasets = [
  2935. {
  2936. label: mwi.isZh ? '卖一' : "ask1",
  2937. data: data.ask.map(x => x.price),
  2938. borderColor: '#00cc00',
  2939. backgroundColor: '#00cc00',
  2940. borderWidth: 1.5
  2941. },
  2942. {
  2943. label: mwi.isZh ? '买一' : "bid1",
  2944. data: data.bid.map(x => x.price),
  2945. borderColor: '#ff3300',
  2946. backgroundColor: '#ff3300',
  2947. borderWidth: 1.5
  2948. },
  2949. {
  2950. label: mwi.isZh ? '均线' : "mean",
  2951. data: sma,
  2952. borderColor: '#ff9900',
  2953. borderWidth: 3,
  2954. tension: 0.5,
  2955. fill: true
  2956. },
  2957.  
  2958. ];
  2959. let timeUnit, timeFormat;
  2960. if (day <= 3) {
  2961. timeUnit = 'hour';
  2962. timeFormat = 'HH:mm';
  2963. } else {
  2964. timeUnit = 'day';
  2965. timeFormat = 'MM/dd';
  2966. }
  2967. chart.options.scales.x.time.unit = timeUnit;
  2968. chart.options.scales.x.time.tooltipFormat = timeFormat;
  2969.  
  2970.  
  2971. chart.setDatasetVisibility(0, config.filter.ask);
  2972. chart.setDatasetVisibility(1, config.filter.bid);
  2973. chart.setDatasetVisibility(2, config.filter.mean);
  2974.  
  2975. chart.update()
  2976. }
  2977. function save_config() {
  2978. if (mwi.character?.gameMode !== "standard") {
  2979. btn_switch.style.display = "none";
  2980. return;//铁牛不保存
  2981. }
  2982. btn_switch.style.display = "inline-block";
  2983.  
  2984. if (chart && chart.data && chart.data.datasets && chart.data.datasets.length == 3) {
  2985. config.filter.ask = chart.getDatasetMeta(0).visible;
  2986. config.filter.bid = chart.getDatasetMeta(1).visible;
  2987. config.filter.mean = chart.getDatasetMeta(2).visible;
  2988. }
  2989. if (container.checkVisibility()) {
  2990. config.x = Math.max(0, Math.min(container.getBoundingClientRect().x, window.innerWidth - 50));
  2991. config.y = Math.max(0, Math.min(container.getBoundingClientRect().y, window.innerHeight - 50));
  2992.  
  2993. if (uiContainer.style.display === 'none') {
  2994. config.minWidth = container.offsetWidth;
  2995. config.minHeight = container.offsetHeight;
  2996. }
  2997. else {
  2998. config.w = container.offsetWidth;
  2999. config.h = container.offsetHeight;
  3000. }
  3001. }
  3002.  
  3003. localStorage.setItem("mooket_config", JSON.stringify(config));
  3004. }
  3005. let lastItemHridLevel = null;
  3006. setInterval(() => {
  3007. let inMarketplace = document.querySelector(".MarketplacePanel_marketplacePanel__21b7o")?.checkVisibility();
  3008. let hasFavo = Object.entries(config.favo || {}).length > 0;
  3009. if ((inMarketplace || (!inMarketplace && !config.autoHide))) {
  3010. container.style.display = "block"
  3011. try {
  3012. let currentItem = document.querySelector(".MarketplacePanel_currentItem__3ercC");
  3013. let levelStr = currentItem?.querySelector(".Item_enhancementLevel__19g-e");
  3014. let enhancementLevel = parseInt(levelStr?.textContent.replace("+", "") || "0");
  3015. let itemHrid = mwi.ensureItemHrid(currentItem?.querySelector(".Icon_icon__2LtL_")?.ariaLabel);
  3016. let itemHridLevel = itemHrid + ":" + enhancementLevel;
  3017. if (itemHrid) {
  3018. if (lastItemHridLevel !== itemHridLevel) {//防止重复请求
  3019. //显示历史价格
  3020.  
  3021. let tradeHistoryDiv = document.querySelector("#mooket_tradeHistory");
  3022. if (!tradeHistoryDiv) {
  3023. tradeHistoryDiv = document.createElement("div");
  3024. tradeHistoryDiv.id = "mooket_tradeHistory";
  3025. tradeHistoryDiv.style.position = "absolute";
  3026. tradeHistoryDiv.style.marginTop = "-24px";
  3027. tradeHistoryDiv.style.left = "50%";
  3028. tradeHistoryDiv.style.transform = "translateX(-50%)";
  3029. tradeHistoryDiv.title = mwi.isZh ? "我的最近买/卖价格" : "My recently buy/sell price";
  3030. currentItem.prepend(tradeHistoryDiv);
  3031. }
  3032. if (trade_history[itemHridLevel]) {
  3033. let buy = trade_history[itemHridLevel].buy || "--";
  3034. let sell = trade_history[itemHridLevel].sell || "--";
  3035.  
  3036. tradeHistoryDiv.innerHTML = `
  3037. <span style="color:red">${showNumber(buy)}</span>
  3038. <span style="color:#AAAAAA">/</span>
  3039. <span style="color:lime">${showNumber(sell)}</span>`;
  3040. tradeHistoryDiv.style.display = "block";
  3041. } else {
  3042. tradeHistoryDiv.style.display = "none";
  3043. }
  3044. //添加订阅button
  3045. if (mwi.character?.gameMode === "standard") {
  3046. let btn_favo = document.querySelector("#mooket_addFavo");
  3047. if (!btn_favo) {
  3048. btn_favo = document.createElement('button');
  3049. btn_favo.type = 'button';
  3050. btn_favo.id = "mooket_addFavo";
  3051. btn_favo.innerText = '📌';
  3052. btn_favo.style.position = "absolute";
  3053. btn_favo.style.padding = "0";
  3054. btn_favo.style.fontSize = "18px";
  3055. btn_favo.style.marginLeft = "32px";
  3056. btn_favo.title = mwi.isZh ? "添加到自选" : "Add favorite";
  3057. btn_favo.onclick = () => { if (btn_favo.itemHridLevel) addFavo(btn_favo.itemHridLevel) };
  3058. currentItem.prepend(btn_favo);
  3059. }
  3060. btn_favo.itemHridLevel = itemHridLevel;
  3061. }
  3062. //记录当前
  3063. lastItemHridLevel = itemHridLevel;
  3064. if (uiContainer.style.display === 'none') {//延迟到打开的时候请求
  3065. delayItemHridName = itemHrid;
  3066. delayItemLevel = enhancementLevel;
  3067. } else {
  3068. requestItemPrice(itemHrid, curDay, enhancementLevel);
  3069. }
  3070. }
  3071. }
  3072. } catch (e) {
  3073. console.error(e)
  3074. }
  3075. } else {
  3076. container.style.display = "none"
  3077. }
  3078. }, 500);
  3079. //setInterval(updateInventoryStatus, 60000);
  3080. toggle();
  3081. console.info("mooket 初始化完成");
  3082. }
  3083. new Promise(resolve => {
  3084. let count = 0;
  3085. const interval = setInterval(() => {
  3086. count++;
  3087. if (count > 30) {
  3088. if (document.querySelector(".GamePage_gamePanel__3uNKN")) {
  3089. clearInterval(interval);
  3090. console.info("mooket 初始化超时,部分功能受限");
  3091. resolve();
  3092. } else {
  3093. //异常
  3094. clearInterval(interval);
  3095. console.info("mooket 初始化失败");
  3096. }
  3097. }//最多等待10秒
  3098. if (document.body && mwi.character?.gameMode) {//等待必须组件加载完毕后再初始化
  3099. clearInterval(interval);
  3100. resolve();
  3101. }
  3102. }, 1000);
  3103. }).then(() => {
  3104. mooket();
  3105. });
  3106.  
  3107. })();

QingJ © 2025

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