[银河奶牛]食用工具

开箱记录、箱子期望、离线统计

目前為 2024-07-09 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name [银河奶牛]食用工具
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.33
  5. // @description 开箱记录、箱子期望、离线统计
  6. // @author Truth_Light
  7. // @license Truth_Light
  8. // @match https://www.milkywayidle.com/*
  9. // @match https://test.milkywayidle.com/*
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. const itemSelector = '.ItemDictionary_drop__24I5f';
  16. const iconSelector = '.Icon_icon__2LtL_ use';
  17. const chestNameSelector = '#root > div > div > div.Modal_modalContainer__3B80m > div.Modal_modal__1Jiep > div.ItemDictionary_modalContent__WvEBY > div.ItemDictionary_itemAndDescription__28_he > div.Item_itemContainer__x7kH1 > div > div > div > div > svg > use';
  18. const resultDisplaySelector = '.ItemDictionary_openToLoot__1krnv';
  19. const marketDataStr = localStorage.getItem('MWITools_marketAPI_json');
  20. const marketData = JSON.parse(marketDataStr);
  21. let timer = null;
  22. let chestList = {};
  23.  
  24. function getSpecialItemPrice(itemName, priceType) {
  25. if (marketDataStr && marketData) {
  26. if (marketData.market && marketData.market[itemName]) {
  27. const itemPrice = marketData.market[itemName][priceType];
  28. if (itemPrice !== undefined && itemPrice !== -1) {
  29. return itemPrice;
  30. }
  31. }
  32. }
  33. console.error(`未找到物品 ${itemName} ${priceType} 价格信息`);
  34. return null; // 或者返回默认值,视情况而定
  35. }
  36.  
  37. let specialItemPrices = {
  38. 'Coin': { ask: 1, bid: 1 }, // 默认的特殊物品价值,包括ask和bid价值
  39. 'Cowbell': {
  40. ask: getSpecialItemPrice('Bag Of 10 Cowbells', 'ask')/10,
  41. bid: getSpecialItemPrice('Bag Of 10 Cowbells', 'bid')/10
  42. },
  43. 'Chimerical Token': {
  44. ask: getSpecialItemPrice('Chimerical Essence', 'ask'),
  45. bid: getSpecialItemPrice('Chimerical Essence', 'bid')
  46. },
  47. 'Sinister Token': {
  48. ask: getSpecialItemPrice('Sinister Essence', 'ask'),
  49. bid: getSpecialItemPrice('Sinister Essence', 'bid')
  50. },
  51. 'Enchanted Token': {
  52. ask: getSpecialItemPrice('Enchanted Essence', 'ask'),
  53. bid: getSpecialItemPrice('Enchanted Essence', 'bid')
  54. },
  55. };
  56.  
  57. function saveChestList() {
  58. localStorage.setItem('chestList', JSON.stringify(chestList));
  59. }
  60.  
  61. function loadChestList() {
  62. const savedChestList = localStorage.getItem('chestList');
  63. chestList = savedChestList ? JSON.parse(savedChestList) : {};
  64. }
  65.  
  66. function getItemNameFromElement(element) {
  67. const itemNameRaw = element.getAttribute('href').split('#').pop();
  68. return formatItemName(itemNameRaw);
  69. }
  70.  
  71. function handleNaNValues(itemName,values) {
  72. if (isNaN(values)) {
  73. console.error(`物品 ${itemName} 的值 NaN`);
  74. return -1;
  75. }
  76. return values;
  77. }
  78.  
  79. function getItemPrice(itemName) {
  80. let itemAskValue = 0;
  81. let itemBidValue = 0;
  82. let priceColor = '#E7E7E7';
  83.  
  84. if (chestList[itemName] && chestList[itemName].totalAskValue) {
  85. // 如果是箱子,直接使用chestList中的价格信息
  86. itemAskValue = chestList[itemName].totalAskValue;
  87. itemBidValue = chestList[itemName].totalBidValue;
  88. } else {
  89. if (specialItemPrices[itemName]) {
  90. itemAskValue = specialItemPrices[itemName].ask;
  91. itemBidValue = specialItemPrices[itemName].bid;
  92. } else {
  93. if (marketDataStr) {
  94. try {
  95. if (marketData && marketData.market && marketData.market[itemName]) {
  96. itemAskValue = marketData.market[itemName].ask;
  97. itemBidValue = marketData.market[itemName].bid;
  98.  
  99. if (itemAskValue === -1 && itemBidValue === -1) {
  100. priceColor = 'yellow';
  101. } else if (itemAskValue === -1) {
  102. priceColor = '#D95961';
  103. } else if (itemBidValue === -1) {
  104. priceColor = '#2FC4A7';
  105. }
  106.  
  107. if (itemAskValue === -1 && itemBidValue !== -1) {
  108. itemAskValue = itemBidValue;
  109. }
  110. } else {
  111. console.error(`未找到物品 ${itemName} 的价格信息`);
  112. priceColor = 'yellow';
  113. }
  114.  
  115. } catch (error) {
  116. console.error(`解析 MWITools_marketAPI_json 数据时出错:`, error);
  117. }
  118. } else {
  119. console.error('未找到 MWITools_marketAPI_json 的本地存储数据');
  120. }
  121. }
  122. }
  123.  
  124. return { ask: itemAskValue, bid: itemBidValue, priceColor };
  125. }
  126.  
  127. function formatItemName(itemNameRaw) {
  128. let formattedName = itemNameRaw.replace('#', '').replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());
  129.  
  130. if (formattedName.includes(' ')) {
  131. const words = formattedName.split(' ');
  132. let firstWord = words[0];
  133. const restOfName = words.slice(1).join(' ');
  134. if (firstWord.endsWith('s') && !firstWord.endsWith("'s")) {
  135. firstWord = `${firstWord.slice(0, -1)}'${firstWord.slice(-1)}`;
  136. }
  137. formattedName = `${firstWord}${restOfName ? " " + restOfName : ""}`;
  138. }
  139.  
  140. return formattedName;
  141. }
  142.  
  143. function parseQuantityRange(rangeText) {
  144. const parts = rangeText.split('-').map(str => parseInt(str.trim().replace(',', ''), 10));
  145. if (parts.length === 1) {
  146. return { min: parts[0], max: parts[0] };
  147. } else {
  148. return { min: parts[0], max: parts[1] };
  149. }
  150. }
  151.  
  152. function parseProbability(probabilityText) {
  153. const probPercentage = parseFloat(probabilityText.replace('%', ''));
  154. return probPercentage / 100;
  155. }
  156.  
  157. function formatPrice(value) {
  158. if (value >= 1000000) {
  159. return (value / 1000000).toFixed(1) + 'M';
  160. } else if (value >= 1000) {
  161. return (value / 1000).toFixed(1) + 'K';
  162. } else {
  163. return value.toString();
  164. }
  165. }
  166.  
  167. function parseQuantityString(quantityStr) {
  168. const suffix = quantityStr.slice(-1);
  169. const base = parseFloat(quantityStr.slice(0, -1));
  170. if (suffix === 'K') {
  171. return base * 1000;
  172. } else if (suffix === 'M') {
  173. return base * 1000000;
  174. } else if (suffix === 'B') {
  175. return base * 1000000000;
  176. } else {
  177. return parseFloat(quantityStr);
  178. }
  179. }
  180.  
  181. function displayResult(container, totalExpectedOutputASK, totalExpectedOutputBID) {
  182. const formattedASK = formatPrice(totalExpectedOutputASK);
  183. const formattedBID = formatPrice(totalExpectedOutputBID);
  184.  
  185. const dropListContainer = container.querySelector(resultDisplaySelector);
  186.  
  187. // 继续执行其他操作
  188. const previousResults = dropListContainer.querySelectorAll('.resultDiv');
  189. previousResults.forEach(result => result.remove());
  190.  
  191. // 创建期望产出(最低买入价计算)元素
  192. const minPriceOutput = document.createElement('div');
  193. minPriceOutput.className = 'resultDiv';
  194. minPriceOutput.textContent = `期望产出 (最低买入价计算): ${formattedASK}`;
  195. minPriceOutput.style.color = 'gold';
  196. minPriceOutput.style.fontSize = '14px';
  197. minPriceOutput.style.fontWeight = '400';
  198. minPriceOutput.style.paddingTop = '10px';
  199.  
  200. // 创建期望产出(最高收购价计算)元素
  201. const maxPriceOutput = document.createElement('div');
  202. maxPriceOutput.className = 'resultDiv';
  203. maxPriceOutput.textContent = `期望产出 (最高收购价计算): ${formattedBID}`;
  204. maxPriceOutput.style.color = 'gold';
  205. maxPriceOutput.style.fontSize = '14px';
  206. maxPriceOutput.style.fontWeight = '400';
  207. maxPriceOutput.style.paddingTop = '10px';
  208.  
  209. // 插入新创建的元素到掉落物表的最后一个物品后面
  210. dropListContainer.appendChild(minPriceOutput);
  211. dropListContainer.appendChild(maxPriceOutput);
  212. }
  213.  
  214. function displayChestStatistics(chestName) {
  215. const elementA = document.querySelector('.Inventory_modalContent__3ObSx');
  216.  
  217. if (elementA) {
  218. // 获取总计开箱次数和开箱价值(ask/bid)
  219. const chestData = chestList[chestName];
  220. const totalOpened = chestData ? chestData.totalOpened : 0;
  221. const lastOpenAskValue = chestData ? chestData.lastOpenAskValue : 0;
  222. const lastOpenBidValue = chestData ? chestData.lastOpenBidValue : 0;
  223. const openTotalAskValue = chestData ? chestData.OpenTotalAskValue : 0;
  224. const openTotalBidValue = chestData ? chestData.OpenTotalBidValue : 0;
  225.  
  226. // 创建显示内容
  227. const displayElement = document.createElement('div');
  228. displayElement.classList.add('ChestStatistics'); // 自定义类名,用于样式控制
  229. displayElement.style.position = 'absolute';
  230. displayElement.style.left = `${elementA.offsetLeft}px`;
  231. displayElement.style.top = `${elementA.offsetTop}px`;
  232. displayElement.style.fontSize = '12px';
  233. displayElement.innerHTML = `
  234. 总计开箱次数: ${totalOpened}<br>
  235. 本次开箱价值:<br>
  236. ${formatPrice(lastOpenAskValue)}/${formatPrice(lastOpenBidValue)}<br>
  237. 总计开箱价值:<br>
  238. ${formatPrice(openTotalAskValue)}/${formatPrice(openTotalBidValue)}<br>
  239. `;
  240.  
  241. // 插入到元素A内部
  242. elementA.appendChild(displayElement);
  243.  
  244. // 返回显示元素,以便后续删除
  245. return displayElement;
  246. } else {
  247. console.error('未找到窗体元素');
  248. return null;
  249. }
  250. }
  251.  
  252.  
  253. function processItems() {
  254. const modalContainer = document.querySelector(".Modal_modalContainer__3B80m");
  255. if (!modalContainer) return; // 如果不存在 Modal_modalContainer__3B80m 元素,则直接返回
  256.  
  257. const chestNameElem = document.querySelector(chestNameSelector);
  258. if (!chestNameElem) return;
  259.  
  260. const chestName = getItemNameFromElement(chestNameElem);
  261.  
  262. const items = document.querySelectorAll(itemSelector);
  263.  
  264. const itemDataList = [];
  265. let totalAskValue = 0;
  266. let totalBidValue = 0;
  267.  
  268. items.forEach(item => {
  269. const quantityRangeElem = item.querySelector('div:first-child');
  270. const quantityRangeText = quantityRangeElem.textContent.trim();
  271. const quantityRange = parseQuantityRange(quantityRangeText);
  272.  
  273. const itemName = getItemNameFromElement(item.querySelector(iconSelector));
  274.  
  275. let probabilityElem = item.querySelector('div:nth-child(3)');//提取物品的概率
  276. let probabilityText = probabilityElem ? probabilityElem.textContent.trim() : '';
  277. probabilityText = probabilityText.replace('~', '');
  278.  
  279. let probability;
  280. if (probabilityText === '') {
  281. probability = 1.0; // 如果概率文本为空,则假定掉落率为100%
  282. } else {
  283. probability = parseProbability(probabilityText);
  284. }
  285.  
  286. let expectedOutput = 0;
  287. if (quantityRange.min === quantityRange.max) {
  288. expectedOutput = quantityRange.min * probability;
  289. } else {
  290. const average = (quantityRange.min + quantityRange.max) / 2;
  291. expectedOutput = average * probability;
  292. }
  293.  
  294. let { ask: itemAskValue, bid: itemBidValue, priceColor } = getItemPrice(itemName);
  295.  
  296. const itemTotalAskValue = expectedOutput * itemAskValue;
  297. const itemTotalBidValue = expectedOutput * itemBidValue;
  298.  
  299. totalAskValue += itemTotalAskValue;
  300. totalBidValue += itemTotalBidValue;
  301.  
  302. const itemData = {
  303. itemName,
  304. quantityRange: `${quantityRange.min}-${quantityRange.max}`,
  305. probability: probability * 100,
  306. expectedOutput: expectedOutput.toFixed(2),
  307. itemAskValue,
  308. itemBidValue,
  309. itemTotalAskValue: itemTotalAskValue.toFixed(2),
  310. itemTotalBidValue: itemTotalBidValue.toFixed(2),
  311. priceColor
  312. };
  313.  
  314. itemDataList.push(itemData);
  315.  
  316. const itemNameElem = item.querySelector('.Item_name__2C42x');
  317. if (itemNameElem) {
  318. if (priceColor) {
  319. itemNameElem.style.color = priceColor;
  320. }
  321. }
  322.  
  323. });
  324.  
  325. if (itemDataList.length > 0) {
  326. chestList[chestName] = {
  327. items: itemDataList,
  328. totalAskValue: totalAskValue.toFixed(2),
  329. totalBidValue: totalBidValue.toFixed(2)
  330. };
  331. saveChestList();
  332. displayResult(document.body, totalAskValue, totalBidValue);
  333. }
  334. }
  335.  
  336. function recordChestOpening(modalElement) {
  337.  
  338. const chestNameElement = modalElement.querySelector("div.Modal_modal__1Jiep > div.Inventory_modalContent__3ObSx > div.Item_itemContainer__x7kH1 > div > div > div.Item_iconContainer__5z7j4 > div > svg > use");
  339. const chestCountElement = modalElement.querySelector("div.Modal_modal__1Jiep > div.Inventory_modalContent__3ObSx > div.Item_itemContainer__x7kH1 > div > div > div.Item_count__1HVvv");
  340.  
  341. if (chestNameElement && chestCountElement) {
  342. const chestName = getItemNameFromElement(chestNameElement);
  343. const chestCount = parseQuantityString(chestCountElement.textContent.trim());
  344.  
  345. const itemsContainer = modalElement.querySelector('.Inventory_gainedItems___e9t9');
  346. const itemElements = itemsContainer.querySelectorAll('.Item_itemContainer__x7kH1');
  347.  
  348. let totalAskValue = 0;
  349. let totalBidValue = 0;
  350. const items = [];
  351.  
  352. itemElements.forEach(itemElement => {
  353. const itemNameElement = itemElement.querySelector('.Item_iconContainer__5z7j4 use');
  354. const itemQuantityElement = itemElement.querySelector('.Item_count__1HVvv');
  355.  
  356. if (itemNameElement && itemQuantityElement) {
  357. const itemName = getItemNameFromElement(itemNameElement);
  358. const itemQuantity = parseQuantityString(itemQuantityElement.textContent.trim());
  359. const { ask: itemAskValue, bid: itemBidValue, priceColor } = getItemPrice(itemName);
  360.  
  361. const itemOpenTotalAskValue = itemAskValue * itemQuantity;
  362. const itemOpenTotalBidValue = itemBidValue * itemQuantity;
  363.  
  364. items.push({
  365. itemName,
  366. itemAskValue,
  367. itemBidValue,
  368. itemOpenTotalAskValue,
  369. itemOpenTotalBidValue,
  370. quantity: itemQuantity,
  371. priceColor
  372. });
  373.  
  374. totalAskValue += itemOpenTotalAskValue;
  375. totalBidValue += itemOpenTotalBidValue;
  376. }
  377. });
  378.  
  379. if (!chestList[chestName]) {
  380. chestList[chestName] = {
  381. items: [],
  382. OpenTotalAskValue: 0,
  383. OpenTotalBidValue: 0,
  384. totalOpened: 0,
  385. lastOpenAskValue: 0,
  386. lastOpenBidValue: 0
  387. };
  388. } else {
  389. const chestData = chestList[chestName];
  390.  
  391. chestData.OpenTotalAskValue = chestData.OpenTotalAskValue || 0;
  392. chestData.OpenTotalBidValue = chestData.OpenTotalBidValue || 0;
  393. chestData.totalOpened = chestData.totalOpened || 0;
  394. chestData.lastOpenAskValue = chestData.lastOpenAskValue || 0;
  395. chestData.lastOpenBidValue = chestData.lastOpenBidValue || 0;
  396. }
  397.  
  398. const chestData = chestList[chestName];
  399.  
  400. chestData.lastOpenAskValue = totalAskValue;
  401. chestData.lastOpenBidValue = totalBidValue;
  402. chestData.OpenTotalAskValue += totalAskValue;
  403. chestData.OpenTotalBidValue += totalBidValue;
  404. chestData.totalOpened += chestCount;
  405.  
  406. items.forEach(item => {
  407. const existingItem = chestData.items.find(i => i.itemName === item.itemName);
  408. if (existingItem) {
  409. existingItem.quantity += item.quantity;
  410. existingItem.itemOpenTotalAskValue += item.itemOpenTotalAskValue;
  411. existingItem.itemOpenTotalBidValue += item.itemOpenTotalBidValue;
  412. } else {
  413. chestData.items.push(item);
  414. }
  415. });
  416.  
  417. saveChestList();
  418. displayChestStatistics(chestName);
  419.  
  420. }
  421. }
  422.  
  423.  
  424. function calculateTotalValues(itemElements) {
  425. let totalAskValue = 0;
  426. let totalBidValue = 0;
  427. console.log("1")
  428. itemElements.forEach(itemElement => {
  429. const itemNameElement = itemElement.querySelector('.Item_iconContainer__5z7j4 use');
  430. const itemQuantityElement = itemElement.querySelector('.Item_count__1HVvv');
  431. console.log("2")
  432. if (itemNameElement && itemQuantityElement) {
  433. const itemName = getItemNameFromElement(itemNameElement);
  434. const itemQuantity = parseQuantityString(itemQuantityElement.textContent.trim());
  435. const { ask: itemAskValue, bid: itemBidValue, priceColor } = getItemPrice(itemName);
  436.  
  437. const itemTotalAskValue = itemAskValue * itemQuantity;
  438. const itemTotalBidValue = itemBidValue * itemQuantity;
  439. console.log("3")
  440. totalAskValue += itemTotalAskValue;
  441. totalBidValue += itemTotalBidValue;
  442. }
  443. });
  444. console.log("4")
  445. console.log(totalAskValue)
  446. return { totalAskValue, totalBidValue };
  447. }
  448.  
  449.  
  450. function OfflineStatistics(modalElement) {
  451. const itemsContainer = modalElement.querySelectorAll(".OfflineProgressModal_itemList__26h-Y");
  452. const itemsContainer_0 = itemsContainer[0];
  453. const itemsContainer_1 = itemsContainer[1];
  454. let itemsContainer_2 = null;
  455. let spenditemtotalAskValue = 0;
  456. let spenditemtotalBidValue = 0;
  457. if (itemsContainer[2]) {
  458. itemsContainer_2 = itemsContainer[2];
  459. const spenditemElements = itemsContainer_2.querySelectorAll('.Item_itemContainer__x7kH1');
  460. const { totalAskValue, totalBidValue } = calculateTotalValues(spenditemElements);
  461. spenditemtotalAskValue = totalAskValue;
  462. spenditemtotalBidValue = totalBidValue;
  463. }
  464. let TotalSec = null;
  465. if (itemsContainer_0) {
  466. const textContent = itemsContainer_0.textContent;
  467. const match = textContent.match(/(?:(\d+)d\s*)?(?:(\d+)h\s*)?(?:(\d+)m\s*)?(?:(\d+)s)/);
  468. if (match) {
  469. let days = parseInt(match[1], 10) || 0;
  470. let hours = parseInt(match[2], 10) || 0;
  471. let minutes = parseInt(match[3], 10) || 0;
  472. let seconds = parseInt(match[4], 10) || 0;
  473. TotalSec = days * 86400 + hours * 3600 + minutes * 60 + seconds;
  474.  
  475. }
  476. }
  477.  
  478. const getitemElements = itemsContainer_1.querySelectorAll('.Item_itemContainer__x7kH1');
  479. const { totalAskValue:getitemtotalAskValue, totalBidValue:getitemtotalBidValue } = calculateTotalValues(getitemElements);
  480.  
  481.  
  482.  
  483.  
  484. if (itemsContainer_0) {
  485. const newElement = document.createElement('span');
  486. newElement.textContent = `利润:${formatPrice(getitemtotalBidValue-spenditemtotalAskValue)}[${formatPrice((getitemtotalBidValue-spenditemtotalAskValue)/(TotalSec/3600)*24)}/天]`;
  487. newElement.style.float = 'right';
  488. newElement.style.color = 'gold';
  489. itemsContainer_0.querySelector(':first-child').appendChild(newElement);
  490. }
  491. if (itemsContainer_1) {
  492. const newElement = document.createElement('span');
  493. newElement.textContent = `产出:[${formatPrice(getitemtotalAskValue)}/${formatPrice(getitemtotalBidValue)}]`;
  494. newElement.style.float = 'right';
  495. newElement.style.color = 'gold';
  496. itemsContainer_1.querySelector(':first-child').appendChild(newElement);
  497. }
  498. if (itemsContainer_2) {
  499. const newElement = document.createElement('span');
  500. newElement.textContent = `成本:[${formatPrice(spenditemtotalAskValue)}/${formatPrice(spenditemtotalBidValue)}]`;
  501. newElement.style.float = 'right';
  502. newElement.style.color = 'gold';
  503. itemsContainer_2.querySelector(':first-child').appendChild(newElement);
  504. }
  505. }
  506.  
  507. // 初始化时加载已保存的箱子列表
  508. loadChestList();
  509. console.log(chestList);
  510. // 初始化
  511.  
  512.  
  513. function initObserver() {
  514. // 选择要观察的目标节点
  515. const targetNode = document.body;
  516.  
  517. // 观察器的配置(需要观察子节点的变化)
  518. const config = { childList: true, subtree: true };
  519.  
  520. // 创建一个观察器实例并传入回调函数
  521. const observer = new MutationObserver(mutationsList => {
  522. for (let mutation of mutationsList) {
  523. if (mutation.type === 'childList') {
  524. // 监听到子节点变化
  525. mutation.addedNodes.forEach(addedNode => {
  526. // 检查是否是我们关注的 Modal_modalContainer__3B80m 元素被添加
  527. if (addedNode.classList && addedNode.classList.contains('Modal_modalContainer__3B80m')) {
  528. // Modal_modalContainer__3B80m 元素被添加,执行处理函数
  529. processItems();
  530. recordChestOpening(addedNode);
  531.  
  532. // 开始监听箱子图标的变化
  533. startIconObserver();
  534. }
  535. if (addedNode.classList && addedNode.classList.contains('OfflineProgressModal_modalContainer__knnk7')) {
  536. OfflineStatistics(addedNode);
  537. console.log("离线报告已创建!")
  538. }
  539. });
  540.  
  541. mutation.removedNodes.forEach(removedNode => {
  542. // 检查是否是 Modal_modalContainer__3B80m 元素被移除
  543. if (removedNode.classList && removedNode.classList.contains('Modal_modalContainer__3B80m')) {
  544. // Modal_modalContainer__3B80m 元素被移除,停止监听箱子图标的变化
  545. stopIconObserver();
  546. }
  547. });
  548. }
  549. }
  550. });
  551.  
  552. // 以上述配置开始观察目标节点
  553. observer.observe(targetNode, config);
  554.  
  555. // 定义箱子图标变化的观察器
  556. let iconObserver = null;
  557.  
  558. // 开始监听箱子图标的变化
  559. function startIconObserver() {
  560. const chestNameElem = document.querySelector(chestNameSelector);
  561. if (!chestNameElem) return;
  562.  
  563. // 创建一个观察器实例来监听图标的变化
  564. iconObserver = new MutationObserver(() => {
  565. // 当箱子图标变化时,执行处理函数
  566. processItems();
  567. });
  568.  
  569. // 配置观察器的选项
  570. const iconConfig = { attributes: true, attributeFilter: ['href'] };
  571.  
  572. // 以上述配置开始观察箱子图标节点
  573. iconObserver.observe(chestNameElem, iconConfig);
  574. }
  575.  
  576. // 停止监听箱子图标的变化
  577. function stopIconObserver() {
  578. if (iconObserver) {
  579. iconObserver.disconnect();
  580. iconObserver = null;
  581. }
  582. }
  583. }
  584.  
  585.  
  586. initObserver();
  587.  
  588. })();