MediaWiki:Common.js

来自Mindustry中文wiki

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的变更的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
  • Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
  • Internet Explorer或Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
  • Opera:按 Ctrl-F5。
/* MediaWiki:Common.js */
(function () {
  'use strict';

  function fallbackCopy(text) {
    if (!window.jQuery) return;
    var $ = window.jQuery;
    var $temp = $('<textarea>');
    $('body').append($temp);
    $temp.val(text).select();
    document.execCommand('copy');
    $temp.remove();
    alert('复制成功!');
  }

  // 点击按钮复制内容:<button class="copy-button" data-text="...">复制</button>
  if (window.jQuery) {
    window.jQuery(function ($) {
      $(document).on('click', '.copy-button', function () {
        var text = $(this).attr('data-text') || '';
        if (navigator.clipboard && navigator.clipboard.writeText) {
          navigator.clipboard.writeText(text).then(function () {
            alert('复制成功!');
          }, function () {
            fallbackCopy(text);
          });
        } else {
          fallbackCopy(text);
        }
      });
    });
  }

  // Timeless:把 Sidebar 里以 "-- " 开头的条目变成可折叠子项
  mw.loader.using(['mediawiki.util'], function () {
    if (mw.config.get('skin') !== 'timeless') return;

    function initNavTree() {
      var siteNav = document.getElementById('mw-site-navigation');
      if (!siteNav) return;

      var pNav = siteNav.querySelector('#p-navigation');
      if (!pNav) return;

      var root = pNav.querySelector('.mw-portlet-body > ul') ||
        pNav.querySelector('ul');
      if (!root) return;

      if (root.getAttribute('data-mdtNav') === '1') return;
      root.setAttribute('data-mdtNav', '1');

      var KEY = 'mdtNavTreeOpen';
      var store = {};
      try {
        store = JSON.parse(localStorage.getItem(KEY) || '{}');
      } catch (e) {
        store = {};
      }

      function getKey(li) {
        if (li && li.id) return li.id;
        var a = li ? li.querySelector('a') : null;
        return a ? (a.getAttribute('href') || '') : '';
      }

      function setStored(li, open) {
        var k = getKey(li);
        if (!k) return;
        store[k] = open;
        try {
          localStorage.setItem(KEY, JSON.stringify(store));
        } catch (e) {}
      }

      function setOpen(li, open, persist) {
        li.classList.toggle('mdtNavOpen', open);
        if (persist) setStored(li, open);
      }

      function ensureGroup(li) {
        li.classList.add('mdtNavGroup');

        var sub = li.querySelector('ul.mdtNavSublist');
        if (!sub) {
          sub = document.createElement('ul');
          sub.className = 'mdtNavSublist';
          li.appendChild(sub);
        }

        var btn = li.querySelector('button.mdtNavToggle');
        if (!btn) {
          btn = document.createElement('button');
          btn.type = 'button';
          btn.className = 'mdtNavToggle';
          btn.setAttribute('aria-label', '展开/收起');
          btn.setAttribute('aria-expanded', 'false');
          li.insertBefore(btn, sub);

          btn.addEventListener('click', function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            var isOpen = li.classList.contains('mdtNavOpen');
            setOpen(li, !isOpen, true);
            btn.setAttribute('aria-expanded', String(!isOpen));
          });
        }

        var k = getKey(li);
        if (store[k] === true) {
          li.classList.add('mdtNavOpen');
          btn.setAttribute('aria-expanded', 'true');
        }

        return sub;
      }

      var items = Array.prototype.slice.call(root.children);
      var lastAtDepth = [];

      for (var i = 0; i < items.length; i++) {
        var li = items[i];
        if (!li || li.tagName !== 'LI') continue;

        var a = li.querySelector('a');
        if (!a) continue;

        var raw = (a.textContent || '').trim();
        var m = raw.match(/^(-{2,})\s*(.*)$/);

        var depth = 0;
        if (m) {
          depth = Math.min(Math.floor(m[1].length / 2), 3);
          a.textContent = m[2];
        }

        li.classList.add('mdtNavItem');

        if (depth > 0 && lastAtDepth[depth - 1]) {
          li.classList.add('mdtNavSubItem');
          li.classList.add('mdtNavDepth' + String(depth));
          var sublist = ensureGroup(lastAtDepth[depth - 1]);
          sublist.appendChild(li);
        } else {
          depth = 0;
        }

        lastAtDepth[depth] = li;
        lastAtDepth.length = depth + 1;
      }

      // 当前页面高亮 + 自动展开父级
      var current = (mw.config.get('wgPageName') || '').replace(/ /g, '_');
      var links = pNav.querySelectorAll('a');

      function titleFromHref(href) {
        var t = mw.util.getParamValue('title', href);
        if (t) return t.replace(/ /g, '_');

        var mark = '/index.php/';
        var pos = href.indexOf(mark);
        if (pos !== -1) {
          return decodeURIComponent(href.slice(pos + mark.length))
            .replace(/ /g, '_');
        }

        return '';
      }

      for (var j = 0; j < links.length; j++) {
        var href = links[j].getAttribute('href') || '';
        var page = titleFromHref(href);

        if (page && page === current) {
          links[j].classList.add('mdtNavActive');

          var n = links[j].parentNode;
          while (n && n !== root) {
            if (n.tagName === 'LI' && n.classList.contains('mdtNavGroup')) {
              setOpen(n, true, false);
              var btn = n.querySelector('button.mdtNavToggle');
              if (btn) btn.setAttribute('aria-expanded', 'true');
            }
            n = n.parentNode;
          }
          break;
        }
      }
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', initNavTree);
    } else {
      initNavTree();
    }
  });

  // 可折叠标题:在标题旁边加一个展开/收起按钮
  // 用法:把任意标题写成:== 战役区块 <span class="mdtFold"></span> ==
  // 默认收起:== 战役区块 <span class="mdtFold mdtFoldClosed"></span> ==
  mw.loader.using(['mediawiki.util'], function () {
    var skin = String(mw.config.get('skin') || '').toLowerCase();
    if (skin !== 'timeless') return;

    var action = String(mw.config.get('wgAction') || 'view').toLowerCase();
    if (action === 'edit' || action === 'submit') return;

    function findHeading(node) {
      while (node && node !== document.body) {
        if (node.nodeType === 1 && /^H[1-6]$/.test(node.tagName)) return node;
        node = node.parentNode;
      }
      return null;
    }

    var KEY = 'mdtFoldSections';
    var store = {};
    try {
      store = JSON.parse(localStorage.getItem(KEY) || '{}');
    } catch (e) {
      store = {};
    }

    function saveStore() {
      try {
        localStorage.setItem(KEY, JSON.stringify(store));
      } catch (e) {}
    }

    function getHeadingBlock(headingEl) {
      if (!headingEl || !headingEl.parentElement) return headingEl;

      // MediaWiki 新版可能会把 h2 包在 <div class="mw-heading"> 里。
      // 如果不处理这个 wrapper,折叠只会影响 wrapper 内部(看起来“没效果”)。
      var p = headingEl.parentElement;
      if (p.classList && p.classList.contains('mw-heading')) return p;
      return headingEl;
    }

    function getHeadingLevelFromNode(node) {
      if (!node || node.nodeType !== 1) return null;

      if (/^H[1-6]$/.test(node.tagName)) {
        return parseInt(String(node.tagName).slice(1), 10) || 6;
      }

      if (node.classList && node.classList.contains('mw-heading')) {
        var h = node.querySelector('h1,h2,h3,h4,h5,h6');
        if (h && /^H[1-6]$/.test(h.tagName)) {
          return parseInt(String(h.tagName).slice(1), 10) || 6;
        }
      }

      return null;
    }

    function initFoldSections(root) {
      var content = root || document.getElementById('mw-content-text') ||
        document.querySelector('.mw-parser-output') ||
        document.body;
      if (!content) return;

      var nodes = [];
      var markers = content.querySelectorAll('.mdtFold');
      var headingNodes = content.querySelectorAll('h1.mdtFoldHeading,h2.mdtFoldHeading,h3.mdtFoldHeading,h4.mdtFoldHeading,h5.mdtFoldHeading,h6.mdtFoldHeading');
      for (var h = 0; h < headingNodes.length; h++) nodes.push(headingNodes[h]);
      for (var m = 0; m < markers.length; m++) nodes.push(markers[m]);
      if (!nodes.length) return;

      for (var i = 0; i < nodes.length; i++) {
        (function (nodeOrMarker) {
          var marker = null;
          var heading = null;

          if (nodeOrMarker && nodeOrMarker.nodeType === 1 && /^H[1-6]$/.test(nodeOrMarker.tagName)) {
            heading = nodeOrMarker;
          } else {
            marker = nodeOrMarker;
            heading = findHeading(marker);
          }
          if (!heading) return;

          // 兼容:如果是通过 h2.mdtFoldHeading 触发,但里面也有 span.mdtFold,
          // 也要把 marker 当作触发点,这样可以读取默认收起并移除 marker。
          if (!marker) {
            marker = heading.querySelector('.mdtFold');
          }

          var headingBlock = getHeadingBlock(heading);
          if (!headingBlock) return;

          if (headingBlock.getAttribute('data-mdtFoldInit') === '1') return;
          headingBlock.setAttribute('data-mdtFoldInit', '1');

          var level = parseInt(String(heading.tagName).slice(1), 10) || 2;
          var headline = heading.querySelector('.mw-headline');

          // Body: 优先折叠“紧跟着”的图标网格(你这个场景就是 h2 + .mdtIconGrid)。
          // 也支持手动标记:<div class="mdtFoldBody">...</div>
          var body = null;
          var nextEl = headingBlock.nextElementSibling;
          if (nextEl && nextEl.classList) {
            if (nextEl.classList.contains('mdtFoldBody') || nextEl.classList.contains('mdtIconGrid')) {
              body = nextEl;
              body.classList.add('mdtFoldBody');
            }
          }

          // 自动模式:把标题后面直到下一个“同级或更高级标题”的所有节点包起来。
          if (!body) {
            body = document.createElement('div');
            body.className = 'mdtFoldBody';

            var node = headingBlock.nextSibling;
            while (node) {
              var next = node.nextSibling;
              var nodeLevel = getHeadingLevelFromNode(node);
              if (nodeLevel !== null && nodeLevel <= level) break;
              body.appendChild(node);
              node = next;
            }

            headingBlock.parentNode.insertBefore(body, node);
          }

          // Toggle button
          var btn = document.createElement('button');
          btn.type = 'button';
          btn.className = 'mdtFoldToggle';
          btn.setAttribute('aria-label', '展开/收起');
          btn.setAttribute('aria-expanded', 'true');
          btn.title = '展开/收起';
          btn.textContent = '\u25BE';

          // Inline style fallback: in case Timeless.css is not loaded yet.
          btn.style.width = '1.6rem';
          btn.style.height = '1.6rem';
          btn.style.marginLeft = '0.25rem';
          btn.style.border = '0';
          btn.style.padding = '0';
          btn.style.borderRadius = '10px';
          btn.style.display = 'inline-flex';
          btn.style.alignItems = 'center';
          btn.style.justifyContent = 'center';
          btn.style.background = 'rgba(0, 175, 137, 0.10)';
          btn.style.color = 'var(--mdtBrand)';
          btn.style.cursor = 'pointer';
          btn.style.fontFamily = 'inherit';
          btn.style.fontSize = '16px';
          btn.style.fontWeight = '700';
          btn.style.lineHeight = '1';
          btn.style.boxShadow = 'none';
          btn.style.outline = 'none';
          btn.style.appearance = 'none';
          btn.style.webkitAppearance = 'none';

          if (headline) {
            headline.classList.add('mdtFoldHeadline');
            headline.appendChild(btn);
          } else {
            var wrap = document.createElement('span');
            wrap.className = 'mdtFoldHeadline';

            while (heading.firstChild) {
              wrap.appendChild(heading.firstChild);
            }

            heading.appendChild(wrap);
            wrap.appendChild(btn);
            headline = wrap;
          }

          // Marker/heading default state
          var defaultClosed = false;
          if (marker && marker.classList && marker.classList.contains('mdtFoldClosed')) {
            defaultClosed = true;
          }
          if (heading.classList && heading.classList.contains('mdtFoldClosed')) {
            defaultClosed = true;
          }

          // Remove marker to avoid extra spacing
          if (marker && marker.parentNode) marker.parentNode.removeChild(marker);

          var page = (mw.config.get('wgPageName') || '').replace(/ /g, '_');
          var id = '';
          if (headline && headline.id) id = headline.id;
          if (!id) id = (heading.textContent || '').trim();
          var storageKey = page + '::' + id;

          function setCollapsed(collapsed, persist) {
            headingBlock.classList.toggle('mdtFoldCollapsed', collapsed);
            btn.setAttribute('aria-expanded', String(!collapsed));
            btn.textContent = collapsed ? '\u25B8' : '\u25BE';
            if (body) {
              body.classList.toggle('mdtFoldHidden', collapsed);
              // Ensure it works even if CSS is missing/cached.
              body.style.display = collapsed ? 'none' : '';
            }
            if (persist) {
              store[storageKey] = collapsed;
              saveStore();
            }
          }

          var collapsed = false;
          if (typeof store[storageKey] === 'boolean') {
            collapsed = store[storageKey];
          } else if (defaultClosed) {
            collapsed = true;
          }

          setCollapsed(collapsed, false);

          btn.addEventListener('click', function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            var isCollapsed = headingBlock.classList.contains('mdtFoldCollapsed');
            setCollapsed(!isCollapsed, true);
          });
        })(nodes[i]);
      }
    }

    function runOnPage() {
      initFoldSections(document.getElementById('mw-content-text') ||
        document.querySelector('.mw-parser-output') ||
        document.body);
    }

    // MediaWiki 推荐:内容渲染/替换后触发(兼容预览、部分皮肤/插件)。
    if (mw.hook && window.jQuery) {
      mw.hook('wikipage.content').add(function ($content) {
        initFoldSections($content && $content[0] ? $content[0] : null);
      });
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', runOnPage);
    } else {
      runOnPage();
    }
  });
})();

(function () {
  'use strict';

  /* Timeless: 左/右侧栏抽屉 + 首页按钮 */
  mw.loader.using(['mediawiki.util'], function () {
    if (mw.config.get('skin') !== 'timeless') return;

    function onReady(fn) {
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', fn);
      } else {
        fn();
      }
    }

    var ICON_HOME =
      '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></svg>';

    var ICON_MENU =
      '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h16v2H4zm0 5h16v2H4zm0 5h16v2H4z"/></svg>';

    var ICON_GEAR =
      '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19.14 12.94c.04-.31.06-.63.06-.94s-.02-.63-.06-.94l2.03-1.58a.5.5 0 0 0 .12-.64l-1.92-3.32a.5.5 0 0 0-.6-.22l-2.39.96c-.5-.38-1.04-.7-1.63-.94l-.36-2.54A.5.5 0 0 0 13.9 2h-3.8a.5.5 0 0 0-.49.42l-.36 2.54c-.59.24-1.13.56-1.63.94l-2.39-.96a.5.5 0 0 0-.6.22L2.71 8.48a.5.5 0 0 0 .12.64l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94L2.83 14.52a.5.5 0 0 0-.12.64l1.92 3.32c.13.22.39.31.6.22l2.39-.96c.5.38 1.04.7 1.63.94l.36 2.54c.05.24.25.42.49.42h3.8c.24 0 .44-.18.49-.42l.36-2.54c.59-.24 1.13-.56 1.63-.94l2.39.96c.22.09.47 0 .6-.22l1.92-3.32a.5.5 0 0 0-.12-.64l-2.03-1.58zM12 15.5A3.5 3.5 0 1 1 12 8.5a3.5 3.5 0 0 1 0 7z"/></svg>';

    function wrapIcon(svg) {
      var span = document.createElement('span');
      span.className = 'mdtDockIcon';
      span.innerHTML = svg;
      return span;
    }

    onReady(function () {
      if (document.getElementById('mdtDockLeft')) return;

      var siteNav = document.getElementById('mw-site-navigation');
      var relatedNav = document.getElementById('mw-related-navigation');
      if (!siteNav && !relatedNav) return;

      document.body.classList.add('mdtDockEnabled');

      var backdrop = document.createElement('div');
      backdrop.id = 'mdtDockBackdrop';

      function syncBackdrop() {
        var open =
          document.body.classList.contains('mdtDockNavOpen') ||
          document.body.classList.contains('mdtDockToolsOpen');
        backdrop.classList.toggle('is-active', open);
      }

      function closeAll() {
        document.body.classList.remove('mdtDockNavOpen', 'mdtDockToolsOpen');
        syncBackdrop();
      }

      backdrop.addEventListener('click', closeAll);
      document.addEventListener('keydown', function (e) {
        if (e.key === 'Escape') closeAll();
      });

      // 左侧:홈 + 汉堡
      var left = document.createElement('div');
      left.id = 'mdtDockLeft';

      var home = document.createElement('a');
      home.className = 'mdtDockBtn';
      home.href = mw.util.getUrl('首页'); 
      home.title = '首页';
      home.setAttribute('aria-label', '首页');
      home.appendChild(wrapIcon(ICON_HOME));
      left.appendChild(home);

      if (siteNav) {
        var navBtn = document.createElement('button');
        navBtn.type = 'button';
        navBtn.className = 'mdtDockBtn';
        navBtn.title = '导航';
        navBtn.setAttribute('aria-label', '导航');
        navBtn.appendChild(wrapIcon(ICON_MENU));
        navBtn.addEventListener('click', function () {
          var nowOpen = document.body.classList.toggle('mdtDockNavOpen');
          if (nowOpen) document.body.classList.remove('mdtDockToolsOpen');
          syncBackdrop();
        });
        left.appendChild(navBtn);
      }

// 右侧:齿轮
var right = document.createElement('div');
right.id = 'mdtDockRight';

if (relatedNav) {
  var toolsBtn = document.createElement('button');
  toolsBtn.type = 'button';
  toolsBtn.className = 'mdtDockBtn';
  toolsBtn.title = '页面工具';
  toolsBtn.setAttribute('aria-label', '页面工具');
  toolsBtn.appendChild(wrapIcon(ICON_GEAR));
  toolsBtn.addEventListener('click', function () {
    var nowOpen = document.body.classList.toggle('mdtDockToolsOpen');
    if (nowOpen) document.body.classList.remove('mdtDockNavOpen');
    syncBackdrop();
  });
  left.appendChild(toolsBtn);
}

document.body.appendChild(backdrop);
document.body.appendChild(left);


      document.body.appendChild(backdrop);
      document.body.appendChild(left);
      document.body.appendChild(right);
      syncBackdrop();
    });
  });
})();

(function () {
  'use strict';

  function isTimeless() {
    try {
      return String(mw.config.get('skin') || '').toLowerCase() === 'timeless';
    } catch (e) {
      return false;
    }
  }

  function isViewMode() {
    var a = String(mw.config.get('wgAction') || 'view').toLowerCase();
    return a === 'view';
  }

  function isMobileUA() {
    var ua = String(navigator.userAgent || '');
    return /Mobi|Android|iPhone|iPad|iPod/i.test(ua);
  }

  function normalizeText(text) {
    return String(text || '')
      .replace(/\s+/g, ' ')
      .replace(/[\u25B8\u25BE]/g, '')
      .trim();
  }

  function collectGroups(root) {
    var nodes = root.querySelectorAll('h2, h3');
    var groups = [];
    var current = null;

    for (var i = 0; i < nodes.length; i++) {
      var h = nodes[i];
      if (!h) continue;

      var id = h.id || '';
      if (!id) continue;

      var text = normalizeText(h.textContent);
      if (!text) continue;

      if (h.tagName === 'H2') {
        current = { id: id, text: text, children: [] };
        groups.push(current);
      } else {
        if (!current) continue;
        current.children.push({ id: id, text: text });
      }
    }

    return groups;
  }

  function flattenIds(groups) {
    var ids = [];
    for (var i = 0; i < groups.length; i++) {
      ids.push(groups[i].id);
      var children = groups[i].children || [];
      for (var j = 0; j < children.length; j++) {
        ids.push(children[j].id);
      }
    }
    return ids;
  }

  function buildPanel(groups) {
    var wrap = document.createElement('div');
    wrap.id = 'mdtFloatToc';
    wrap.className = 'mdtFloatToc';

    wrap.innerHTML =
      "<button type='button' class='mdtFloatTocBtn' aria-label='目录'>≡</button>" +
      "<div class='mdtFloatTocPanel' role='dialog' aria-label='目录'>" +
      "  <div class='mdtFloatTocHead'>" +
      "    <button type='button' class='mdtFloatTocTop'><span aria-hidden='true'>↑</span>返回顶部</button>" +
      "    <div class='mdtFloatTocTitle'>目录</div>" +
      "    <button type='button' class='mdtFloatTocClose' aria-label='关闭'>✕</button>" +
      "  </div>" +
      "  <ul class='mdtFloatTocList'></ul>" +
      "</div>";

    var ul = wrap.querySelector('.mdtFloatTocList');
    for (var i = 0; i < groups.length; i++) {
      (function (g) {
        var li = document.createElement('li');
        li.className = 'mdtFloatTocItem mdtFloatTocGroup';

        var row = document.createElement('div');
        row.className = 'mdtFloatTocRow';

        var a = document.createElement('a');
        a.href = '#' + encodeURIComponent(g.id).replace(/%2F/g, '/');
        a.textContent = g.text;
        row.appendChild(a);

        if (g.children && g.children.length) {
          var btn = document.createElement('button');
          btn.type = 'button';
          btn.className = 'mdtFloatTocGroupToggle';
          btn.setAttribute('aria-label', '展开/收起');
          btn.setAttribute('aria-expanded', 'false');
          btn.textContent = '▸';
          row.appendChild(btn);

          var sub = document.createElement('ul');
          sub.className = 'mdtFloatTocSublist';

          for (var j = 0; j < g.children.length; j++) {
            var c = g.children[j];
            var cli = document.createElement('li');
            cli.className = 'mdtFloatTocItem';
            cli.innerHTML = "<a href='#" + encodeURIComponent(c.id).replace(/%2F/g, '/') + "'>" +
              mw.html.escape(c.text) + "</a>";
            sub.appendChild(cli);
          }

          li.appendChild(row);
          li.appendChild(sub);

          btn.addEventListener('click', function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            var open = li.classList.toggle('mdtFloatTocGroupOpen');
            btn.setAttribute('aria-expanded', String(open));
            btn.textContent = open ? '▾' : '▸';
          });
        } else {
          li.appendChild(row);
        }

        ul.appendChild(li);
      })(groups[i]);
    }

    function openPanel(open) {
      wrap.classList.toggle('mdtFloatTocOpen', open);
    }

    wrap.querySelector('.mdtFloatTocBtn').addEventListener('click', function () {
      openPanel(true);
    });

    wrap.querySelector('.mdtFloatTocClose').addEventListener('click', function () {
      openPanel(false);
    });

    wrap.querySelector('.mdtFloatTocTop').addEventListener('click', function () {
      openPanel(false);
      window.scrollTo({ top: 0, behavior: 'smooth' });
    });

    // Click a toc item -> close + smooth scroll
    wrap.addEventListener('click', function (ev) {
      var a = ev.target && ev.target.closest ? ev.target.closest('a') : null;
      if (!a) return;
      var href = a.getAttribute('href') || '';
      if (href.charAt(0) !== '#') return;

      ev.preventDefault();
      openPanel(false);

      var id = decodeURIComponent(href.slice(1));
      var target = document.getElementById(id);
      if (target) {
        target.scrollIntoView({ behavior: 'smooth', block: 'start' });
        history.replaceState(null, '', '#' + encodeURIComponent(id));
      }
    });

    // Close when tapping outside
    document.addEventListener('click', function (ev) {
      if (!wrap.classList.contains('mdtFloatTocOpen')) return;
      if (wrap.contains(ev.target)) return;
      openPanel(false);
    });

    // Highlight active heading
    var linkById = {};
    var links = wrap.querySelectorAll('a');
    for (var k = 0; k < links.length; k++) {
      var id2 = decodeURIComponent((links[k].getAttribute('href') || '').slice(1));
      linkById[id2] = links[k];
    }

    var ids = flattenIds(groups);
    var ticking = false;
    function updateActive() {
      ticking = false;

      var bestId = '';
      var bestTop = -Infinity;
      for (var i2 = 0; i2 < ids.length; i2++) {
        var el = document.getElementById(ids[i2]);
        if (!el) continue;
        var rect = el.getBoundingClientRect();
        if (rect.top <= 120 && rect.top > bestTop) {
          bestTop = rect.top;
          bestId = ids[i2];
        }
      }

      for (var idKey in linkById) {
        linkById[idKey].classList.toggle('mdtFloatTocActive', idKey === bestId);
      }
    }

    window.addEventListener('scroll', function () {
      if (ticking) return;
      ticking = true;
      window.requestAnimationFrame(updateActive);
    }, { passive: true });

    return wrap;
  }

  function ensureHeadingIds(root) {
    var headings = root.querySelectorAll('h2, h3');
    for (var i = 0; i < headings.length; i++) {
      var h = headings[i];
      if (h.id) continue;
      var hl = h.querySelector('.mw-headline');
      if (hl && hl.id) h.id = hl.id;
    }
  }

  function initFloatToc($content) {
    if (!isTimeless() || !isViewMode() || !isMobileUA()) return;

    var content = $content && $content[0] ? $content[0] : null;
    var root = content || document.querySelector('.mw-parser-output') || document.getElementById('mw-content-text');
    if (!root) return;

    if (document.getElementById('mdtFloatToc')) return;

    ensureHeadingIds(root);
    var groups = collectGroups(root);
    if (!groups.length) return;

    document.body.appendChild(buildPanel(groups));
  }

  mw.loader.using(['mediawiki.util', 'mediawiki.html']).then(function () {
    if (mw.hook && window.jQuery) {
      mw.hook('wikipage.content').add(initFloatToc);
    }
    initFloatToc(null);
  });
})();

/*
  MDT Float TOC (desktop: dock to top-right gutter, default open)
  Paste this whole file into: MediaWiki:Common.js (very bottom)
*/
(function () {
  'use strict';

  var DESKTOP_MIN_WIDTH = 1000;
  var GAP_PX = 12;
  var FALLBACK_TOP_REM = 4.1;

  function isViewMode() {
    try {
      return String(mw.config.get('wgAction') || 'view').toLowerCase() === 'view';
    } catch (e) {
      return true;
    }
  }

  function isDesktop() {
    try {
      return (
        window.matchMedia &&
        window.matchMedia('(min-width: ' + String(DESKTOP_MIN_WIDTH) + 'px)').matches
      );
    } catch (e) {
      return false;
    }
  }

  function remToPx(rem) {
    var fs = 16;
    try {
      fs = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
    } catch (e) {}
    return rem * fs;
  }

  function getDockTopPx() {
    var dock = document.getElementById('mdtDockLeft') || document.getElementById('mdtDockRight');
    if (dock && dock.getBoundingClientRect) {
      return Math.round(dock.getBoundingClientRect().top);
    }
    return Math.round(remToPx(FALLBACK_TOP_REM));
  }

  function normalizeText(text) {
    return String(text || '')
      .replace(/\s+/g, ' ')
      .replace(/[\u25B8\u25BE]/g, '')
      .trim();
  }

  function ensureHeadingIds(root) {
    var headings = root.querySelectorAll('h2, h3');
    for (var i = 0; i < headings.length; i++) {
      var h = headings[i];
      if (!h || h.id) continue;
      var hl = h.querySelector('.mw-headline');
      if (hl && hl.id) h.id = hl.id;
    }
  }

  function shouldSkipHeading(h) {
    if (!h) return true;
    if (!h.id) return true;
    if (h.closest('#mw-site-navigation, #mw-related-navigation, .mw-portlet, .mdtRightRail')) return true;
    return false;
  }

  function collectGroups(root) {
    var nodes = root.querySelectorAll('h2, h3');
    var groups = [];
    var current = null;

    for (var i = 0; i < nodes.length; i++) {
      var h = nodes[i];
      if (shouldSkipHeading(h)) continue;

      var id = h.id;
  var headline = h.querySelector('.mw-headline');
  var text = normalizeText(headline ? headline.textContent : h.textContent);
      if (!text) continue;

      if (h.tagName === 'H2') {
        current = { id: id, text: text, children: [] };
        groups.push(current);
      } else {
        if (!current) continue;
        current.children.push({ id: id, text: text });
      }
    }

    return groups;
  }

  function flattenIds(groups) {
    var ids = [];
    for (var i = 0; i < groups.length; i++) {
      ids.push(groups[i].id);
      var children = groups[i].children || [];
      for (var j = 0; j < children.length; j++) ids.push(children[j].id);
    }
    return ids;
  }

  function injectCssOnce() {
    if (document.getElementById('mdtFloatTocStyle')) return;

    var css = [
      '#mw-content-text .mw-headline{scroll-margin-top:5rem;}',

      /* wrapper (mobile default: bottom-right) */
      '#mdtFloatToc{position:fixed;right:0.9rem;bottom:1.1rem;top:auto;z-index:9999;font-family:inherit;display:block !important;}',

      /* open button */
      '#mdtFloatToc .mdtFloatTocBtn{width:3rem;height:3rem;border-radius:999px;border:1px solid rgba(255,255,255,0.14);background:rgba(0,0,0,0.70);color:rgba(255,255,255,0.92);box-shadow:0 12px 28px rgba(0,0,0,0.28);cursor:pointer;display:inline-flex;align-items:center;justify-content:center;font-weight:900;}',
      '#mdtFloatToc .mdtFloatTocBtn:hover{border-color:rgba(0,207,160,0.60);box-shadow:0 12px 28px rgba(0,0,0,0.28),0 0 0 3px rgba(0,207,160,0.18);}',
      '#mdtFloatToc.mdtFloatTocOpen .mdtFloatTocBtn{opacity:0;pointer-events:none;}',

      /* panel (mobile default: popup) */
      '#mdtFloatToc .mdtFloatTocPanel{position:absolute;right:0;bottom:3.75rem;width:min(22rem,88vw);max-height:min(70vh,34rem);overflow:auto;padding:0.85rem 0.9rem;border-radius:16px;background:rgba(36,46,45,0.92);border:1px solid rgba(255,255,255,0.14);box-shadow:0 18px 44px rgba(0,0,0,0.32);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);color:rgba(255,255,255,0.92);display:none;}',
      '#mdtFloatToc.mdtFloatTocOpen .mdtFloatTocPanel{display:block;}',

      /* head */
      '#mdtFloatToc .mdtFloatTocHead{display:flex;align-items:center;justify-content:space-between;gap:0.75rem;padding:0 0 0.55rem 0;margin:0 0 0.6rem 0;border-bottom:1px solid rgba(255,255,255,0.10);}',
      '#mdtFloatToc .mdtFloatTocTitle{font-weight:900;opacity:0.9;letter-spacing:0.06em;}',
      '#mdtFloatToc .mdtFloatTocTop,#mdtFloatToc .mdtFloatTocClose{border:0;background:transparent;color:inherit;cursor:pointer;padding:0;font-family:inherit;}',
      '#mdtFloatToc .mdtFloatTocTop{display:inline-flex;align-items:center;gap:0.55rem;font-weight:900;color:var(--mdtBrand2,#00cfa0);}',
      '#mdtFloatToc .mdtFloatTocClose{width:2rem;height:2rem;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;background:rgba(255,255,255,0.06);}',
      '#mdtFloatToc .mdtFloatTocClose:hover{background:rgba(255,255,255,0.12);}',

      /* list */
      '#mdtFloatToc .mdtFloatTocList{list-style:none;margin:0;padding:0 0 0 0.85rem;border-left:1px solid rgba(255,255,255,0.12);}',
      '#mdtFloatToc .mdtFloatTocRow{display:flex;align-items:center;gap:0.35rem;}',
      '#mdtFloatToc .mdtFloatTocItem{margin:0.18rem 0;}',
      '#mdtFloatToc .mdtFloatTocItem a,#mdtFloatToc .mdtFloatTocItem a:visited{color:rgba(255,255,255,0.86);text-decoration:none;font-weight:750;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}',
      '#mdtFloatToc .mdtFloatTocItem a:hover{color:var(--mdtBrand2,#00cfa0);text-decoration:underline;}',
      '#mdtFloatToc .mdtFloatTocItem a.mdtFloatTocActive{color:var(--mdtBrand2,#00cfa0);text-decoration:underline;}',

      /* sub list */
      '#mdtFloatToc .mdtFloatTocGroupToggle{border:0;background:rgba(255,255,255,0.06);color:rgba(255,255,255,0.80);cursor:pointer;padding:0;width:2rem;height:2rem;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;}',
      '#mdtFloatToc .mdtFloatTocGroupToggle:hover{background:rgba(255,255,255,0.12);}',
      '#mdtFloatToc .mdtFloatTocGroup.mdtFloatTocGroupOpen .mdtFloatTocGroupToggle{color:var(--mdtBrand2,#00cfa0);}',
      '#mdtFloatToc .mdtFloatTocSublist{list-style:none;margin:0.35rem 0 0.25rem;padding:0 0 0 0.85rem;border-left:1px solid rgba(255,255,255,0.12);display:none;}',
      '#mdtFloatToc .mdtFloatTocGroup.mdtFloatTocGroupOpen .mdtFloatTocSublist{display:block;}'
    ].join('\n');

    var style = document.createElement('style');
    style.id = 'mdtFloatTocStyle';
    style.type = 'text/css';
    style.textContent = css;
    document.head.appendChild(style);
  }

  function applyDesktopDock(wrap) {
    if (!wrap) return;
    var panel = wrap.querySelector('.mdtFloatTocPanel');
    if (!panel) return;

    if (!isDesktop()) {
      wrap.style.top = '';
      wrap.style.right = '';
      wrap.style.bottom = '';
      panel.style.position = '';
      panel.style.top = '';
      panel.style.right = '';
      panel.style.bottom = '';
      panel.style.left = '';
      panel.style.width = '';
      panel.style.maxHeight = '';
      return;
    }

    var topPx = getDockTopPx();
    wrap.style.top = String(topPx) + 'px';
    wrap.style.right = String(GAP_PX) + 'px';
    wrap.style.bottom = 'auto';

    // Fit into the right gutter: don't cover the white content card
    var content = document.getElementById('mw-content') || document.getElementById('content');
    if (!content || !content.getBoundingClientRect) return;

    var rect = content.getBoundingClientRect();
    var leftPx = Math.round(rect.right + GAP_PX);
    var available = Math.round(window.innerWidth - leftPx - GAP_PX);

    // No right gutter -> keep mobile popup style
    if (available < 220) return;

  panel.style.position = 'fixed';
  panel.style.top = String(topPx) + 'px';
  panel.style.right = String(GAP_PX) + 'px';
  panel.style.bottom = 'auto';
  panel.style.left = String(leftPx) + 'px';
  panel.style.width = 'auto';
  panel.style.maxHeight = 'calc(100vh - ' + String(topPx + GAP_PX) + 'px)';

    // Default open once per page load
    if (wrap.getAttribute('data-mdtDefaultOpen') !== '1') {
      wrap.classList.add('mdtFloatTocOpen');
      wrap.setAttribute('data-mdtDefaultOpen', '1');
    }
  }

  function buildPanel(groups) {
    injectCssOnce();

    var wrap = document.createElement('div');
    wrap.id = 'mdtFloatToc';
    wrap.className = 'mdtFloatToc';

    var openBtn = document.createElement('button');
    openBtn.type = 'button';
    openBtn.className = 'mdtFloatTocBtn';
    openBtn.setAttribute('aria-label', '\u76ee\u5f55');
    openBtn.textContent = '\u2261';
    wrap.appendChild(openBtn);

    var panel = document.createElement('div');
    panel.className = 'mdtFloatTocPanel';
    panel.setAttribute('role', 'dialog');
    panel.setAttribute('aria-label', '\u76ee\u5f55');
    wrap.appendChild(panel);

    var head = document.createElement('div');
    head.className = 'mdtFloatTocHead';
    panel.appendChild(head);

    var topBtn = document.createElement('button');
    topBtn.type = 'button';
    topBtn.className = 'mdtFloatTocTop';
    topBtn.textContent = '\u2191 \u8fd4\u56de\u9876\u90e8';
    head.appendChild(topBtn);

    var title = document.createElement('div');
    title.className = 'mdtFloatTocTitle';
    title.textContent = '\u76ee\u5f55';
    head.appendChild(title);

    var closeBtn = document.createElement('button');
    closeBtn.type = 'button';
    closeBtn.className = 'mdtFloatTocClose';
    closeBtn.setAttribute('aria-label', '\u5173\u95ed');
    closeBtn.textContent = 'X';
    head.appendChild(closeBtn);

    var ul = document.createElement('ul');
    ul.className = 'mdtFloatTocList';
    panel.appendChild(ul);

    function openPanel(open) {
      wrap.classList.toggle('mdtFloatTocOpen', open);
    }

    openBtn.addEventListener('click', function () {
      openPanel(true);
      applyDesktopDock(wrap);
    });

    closeBtn.addEventListener('click', function () {
      openPanel(false);
    });

    topBtn.addEventListener('click', function () {
      if (!isDesktop()) openPanel(false);
      window.scrollTo({ top: 0, behavior: 'smooth' });
    });

    for (var i = 0; i < groups.length; i++) {
      (function (g) {
        var li = document.createElement('li');
        li.className = 'mdtFloatTocItem mdtFloatTocGroup';

        var row = document.createElement('div');
        row.className = 'mdtFloatTocRow';
        li.appendChild(row);

        var a = document.createElement('a');
        a.href = '#' + encodeURIComponent(g.id).replace(/%2F/g, '/');
        a.textContent = g.text;
        row.appendChild(a);

        if (g.children && g.children.length) {
          var toggle = document.createElement('button');
          toggle.type = 'button';
          toggle.className = 'mdtFloatTocGroupToggle';
          toggle.setAttribute('aria-label', '\u5c55\u5f00/\u6536\u8d77');
          toggle.setAttribute('aria-expanded', 'false');
          toggle.textContent = '>';
          row.appendChild(toggle);

          var sub = document.createElement('ul');
          sub.className = 'mdtFloatTocSublist';
          li.appendChild(sub);

          for (var j = 0; j < g.children.length; j++) {
            var c = g.children[j];
            var cli = document.createElement('li');
            cli.className = 'mdtFloatTocItem';
            var ca = document.createElement('a');
            ca.href = '#' + encodeURIComponent(c.id).replace(/%2F/g, '/');
            ca.textContent = c.text;
            cli.appendChild(ca);
            sub.appendChild(cli);
          }

          toggle.addEventListener('click', function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            var open = li.classList.toggle('mdtFloatTocGroupOpen');
            toggle.setAttribute('aria-expanded', String(open));
            toggle.textContent = open ? 'v' : '>';
          });
        }

        ul.appendChild(li);
      })(groups[i]);
    }

    // Click a toc item -> smooth scroll
    wrap.addEventListener('click', function (ev) {
      var target = ev.target;
      if (!target) return;
      var a = target.closest ? target.closest('a') : null;
      if (!a) return;

      var href = a.getAttribute('href') || '';
      if (href.charAt(0) !== '#') return;

      ev.preventDefault();
      if (!isDesktop()) openPanel(false);

      var id = decodeURIComponent(href.slice(1));
      var el = document.getElementById(id);
      if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'start' });
        try {
          history.replaceState(null, '', '#' + encodeURIComponent(id));
        } catch (e) {}
      }
    });

    // Mobile only: tap outside to close. Desktop: do nothing.
    document.addEventListener('click', function (ev) {
      if (isDesktop()) return;
      if (!wrap.classList.contains('mdtFloatTocOpen')) return;
      if (wrap.contains(ev.target)) return;
      openPanel(false);
    });

    // Highlight active heading
    var linkById = {};
    var links = wrap.querySelectorAll('a');
    for (var k = 0; k < links.length; k++) {
      var id2 = decodeURIComponent((links[k].getAttribute('href') || '').slice(1));
      linkById[id2] = links[k];
    }

    var ids = flattenIds(groups);
    var ticking = false;

    function updateActive() {
      ticking = false;

      var bestId = '';
      var bestTop = -Infinity;

      for (var i2 = 0; i2 < ids.length; i2++) {
        var el2 = document.getElementById(ids[i2]);
        if (!el2) continue;
        var rect = el2.getBoundingClientRect();
        if (rect.top <= 120 && rect.top > bestTop) {
          bestTop = rect.top;
          bestId = ids[i2];
        }
      }

      for (var idKey in linkById) {
        linkById[idKey].classList.toggle('mdtFloatTocActive', idKey === bestId);
      }
    }

    window.addEventListener(
      'scroll',
      function () {
        if (ticking) return;
        ticking = true;
        window.requestAnimationFrame(updateActive);
      },
      { passive: true }
    );

    return wrap;
  }

  var resizeBound = false;

  function initFloatToc($content) {
    if (!isViewMode()) return;

    if (document.getElementById('mdtFloatToc')) {
      applyDesktopDock(document.getElementById('mdtFloatToc'));
      return;
    }

    var content = $content && $content[0] ? $content[0] : null;
    var root =
      content || document.querySelector('.mw-parser-output') || document.getElementById('mw-content-text');
    if (!root) return;

    ensureHeadingIds(root);
    var groups = collectGroups(root);
    if (!groups.length) return;

    var wrap = buildPanel(groups);
    document.body.appendChild(wrap);

    applyDesktopDock(wrap);

    if (!resizeBound) {
      resizeBound = true;
      window.addEventListener(
        'resize',
        function () {
          var el = document.getElementById('mdtFloatToc');
          if (el) applyDesktopDock(el);
        },
        { passive: true }
      );
      window.addEventListener('load', function () {
        var el = document.getElementById('mdtFloatToc');
        if (el) applyDesktopDock(el);
      });
    }
  }

  mw.loader.using(['mediawiki.util']).then(function () {
    if (mw.hook && window.jQuery) {
      mw.hook('wikipage.content').add(initFloatToc);
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', function () {
        initFloatToc(null);
      });
    } else {
      initFloatToc(null);
    }
  });
})();

/* MDTWIKI_APPEND_ICON_TOOL v20260123
 * Paste this file at the END of MediaWiki:Common.js (do not replace your existing code).
 * Timeless skin only. Works in action=edit (source editor textarea wpTextbox1).
 */
(function () {
  'use strict';

  if (!window.mw) return;
  if (window.__mdtIconEditorToolInit) return;
  window.__mdtIconEditorToolInit = true;

  mw.loader.using(['mediawiki.util'], function () {
    var skin = String(mw.config.get('skin') || '').toLowerCase();
    if (skin !== 'timeless') return;

    var action = String(mw.config.get('wgAction') || 'view').toLowerCase();
    if (action !== 'edit') return;

    var MDT_ICON_SIZE = 18;

    // Map: page title (wgPageName format) -> uploaded file name.
    // Add more entries as needed.
var MDT_ICON_MAP = {

    '\u94dc': 'Item-copper-ui.png',
    '\u94b0': 'Item-lead-ui.png',
    '\u7164\u70ad': 'Item-coal-ui.png',
    '\u77f3\u58a8': 'Item-graphite-ui.png',
    '\u949b': 'Item-titanium-ui.png',
    '\u94b1': 'Item-thorium-ui.png',
    '\u7845': 'Item-silicon-ui.png',
    '\u5851\u94a2': 'Item-plastanium-ui.png',
    '\u76f8\u7ec7\u5e03': 'Item-phase-fabric-ui.png',
    '\u5de8\u6d6a\u5408\u91d1': 'Item-surge-alloy-ui.png',
    '\u5b62\u5b50\u8350': 'Item-spore-pod-ui.png',
    '\u6c99': 'Item-sand-ui.png',
    '\u7206\u70b8\u6df7\u5408\u7269': 'Item-blast-compound-ui.png',
    '\u786b\u5316\u7269': 'ohno.png',
    '\u94a2\u5316\u73bb\u7483': 'Item-metaglass-ui.png',
    '\u5e9f\u6599': 'Item-scrap-ui.png',
    '\u88c2\u53d8\u4ea7\u7269': 'Item-fissile-matter-ui.png',
    '\u94bd': 'Item-beryllium-ui.png',
    '\u949e': 'Item-tungsten-ui.png',
    '\u6c27\u5316\u7269': 'Item-oxide-ui.png',
    '\u78b3\u5316\u7269': 'Item-carbide-ui.png',
    '\u4f11\u7720\u56ca\u80bf': 'Item-dormant-cyst-ui.png',

    '\u6c34': 'Liquid-water-ui.png',
    '\u77ff\u6e23': 'Liquid-slag-ui.png',
    '\u77f3\u6cb9': 'Liquid-oil-ui.png',
    '\u51b7\u51bb\u6db2': 'Liquid-cryofluid-ui.png',
    '\u7624\u6db2': 'Liquid-neoplasm-ui.png',
    '\u82b3\u6cb9': 'Liquid-arkycite-ui.png',
    '\u92e0\u6db2': 'Liquid-gallium-ui.png',
    '\u6c27\u6c27': 'Liquid-ozone-ui.png',
    '\u6c22\u6c14': 'Liquid-hydrogen-ui.png',
    '\u6c2e\u6c14': 'Liquid-nitrogen-ui.png',
    '\u6c2e\u6c14': 'Liquid-cyanogen-ui.png',

    '\u5c16\u5200': 'Unit-dagger-ui.png',
    '\u6218\u9524': 'Unit-mace-ui.png',
    '\u5821\u5792': 'Unit-fortress-ui.png',
    '\u65b0\u661f': 'Unit-nova-ui.png',
    '\u6052\u661f': 'Unit-pulsar-ui.png',
    '\u8000\u661f': 'Unit-quasar-ui.png',
    '\u722c\u866b': 'Unit-crawler-ui.png',
    '\u6bd2\u879e': 'Unit-atrax-ui.png',
    '\u8840\u87b2': 'Unit-spiroct-ui.png',
    '\u6bd2\u86c7': 'Unit-arkyid-ui.png',
    '\u5929\u874e': 'Unit-toxopid-ui.png',
    '\u661f\u8f89': 'Unit-stell-ui.png',
    '\u5929\u57b0': 'Unit-vela-ui.png',
    '\u82cd\u7a79': 'Unit-corvus-ui.png',
    '\u6708\u5f71': 'Unit-antumbra-ui.png',
    '\u65e5\u8681': 'Unit-eclipse-ui.png',
    '\u72ec\u5f71': 'Unit-obviate-ui.png',
    '\u5e7b\u578b': 'Unit-elude-ui.png',
    '\u5de8\u50cf': 'Unit-emanate-ui.png',
    '\u96f7\u96f7': 'Unit-evoke-ui.png',
    '\u8981\u585e': 'Unit-conquer-ui.png',
    '\u68d2\u9c7c': 'Unit-bryde-ui.png',
    '\u98de\u9ca8': 'Unit-minke-ui.png',
    '\u6218\u9cb8': 'Unit-sei-ui.png',
    '\u86f9\u9f99': 'Unit-omura-ui.png',
    '\u6d77\u795e': 'Unit-retusa-ui.png',
    '\u6f5c\u87ba': 'Unit-cyerce-ui.png',
    '\u7535\u9cca': 'Unit-oxynoe-ui.png',
    '\u6c5f\u8c5a': 'Unit-risso-ui.png',
    '\u7384\u6b66': 'Unit-navanax-ui.png',
    '\u9f99\u738b': 'Unit-anthicus-ui.png',
    '\u963f\u5c14\u6cd5': 'Unit-alpha-ui.png',
    '\u8d1d\u5854': 'Unit-beta-ui.png',
    '\u4f3d\u9a6c': 'Unit-gamma-ui.png',
    '\u6743\u6756': 'Unit-scepter-ui.png',
    '\u738b\u5ea7': 'Unit-reign-ui.png',
    '\u707e\u661f': 'Unit-scathe-ui.png',
    '\u6b7b\u661f': 'Unit-horizon-ui.png',
    '\u56f4\u62a4': 'Unit-avert-ui.png',
    '\u5f99\u8ff9': 'Unit-locus-ui.png',
    '\u51c6\u7ef3': 'Unit-precept-ui.png',
    '\u5f81\u670d': 'Unit-vanquish-ui.png',
    '\u9886\u4e3b': 'Unit-tecta-ui.png',
    '\u5929\u5b88': 'Unit-collaris-ui.png',
    '\u5929\u8d50': 'Unit-disrupt-ui.png',
    '\u5929\u707e': 'Unit-quell-ui.png',
    '\u5929\u7406': 'Unit-elude-ui.png',
    '\u5929\u5e1d': 'Unit-emanate-ui.png',
    '\u62c9\u8131': 'Unit-flare-ui.png',
    '\u906e\u853d': 'Unit-horizon-ui.png',
    '\u6d88\u6563': 'Unit-disperse-ui.png',
    '\u907c\u6b62': 'Unit-obviate-ui.png',
    '\u60b2\u6071': 'Unit-merui-ui.png',
    '\u82cf\u9192': 'Unit-emanate-ui.png',
    '\u7b56\u52a8': 'Unit-incite-ui.png',
    '\u53d1\u6563': 'Unit-disperse-ui.png',
    '\u8d27\u8fd0\u65e0\u4eba\u673a': 'Unit-cargo-drone-ui.png',
    '\u88c5\u914d\u65e0\u4eba\u673a': 'Unit-assembly-drone-ui.png',
    'Latum': 'Unit-latum-ui.png',
    'Renale': 'Unit-renale-ui.png',

    '\u5dee\u6270': 'ohno.png',
    '\u60ac\u5d16': 'Block-cliff-ui.png',
    '\u7802\u5ca9': 'Block-dacite-ui.png',
    '\u7384\u6b66\u5ca9\u77f3\u5757': 'Block-basalt-boulder-ui.png',
    '\u7a91\u7089': 'Block-kiln-ui.png',
    '\u77f3\u58a8\u538b\u7f29\u673a': 'Block-graphite-press-ui.png',
    '\u591a\u91cd\u538b\u7f29\u673a': 'Block-multi-press-ui.png',
    '\u654c\u4eba\u51fa\u751f\u70b9': 'Block-spawn-ui.png',
    '\u79fb\u9664\u5899\u4f53': 'Block-remove-wall-ui.png',
    '\u79fb\u9664\u77ff': 'Block-remove-ore-ui.png',
    '\u521d\u4ee3\u6838\u5fc3': 'Block-core-shard-ui.png',
    '\u6b21\u4ee3\u6838\u5fc3': 'Block-core-foundation-ui.png',
    '\u7ec8\u4ee3\u6838\u5fc3': 'Block-core-nucleus-ui.png',
    '\u53cc\u7ba1': 'Block-duo-ui.png',
    '\u706b\u7130': 'Block-scorch-ui.png',
    '\u5206\u88c2': 'Block-ripple-ui.png',
    '\u51b0\u970d': 'Block-hail-ui.png',
    '\u84dd\u745e': 'Block-lancer-ui.png',
    '\u4f20\u9001\u5e26': 'Block-conveyor-ui.png',
    '\u949b\u4f20\u9001\u5e26': 'Block-titanium-conveyor-ui.png',
    '\u5851\u94a2\u4f20\u9001\u5e26': 'Block-plastanium-conveyor-ui.png',
    '\u88c5\u7532\u4f20\u9001\u5e26': 'Block-armored-conveyor-ui.png',
    '\u4ea4\u53c9\u5668': 'Block-junction-ui.png',
    '\u8def\u7531\u5668': 'Block-router-ui.png',
    '\u5206\u914d\u5668': 'Block-distributor-ui.png',
    '\u5206\u7c7b\u5668': 'Block-sorter-ui.png',
    '\u53cd\u5411\u5206\u7c7b\u5668': 'Block-inverted-sorter-ui.png',
    '\u4fe1\u606f\u677f': 'Block-message-ui.png',
    '\u5f3a\u5316\u4fe1\u606f\u677f': 'Block-reinforced-message-ui.png',
    '\u4e16\u754c\u4fe1\u606f\u677f': 'Block-world-message-ui.png',
    '\u4e16\u754c\u5f00\u5173': 'Block-world-switch-ui.png',
    '\u7167\u660e\u5668': 'Block-illuminator-ui.png',
    '\u6ea2\u6d41\u95e8': 'Block-overflow-gate-ui.png',
    '\u53cd\u5411\u6ea2\u6d41\u95e8': 'Block-underflow-gate-ui.png',
    '\u7845\u51b6\u70bc\u5382': 'Block-silicon-smelter-ui.png',
    '\u76f8\u7ec7\u5e03\u7f16\u7ec7\u5668': 'Block-phase-weaver-ui.png',
    '\u7c89\u788e\u673a': 'Block-pulverizer-ui.png',
    '\u51b7\u51bb\u6db2\u6df7\u5408\u5668': 'Block-cryofluid-mixer-ui.png',
    '\u7194\u7089': 'Block-melter-ui.png',
    '\u711a\u5316\u7089': 'Block-incinerator-ui.png',
    '\u5b62\u5b50\u538b\u7f29\u673a': 'Block-spore-press-ui.png',
    '\u5206\u79bb\u673a': 'Block-separator-ui.png',
    '\u7164\u70ad\u79bb\u5fc3\u673a': 'Block-coal-centrifuge-ui.png',
    '\u7535\u529b\u8282\u70b9': 'Block-power-node-ui.png',
    '\u5927\u578b\u7535\u529b\u8282\u70b9': 'Block-power-node-large-ui.png',
    '\u5de8\u6d6a\u7535\u529b\u5854': 'Block-surge-tower-ui.png',
    '\u4e8c\u6781\u7ba1': 'Block-diode-ui.png',
    '\u7535\u6c60': 'Block-battery-ui.png',
    '\u5927\u578b\u7535\u6c60': 'Block-battery-large-ui.png',
    '\u706b\u529b\u53d1\u7535\u673a': 'Block-combustion-generator-ui.png',
    '\u6da1\u8f6e\u53d1\u7535\u673a': 'Block-steam-generator-ui.png',
    '\u6e29\u5dee\u53d1\u7535\u673a': 'Block-thermal-generator-ui.png',
    '\u51b2\u51fb\u53cd\u5e94\u5806': 'Block-impact-reactor-ui.png',
    '\u673a\u68b0\u94bb\u5934': 'Block-mechanical-drill-ui.png',
    '\u6c14\u52a8\u94bb\u5934': 'Block-pneumatic-drill-ui.png',
    '\u6fc0\u5149\u94bb\u5934': 'Block-laser-drill-ui.png',
    '\u62bd\u6c34\u673a': 'Block-water-extractor-ui.png',
    '\u57f9\u517b\u673a': 'Block-cultivator-ui.png',
    '\u5bfc\u7ba1': 'Block-conduit-ui.png',
    '\u673a\u68b0\u6cf5': 'Block-mechanical-pump-ui.png',
    '\u7269\u54c1\u6e90': 'Block-item-source-ui.png',
    '\u7269\u54c1\u9ed1\u6d1e': 'Block-item-void-ui.png',
    '\u6db2\u4f53\u6e90': 'Block-liquid-source-ui.png',
    '\u6db2\u4f53\u9ed1\u6d1e': 'Block-liquid-void-ui.png',
    '\u7535\u529b\u9ed1\u6d1e': 'Block-power-void-ui.png',
    '\u7535\u529b\u6e90': 'Block-power-source-ui.png',
    '\u88c5\u5378\u5668': 'Block-unloader-ui.png',
    '\u4ed3\u5e93': 'Block-vault-ui.png',
    '\u6ce2\u6d6a': 'Block-wave-ui.png',
    '\u6d77\u55d4': 'Block-tsunami-ui.png',
    '\u8702\u7fa4': 'Block-swarmer-ui.png',
    '\u9f50\u5c04': 'Block-salvo-ui.png',
    '\u6d6a\u6d8c': 'Block-surge-ui.png',
    '\u76f8\u7ec7\u5e03\u4f20\u9001\u5e26\u6865': 'Block-phase-conveyor-ui.png',
    '\u4f20\u9001\u5e26\u6865': 'Block-bridge-conveyor-ui.png',
    '\u5851\u94a2\u538b\u7f29\u673a': 'Block-plastanium-compressor-ui.png',
    '\u786b\u5316\u7269\u6df7\u5408\u5668': 'Block-sulfide-mixer-ui.png',
    '\u7206\u70b8\u7269\u6df7\u5408\u5668': 'Block-blast-mixer-ui.png',
    '\u592a\u9633\u80fd\u677f': 'Block-solar-panel-ui.png',
    '\u5927\u578b\u592a\u9633\u80fd\u677f': 'Block-solar-panel-large-ui.png',
    '\u77f3\u6cb9\u94bb\u4e95': 'Block-oil-extractor-ui.png',
    '\u7ef4\u4fee\u70b9': 'Block-repair-point-ui.png',
    '\u7ef4\u4fee\u5854': 'Block-repair-turret-ui.png',
    '\u8109\u51b2\u5bfc\u7ba1': 'Block-pulse-conduit-ui.png',
    '\u7535\u9540\u5bfc\u7ba1': 'Block-plated-conduit-ui.png',
    '\u76f8\u7ec7\u5e03\u5bfc\u7ba1\u6865': 'Block-phase-conduit-ui.png',
    '\u6d41\u4f53\u8def\u7531\u5668': 'Block-liquid-router-ui.png',
    '\u6d41\u4f53\u50a8\u7f50': 'Block-liquid-tank-ui.png',
    '\u6d41\u4f53\u5bb9\u5668': 'Block-liquid-container-ui.png',
    '\u6d41\u4f53\u4ea4\u53c9\u5668': 'Block-liquid-junction-ui.png',
    '\u5bfc\u7ba1\u6865': 'Block-bridge-conduit-ui.png',
    '\u56de\u8f6c\u6cf5': 'Block-rotary-pump-ui.png',
    '\u94b1\u53cd\u5e94\u5806': 'Block-thorium-reactor-ui.png',
    '\u8d28\u91cf\u9a71\u52a8\u5668': 'Block-mass-driver-ui.png',
    '\u7206\u7834\u94bb\u5934': 'Block-blast-drill-ui.png',
    '\u8109\u51b2\u6cf5': 'Block-impulse-pump-ui.png',
    '\u70ed\u80fd\u53d1\u7535\u673a': 'Block-differential-generator-ui.png',
    '\u5408\u91d1\u51b6\u70bc\u5382': 'Block-alloy-smelter-ui.png',
    '\u4fee\u7406\u5668': 'Block-mender-ui.png',
    '\u4fee\u7406\u6295\u5f71': 'Block-mend-projector-ui.png',
    '\u5408\u91d1\u5899': 'Block-surge-wall-ui.png',
    '\u5927\u578b\u5408\u91d1\u5899': 'Block-surge-wall-large-ui.png',
    '\u6c14\u65cb': 'Block-cyclone-ui.png',
    '\u96f7\u5149': 'Block-arc-ui.png',
    '\u8109\u51b2\u5730\u96f7': 'Block-shock-mine-ui.png',
    '\u8d85\u901f\u6295\u5f71': 'Block-overdrive-projector-ui.png',
    '\u529b\u5899\u6295\u5f71': 'Block-force-projector-ui.png',
    '\u7535\u5f27': 'Block-arc-ui.png',
    'RTG\u53d1\u7535\u673a': 'Block-rtg-generator-ui.png',
    '\u5e7b\u5f71': 'Block-phantom-ui.png',
    '\u7194\u6bc1': 'Block-meltdown-ui.png',
    '\u5384\u5146': 'Block-afflict-ui.png',
    '\u5bb9\u5668': 'Block-container-ui.png',
    '\u53d1\u5c04\u53f0': 'Block-launch-pad-ui.png',
    '\u63a5\u6536\u53f0': 'Block-landing-pad-ui.png',
    '\u88c2\u89e3': 'Block-disassembler-ui.png',
    '\u9646\u519b\u5de5\u5382': 'Block-ground-factory-ui.png',
    '\u7a7a\u519b\u5de5\u5382': 'Block-air-factory-ui.png',
    '\u6d77\u519b\u5de5\u5382': 'Block-naval-factory-ui.png',
    '\u6570\u589e\u7ea7\u5355\u4f4d\u91cd\u6784\u5de5\u5382': 'Block-additive-reconstructor-ui.png',
    '\u500d\u4e58\u7ea7\u5355\u4f4d\u91cd\u6784\u5de5\u5382': 'Block-multiplicative-reconstructor-ui.png',
    '\u591a\u5e42\u7ea7\u5355\u4f4d\u91cd\u6784\u5de5\u5382': 'Block-exponential-reconstructor-ui.png',
    '\u65e0\u91cf\u7ea7\u5355\u4f4d\u91cd\u6784\u5de5\u5382': 'Block-tetrative-reconstructor-ui.png',
    '\u8f7d\u8377\u4f20\u9001\u5e26': 'Block-payload-conveyor-ui.png',
    '\u8f7d\u8377\u8def\u7531\u5668': 'Block-payload-router-ui.png',
    '\u7269\u54c1\u7ba1\u9053': 'Block-duct-ui.png',
    '\u7269\u54c1\u7ba1\u9053\u8def\u7531\u5668': 'Block-duct-router-ui.png',
    '\u7269\u54c1\u7ba1\u9053\u6865': 'Block-duct-bridge-ui.png',
    '\u5927\u578b\u8f7d\u8379\u8d28\u91cf\u9a71\u52a8\u5668': 'Block-large-payload-mass-driver-ui.png',
    '\u8f7d\u8379\u9ed1\u6d1e': 'Block-payload-void-ui.png',
    '\u8f7d\u8379\u6e90': 'Block-payload-source-ui.png',
    '\u89e3\u79bb\u673a': 'Block-disassembler-ui.png',
    '\u70ed\u80fd\u5759\u5759': 'Block-slag-heater-ui.png',
    '\u8d85\u901f\u7a84\u9876': 'Block-overdrive-dome-ui.png',
    '\u884c\u661f\u9645\u52a0\u901f\u5668': 'Block-interplanetary-accelerator-ui.png',
    '\u52cb\u7b51\u5668': 'Block-constructor-ui.png',
    '\u5927\u578b\u52cb\u7b51\u5668': 'Block-large-constructor-ui.png',
    '\u5927\u578b\u89e3\u6784\u5668': 'Block-deconstructor-ui.png',
    '\u8f7d\u8379\u88c5\u8f7d\u5668': 'Block-payload-loader-ui.png',
    '\u8f7d\u8379\u5378\u8f7d\u5668': 'Block-payload-unloader-ui.png',
    '\u70ed\u91cf\u6e90': 'Block-heat-source-ui.png',
    '\u7a7a': 'Block-empty-ui.png',
    '\u6d41\u7eb9\u5ca9\u5751': 'Block-rhyolite-crater-ui.png',
    '\u7c97\u7cd9\u6d41\u7eb9\u5ca9': 'Block-rough-rhyolite-ui.png',
    '\u6d41\u7eb9\u5ca9': 'Block-rhyolite-ui.png',
    '\u9ec4\u77f3': 'Block-yellow-stone-ui.png',
    '\u78b3\u77f3': 'Block-carbon-stone-ui.png',
    '\u94c1\u77f3': 'Block-ferric-stone-ui.png',
    '\u94c1\u9645\u77f3\u5751': 'Block-ferric-craters-ui.png',
    '\u94bd\u77f3': 'Block-beryllic-stone-ui.png',
    '\u6676\u77f3': 'Block-crystalline-stone-ui.png',
    '\u6676\u77f3\u5730\u677f': 'Block-crystal-floor-ui.png',
    '\u9ec4\u77f3\u5730\u677f': 'Block-yellow-stone-plates-ui.png',
    '\u7ea2\u77f3': 'Block-red-stone-ui.png',
    '\u9ad8\u5bc6\u7ea2\u77f3': 'Block-dense-red-stone-ui.png',
    '\u7ea2\u51b0': 'Block-red-ice-ui.png',
    //'\u82b3\u6cb9': 'Block-arkyic-stone-ui.png',   这是地板!ai都不看重复的吗
    '\u82b3\u77f3': 'Block-arkyic-stone-ui.png',
    '\u6d41\u7eb9\u77f3\u55b7\u53e3': 'Block-rhyolite-vent-ui.png',
    '\u78b3\u77f3\u55b7\u53e3': 'Block-carbon-vent-ui.png',
    '\u82b3\u77f3\u55b7\u53e3': 'Block-arkyic-vent-ui.png',
    '\u9ec4\u77f3\u55b7\u53e3': 'Block-yellow-stone-vent-ui.png',
    '\u7ea2\u77f3\u55b7\u53e3': 'Block-red-stone-vent-ui.png',
    '\u6676\u77f3\u55b7\u53e3': 'Block-crystalline-vent-ui.png',
    '\u5ca9\u77f3\u55b7\u53e3': 'Block-stone-vent-ui.png',
    '\u7384\u6b66\u5ca9\u55b7\u53e3': 'Block-basalt-vent-ui.png',
    '\u7ea2\u5730\u57ab': 'Block-redmat-ui.png',
    '\u84dd\u5730\u57ab': 'Block-bluemat-ui.png',
    '\u6838\u5fc3\u533a': 'Block-core-zone-ui.png',
    '\u98ce\u5316\u5899': 'Block-regolith-wall-ui.png',
    '\u9ec4\u77f3\u5899': 'Block-yellow-stone-wall-ui.png',
    '\u6d41\u7eb9\u5ca9\u5899': 'Block-rhyolite-wall-ui.png',
    '\u78b3\u77f3\u5899': 'Block-carbon-wall-ui.png',
    '\u94c1\u77f3\u5899': 'Block-ferric-stone-wall-ui.png',
    '\u94bd\u77f3\u5899': 'Block-beryllic-stone-wall-ui.png',
    '\u82b3\u77f3\u5899': 'Block-arkyic-wall-ui.png',
    '\u6676\u77f3\u5899': 'Block-crystalline-stone-wall-ui.png',
    '\u7ea2\u51b0\u5899': 'Block-red-ice-wall-ui.png',
    '\u7ea2\u77f3\u5899': 'Block-red-stone-wall-ui.png',
    '\u7ea2\u94bb\u5899': 'Block-red-diamond-wall-ui.png',
    '\u8d64\u85fb': 'Block-redweed-ui.png',
    '\u7d2b\u704c\u6728\u4e1b': 'Block-pur-bush-ui.png',
    '\u9ec4\u73ca\u745a': 'Block-yellowcoral-ui.png',
    '\u78b3\u77f3\u5757': 'Block-carbon-boulder-ui.png',
    '\u94c1\u77f3\u5757': 'Block-ferric-boulder-ui.png',
    '\u94bd\u77f3\u5757': 'Block-beryllic-boulder-ui.png',
    '\u9ec4\u77f3\u5757': 'Block-yellow-stone-boulder-ui.png',
    '\u82b3\u77f3\u5757': 'Block-arkyic-boulder-ui.png',
    '\u6c34\u6676\u7c07': 'Block-crystal-cluster-ui.png',
    '\u9c9c\u8273\u6c34\u6676\u7c07': 'Block-vibrant-crystal-cluster-ui.png',
    '\u98ce\u5316\u6676\u4f53': 'Block-weathered-crystal-ui.png',
    '\u6676\u77f3\u7403': 'Block-crystal-orbs-ui.png',
    '\u6676\u77f3\u5757': 'Block-crystal-blocks-ui.png',
    '\u7ea2\u51b0\u77f3\u5757': 'Block-red-ice-boulder-ui.png',
    '\u6d41\u7eb9\u77f3\u5757': 'Block-rhyolite-boulder-ui.png',
    '\u7ea2\u77f3\u5757': 'Block-red-stone-boulder-ui.png',
    '\u77f3\u58a8\u5899': 'Block-graphitic-wall-ui.png',
    '\u7535\u5f27\u7845\u7089': 'Block-silicon-arc-furnace-ui.png',
    '\u7535\u89e3\u673a': 'Block-electrolyzer-ui.png',
    '\u5927\u6c14\u6536\u96c6\u5668': 'Block-atmospheric-concentrator-ui.png',
    '\u6c27\u5316\u5ba4': 'Block-oxidation-chamber-ui.png',
    '\u7535\u5236\u70ed\u673a': 'Block-electric-heater-ui.png',
    '\u77ff\u6e23\u5236\u70ed\u673a': 'Block-slag-heater-ui.png',
    '\u76f8\u7ec7\u5236\u70ed\u673a': 'Block-phase-heater-ui.png',
    '\u70ed\u91cf\u4f20\u8f93\u673a': 'Block-heat-redirector-ui.png',
    '\u5c0f\u578b\u70ed\u91cf\u4f20\u8f93\u673a': 'Block-small-heat-redirector-ui.png',
    '\u70ed\u91cf\u8def\u7531\u5668': 'Block-heat-router-ui.png',
    '\u77ff\u6e23\u711a\u5316\u7089': 'Block-slag-incinerator-ui.png',
    '\u78b3\u5316\u7269\u5759\u5759': 'Block-carbide-crucible-ui.png',
    '\u77ff\u6e23\u79bb\u5fc3\u673a': 'Block-slag-centrifuge-ui.png',
    '\u5408\u91d1\u5759\u5759': 'Block-alloy-crucible-ui.png',
    '\u6c27\u5408\u6210\u673a': 'Block-cyanogen-synthesizer-ui.png',
    '\u76f8\u7ec7\u5e03\u5408\u6210\u673a': 'Block-phase-synthesizer-ui.png',
    '\u70ed\u91cf\u53cd\u5e94\u5806': 'Block-heat-reactor-ui.png',
    '\u94bd\u5899': 'Block-beryllium-wall-ui.png',
    '\u5927\u578b\u94bd\u5899': 'Block-beryllium-wall-large-ui.png',
    '\u949e\u5899': 'Block-tungsten-wall-ui.png',
    '\u5927\u578b\u949e\u5899': 'Block-tungsten-wall-large-ui.png',
    '\u9632\u7206\u95f8\u95e8': 'Block-blast-door-ui.png',
    '\u78b3\u5316\u7269\u5899': 'Block-carbide-wall-ui.png',
    '\u5927\u578b\u78b3\u5316\u7269\u5899': 'Block-carbide-wall-large-ui.png',
    '\u5f3a\u5316\u5408\u91d1\u5899': 'Block-reinforced-surge-wall-ui.png',
    '\u5927\u578b\u5f3a\u5316\u5408\u91d1\u5899': 'Block-reinforced-surge-wall-large-ui.png',
    '\u76fe\u5899': 'Block-shielded-wall-ui.png',
    '\u96f7\u8fbe': 'Block-radar-ui.png',
    '\u5efa\u9020\u5854': 'Block-build-tower-ui.png',
    '\u518d\u751f\u6295\u5f71\u5668': 'Block-regen-projector-ui.png',
    '\u9707\u7206\u5854': 'Block-shockwave-tower-ui.png',
    '\u62a4\u76fe\u6295\u5f71\u5668': 'Block-shield-projector-ui.png',
    '\u5927\u578b\u62a4\u76fe\u6295\u5f71\u5668': 'Block-large-shield-projector-ui.png',
    '\u88c5\u7532\u7ba1\u9053': 'Block-armored-duct-ui.png',
    '\u6ea2\u6d41\u7ba1\u9053': 'Block-overflow-duct-ui.png',
    '\u53cd\u5411\u6ea2\u6d41\u7ba1': 'Block-underflow-duct-ui.png',
    '\u7ba1\u9053\u88c5\u5378\u5668': 'Block-duct-unloader-ui.png',
    '\u5408\u91d1\u4f20\u9001\u5e26': 'Block-surge-conveyor-ui.png',
    '\u5408\u91d1\u8def\u7531\u5668': 'Block-surge-router-ui.png',
    '\u5355\u4f4d\u7269\u6d41\u88c5\u8f7d\u5668': 'Block-unit-cargo-loader-ui.png',
    '\u5355\u4f4d\u7269\u6d41\u5378\u8f7d\u70b9': 'Block-unit-cargo-unload-point-ui.png',
    '\u5f3a\u5316\u6cf5': 'Block-reinforced-pump-ui.png',
    '\u5f3a\u5316\u5bfc\u7ba1': 'Block-reinforced-conduit-ui.png',
    '\u5f3a\u5316\u6d41\u4f53\u4ea4\u53c9\u5668': 'Block-reinforced-liquid-junction-ui.png',
    '\u5f3a\u5316\u6d41\u4f53\u5e26\u6865': 'Block-reinforced-bridge-conduit-ui.png',
    '\u5f3a\u5316\u6d41\u4f53\u8def\u7531\u5668': 'Block-reinforced-liquid-router-ui.png',
    '\u5f3a\u5316\u6d41\u4f53\u5bb9\u5668': 'Block-reinforced-liquid-container-ui.png',
    '\u5f3a\u5316\u6d41\u4f53\u50a8\u7f50': 'Block-reinforced-liquid-tank-ui.png',
    '\u6fc0\u5149\u8282\u70b9': 'Block-beam-node-ui.png',
    '\u6fc0\u5149\u5854': 'Block-beam-tower-ui.png',
    '\u6fc0\u5149\u8fde\u63a5\u5668': 'Block-beam-link-ui.png',
    '\u6da1\u8f6e\u51b7\u51dd\u5668': 'Block-turbine-condenser-ui.png',
    '\u5316\u5b66\u71c3\u70e7\u5ba4': 'Block-chemical-combustion-chamber-ui.png',
    '\u70ed\u89e3\u53d1\u751f\u5668': 'Block-pyrolysis-generator-ui.png',
    '\u6392\u6c14\u51b7\u51dd\u5668': 'Block-vent-condenser-ui.png',
    '\u5899\u58c1\u7c89\u788e\u673a': 'Block-cliff-crusher-ui.png',
    '\u9ad8\u7ea7\u5899\u58c1\u7c89\u788e\u673a': 'Block-large-cliff-crusher-ui.png',
    '\u7b49\u79bb\u5b50\u94bb\u673a': 'Block-plasma-bore-ui.png',
    '\u5927\u578b\u7b49\u79bb\u5b50\u94bb\u673a': 'Block-large-plasma-bore-ui.png',
    '\u51b2\u51fb\u94bb\u5934': 'Block-impact-drill-ui.png',
    '\u7206\u88c2\u94bb\u5934': 'Block-eruption-drill-ui.png',
    '\u57ce\u5821\u6838\u5fc3': 'Block-core-citadel-ui.png',
    '\u5821\u5792\u6838\u5fc3': 'Block-core-bastion-ui.png',
    '\u536b\u57ce\u6838\u5fc3': 'Block-core-acropolis-ui.png',
    '\u5f3a\u5316\u5bb9\u5668': 'Block-reinforced-container-ui.png',
    '\u5f3a\u5316\u4ed3\u5e93': 'Block-reinforced-vault-ui.png',
    '\u6495\u88c2': 'Block-ripper-ui.png',
    '\u5347\u534e': 'Block-sublimate-ui.png',
    '\u6cf0\u5766': 'Block-titan-ui.png',
    '\u9a71\u79bb': 'Block-disperse-ui.png',
    '\u52ab\u96be': 'Block-afflict-ui.png',
    '\u5149\u8f89': 'Block-lustre-ui.png',
    '\u521b\u4f24': 'Block-scathe-ui.png',
    '\u5766\u514b\u91cd\u6784\u5382': 'Block-tank-refabricator-ui.png',
    '\u673a\u7532\u91cd\u6784\u5382': 'Block-mech-refabricator-ui.png',
    '\u98de\u8239\u91cd\u6784\u5382': 'Block-ship-refabricator-ui.png',
    '\u5766\u514b\u7ec4\u88c5\u5382': 'Block-tank-assembler-ui.png',
    '\u98de\u8239\u7ec4\u88c5\u5382': 'Block-ship-assembler-ui.png',
    '\u673a\u7532\u7ec4\u88c5\u5382': 'Block-mech-assembler-ui.png',
    '\u5f3a\u5316\u8f7d\u8379\u4f20\u9001\u5e26': 'Block-reinforced-payload-conveyor-ui.png',
    '\u5f3a\u5316\u8f7d\u8379\u8def\u7531\u5668': 'Block-reinforced-payload-router-ui.png',
    '\u8f7d\u8379\u8d28\u91cf\u9a71\u52a8\u5668': 'Block-payload-mass-driver-ui.png',
    '\u89e3\u6784\u5668': 'Block-deconstructor-ui.png',
    '\u753b\u677f': 'Block-canvas-ui.png',
    '\u4e16\u754c\u5904\u7406\u5668': 'Block-world-processor-ui.png',
    '\u4e16\u754c\u5185\u5b58\u5143': 'Block-world-cell-ui.png',
    '\u5766\u514b\u5236\u9020\u5382': 'Block-tank-fabricator-ui.png',
    '\u673a\u7532\u5236\u9020\u5382': 'Block-mech-fabricator-ui.png',
    '\u98de\u8239\u5236\u9020\u5382': 'Block-ship-fabricator-ui.png',
    '\u9ad8\u7ea7\u518d\u91cd\u6784\u5de5\u5382': 'Block-prime-refabricator-ui.png',
    '\u5355\u4f4d\u7ef4\u4fee\u5854': 'Block-unit-repair-tower-ui.png',
    '\u6269\u6563': 'Block-diffuse-ui.png',
    '\u57fa\u672c\u88c5\u914d\u5382\u6a21\u5757': 'Block-basic-assembler-module-ui.png',
    '\u5929\u8c26': 'Block-smite-ui.png',
    '\u9b54\u7075': 'Block-malign-ui.png',
    '\u901a\u91cf\u53cd\u5e94\u5806': 'Block-flux-reactor-ui.png',
    '\u7624\u53d8\u53cd\u5e94\u5806': 'Block-neoplasia-reactor-ui.png',
    '\u5f00\u5173': 'Block-switch-ui.png',
    '\u5fae\u578b\u5904\u7406\u5668': 'Block-micro-processor-ui.png',
    '\u903b\u8f91\u5904\u7406\u5668': 'Block-logic-processor-ui.png',
    '\u8d85\u6838\u5904\u7406\u5668': 'Block-hyper-processor-ui.png',
    '\u903b\u8f91\u663e\u793a\u5c4f': 'Block-logic-display-ui.png',
    '\u5927\u578b\u903b\u8f91\u663e\u793a\u5c4f': 'Block-large-logic-display-ui.png',
    '\u903b\u8f91\u663e\u793a\u5355\u5143': 'Block-tile-logic-display-ui.png',
    '\u5185\u5b58\u5143': 'Block-memory-cell-ui.png',
    '\u5185\u5b58\u5e93': 'Block-memory-bank-ui.png',

    '\u8349\u5730': 'Block-grass-ui.png',
    '\u77ff\u6e23\u6db2': 'Block-molten-slag-ui.png',
    //'\u51b7\u51bb\u6db2': 'Block-pooled-cryofluid-ui.png',   这是地板!ai都不看重复的吗
    '\u592a\u7a7a': 'Block-space-ui.png',
    '\u76d0\u78b1\u5730': 'Block-salt-ui.png',
    '\u76d0\u5899': 'Block-salt-wall-ui.png',
    '\u9e4f\u5375\u77f3': 'Block-pebbles-ui.png',
    '\u5377\u987b': 'Block-tendrils-ui.png',
    '\u6c99\u5899': 'Block-sand-wall-ui.png',
    '\u5b62\u5b50\u6811': 'Block-spore-pine-ui.png',
    '\u5b62\u5b50\u5899': 'Block-spore-wall-ui.png',
    '\u77f3\u5757': 'Block-stone-ui.png',
    '\u96ea\u77f3\u5757': 'Block-snow-boulder-ui.png',
    '\u96ea\u6811': 'Block-snow-pine-ui.png',
    '\u9875\u5ca9\u5730': 'Block-shale-ui.png',
    '\u9875\u5ca9\u77f3\u5757': 'Block-shale-boulder-ui.png',
    '\u829c\u85fb\u5730': 'Block-moss-ui.png',
    '\u704c\u6728\u4e1b': 'Block-shrubs-ui.png',
    '\u5b62\u5b50\u829c\u85fb\u5730': 'Block-spore-moss-ui.png',
    '\u9875\u5ca9\u5899': 'Block-shale-wall-ui.png',
    '\u5e9f\u5899': 'Block-scrap-wall-ui.png',
    '\u5927\u578b\u5e9f\u5899': 'Block-scrap-wall-large-ui.png',
    '\u5de8\u578b\u5e9f\u5899': 'Block-scrap-wall-huge-ui.png',
    '\u8d85\u5de8\u578b\u5e9f\u5899': 'Block-scrap-wall-gigantic-ui.png',
    '\u63a8\u8fdb\u5668\u6b8b\u9ab5': 'Block-thruster-ui.png',
    '\u6df1\u6c34': 'Block-deep-water-ui.png',
    //'\u6c34': 'Block-shallow-water-ui.png',   这是地板!ai都不看重复的吗?
    '\u6c61\u6c34': 'Block-tainted-water-ui.png',
    '\u6df1\u6c61\u6c34': 'Block-deep-tainted-water-ui.png',
    '\u9ed1\u6c99\u6c61\u6c34': 'Block-darksand-tainted-water-ui.png',
    '\u77f3\u6cb9': 'Block-tar-ui.png',
    '\u77f3\u5934': 'Block-stone-ui.png',
    '\u6c99\u5b50': 'Block-sand-floor-ui.png',
    '\u9ed1\u6c99': 'Block-darksand-ui.png',
    '\u51b0': 'Block-ice-ui.png',
    '\u96ea': 'Block-snow-ui.png',
    '\u9676\u77f3\u5751': 'Block-crater.png',
    '\u6d45\u6ee9': 'Block-shallow-water-ui.png',
    '\u9ed1\u6c99\u6d45\u6ee9': 'Block-darksand-water-ui.png',
    '\u7126\u571f': 'Block-scorch-ui.png',
    '\u5b89\u5c71\u5ca9': 'Block-dacite-ui.png',
    '\u6d41\u7eb9\u5ca9': 'Block-rhyolite-ui.png',
    '\u5b89\u5c71\u5ca9\u5899': 'Block-dacite-wall-ui.png',
    '\u5b89\u5c71\u77f3\u5757': 'Block-dacite-boulder-ui.png',
    '\u51b0\u96ea\u5730': 'Block-ice-snow-ui.png',
    '\u77f3\u5899': 'Block-stone-wall-ui.png',
    '\u51b0\u5899': 'Block-ice-wall-ui.png',
    '\u96ea\u5899': 'Block-snow-wall-ui.png',
    '\u6c99\u4e18\u5ca9': 'Block-dune-wall-ui.png',
    '\u677e\u6811': 'Block-pine-ui.png',
    '\u6ce5\u571f': 'Block-dirt-ui.png',
    '\u6ce5\u571f\u5899': 'Block-dirt-wall-ui.png',
    '\u6ce5\u5df4': 'Block-mud-ui.png',
    '\u67af\u840e\u7684\u767d\u6811': 'Block-white-tree-dead-ui.png',
    '\u767d\u6811': 'Block-white-tree-ui.png',
    '\u5b62\u5b50\u7c07': 'Block-spore-cluster-ui.png',
    '\u91d1\u5c5e\u5730\u677f1': 'Block-metal-floor-ui.png',
    '\u91d1\u5c5e\u5730\u677f2': 'Block-metal-floor-2-ui.png',
    '\u91d1\u5c5e\u5730\u677f3': 'Block-metal-floor-3-ui.png',
    '\u91d1\u5c5e\u5730\u677f4': 'Block-metal-floor-4-ui.png',
    '\u91d1\u5c5e\u5730\u677f5': 'Block-metal-floor-5-ui.png',
    '\u635f\u574f\u7684\u91d1\u5c5e\u5730\u677f': 'Block-metal-floor-damaged-ui.png',
    '\u91d1\u5c5e\u5730\u57fa1': 'Block-metal-tiles-1-ui.png',
    '\u91d1\u5c5e\u5730\u57fa2': 'Block-metal-tiles-2-ui.png',
    '\u91d1\u5c5e\u5730\u57fa3': 'Block-metal-tiles-3-ui.png',
    '\u91d1\u5c5e\u5730\u57fa4': 'Block-metal-tiles-4-ui.png',
    '\u91d1\u5c5e\u5730\u57fa5': 'Block-metal-tiles-5-ui.png',
    '\u91d1\u5c5e\u5730\u57fa6': 'Block-metal-tiles-6-ui.png',
    '\u91d1\u5c5e\u5730\u57fa7': 'Block-metal-tiles-7-ui.png',
    '\u91d1\u5c5e\u5730\u57fa8': 'Block-metal-tiles-8-ui.png',
    '\u91d1\u5c5e\u5730\u57fa9': 'Block-metal-tiles-9-ui.png',
    '\u91d1\u5c5e\u5730\u57fa10': 'Block-metal-tiles-10-ui.png',
    '\u91d1\u5c5e\u5730\u57fa11': 'Block-metal-tiles-11-ui.png',
    '\u91d1\u5c5e\u5730\u57fa12': 'Block-metal-tiles-12-ui.png',
    '\u91d1\u5c5e\u5730\u57fa13': 'Block-metal-tiles-13-ui.png',
    '\u91d1\u5c5e\u58991': 'Block-metal-wall-1-ui.png',
    '\u91d1\u5c5e\u58992': 'Block-metal-wall-2-ui.png',
    '\u91d1\u5c5e\u58993': 'Block-metal-wall-3-ui.png',
    '\u67d3\u8272\u5730\u677f': 'Block-colored-floor-ui.png',
    '\u67d3\u8272\u5899\u58c8': 'Block-colored-wall-ui.png',
    '\u6807\u8bc6\u8d34\u7247': 'Block-character-overlay-ui.png',
    '\u6807\u8bc6\u8d34\u7247(\u767d\u8272)': 'Block-character-overlay-white-ui.png',
    '\u7b26\u6587\u8d34\u7247': 'Block-rune-overlay-ui.png',
    '\u7b26\u6587\u8d34\u7247\uff08\u7ea2\u961f\uff09': 'Block-rune-overlay-crux-ui.png',
    '\u6697\u9762\u677f1': 'Block-dark-panel-1-ui.png',
    '\u6697\u9762\u677f2': 'Block-dark-panel-2-ui.png',
    '\u6697\u9762\u677f3': 'Block-dark-panel-3-ui.png',
    '\u6697\u9762\u677f4': 'Block-dark-panel-4-ui.png',
    '\u6697\u9762\u677f5': 'Block-dark-panel-5-ui.png',
    '\u6697\u9762\u677f6': 'Block-dark-panel-6-ui.png',
    '\u6697\u91d1\u5c5e': 'Block-dark-metal-ui.png',
    '\u7384\u6b66\u5ca9': 'Block-basalt-ui.png',
    '\u707c\u70ed\u5ca9\u77f3': 'Block-hotrock-ui.png',
    '\u7194\u878d\u5ca9\u77f3': 'Block-magmarock-ui.png',
    '\u94dc\u5899': 'Block-copper-wall-ui.png',
    '\u5927\u578b\u94dc\u5899': 'Block-copper-wall-large-ui.png',
    '\u949b\u5899': 'Block-titanium-wall-ui.png',
    '\u5927\u578b\u949b\u5899': 'Block-titanium-wall-large-ui.png',
    '\u5851\u94a2\u5899': 'Block-plastanium-wall-ui.png',
    '\u5927\u578b\u5851\u94a2\u5899': 'Block-plastanium-wall-large-ui.png',
    '\u76f8\u7ec7\u5e03\u5899': 'Block-phase-wall-ui.png',
    '\u5927\u578b\u76f8\u7ec7\u5e03\u5899': 'Block-phase-wall-large-ui.png',
    '\u94b1\u5899': 'Block-thorium-wall-ui.png',
    '\u5927\u578b\u94b1\u5899': 'Block-thorium-wall-large-ui.png',
    '\u95e8': 'Block-door-ui.png',
    '\u5927\u95e8': 'Block-door-large-ui.png',

    '\u585e\u666e\u7f57': 'Planet-serpulo.png',
    '\u57c3\u91cc\u514b\u5c14': 'Planet-erekir.png',
    '\u592a\u9633': 'Sun.png',

    '\u964d\u96e8': 'ohno.png',
    '\u964d\u96ea': 'ohno.png',
    '\u6c99\u5c18\u66b4': 'ohno.png',
    '\u5b62\u5b50\u98ce\u66b4': 'ohno.png',
    '\u96fe': 'ohno.png',

    '\u71c3\u70e7': 'Status-burning-ui.png',
    '\u51bb\u7ed3': 'Status-freezing-ui.png',
    '\u6f6e\u6e7f': 'Status-wet-ui.png',
    '\u6ce5\u6c61': 'Status-muddy-ui.png',
    '\u7194\u5316': 'Status-melting-ui.png',
    '\u5f31\u5316': 'Status-slow-ui.png',
    '\u9ebb\u75f9': 'Status-electrified-ui.png',
    '\u5b62\u5b50\u51cf\u901f': 'Status-spore-slowed-ui.png',
    '\u6cb9\u6d78': 'Status-tarred-ui.png',
    '\u8fc7\u8f7d': 'Status-overdrive-ui.png',
    '\u8d85\u9891': 'Status-overclock-ui.png',
    '\u7535\u51fb': 'Status-shocked-ui.png',
    '\u7206\u70b8': 'Status-blasted-ui.png',
    '\u8150\u8680': 'Status-corroded-ui.png',
    '\u9759\u6b62': 'Status-unmoving-ui.png',
    'Boss': 'Status-boss-ui.png'

};

    function getEditorTextarea() {
      return document.getElementById('wpTextbox1') ||
        document.querySelector('textarea#wpTextbox1');
    }

    function buildIconWikitext(filename, title) {
      var file = String(filename);
      var t = String(title);
      return '<span class="mdtPixelIcon">[[File:' + file + '|' + String(MDT_ICON_SIZE) + 'px|link=' + t + ']]</span>';
    }

    function buildTitlePattern(titles) {
      // Prefer longer first to avoid partial matches.
      var list = titles.slice().sort(function (a, b) { return b.length - a.length; });
      var escaped = [];
      for (var i = 0; i < list.length; i++) {
        escaped.push(list[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
      }
      return escaped.join('|');
    }

    function convertWikitext(text) {
      var titles = Object.keys(MDT_ICON_MAP || {});
      if (!titles.length) return { text: text, changed: 0 };

      var pattern = buildTitlePattern(titles);

      // Only convert links like [[Title]] or [[Title|Label]].
      // Skip links already preceded by mdtPixelIcon span.
      var re = new RegExp('\\[\\[(' + pattern + ')(?:\\|[^\\]]*)?\\]\\]', 'g');
      
      var changed = 0;
      var out = text.replace(re, function (m, title, offset) {
        var before = text.slice(Math.max(0, offset - 120), offset);
        if (before.indexOf('class="mdtPixelIcon"') !== -1) return m;
        if (/\[\[File:|\[\[Image:/i.test(m)) return m;

        var filename = MDT_ICON_MAP[title];
        if (!filename) return m;

        changed++;
        return buildIconWikitext(filename, title) + ' ' + m;
      });

      return { text: out, changed: changed };
    }

    function initEditorTool() {
      var ta = getEditorTextarea();
      if (!ta) return;
      if (ta.getAttribute('data-mdtIconTool') === '1') return;
      ta.setAttribute('data-mdtIconTool', '1');

      var host = document.createElement('div');
      host.style.margin = '0 0 8px 0';
      host.style.display = 'flex';
      host.style.gap = '8px';
      host.style.flexWrap = 'wrap';
      host.style.alignItems = 'center';

      var btn = document.createElement('button');
      btn.type = 'button';
      btn.className = 'mw-ui-button mw-ui-progressive';
      btn.textContent = '\u4e00\u952e\u914d\u56fe\u6807';

      var undo = document.createElement('button');
      undo.type = 'button';
      undo.className = 'mw-ui-button';
      undo.textContent = '\u64a4\u9500\u914d\u56fe\u6807';
      undo.disabled = true;

      var note = document.createElement('span');
      note.style.opacity = '0.75';
      note.style.fontSize = '12px';
      note.textContent = '\u53ea\u5904\u7406\u005b\u005b\u002e\u002e\u002e\u005d\u005d\u94fe\u63a5';

      host.appendChild(btn);
      host.appendChild(undo);
      host.appendChild(note);

      if (ta.parentNode) ta.parentNode.insertBefore(host, ta);

      var backup = '';
      btn.addEventListener('click', function () {
        var current = String(ta.value || '');
        var result = convertWikitext(current);
        if (!result.changed) {
          alert('\u6ca1\u6709\u53ef\u66ff\u6362\u7684\u94fe\u63a5');
          return;
        }
        backup = current;
        undo.disabled = false;
        ta.value = result.text;
        alert('\u5df2\u63d2\u5165 ' + String(result.changed) + ' \u4e2a\u56fe\u6807');
      });

      undo.addEventListener('click', function () {
        if (!backup) {
          alert('\u6ca1\u6709\u5907\u4efd');
          return;
        }
        ta.value = backup;
        backup = '';
        undo.disabled = true;
        alert('\u5df2\u64a4\u9500');
      });
    }

    if (document.readyState === 'loading') {
      document.addEventListener('DOMContentLoaded', initEditorTool);
    } else {
      initEditorTool();
    }
  });
})();

/* Timeless:原生搜索联想,并兼容中文输入法 */
  (function () {
    'use strict';

    if (mw.config.get('skin') !== 'timeless') {
      return;
    }

    mw.loader.using('mediawiki.searchSuggest').then(function () {
      var $input = jQuery('#searchInput');

      if (!$input.length) {
        return;
      }

      /*
       * MediaWiki 1.41 的旧搜索联想主要监听 keypress。
       * 中文输入法有时只触发 input,导致输入中文后不出现联想。
       */
      $input
        .off('input.mdtSearchSuggest')
        .on('input.mdtSearchSuggest', function () {
          jQuery(this).trigger('keypress');
        });

      /* 脚本加载前已经输入文字时,立即发起一次联想 */
      if ($input.val()) {
        $input.trigger('keypress');
      }
    });
  }());

/* BEGIN MDT REDESIGN JS */
window.MDT_REDESIGN={"rail": "<div class=\"nav-group\"><h2><span id=\".E6.B8.B8.E6.88.8F.E8.B5.84.E6.96.99\"></span><span class=\"mw-headline\" id=\"游戏资料\">游戏资料</span></h2><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/4/46/MDT-home-block-mechanical-drill-full.png/24px-MDT-home-block-mechanical-drill-full.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E5%BB%BA%E7%AD%91\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">建筑</a></span></div></div><ul class=\"nav-sub\"><li><a href=\"https://mdtwiki.top/index.php?title=%E5%A1%9E%E6%99%AE%E7%BD%97#工厂\" title=\"塞普罗\" rel=\"noopener noreferrer\">塞普罗生产建筑</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%A1%9E%E6%99%AE%E7%BD%97#物品运输设施\" title=\"塞普罗\" rel=\"noopener noreferrer\">塞普罗运输建筑</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%A1%9E%E6%99%AE%E7%BD%97#电力设施\" title=\"塞普罗\" rel=\"noopener noreferrer\">塞普罗电力建筑</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%A1%9E%E6%99%AE%E7%BD%97#炮台\" title=\"塞普罗\" rel=\"noopener noreferrer\">塞普罗防御与炮塔</a></li></ul></div><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/b/ba/MDT-home-unit-dagger-full.png/24px-MDT-home-unit-dagger-full.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E5%8D%95%E4%BD%8D\" title=\"单位\" rel=\"noopener noreferrer\">单位</a></span></div></div><ul class=\"nav-sub\"><li><a href=\"https://mdtwiki.top/index.php?title=%E5%8D%95%E4%BD%8D\" title=\"特殊:搜索/陆军\" rel=\"noopener noreferrer\">陆军单位检索</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%8D%95%E4%BD%8D\" title=\"特殊:搜索/空军\" rel=\"noopener noreferrer\">空军单位检索</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%8D%95%E4%BD%8D\" title=\"特殊:搜索/海军\" rel=\"noopener noreferrer\">海军单位检索</a></li></ul></div><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/c/cd/MDT-home-item-copper.png/24px-MDT-home-item-copper.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E7%89%A9%E5%93%81\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">物品</a></span></div></div><ul class=\"nav-sub\"><li><a href=\"https://mdtwiki.top/index.php?title=%E7%89%A9%E5%93%81\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">物品总览</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E9%93%9C\" title=\"铜\" rel=\"noopener noreferrer\">铜</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E9%93%85\" title=\"铅\" rel=\"noopener noreferrer\">铅</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E7%A1%85\" title=\"硅\" rel=\"noopener noreferrer\">硅</a></li></ul></div><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/0/0a/MDT-home-liquid-water.png/24px-MDT-home-liquid-water.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E6%B6%B2%E4%BD%93\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">液体</a></span></div></div><ul class=\"nav-sub\"><li><a href=\"https://mdtwiki.top/index.php?title=%E6%B6%B2%E4%BD%93\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">液体总览</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E6%B0%B4\" title=\"水\" rel=\"noopener noreferrer\">水</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E7%9F%B3%E6%B2%B9\" title=\"石油\" rel=\"noopener noreferrer\">石油</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E7%9F%BF%E6%B8%A3\" title=\"矿渣\" rel=\"noopener noreferrer\">矿渣</a></li></ul></div></div><div class=\"nav-group\"><h2><span id=\".E6.98.9F.E7.90.83.E4.B8.8E.E6.95.99.E7.A8.8B\"></span><span class=\"mw-headline\" id=\"星球与教程\">星球与教程</span></h2><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/5/53/Sx.png/24px-Sx.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E5%A1%9E%E6%99%AE%E7%BD%97\" title=\"塞普罗\" rel=\"noopener noreferrer\">塞普罗战役</a></span></div></div><ul class=\"nav-sub\"><li><a href=\"https://mdtwiki.top/index.php?title=%E5%A1%9E%E6%99%AE%E7%BD%97\" title=\"塞普罗\" rel=\"noopener noreferrer\">星球概况</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%8C%BA%E5%9D%97\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">区块资料</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E7%A7%91%E6%8A%80%E6%A0%91\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">科技解锁</a></li></ul></div><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/9/9e/Ex.png/24px-Ex.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E5%9F%83%E9%87%8C%E5%85%8B%E5%B0%94\" title=\"埃里克尔\" rel=\"noopener noreferrer\">埃里克尔战役</a></span></div></div><ul class=\"nav-sub\"><li><a href=\"https://mdtwiki.top/index.php?title=%E5%9F%83%E9%87%8C%E5%85%8B%E5%B0%94\" title=\"埃里克尔\" rel=\"noopener noreferrer\">星球概况</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%8C%BA%E5%9D%97\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">区块资料</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E7%A7%91%E6%8A%80%E6%A0%91\" title=\"用户:Mdtwikibot/资料索引\" rel=\"noopener noreferrer\">科技解锁</a></li></ul></div><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/6/67/MDT-home-block-core-shard-full.png/24px-MDT-home-block-core-shard-full.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E6%95%99%E7%A8%8B%E4%B8%AD%E5%BF%83\" title=\"教程中心\" rel=\"noopener noreferrer\">教程中心</a></span></div></div><ul class=\"nav-sub\"><li><a href=\"https://mdtwiki.top/index.php?title=%E6%95%99%E7%A8%8B%E4%B8%AD%E5%BF%83\" title=\"教程中心\" rel=\"noopener noreferrer\">教程总览</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E9%80%BB%E8%BE%91\" title=\"逻辑\" rel=\"noopener noreferrer\">逻辑编程</a></li><li><a href=\"https://mdtwiki.top/index.php?title=%E5%9C%B0%E5%9B%BE%E7%BC%96%E8%BE%91%E5%99%A8\" title=\"地图编辑器\" rel=\"noopener noreferrer\">地图编辑器</a></li><li><a href=\"https://mdtwiki.top/index.php?title=Learn_Mindustry_Mod\" title=\"Learn Mindustry Mod\" rel=\"noopener noreferrer\">模组开发</a></li></ul></div></div><div class=\"nav-group\"><h2><span id=\"Wiki_.E5.B7.A5.E5.85.B7\"></span><span class=\"mw-headline\" id=\"Wiki_工具\">Wiki 工具</span></h2><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/8/87/MDT-home-sector-groundZero.png/24px-MDT-home-sector-groundZero.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E7%89%B9%E6%AE%8A:%E6%9C%80%E8%BF%91%E6%9B%B4%E6%94%B9\" title=\"特殊:最近更改\" rel=\"noopener noreferrer\">最近更改</a></span></div></div></div><div class=\"nav-item\"><div class=\"nav-row\"><div class=\"nav-link\"><span><span><img alt=\"\" src=\"https://mdtwiki.top/images/thumb/c/cd/MDT-home-item-copper.png/24px-MDT-home-item-copper.png\" width=\"24\" height=\"24\" class=\"mw-file-element\"></span></span><span><a href=\"https://mdtwiki.top/index.php?title=%E7%89%B9%E6%AE%8A:%E9%A1%B5%E9%9D%A2%E5%88%86%E7%B1%BB\" title=\"特殊:页面分类\" rel=\"noopener noreferrer\">分类索引</a></span></div></div></div></div><div class=\"nav-foot\">首页标注版本 <b>v160.7</b></div>", "pages": {"塞普罗": {"kind": "星球资料", "category": "区块", "image": "https://mdtwiki.top/images/5/53/Sx.png", "description": "战役区块、资源、建筑与单位资料。"}, "埃里克尔": {"kind": "星球资料", "category": "区块", "image": "https://mdtwiki.top/images/9/9e/Ex.png", "description": "战役区块、资源、建筑与单位资料。"}, "铜": {"kind": "物品资料", "category": "物品", "image": "https://mdtwiki.top/images/c/cd/MDT-home-item-copper.png", "description": "资源属性、生产来源与使用方式。"}, "水": {"kind": "液体资料", "category": "液体", "image": "https://mdtwiki.top/images/0/0a/MDT-home-liquid-water.png", "description": "流体属性、生产来源与使用方式。"}, "机械钻头": {"kind": "建筑资料", "category": "建筑", "image": "https://mdtwiki.top/images/4/46/MDT-home-block-mechanical-drill-full.png", "description": "建筑属性、输入输出与机制说明。"}, "尖刀": {"kind": "单位资料", "category": "单位", "image": "https://mdtwiki.top/images/b/ba/MDT-home-unit-dagger-full.png", "description": "单位属性、武器与生产资料。"}, "零号地区": {"kind": "战役区块", "category": "区块", "image": "https://mdtwiki.top/images/8/87/MDT-home-sector-groundZero.png", "description": "区块资源、环境与战役攻略。"}, "建筑": {"kind": "资料索引", "image": "https://mdtwiki.top/images/4/46/MDT-home-block-mechanical-drill-full.png", "description": "按星球与用途浏览生产、物流、电力、防御和逻辑建筑。"}, "物品": {"kind": "资料索引", "image": "https://mdtwiki.top/images/c/cd/MDT-home-item-copper.png", "description": "按星球浏览物品条目,查阅资源属性、生产方式与用途。"}, "液体": {"kind": "资料索引", "image": "https://mdtwiki.top/images/0/0a/MDT-home-liquid-water.png", "description": "按星球浏览液体资料,查阅生产、冷却和弹药用途。"}, "单位": {"kind": "资料索引", "image": "https://mdtwiki.top/images/b/ba/MDT-home-unit-dagger-full.png", "description": "按星球浏览单位资料,查阅属性、武器与生产方式。"}, "区块": {"kind": "资料索引", "image": "https://mdtwiki.top/images/8/87/MDT-home-sector-groundZero.png", "description": "按星球浏览战役区块,查阅地图资源与攻略。"}, "科技树": {"kind": "资料索引", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png", "description": "研究项目与前置解锁资料索引。"}, "教程中心": {"kind": "专题资料", "description": "相关机制、说明与资料索引。", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png"}, "逻辑": {"kind": "专题资料", "description": "相关机制、说明与资料索引。", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png"}, "地图编辑器": {"kind": "专题资料", "description": "相关机制、说明与资料索引。", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png"}, "模组": {"kind": "专题资料", "description": "相关机制、说明与资料索引。", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png"}, "服务器": {"kind": "专题资料", "description": "相关机制、说明与资料索引。", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png"}, "状态效果": {"kind": "专题资料", "description": "相关机制、说明与资料索引。", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png"}, "天气": {"kind": "专题资料", "description": "相关机制、说明与资料索引。", "image": "https://mdtwiki.top/images/6/67/MDT-home-block-core-shard-full.png"}}};
/* Shared encyclopedia layout and real inline search. No gameplay data rewriting. */
(function () {
  'use strict';
  var config = window.MDT_REDESIGN || {};
  var rootUrl = 'https://mdtwiki.top/index.php';
  function link(title) { return rootUrl + '?title=' + encodeURIComponent(title); }
  function node(tag, cls, text) {
    var el = document.createElement(tag);
    if (cls) el.className = cls;
    if (text) el.textContent = text;
    return el;
  }
  function search(host) {
    if (host.querySelector('input')) return;
    host.replaceChildren();
    host.classList.add('mdt-search-box');
    var form = node('form', 'mdt-search-form');
    form.setAttribute('role', 'search');
    var input = node('input'); input.type = 'search'; input.name = 'search';
    input.placeholder = '搜索建筑、单位、资源或教程'; input.setAttribute('aria-label', '搜索 Wiki 条目');
    input.maxLength = 200;
    var submit = node('button', '', '搜索'); submit.type = 'submit';
    var output = node('div', 'mdt-search-results'); output.hidden = true;
    var notice = node('p', 'mdt-search-status'); notice.setAttribute('role', 'status');
    var list = node('ul'); output.append(notice, list); form.append(input, submit); host.append(form, output);
    var sequence = 0, controller;
    input.addEventListener('input', function () {
      sequence++; if(controller)controller.abort(); output.hidden = true;
    });
    form.addEventListener('submit', function (event) {
      event.preventDefault();
      var term = input.value.trim(); if (!term) { output.hidden=false;notice.textContent='请输入要查询的条目名称。';list.replaceChildren();input.focus();return; }
      var ticket = ++sequence; if (controller) controller.abort(); controller = new AbortController();
      output.hidden = false; notice.textContent = '正在查询…'; list.replaceChildren();
      var params = new URLSearchParams({action:'query',format:'json',formatversion:'2',list:'search',srsearch:term,srlimit:'8',srprop:'snippet',origin:'*'});
      fetch('https://mdtwiki.top/api.php?' + params, {signal:controller.signal,credentials:'omit'}).then(function(response){
        if(!response.ok)throw Error('HTTP');return response.json();
      }).then(function(result){
        if(result.error)throw Error('API');
        if(ticket !== sequence)return;
        var hits = result.query.search;
        notice.textContent = hits.length ? '查询结果' : '没有找到相关条目,可尝试更短的名称或其他关键词。';
        hits.forEach(function(hit) {
          var item=node('li'), a=node('a','',hit.title); a.href=link(hit.title);
          var description=node('small');
          description.textContent=new DOMParser().parseFromString(hit.snippet || '', 'text/html').body.textContent;
          item.append(a,description);list.append(item);
        });
        if(hits.length){var more=node('li'), a=node('a','','查看全部搜索结果 ›');a.href=rootUrl+'?title=Special:Search&search='+encodeURIComponent(term);more.append(a);list.append(more);}
      }).catch(function(error) {
        if(ticket !== sequence)return;
        notice.textContent='查询暂时失败,请重试。';
        var fallback=node('a','','打开站内搜索');fallback.href=rootUrl+'?title=Special:Search&search='+encodeURIComponent(term);list.append(fallback);
      });
    });
  }
  // Animate measured sizes, then release them so wrapping and nested menus stay fluid.
  function fold(panel, open, animate) {
    var properties=['height','paddingTop','paddingBottom','marginTop','marginBottom','opacity'];
    function frame() {
      var style=getComputedStyle(panel), result={overflow:'hidden'};
      properties.forEach(function(key){result[key]=style[key];});
      return result;
    }
    function zero() { return {height:'0px',paddingTop:'0px',paddingBottom:'0px',marginTop:'0px',marginBottom:'0px',opacity:'0',overflow:'hidden'}; }
    var start=panel.hidden?zero():frame();
    if(panel._foldAnimation){panel._foldAnimation.cancel();panel._foldAnimation=null;}
    panel.inert=!open;
    if(!animate || !panel.animate || window.matchMedia('(prefers-reduced-motion: reduce)').matches){panel.hidden=!open;return;}
    panel.hidden=false;
    var animation=panel.animate([start,open?frame():zero()],{duration:240,easing:'cubic-bezier(.25,.1,.25,1)',fill:'both'});
    panel._foldAnimation=animation;
    animation.onfinish=function(){
      if(panel._foldAnimation!==animation)return;
      panel.hidden=!open;animation.cancel();panel._foldAnimation=null;
    };
  }
  function navigation(scope) {
    scope.querySelectorAll('.nav-item').forEach(function(item, index) {
      var row=item.querySelector('.nav-row'), list=item.querySelector('.nav-sub');
      if(!row||!list||row.querySelector('.nav-toggle'))return;
      var b=node('button','nav-toggle');b.type='button';b.innerHTML='<span aria-hidden="true">›</span>';
      list.id='mdt-new-nav-'+index; b.setAttribute('aria-controls',list.id);
      function set(open,animate){fold(list,open,animate);b.setAttribute('aria-expanded',String(open));b.setAttribute('aria-label',(open?'收起':'展开')+row.textContent.trim()+'次级导航');item.classList.toggle('open',open);}
      set(false);b.onclick=function(){set(b.getAttribute('aria-expanded')!=='true',true);};row.append(b);
    });
  }
  function integrateNavigation(home) {
    var rail=home.querySelector('.wiki-rail'), source=document.querySelector('#p-navigation .mw-portlet-body');
    if(!rail || !source || rail.getAttribute('data-integrated'))return;
    rail.setAttribute('data-integrated','true');rail.replaceChildren();
    var top=node('div','rail-top'), back=node('a','rail-home','返回首页');back.href=link('首页');
    back.insertAdjacentHTML('afterbegin','<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 11 12 3l9 8h-3v10h-5v-6h-2v6H6V11Z" fill="currentColor"/></svg>');
    var toggle=node('button','rail-mobile-toggle','站点导航');toggle.type='button';toggle.setAttribute('aria-expanded','false');toggle.setAttribute('aria-controls','mdt-integrated-links');
    var contents=node('div','rail-contents');contents.id='mdt-integrated-links';top.append(back,toggle);rail.append(top,contents);
    toggle.onclick=function(){var open=toggle.getAttribute('aria-expanded')!=='true';toggle.setAttribute('aria-expanded',String(open));rail.classList.toggle('rail-open',open);};
    function copyAnchor(a,label){var copy=node('a','',label||a.textContent.trim());copy.href=a.href;if(a.getAttribute('href')==='javascript:print();'){copy.href='#';copy.onclick=function(e){e.preventDefault();window.print();};}return copy;}
    function item(a,label){var el=node('div','nav-item'),row=node('div','nav-row'),wrap=node('div','nav-link');wrap.append(copyAnchor(a,label));row.append(wrap);el.append(row);return el;}
    var group=node('div','nav-group');group.append(node('h2','','游戏与社区'));contents.append(group);
    var last=null;
    source.querySelectorAll('li > a').forEach(function(a){
      var label=a.textContent.trim(),marked=/^-{2,}\s*/.test(label),nested=!!a.closest('.mdtNavSublist');
      label=label.replace(/^-{2,}\s*/,'');
      if((marked||nested)&&last){var sub=last.querySelector('.nav-sub');if(!sub){sub=node('ul','nav-sub');last.append(sub);}var li=node('li');li.append(copyAnchor(a,label));sub.append(li);}
      else{last=item(a,label);group.append(last);}
    });
    ['#site-tools','#mw-related-navigation'].forEach(function(selector,index){
      var original=document.querySelector(selector);if(!original)return;
      var section=node('div','nav-group');section.append(node('h2','',index?'页面工具':'Wiki 工具'));
      var seen={};original.querySelectorAll('.mw-portlet-body a').forEach(function(a){if(seen[a.href])return;seen[a.href]=true;section.append(item(a));});
      if(section.children.length>1)contents.append(section);
    });
    contents.querySelectorAll('.nav-group').forEach(function(section,index){
      var heading=section.querySelector('h2'),label=heading.textContent;
      var body=node('div','rail-group-body'),button=node('button','rail-group-toggle');
      body.id='mdt-rail-group-'+index;button.type='button';
      button.setAttribute('aria-controls',body.id);
      button.append(node('span','',label));
      var arrow=node('span','rail-group-arrow','›');arrow.setAttribute('aria-hidden','true');button.append(arrow);
      while(heading.nextSibling)body.append(heading.nextSibling);
      heading.replaceChildren(button);section.append(body);
      var key='mdt-rail-group-collapsed:'+label,closed=false;
      try{closed=localStorage.getItem(key)==='true';}catch(e){}
      function set(open,animate){fold(body,open,animate);button.setAttribute('aria-expanded',String(open));button.setAttribute('aria-label',(open?'收起':'展开')+label);}
      set(!closed);
      button.onclick=function(){var open=button.getAttribute('aria-expanded')!=='true';set(open,true);try{localStorage.setItem(key,String(!open));}catch(e){}};
    });
    rail.append(node('div','nav-foot','Mindustry 中文 Wiki'));
    document.body.classList.add('mdt-navigation-integrated');
  }
  function floatingContents(home) {
    var original=home.querySelector('.article-toc'),main=home.querySelector('.wiki-main');
    if(!original||original.getAttribute('data-floating-ready'))return;
    original.setAttribute('data-floating-ready','true');
    var floating=node('nav','mdt-floating-contents');floating.setAttribute('aria-label','悬浮本页目录');floating.hidden=true;
    var toggle=node('button','floating-contents-toggle','本页目录');toggle.type='button';toggle.setAttribute('aria-expanded','false');toggle.setAttribute('aria-controls','mdt-floating-links');
    var links=node('div','floating-contents-links');links.id='mdt-floating-links';
    original.querySelectorAll('a').forEach(function(a){var copy=a.cloneNode(true);copy.removeAttribute('id');links.append(copy);});
    floating.append(toggle,links);document.body.append(floating);
    toggle.onclick=function(){var open=toggle.getAttribute('aria-expanded')!=='true';toggle.setAttribute('aria-expanded',String(open));floating.classList.toggle('contents-open',open);};
    links.addEventListener('click',function(event){
      var a=event.target.closest('a');if(!a||event.ctrlKey||event.metaKey||event.shiftKey||event.altKey)return;
      var id;try{id=decodeURIComponent(a.hash.slice(1));}catch(e){return;}
      var target=document.getElementById(id);if(!target)return;
      event.preventDefault();floating.classList.remove('contents-open');toggle.setAttribute('aria-expanded','false');
      var heading=target.closest('h2,h3,h4')||target;
      window.scrollTo({top:Math.max(0,window.scrollY+heading.getBoundingClientRect().top-floating.getBoundingClientRect().height-32),behavior:'auto'});
      if(window.history&&history.replaceState)history.replaceState(null,'',a.hash);
    });
    var queued=false;
    function update(){queued=false;var rect=main.getBoundingClientRect();var show=original.getBoundingClientRect().bottom<=12&&rect.bottom>80;
      floating.hidden=!show;floating.style.left=Math.max(8,rect.left)+'px';floating.style.width=Math.max(0,Math.min(rect.width,window.innerWidth-Math.max(8,rect.left)-8))+'px';
      if(!show){floating.classList.remove('contents-open');toggle.setAttribute('aria-expanded','false');}
    }
    function schedule(){if(!queued){queued=true;requestAnimationFrame(update);}}
    window.addEventListener('scroll',schedule,{passive:true});window.addEventListener('resize',schedule);
    if(window.ResizeObserver){var observer=new ResizeObserver(schedule);observer.observe(main);}
    update();
  }
  function enhance() {
    var content=document.querySelector('#mw-content-text .mw-parser-output');
    var home=document.querySelector('.mdt-home');
    var mainPage=window.mw && mw.config && mw.config.get('wgNamespaceNumber')===0 && mw.config.get('wgAction')==='view';
    if(!home && content && mainPage && !document.querySelector('.diff') && !new URLSearchParams(location.search).has('oldid')) {
      var title=mw.config.get('wgTitle');
      var meta=(config.pages||{})[title] || {};
      home=node('div','mdt-home mdt-article');
      var layout=node('div','layout');
      var rail=node('div','wiki-rail');rail.setAttribute('role','navigation');rail.setAttribute('aria-label','资料导航');rail.innerHTML=config.rail||'';
      var main=node('div','wiki-main');
      var crumb=node('div','mdt-breadcrumb'), start=node('a','','首页');start.href=link('首页');crumb.append(start,document.createTextNode(' / '));
      if(meta.category){var parent=node('a','',meta.category);parent.href=link(meta.category);crumb.append(parent,document.createTextNode(' / '));}
      crumb.append(document.createTextNode(title));main.append(crumb);
      var mast=node('div','panel article-masthead');
      var copy=node('div','article-title-copy');copy.append(node('span','article-kicker',meta.kind||'游戏资料'),node('h1','',title),node('p','',meta.description||'条目资料、机制说明与相关内容。'));
      if(title==='塞普罗'){mast.classList.add('serpulo-masthead');copy.querySelector('.article-kicker').textContent='SERPULO';}
      if(title==='埃里克尔'){mast.classList.add('erekir-masthead');copy.querySelector('.article-kicker').textContent='EREKIR';}
      mast.append(copy);
      if(meta.image){var art=node('img','article-art');art.src=meta.image;art.alt='';mast.append(art);}
      main.append(mast);
      var headings=[].slice.call(content.querySelectorAll('h2,h3')).filter(function(h){return h.id || h.querySelector('[id]');});
      if(headings.length){var toc=node('nav','article-toc');toc.setAttribute('aria-label','本页章节');toc.append(node('span','','本页目录'));headings.forEach(function(h){var anchor=h.id?h:h.querySelector('[id]');var a=node('a','',h.textContent.replace(/\[.*?\]/g,'').trim());a.href='#'+anchor.id;toc.append(a);});main.append(toc);}
      var body=node('div','article-body');while(content.firstChild)body.append(content.firstChild);
      main.append(body);layout.append(rail,main);home.append(layout);content.append(home);
    }
    if(!home)return;
    document.body.classList.add('mdt-redesigned');
    integrateNavigation(home);
    navigation(home);
    floatingContents(home);
    home.querySelectorAll('.wiki-search').forEach(search);
    home.querySelectorAll('.wiki-rail a').forEach(function(a){
      try{var u=new URL(a.href);if(u.searchParams.get('title') === (window.mw && mw.config.get('wgTitle')) && !u.hash && !u.searchParams.has('action') && !u.searchParams.has('oldid') && !a.closest('.nav-group:last-of-type')){a.setAttribute('aria-current','page');}}catch(e){}
    });
  }
  if(window.mw && mw.hook)mw.hook('wikipage.content').add(enhance);
  if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',enhance);else enhance();
}());

/* END MDT REDESIGN JS */

/* BEGIN MDT CALCULATOR */
(function (root) {
  'use strict';
  var DATA = {"version":"v160.7","tickRate":60,"minArmorDamage":0.1,"factory":{"title":"石墨压缩机","id":"graphite-press","craftTime":90,"inputAmount":2,"outputAmount":1,"power":0},"turret":{"title":"双管","reload":20,"shots":1,"range":160,"ammoPerShot":1,"coolantMultiplier":10,"ammo":{"copper":{"class":"BasicBulletType","damage":9,"splashDamage":0,"splashDamageRadius":-1,"buildingDamageMultiplier":1,"ammoMultiplier":2,"reloadMultiplier":1,"rangeChange":0,"speed":2.5,"lifetime":70,"pierce":false,"pierceBuilding":false,"pierceCap":-1,"homingPower":0,"homingRange":50,"homingDelay":-1,"lightning":0,"lightningDamage":-1,"lightningLength":5,"statusDuration":480,"knockback":0,"healPercent":0,"healAmount":0,"incendChance":1,"incendAmount":0,"fragBullets":9,"intervalBullets":1,"bulletInterval":20,"suppressionRange":-1,"suppressionDuration":480,"pierceArmor":false,"collidesAir":true,"collidesGround":true,"collidesTiles":true,"collides":true,"typeId":113,"status":"none","continuousDps":-1,"title":"铜"},"graphite":{"class":"BasicBulletType","damage":18,"splashDamage":0,"splashDamageRadius":-1,"buildingDamageMultiplier":1,"ammoMultiplier":4,"reloadMultiplier":0.8,"rangeChange":16,"speed":3.5,"lifetime":54.57143,"pierce":false,"pierceBuilding":false,"pierceCap":-1,"homingPower":0,"homingRange":50,"homingDelay":-1,"lightning":0,"lightningDamage":-1,"lightningLength":5,"statusDuration":480,"knockback":0,"healPercent":0,"healAmount":0,"incendChance":1,"incendAmount":0,"fragBullets":9,"intervalBullets":1,"bulletInterval":20,"suppressionRange":-1,"suppressionDuration":480,"pierceArmor":false,"collidesAir":true,"collidesGround":true,"collidesTiles":true,"collides":true,"typeId":114,"status":"none","continuousDps":-1,"title":"石墨"},"silicon":{"class":"BasicBulletType","damage":12,"splashDamage":0,"splashDamageRadius":-1,"buildingDamageMultiplier":1,"ammoMultiplier":5,"reloadMultiplier":1.5,"rangeChange":0,"speed":3,"lifetime":58.333332,"pierce":false,"pierceBuilding":false,"pierceCap":-1,"homingPower":0.2,"homingRange":50,"homingDelay":-1,"lightning":0,"lightningDamage":-1,"lightningLength":5,"statusDuration":480,"knockback":0,"healPercent":0,"healAmount":0,"incendChance":1,"incendAmount":0,"fragBullets":9,"intervalBullets":1,"bulletInterval":20,"suppressionRange":-1,"suppressionDuration":480,"pierceArmor":false,"collidesAir":true,"collidesGround":true,"collidesTiles":true,"collides":true,"typeId":115,"status":"none","continuousDps":-1,"title":"硅"}},"coolantAmount":0.1,"coolants":{"water":{"heatCapacity":0.4,"temperature":0.5,"name":"water","title":"水","flammability":0},"cryofluid":{"heatCapacity":0.9,"temperature":0.25,"name":"cryofluid","title":"冷冻液","flammability":0}}},"images":{"factory":"https://mdtwiki.top/images/4/4c/Block-graphite-press-ui.png","turret":"https://mdtwiki.top/images/6/62/Block-duo-ui.png","copper":"https://mdtwiki.top/images/8/82/Item-copper-ui.png","graphite":"https://mdtwiki.top/images/f/f7/Item-graphite-ui.png","silicon":"https://mdtwiki.top/images/6/62/Item-silicon-ui.png"},"animation":{"sprites":{"stone1":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAeklEQVR42u3VOw6AQAgE0Dnkdvbc/wbaGSvlN2jMFJSEt2EBrLXtbwYE+CzAzM4YB1yLsxHwFGciQgAGYgRwl+v+A1nAUz68idXXhwGdoxhugTahAAJkZ5oKYN0HVItXEegoXkG0AjKIthb8GxBB0BfR+CdkLyXdAgEOh10i6SfREYkAAAAASUVORK5CYII=","graphite-press":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAA99JREFUeJzlW71uFDEQ/nK6N+BHB7ooV1y1TSQqSkSDgugQBRU1DfAIvAIViA4JiQLRISIaREmFRLPVFYkSQUTgGUKBrPi84/GMPd7L3n1Vsusde76dGc/M+rZevX57NplNkYuP79+x9+89eNjreC1GbbvAycFxkZAhYwQAm0zCyP2xqSSM/X/adgEACGMCR8zfP79VE1qP59YmiW2j8EJoCUO2CsnaOwQA5yRIBNzZux+99+jx08617Z3d6HjqHiVDMrdDSgeSAC2ohXALpxTliKFkSZR34EjYevLs+Vl4sWnmrMCSvOHLp6/s/dt3b2XLTr1tat0dC6ipfG2k1kYRpHKBi6y8g3aNYgKGlCdoSBinh5znB7E8QYOUi1lhMpvmb4M+nNL+/+tkCVnb4JBISCE7D8ghQTK+b2LH37/tL104OrwOQJZohDHh5OC44zI54GQ0zTwrBn3e/wAAuHT56tL1qAW4B1LQpM1W0M7F6cK6gJQEHzWjvC9bSkJKh+JagFK4BgmUTAurKyZgMpuSPmlJAiWrbRcm8cakGgToPdeChJjyVmAJ4EpUCtYkWCjPleUAQ4BWeQcrEizfPEfC+MbNvSyhHKg83CmUU7IC5WYfI8EsBoSgFJUkMNQYS58PUY0AIL9q9J+rqTxQSIDUt92Wpdm3peSV5gKdWuDKtf+1QMxntBP6b1DbT5jMpiIL8NcUG390+AOAohZ48/KFaJFa+JbQVw3hlKfAukAfJAB1S2BOeaByEIyhVl6fg5UQcJGwEgKoQLWqljtLQCqPLkG4O9RygVRKH22L11TeoWSL1GB7ZzcaDKO1QOobHiBLhJpmLs7mqB6jBD5pcQLpb45FMUCqmKYa1PYYSy2mahD0lcjtC9T+klSNAOoNSl0m57lcRGuB3IYIQCvvTDW3yNHEEgouqxXXAqkUMgZOeQ0s22tcSs+6gJYEK+W5Z7UkpOoZsxhgrTwnwzImiM4HcIhtV5YJDddjLEWxBfSV1+f2GFNgCZAeRfNJqFnU5MhO6RAlQHMOD6jfvAzn0hRQnC6dc4Khb1kqpmmiamRylhGSFI7ttR8gUUxLeGkpvRYdoRISkgT0daytFBQJElJEeUBpHu4jFclL5vH7CVKLELvAkC2BgyoGDIEE7RrJX4xYTtAnck66kzGgbResMOpeeBor1U8Iq7RUEzasTLWJWiz2RF1AE4yoo2hcKU2VqFzZSsnKOcJHgfzFiI+UWaUWElpCqsegHZ+yBPciYxmj+rT4kCD5+KL6vQCF018/2WfDN2o9XvOCqI8va5EKaxBawsYRACyTUNwSGyqcO/wDtpEXnPSeUi4AAAAASUVORK5CYII=","block-1":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAq0lEQVR42t3XUQqAIAwGYE8cHaFjRM8doOeeuplRYJQwdbLtHz0MfAj9yE1nmJc1bvsBizCMU0QibgAS8QBQiA8gR1xjiWABEkI64AAKEawWpxBdAOp3mgBqWa0KaC0tFQC3vkUBtUU4CDagdfLe77oAnG0SB3Cz/H8A+BaYJyG8DF0cRC6OYheXkYvrWL0hgbdk1o0pCZBElN4dRYBG5AhzQI6AAN4IGCAhTrs4Z350exVBAAAAAElFTkSuQmCC","duo":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAASlJREFUWIXtkzFOwzAYRh/cgYWNgakTEhISC/IF2qVbVlLmMHEEJjJDu2br0l4gYkFCYmVi6FaOERaMHPzbsZ0FJH+bHet7T79jyMnJycn5b3lt6k4pZe0rpagXRRfbdxgLB7i/nlrfpqfHANESwQIa/h0J8rMXI3GQAAfg5fkNgMur897aTPXUDPYPTsAHN6NFzIRMwisQCh8j4RSIhadKWHdUL4pOKvk8OgNgt156gZNZCcDy9kaUuyiqHjPoFWg4wMm8dJ7TcIDy4TGkWhYwR23CfRImXJKQpuoU0BISXJKQ4KaEC+4VAPu+JQkfHOB94+8Y/AeGJMbARYHtx956GSkSEvxutbW6xQmMlQiFOwXGSMTAvQIpErFwUaBt2ySJEPjv7pw/kS+OxI/PVuwySwAAAABJRU5ErkJggg==","duo-barrel-l":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAIVJREFUWIVjYBgFIx0wYhN0dHRE4Xek+DEcO3jmP4xfOGspVn3kACZCCtAtpzbAcACy72ltOVYH0NNynA6gl+VYHUBPy7E6gJ6WY3UAIUDNLEiyA6htOUkOoIXlRDuAVpYT5QBaWk7QAbS2HK8D6GE5VtCfFk3XcmAUjIJRMApGwSgYcAAA9mowExsuptUAAAAASUVORK5CYII=","duo-barrel-r":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAItJREFUWIVjYBgFIx0wUtOwk0v7/yObXTFnE4r8/v37MfQwUdMBaOB/R4ofQUW0dACGIxwdHenuAAxHDIQD8DqCXg7A6Qh6OoCBgYHhP7oAVR1gHl1IcramegiQ6giaRAEpjqBZGiDWETRNhMQ4gua5gJAj6JINyckdNAFoteUoGAWjYBSMglEwOAAAH2geE7fRX70AAAAASUVORK5CYII=","bullet":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAYAAADFeBvrAAAAAXNSR0IArs4c6QAAAKFJREFUaIHt2EsOgCAMRVFx/3vGUZtoQvzwakpzzwJa7gzYNgAAAKyqRS/ovffTwtZCd4YOv8b40sCosMGjGF8cFBUy9C7GlwdEyQc+jfEDiKOkw97G+CGEUbJBX2P8IKIoyZDZGKOImh6gijGzUbvqIFkQlB1B2RGUHUHZEZQdl9ORUs8HU+qBZ0o9wU2pTxJT6hvLlPpoNH9/BQMAAGBdB7GaRChkUSxWAAAAAElFTkSuQmCC","bullet-back":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADQAAAA0CAYAAADFeBvrAAAAAXNSR0IArs4c6QAAAKxJREFUaIHt2VEKhDAMRVE7+99z/UpAQdTpizzCPQtIen+bbQOAzkb1gjnnPCwco3Rn6fBzTC4tjCobfBWTi4uiSobexeTygij5wKcx+QBxlHTY25h8hDBKNujfmHyIKEoyZDUmKKKWB6hiwmrUT/UQFwS5I8gdQe4IckeQO4LcEeSOIHcEuSPIHUHu+Gi80uorOLT6rA+tzimh1cErtDpJhlZH4/D1WR8AetsBTTpEQEgpIycAAAAASUVORK5CYII=","item-coal":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAPlJREFUWIXtltsNhCAQRYd1a7AFacMCSOjVAuzHHgj7xcaFgXn4+ljul8HBczKMUYCef4/JF2KM32trLQzDEPOacRzRh63rWjyvAJrfElTAWgsAIIJzJXKBV61QAwcAmOe52NcUyhemaVLD96l1guzAGXAAfieqR3AELpEgBY6GkiAFtm27VILVAY4EVVOTYB9BC5DuaSREM4AB8jXpkYmHcA84Yz7emk1ngFMufw0fEZB06LIOcCVUM6CVCCEUH6jbZgCD3yZQg98i0IKjAs458r9OC/feFzXoEDrnzLIsol+rFhwDNwWOSiR4C0wKaCVCCIYD7ulJ+QAkp3Lm4kejKwAAAABJRU5ErkJggg==","item-graphite":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAS1JREFUWIXtlr0NwjAQhc8IISjSZIPMQIWE6JnDM1iZATEDc1ATRQoFtLQMgJQmA5gq4DjnnzN2A7wq8vn8Pp8d2wB//bqY3iClfH0LzqHYllKNX+tq0H+53lgN7scd2x8Ob0M2tJxiSYJzAABos5UsrMO7VWxLKThnAAAqSK+JKbHNVtIUC4EwxUYAgnOruVpyV/l1iL6yVgCfmS/XG5K5CuEE0KVvuthyAqSG8AJICeENkAqCBJACggwQGyIIICYEehSrUv933fRaV17ngQ2WVAHMzFUJV5y8BCEQUQGoEK4lCt6EVAjT/REMQIUwKcllRMlJdhlhObfLedQ2OgfyrmHYmyAGRN41ozcoWgGs46dazGfomMYliAmRdw1bPE5ozLoHYkCkqOZf36Unxo90nzzB/+YAAAAASUVORK5CYII=","item-copper":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAcNJREFUWIXtVi1PA0EUnCUkp09QxClEcRhEHU1QKAyCGjD8Akgq9idUQPgHNbgKDCEBdaKuoqauFVWIpqIatYjebm5v337dVZDAqEtuszP73rzZBf46mPwQQhg/58O++u3b4/juMY6Yban3bQsCyZG2OwKlg8Riz/PfSp62O0jbHbVuPR7VEkC2oDg9SV4iJfc7OLsOIy5aYKuAQV45sQ3RlTAqMB/2NfIAUg2bxQQAmM+UsgJKwMf9DQCIo5PDJsQah0sE1QIBAMvZKop8s5hQ5AAgSpNkhW8K6hBHiSAFTF/fmhIHiyh7wHD+6dWlRhyLSiu1EaVMSM69NGUDYlKELwcUlrNVFLHHwEZOWO+CqghXJSJHVqzHI1X5IAE2EQ2yQl1gZQEMnptPithBSCkoD1w8v0gRTsR4ImRkNROGinDlRCgxKaCpiBohZX+SfT7cAh5PANuwiiGV/ml1e8wpIEZESFhVU7HV7QHwBNEujEmEk7afUwDnHHmS1RJhSUVjH7IFnHOS5Pz7y9sOQL/EJJ7epwwABoPBltj3LKeQJxkLEVGdkDzJrBU0WmA7fchmFjjX13oRhYrIk4wVHvrH78UPk3DBcxRUT2EAAAAASUVORK5CYII=","item-silicon":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAARVJREFUWIXtlr0NgzAQhc8oG0SKsgEpUqfzCjBOCmqKrMMEFFQRZYqMEEVkBqcJyGCf7/zTxU9C8o/M+7h7AgCy/l3CtqiUgrqu0UOn80Xp8+Nhv4xf788yvrWNcX8h1ktWgKqqgsw5EFuAAnVimGPSoa5N6zzDBuCa+0KwAHzNfSBIAKrner8p2SC8MpACggUwTcV8oaVPBeGqANn3FBAYQFDoQhSUgQygKzYHSSoQA5GsBaEQJMDQjykhjK8vqwI6RMRbTzwfd2OR3YIYiKEfwWbuBRAKQbUQA7D+KVEQ2zknPzvHngDklewTTAAAKcvlgbquW+1ZKyBlqUNESTe3Cc1ACgjK3AkwQ/xAvCE45llZAABf2X5yGgT4DhgAAAAASUVORK5CYII=","dagger":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAcVJREFUaIHtlaFOA0EQhocGDCEpVCEqegmqhgdA0CAQGHBn0ICB8AiVJwkYOM0DgEEgSBE8AKYKUVGBKpAQDEnBcM3t7uzO7N5S0/nc3uzO/v/N7C6AIAiCIAjC7DKnf8iyTBknSaKM0zR1JrzMr39c8aODfWPPKvvXnGo8ocRz5/gQzYCPsJgm5jmT3j6+yxsaLYAJWm01lfHrYGiswdppudGc5HofDZ3thorRe7CcEACgBl/KmjEskuILdBOcfCv1BSXudQZ08Rxs4qmYDa36BlYDscX7zNFxmUANuMSXS4y1jy/cfDYTxiHm/HlKeOv2Av0+2D0OylfwZ0I5E1HfAQC7eCoWSlQDHIGxTUSvwLQxzkC//6KMt3Y6yhi7y3XWNxro9+enEblWv6Ue7nrO+d4VoK5Bm3gqxsmNYRg4P+uSz7dtI0qgaw5HPKYNrUAVEyGEigdwtNC0TFQRD0CcAY6J/6bQkOc5GmcJvLnvWV9K/VY6XHp05rr63FTGrgrsbXdIfaxbiJOoQBfIjYXu6dUiJ6ddtBLt9ppPmgn6m1Pg07rePR7LRAzxAAEGAKqbiCUeINAAQLiJmOIFQRAEQRBmnV9Bgqjf5e9HUgAAAABJRU5ErkJggg==","crawler":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAbhJREFUaIHtmC1Pw1AUhl8Ifj+BjyCaSQShbplATIFqQPATlsni6rhy2U9AQKZAIRBkrgk/YJkgBIFAYOrmiiBN1pv1nvtJgZzH3fT0PeftuR9tAYZhmDbZCCV8/zgrV8cnx70guYKIysVXhDBBCk6nUyRJQgoNR1kJAP1BTxn39DADAEzGGZlbCIE0TZUxW2Rl+DYBoNFIVbwJw1FWNpkQQmjraBlYRZ4e1RO1YTjKSrljptNs0yS4aW77xDQH2YFq2jQJLz+3a+OPt3elnhy/jujgqNTthFYHfuLJ2+YkDbRRvEluozXwGzHehWTODs9r42InV8cv43o81PEUTh3oLGI6KLCGtQEfxfvQsjLgs3hXTXINyCft6d6lMp46Bzqqa4sYd69XVEk1/vwuxAbahlwD8ttigTzIIgaAIsrRj+r5JmP1PVYdKCK3w8enpvUU8mnCRctpDfgw4arh/C50+3xTGw8udtXx11J8pI6nIDsQ6neIDjq5taZQGya8fpGZCPrAJJdxUdQvlG53X3n/fP6ivK7zv2gV413INEFobattNIQJW03rc8CniZBdZRiGYRiG+c98AV/ijXdA9SrOAAAAAElFTkSuQmCC","mace":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAl5JREFUeJztmSFPA0EQhacNiiBIFQkVNEHV1JIgaBAIFKgadIMCfkJlZVNVTtfjkARDQnA1VQgEAgUhIRgSimrTu+7uvNndO0qYL6nY252dmde92b07IkVRFEVRFEVRFEVRFEVR/hMlqUG32021a7Vaqt1qtdg5BslwYrp+2j5h44nhf56yaHQEbMlzfXlRqABIgkWLIBJgkAwn65Xq7Ce1zWMsEdHb+9dk+pPawjXANnGZPlNztNttyHZjq5pqvzw9L9iZakKSJKn2N6161xMicAW4VLUF4LLNJm+7xv2bLt/oSmAFQCayBYIm7+qz+eeEd9nOE60IZgOKWcyycyHJo7D3SeyqvDO6cvbfN45jumNrAbsCxuPHaMFwyaNjUJDYoVsghgiSxGKIgMYM14AQEXwSChFBEuuKdOL9w+asbdq7s5gSaexWjGNHd68LtkhNmN89bq5v2fHzBO0C3JZm6rclb+uzzYPEgBC8DaKHGiJ38twYiR8JwQJkb4OQ5LmxyPFZSpAAaACS5KU2oSJ4C5Bn8lLbEBG8BHA5jLEsi/QrFgBxlIcIefkVnQOIzEXO5Hh2bU0cEzu3KxbpgS3K06BrO7r82POe12UbYwskAgTo9zrQm5XYIsRIHokdWgFFi1BU8kSCGtDvdUpnF52gdwPnD5vQuHo9xAuePJGwBkgm/i2kMYqL4NFBc2lF8InNaxfwFaFe344yxoRvTOJzwBTbczeXALdEuXeQ0ud9Du9zwDLVg5BYgg5CUsfI1xr0i45vDFmCT4JoAJLE0LHLtAoVRVEURVEURflb/ACg7g89s0R4fAAAAABJRU5ErkJggg==","fortress":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABQCAYAAADvCdDvAAAAAXNSR0IArs4c6QAABHRJREFUeJztnK1SHEEQgPtSwaGiTpw4cWqrqDxARChEBIY8ACoCMKF4BB4hFczlBOrwwUREpEDkAahUoSJOnEBQUXERF0EmNezN9HTPdM+yVf0pituZ6elv5285FsAwDMMwDMMwDMMwDMMwjGocn5yujk9OV13HIcGg6wBKaYv4+OG0133qdfCxUdFnKb0NPDVF9VVKlaCnszkMx6O1BL59s01u//PXq0flv325Qq/f2d0WawsA4G6xHBwd7FOryEZVyHQ2BwAIynBQEhVKEFdISVuOu8VyAACgKeaZWs3/wGQA4AmgfM6htK1UXyRQExKbpkLEEiEpQ6qt4Xi0ciNfA7UpK9XBu8USLT8cj9DPuy7PWZM4qE9ZIVLJeAp0FWN1IRIdpdRRqx1pqgqpnaQ+SqkmJNSx4XgUnatD1+ckh1NPLJ6aUtSEpM4JfscpUkqSQqmHEo8j1bcSVEcIJ3BMCmd0YXc5RUYKTRkAFaYsCSnYdZSfJdoE0JcBUGkNkerI4eY1HG5er/0+Nipi1+dQQwaAkpDQk9jb259FdfqJ3bu/gPHlWfTa8eUZ7N1fBMvmEIpd6w9i4kKwQHOlxBIakhITlSsFi1lDiqgQSoCug9TtaCqRvgBs1MTqwuKg3EDSUsSex1ADc4/FKdtYTMbN919o2ZevXkQ/+/T7dbJttyZR1w6pP4hVPamH/kYRIzUysIRjn1Hq9uHELEE1IRodCyU+JSOHmlKqCMnpUGpKcvgCqDKodfvUkvJcu4FQR9rrR/BwdvOQOEqSOaPCyUg9s7pbLNeu2dnd7vdJPVuGR87dnFtXO5bQxkN7pKgJkZDhkJBCraNrKSpCJGU4SqRwy3YpRVwIRQblwLXYe7/2uxwpoTKhutu0Y6wlRVSIlAxHqZRcGY4upFQ9GOY8y8qVUirDUfpQlIuIkOlsvmqaiURVQXISqVFHjKaZwHQ2F3mmVSwEC6Q9xH1pT/mrQH5s7RsNi1tCStHBsB0AJclNM3n0xJe729IGkxG6ps10Nl8dHexnP2hUP6mH4IyU/3P4xha8+/Mjq73zjS2Afyds6tSqOQVjdPLNRQ5+Ys43ttjl/TJdJZmD+giJ7VIoW2SHP82dM0YKVUZo2ow9s9KWqjpCuFtGbD3hjpQSGRja22A1IbmBU6VgZxH/M0kZDk0pKkJKAy6Roi3DoSWlaA05OtgfcPfeEnNw00wAbh7WkdhIKW3HlecmvmTLCyAwQjgBSB4MsXUkZzfmQzmLhCiVASA0ZVECCXVMQ4qkDAdFioQMAME1JDcgSSkaMihIyQBQ+B/D6Wy+is272J3WLkO5K3PayWkPa0dSBoDCLgsLkLNAUq4NJbFEJPdaaRkAiv+Fi32TsZ00rNOcBJfK4MSl9eoO1Tc5UF8Ok/oaqp8o7l3pb8tTI4Mal+Z7VNTfdUJ9fRJFSu4Uga1r3Li0X2qj/rTX7wDWmVRHS+brVFlqXDXeMPTkXmEUGilSidCs2zAMwzAMwzAMwzAMwzAMwzAMwzB6yV+UDZBS7+t9dQAAAABJRU5ErkJggg==","flare":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAAXNSR0IArs4c6QAAABVQTFRFAAAAbnCAmJqk0GtT/6ZlsLrAAAAAQuAi9wAAAAd0Uk5T////////ABpLA0YAAAEnSURBVEiJ3dbBcsMgDARQpLD+/0+uHQTSCoW2t045BWlfjLGZcbt+Odr/A0AO5EpL3QJwqaVmBajWUq8EqAE+A1QAJ4Ad4AyQAbjBv6JoqYy88NQx4FUoL0ORRAaqGv/0np6BzsTrxfMEdM/vQiPQPZ+FMlDrqeeHmEXNYA7L924itE6g97f4ARB5QO9DACIluDx/C8vfAs+c8utd8rxIX2PMY97fVs9vQEKewekKNdAKaAVW533XM49YlQjCWp99NYG5q9Z2IBIEaIT8EAwk5x8hJyA7kDOQdDAgH8C68sqbWGtl4Pfm+SHi/jkIT60E1l9AE9iWFN7XcB5ON12dB9olH/5I03lYW8f5teXbefCtpnxsMLi8TPnYYHDFMg1q/P0vge/HF8FzKH+pMAUgAAAAAElFTkSuQmCC"}},"battle":{"overdrive":{"phase":2.25,"projector":1.5,"dome":2.5,"normal":1},"units":[{"title":"尖刀","id":"dagger","hitSize":8,"flying":false,"health":150,"armor":0,"speed":0.5},{"title":"爬虫","id":"crawler","hitSize":8,"flying":false,"health":150,"armor":0,"speed":1},{"title":"战锤","id":"mace","hitSize":10,"flying":false,"health":550,"armor":4,"speed":0.5},{"title":"堡垒","id":"fortress","hitSize":13,"flying":false,"health":900,"armor":9,"speed":0.43},{"title":"星辉","id":"flare","hitSize":9,"flying":true,"health":70,"armor":0,"speed":2.7}]}};
  function limited(value, fallback, min, max) {
    if ((value === '' || value == null) && fallback === Infinity) return Infinity;
    var n = value === '' || value == null ? fallback : Number(value);
    if (!Number.isFinite(n) || n < min || n > max) throw new RangeError('参数超出有效范围');
    return n;
  }
  function factory(p) {
    var d = DATA.factory, count = limited(p.count, 1, 1, 10000);
    if (!Number.isInteger(count)) throw new RangeError('建筑数量须为整数');
    var factor = limited(p.efficiency, 100, 0, 100) / 100 * limited(p.overdrive, 1, 1, 3);
    var supply = limited(p.supply, Infinity, 0, Infinity), target = limited(p.target, 60, 0, 10000000);
    var cycles = count * 60 / d.craftTime * factor;
    var actual = Math.min(cycles, supply / d.inputAmount);
    var perBuildingMinute = 60 / d.craftTime * factor * d.outputAmount * 60;
    return {capacity: cycles * d.outputAmount, output: actual * d.outputAmount,
      input: actual * d.inputAmount, neededInput: cycles * d.inputAmount,
      power: d.power * count * factor, utilization: cycles ? actual / cycles : 0,
      required: target === 0 ? 0 : perBuildingMinute ? Math.ceil(target / perBuildingMinute - 1e-10) : null,
      targetInput: target / 60 * d.inputAmount / d.outputAmount,
      targetPossible: target === 0 || (perBuildingMinute > 0 && supply >= target / 60 * d.inputAmount / d.outputAmount),
      limited: actual < cycles - 1e-9};
  }
  function turret(p) {
    var d = DATA.turret, ammo = d.ammo[p.ammo || 'copper'], coolant = p.coolant || 'none';
    if (!ammo || (coolant !== 'none' && !d.coolants[coolant])) throw new RangeError('无效弹药或冷却液');
    var count = limited(p.count, 1, 1, 10000);
    if (!Number.isInteger(count)) throw new RangeError('炮塔数量须为整数');
    var overdrive = limited(p.overdrive, 1, 1, 3), armor = limited(p.armor, 0, 0, 1000000);
    var hit = limited(p.hit, 100, 0, 100) / 100, supply = limited(p.supply, Infinity, 0, Infinity);
    var cooling = coolant === 'none' ? 1 : 1 + d.coolantAmount * d.coolants[coolant].heatCapacity * d.coolantMultiplier;
    var nominalShots = count * 60 / d.reload * ammo.reloadMultiplier * cooling * overdrive;
    var capacity = nominalShots * d.shots;
    var shotEvents = Math.min(nominalShots, supply * ammo.ammoMultiplier / d.ammoPerShot);
    var damage = ammo.pierceArmor ? ammo.damage : Math.max(ammo.damage - armor, DATA.minArmorDamage * ammo.damage);
    return {damage: damage, shots: shotEvents * d.shots, capacity: capacity,
      dps: damage * shotEvents * d.shots * hit, input: shotEvents * d.ammoPerShot / ammo.ammoMultiplier,
      neededInput: nominalShots * d.ammoPerShot / ammo.ammoMultiplier,
      coolant: coolant === 'none' ? 0 : count * d.coolantAmount * 60 * overdrive,
      range: (d.range + ammo.rangeChange) / 8, multiplier: cooling,
      limited: shotEvents < nominalShots - 1e-9};
  }
  /* Deterministic 120 Hz lane model. All stacked barrels share a target and phase. */
function createTurretBattleModel(o) {
  var s={time:0,enemies:[],bullets:[],spawned:0,kills:0,escaped:0,shots:0,hits:0,damage:0,ammo:0,credit:0,clock:0,hitCredit:0,nextSpawn:0};
  function step(dt){
    s.time+=dt;
    if(s.spawned<o.total && s.time+1e-9>=s.nextSpawn){s.enemies.push({id:++s.spawned,x:245,hp:o.hp,max:o.hp});s.nextSpawn+=o.interval;}
    s.enemies.forEach(function(e){e.x-=o.speed*60*dt;});
    s.credit=Math.min(o.count*10*o.ammoMultiplier,s.credit+o.supply*o.ammoMultiplier*dt);
    s.clock=Math.min(1,s.clock+o.rate*dt);
    var target=s.enemies.find(function(e){return e.hp>0&&e.x>=35&&e.x-35<=o.range;});
    if(target&&s.clock>=1-1e-9){
      var n=Math.min(o.count,Math.floor(s.credit+1e-9));
      if(n>0){s.clock=0;s.credit-=n;s.shots+=n;s.ammo+=n/o.ammoMultiplier;
        s.hitCredit+=n*o.hit;var hits=Math.floor(s.hitCredit+1e-9);s.hitCredit-=hits;
        s.bullets.push({x:39,n:n,hits:hits,age:0});}
    }
    s.bullets.forEach(function(b){var old=b.x;b.x+=o.bulletSpeed*60*dt;b.age+=dt;
      var e=s.enemies.find(function(e){return e.hp>0&&e.x>=old-o.hitSize/2&&e.x<=b.x+o.hitSize/2;});
      if(e){var dealt=Math.min(e.hp,o.damage*b.hits);e.hp-=dealt;s.damage+=dealt;s.hits+=b.hits;b.dead=true;if(e.hp<=0)s.kills++;}
    });
    s.bullets=s.bullets.filter(function(b){return !b.dead&&b.x<=35+o.range&&b.age<4;});
    s.enemies=s.enemies.filter(function(e){if(e.hp<=0)return false;if(e.x<0){s.escaped++;return false;}return true;});
  }
  return {state:s,advance:function(dt){if(!Number.isFinite(dt)||dt<0)throw Error('Invalid time');while(dt>1e-9){var h=Math.min(dt,1/120);step(h);dt-=h;}},done:function(){return s.spawned>=o.total&&!s.enemies.length&&!s.bullets.length;}};
}
if(typeof module!=='undefined'&&module.exports)module.exports={createTurretBattleModel:createTurretBattleModel};

function createTurretBattle(section,kind,title,setFields){
  var box=el('div','mdt-battle'),button=el('button','','加载原版战斗演算'),note=el('p','mdt-battle-note','首次打开需要下载原版游戏资源。');
  button.type='button';box.style.position='relative';box.append(button,note);section.append(box);
  var frame,timer,observer,opened=false,ready=false,height=900,started=0;
  function stop(){if(timer){clearInterval(timer);timer=null;}}
  function presentation(){
    if(!ready)return;
    try{
      var quality=frame.contentDocument.getElementById('wiki-quality');
      frame.contentWindow.mindustryWiki.command('presentation',JSON.stringify({fps:opened?(Number(quality&&quality.value)||30):2}));
    }catch(e){}
  }
  function expose(){
    opened=true;frame.style.cssText='display:block;width:100%;height:'+height+'px;border:0';
    button.hidden=true;note.textContent=ready?'':'正在加载原版客户端…';note.hidden=ready;
    presentation();
  }
  function prepare(explicit){
    if(frame){if(explicit)expose();return;}
    if(observer){observer.disconnect();observer=null;}
    frame=el('iframe');frame.title='双管 · 原版战斗演算';
    frame.style.cssText='position:absolute;left:0;top:0;width:100%;height:900px;border:0;visibility:hidden;pointer-events:none';
    frame.src='https://mdtwiki.top/labs/v160.7/playable/?wiki-lab=duo';box.prepend(frame);
    started=Date.now();note.textContent='正在准备原版战场…';
    if(explicit)expose();
    timer=setInterval(function(){
      if(!box.isConnected){stop();frame.remove();return;}
      var status;
      try{status=frame.contentDocument&&frame.contentDocument.getElementById('boot-status');}catch(e){}
      if(status&&status.dataset.state==='ready'){
        ready=true;stop();button.textContent='打开原版战斗演算';note.textContent='原版战场已就绪';note.hidden=opened;
        try{frame.contentWindow.mindustryWiki.command('pause','{}');}catch(e){}
        presentation();
      }else if((status&&status.dataset.state==='error')||Date.now()-started>240000){
        stop();frame.remove();frame=null;opened=false;ready=false;button.hidden=false;
        button.textContent='重新加载原版战斗演算';note.hidden=false;note.textContent='战场加载未完成,点击重试。';
      }
    },300);
  }
  button.onclick=function(){prepare(true);};
  // Respect data-saving preferences; explicit clicks always work.
  var connection=navigator.connection;
  if('IntersectionObserver' in root&&!(connection&&(connection.saveData||/^(slow-)?2g$/.test(connection.effectiveType)))){
    observer=new IntersectionObserver(function(entries){if(entries.some(function(entry){return entry.isIntersecting;}))prepare(false);},{rootMargin:'600px 0px'});
    observer.observe(box);
  }
  root.addEventListener('message',function(event){
    if(frame&&box.isConnected&&event.source===frame.contentWindow&&event.origin===location.origin&&event.data&&event.data.type==='mdt-wiki-height'&&Number.isFinite(event.data.height)){
      height=Math.max(500,Math.min(1600,event.data.height));if(opened)frame.style.height=height+'px';
    }
  });
  return{update:function(){},invalid:function(){},reset:function(){}};
}

  var api = {factory: factory, turret: turret, version: 'v160.7', battle: typeof createTurretBattleModel === 'function' ? createTurretBattleModel : null};
  if (typeof module !== 'undefined' && module.exports) module.exports = api;
  if (!root.document || !DATA) return;
  var doc = root.document;
  function el(tag, className, text) {
    var n = doc.createElement(tag); if (className) n.className = className;
    if (text != null) n.textContent = text; return n;
  }
  function fmt(n) { return Number(n.toFixed(3)).toLocaleString('zh-CN', {maximumFractionDigits: 3}); }
  /* Original v160.7 sprites, Canvas reconstruction of reviewed drawing effects. */
function createBuildingPreview(section, kind, title, setSupply) {
  var box = el('div', 'mdt-run-preview'), toolbar = el('div', 'mdt-run-toolbar');
  var status = el('span', 'mdt-run-status', '正在载入游戏贴图…');status.setAttribute('role', 'status');
  var toggle = el('button', '', '暂停动画');toggle.type = 'button';toggle.setAttribute('aria-pressed', 'false');
  toolbar.append(el('strong', '', '入料与产出'), status, toggle);
  var canvas = el('canvas');canvas.setAttribute('role', 'img');canvas.setAttribute('aria-label', title + '运行预览');
  var scene = el('div', 'mdt-flow-scene'), inlet = el('button', 'mdt-flow-port', kind === 'factory' ? '煤炭入料 · 点击设置' : '弹药入料 · 点击设置');inlet.type = 'button';inlet.setAttribute('aria-expanded', 'false');
  scene.append(canvas, inlet);
  var controls = el('div', 'mdt-flow-controls');controls.id = 'mdt-flow-controls';controls.hidden = true;inlet.setAttribute('aria-controls', controls.id);
  var speedLabel = el('label', '', '总入料速度(物品/秒)'), speed = el('input');speed.type = 'number';speed.min = '0';speed.max = '10000000';speed.step = '0.1';speed.id = 'mdt-flow-speed';speedLabel.htmlFor = speed.id;speedLabel.append(speed);
  var unlimitedLabel = el('label', 'mdt-flow-check'), unlimited = el('input');unlimited.type = 'checkbox';unlimited.id = 'mdt-flow-unlimited';unlimitedLabel.htmlFor = unlimited.id;unlimited.checked = true;unlimitedLabel.append(unlimited, doc.createTextNode('供给充足'));
  var batchLabel = el('label', '', '入料方式'), mode = el('select');mode.id = 'mdt-flow-mode';batchLabel.htmlFor = mode.id;
  [['continuous','持续供料'],['batch','定量投料']].forEach(function (o) {var option = el('option', '', o[1]);option.value = o[0];mode.append(option);});batchLabel.append(mode);
  var amountLabel = el('label', '', '本批投料总数(物品)'), amount = el('input');amount.type = 'number';amount.min = '0';amount.max = '1000000';amount.step = '1';amount.value = '20';amount.id = 'mdt-flow-amount';amountLabel.htmlFor = amount.id;amountLabel.append(amount);amountLabel.hidden = true;
  var restart = el('button', '', '重新开始 / 清零统计');restart.type = 'button';
  var presets = el('div', 'mdt-flow-presets');
  [0,0.5,1,2,4].forEach(function (v) {var b = el('button', '', v === 0 ? '停止入料' : v + ' 个/秒');b.type = 'button';b.addEventListener('click', function () {unlimited.checked = false;speed.value = v;applySpeed();});presets.append(b);});
  var controlError = el('p', 'mdt-flow-error');controlError.hidden = true;controlError.setAttribute('role','status');
  controls.append(speedLabel, unlimitedLabel, batchLabel, amountLabel, presets, restart, controlError);
  var stats = el('div', 'mdt-flow-stats');stats.setAttribute('aria-label','本轮物料统计');
  var caption = el('p', 'mdt-run-caption'), note = el('p', 'mdt-run-note',
    '点击画面左上角入料端设置速度或定量投料。速度为全部建筑合计;图标为流向示意,累计数量按离散物料计算。调整建筑、效率、超速或弹药会清零本轮;供给速度可随时调整。暂停或离开画面会暂停本轮。下方表格为设定条件的稳态估算。');
  box.append(toolbar, scene, controls, stats, caption, note);section.append(box);
  var ctx = canvas.getContext('2d'), images = {}, ready = false, failed = false, visible = false;
  var motion = root.matchMedia('(prefers-reduced-motion: reduce)'), paused = motion.matches;
  var valid = false, params = null, result = null, raf = 0, last = 0, width = 600, height = 230;
  var elapsed = 0, phase = 0, events = [], serial = 0, positions = [], shown = 1;
  var flow = null, flowKey = '', lastReadout = -1, arrivals = [], departures = [];
  box.dataset.events = '0';
  function rate() { return valid ? (kind === 'factory' ? result.output : result.shots) / Number(params.count) : 0; }
  function resetFlow() {
    if (!valid) return;
    var nominal = result.capacity / Number(params.count);
    flow = createMaterialFlow({count:Number(params.count), cost:kind === 'factory' ? 2 : 1 / DATA.turret.ammo[params.ammo].ammoMultiplier,
      period:nominal > 0 ? 1 / nominal : Infinity, supply:params.supply === '' ? result.neededInput : Number(params.supply),
      amount:mode.value === 'batch' ? Number(amount.value) : null});
    events = [];arrivals = [];departures = [];phase = 0;serial = 0;elapsed = 0;lastReadout = -1;box.dataset.events = '0';readout();
  }
  function applySpeed() {
    if (!unlimited.checked && (speed.value === '' || !speed.validity.valid)) {controlError.textContent = '请输入 0–10000000 之间的入料速度。';controlError.hidden = false;return;}
    controlError.hidden = true;setSupply(unlimited.checked ? '' : speed.value);
  }
  function readout() {
    if (!flow || !valid) {stats.replaceChildren();return;}
    var s = flow.state, inputName = kind === 'factory' ? '煤炭' : DATA.turret.ammo[params.ammo].title;
    var rows = [['入料设定', fmt(s.supply) + ' 个/秒'], ['本轮平均入料', fmt(s.time > 0 ? s.delivered / s.time : 0) + ' 个/秒'],
      ['已送入', fmt(s.delivered) + ' ' + inputName], [kind === 'factory' ? '待加工缓存' : '待发射弹药', fmt(kind === 'factory' ? s.stock : s.stock * DATA.turret.ammo[params.ammo].ammoMultiplier) + (kind === 'factory' ? ' 个' : ' 发')], [kind === 'factory' ? '已消耗' : '耗弹(物品当量)', fmt(s.used) + ' 个'],
      [kind === 'factory' ? '已产出石墨' : '已发射', fmt(s.output) + (kind === 'factory' ? ' 个' : ' 发')],
      ['本轮平均产出', fmt(s.time > 0 ? s.output / s.time * 60 : 0) + (kind === 'factory' ? ' 个/分钟' : ' 发/分钟')],
      ['料源剩余', Number.isFinite(s.source) ? fmt(s.source) + ' 个' : '持续供给']];
    stats.replaceChildren();rows.forEach(function (row) {var cell = el('div');cell.append(el('span','',row[0]),el('strong','',row[1]));stats.append(cell);});
    box.dataset.delivered = String(s.delivered);box.dataset.output = String(s.output);box.dataset.stock = String(s.stock);box.dataset.used = String(s.used);
    label();
  }
  function label() {
    var state = failed ? 'error' : !ready ? 'loading' : !valid ? 'invalid' : paused ? 'paused' : flow && flow.running() ? 'running' : 'stopped';
    box.dataset.state = state;
    status.textContent = ({error:'贴图载入失败,请刷新重试', loading:'正在载入游戏贴图…', invalid:'等待有效参数', paused:'本轮已暂停', running:flow && flow.busy() ? (kind === 'factory' ? '生产中' : '持续射击') : '等待入料', stopped:flow && flow.state.source === 0 ? '本批料源已用尽' : '等待入料 / 已停止'})[state];
    toggle.textContent = paused ? '播放动画' : '暂停动画';toggle.setAttribute('aria-pressed', String(paused));
    canvas.setAttribute('aria-label', title + '运行预览:' + status.textContent);
    caption.textContent = valid ? '共 ' + fmt(Number(params.count)) + ' 座 · 展示 ' + shown + ' 座' +
      (Number(params.count) > shown ? ',其余建筑按相同条件演算' : '') + ' · 单座 ' +
      (kind === 'factory' ? fmt(rate() * 60) + ' 石墨/分钟' : fmt(rate()) + ' 发/秒') : '填写有效参数后显示运行状态';
  }
  function layout() {
    width = Math.max(220, Math.round(box.clientWidth - 2));
    var count = valid ? Number(params.count) : 1, cols = width >= 600 ? 2 : 1;
    shown = Math.min(count, width < 600 ? 2 : 4);
    cols = Math.min(cols, shown);height = Math.max(240, Math.ceil(shown / cols) * 220);
    var dpr = Math.min(root.devicePixelRatio || 1, 2);
    canvas.width = Math.round(width * dpr);canvas.height = Math.round(height * dpr);canvas.style.height = height + 'px';
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);ctx.imageSmoothingEnabled = false;
    positions = [];
    for (var i = 0; i < shown; i++) {
      var cell = width / cols, row = Math.floor(i / cols), col = i % cols;
      positions.push({x:cell * (col + (kind === 'factory' ? 0.5 : 0.35)), y:(row + 0.5) * height / Math.ceil(shown / cols) + 8, span:cell, left:col * cell});
    }
    label();draw();
  }
  function sprite(name, x, y, scale, angle) {
    var img = images[name];if (!img || !img.naturalWidth) return;
    ctx.save();ctx.translate(x, y);ctx.rotate(angle || 0);ctx.drawImage(img, -img.width * scale / 2, -img.height * scale / 2, img.width * scale, img.height * scale);ctx.restore();
  }
  function drawFlow(pos, index) {
    if (!flow || !valid) return;
    var start = pos.left + 23, end = pos.left + pos.span - 23, cy = pos.y;
    ctx.lineWidth = 10;ctx.strokeStyle = '#20262ad9';ctx.beginPath();ctx.moveTo(start,cy);ctx.lineTo(pos.x - 42,cy);ctx.stroke();
    if (kind === 'factory') {ctx.beginPath();ctx.moveTo(pos.x + 42,cy);ctx.lineTo(end,cy);ctx.stroke();}
    ctx.lineWidth = 1;ctx.strokeStyle = '#97aaa166';ctx.setLineDash([5,6]);ctx.beginPath();ctx.moveTo(start,cy);ctx.lineTo(pos.x - 42,cy);ctx.stroke();
    if (kind === 'factory') {ctx.beginPath();ctx.moveTo(pos.x + 42,cy);ctx.lineTo(end,cy);ctx.stroke();}ctx.setLineDash([]);
    var inputSprite = kind === 'factory' ? 'item-coal' : 'item-' + params.ammo;
    sprite(inputSprite,start,cy,0.65);
    if (kind === 'factory') sprite('item-graphite',end,cy,0.65);
    arrivals.forEach(function (e) {var t = (elapsed - e.time) / 0.6;if (t >= 0 && t < 1) sprite(inputSprite,start + (pos.x - 42 - start) * t,cy,0.5);});
    departures.forEach(function (e) {var t = (elapsed - e.time) / 0.65;if (e.index === index && t >= 0 && t < 1 && kind === 'factory') sprite('item-graphite',pos.x + 42 + (end - pos.x - 42) * t,cy,0.5);});
    ctx.font = '12px sans-serif';ctx.fillStyle = '#e5e9e5';ctx.textAlign = 'left';
    ctx.fillText(kind === 'factory' ? '煤炭入料 →' : DATA.turret.ammo[params.ammo].title + '入料 →',pos.left + 15,pos.y - 74);
    ctx.textAlign = 'right';ctx.fillText(kind === 'factory' ? '→ 石墨产出' : '→ 弹丸发射',pos.left + pos.span - 15,pos.y - 74);
    ctx.font = '11px sans-serif';ctx.fillStyle = '#d4ba74';ctx.textAlign = 'left';
    ctx.fillText('均入 ' + fmt(flow.state.time ? flow.state.delivered / flow.state.time : 0) + ' 个/秒',pos.left + 15,pos.y + 85);
    ctx.textAlign = 'right';ctx.fillText('均出 ' + fmt(flow.state.time ? flow.state.output / flow.state.time * 60 : 0) + (kind === 'factory' ? ' 个/分钟' : ' 发/分钟'),pos.left + pos.span - 15,pos.y + 85);
    ctx.textAlign = 'center';ctx.fillStyle = '#c4cfca';ctx.fillText('第 ' + (index + 1) + ' 座' + (flow.state.active[index] ? ' · 加工中' : ' · 等待入料'),pos.x,pos.y + 66);
    ctx.textAlign = 'left';
  }
  function draw() {
    ctx.clearRect(0, 0, width, height);ctx.fillStyle = '#36383c';ctx.fillRect(0, 0, width, height);
    if (!ready) return;
    for (var y = 0; y < height; y += 32) for (var x = 0; x < width; x += 32) ctx.drawImage(images.stone1, x, y, 32, 32);
    ctx.fillStyle = '#10151a55';ctx.fillRect(0, 0, width, height);
    positions.forEach(function (pos, index) {
      drawFlow(pos,index);
      var recent = events.filter(function (e) { return e.index === index; });
      if (kind === 'factory') {
        sprite('graphite-press', pos.x, pos.y - 5, 1.25);
        recent.forEach(function (e) {
          var age = elapsed - e.time;if (age > 0.5) return;
          var t = age / 0.5;
          for (var i = 0; i < 5; i++) {
            var angle = (i * 2.39996 + e.id * 1.7), radius = (3 + t * 8) * 4;
            ctx.save();ctx.translate(pos.x + Math.cos(angle) * radius, pos.y - 5 + Math.sin(angle) * radius);
            ctx.rotate(Math.PI / 4);ctx.fillStyle = '#8f8f8f';var size = (1.5 - t) * 4;ctx.fillRect(-size, -size, size * 2, size * 2);ctx.restore();
          }
        });
        ctx.fillStyle = '#24292e';ctx.fillRect(pos.x - 40, pos.y + 53, 80, 4);
        ctx.fillStyle = '#d4ba74';ctx.fillRect(pos.x - 40, pos.y + 53, 80 * (flow ? flow.state.progress[index] : 0), 4);
      } else {
        sprite('block-1', pos.x, pos.y, 2);
        // Source sprites point upward. Rotate the two independent barrels toward the target.
        var kick = [0, 0];recent.forEach(function (e) {var age = elapsed - e.time;if (age < 0.22) kick[e.id % 2] = Math.max(kick[e.id % 2], 1 - age / 0.22);});
        sprite('duo-barrel-l', pos.x - kick[0] * 12, pos.y, 2, Math.PI / 2);
        sprite('duo-barrel-r', pos.x - kick[1] * 12, pos.y, 2, Math.PI / 2);
        sprite('duo', pos.x, pos.y, 2, Math.PI / 2);
        var distance = Math.max(65, pos.span * 0.6 - 30), tx = pos.x + distance;
        ctx.strokeStyle = '#b6bdc477';ctx.lineWidth = 1;ctx.beginPath();ctx.arc(tx, pos.y, 14, 0, Math.PI * 2);ctx.moveTo(tx - 20, pos.y);ctx.lineTo(tx + 20, pos.y);ctx.moveTo(tx, pos.y - 20);ctx.lineTo(tx, pos.y + 20);ctx.stroke();
        recent.forEach(function (e) {
          var age = elapsed - e.time, side = e.id % 2 ? 7 : -7, start = pos.x + 24;
          var duration = Math.max(0.15, (distance - 24) / (e.speed * 60 * 8));
          if (age < duration) {
            var bx = start + (distance - 24) * age / duration;
            ctx.save();ctx.translate(bx, pos.y + side);ctx.rotate(Math.PI / 2);
            ctx.drawImage(e.back, -e.w / 2, -e.h / 2, e.w, e.h);ctx.drawImage(e.front, -e.w / 3, -e.h / 3, e.w * 2 / 3, e.h * 2 / 3);ctx.restore();
          } else if (age < duration + 0.23) {
            var t = (age - duration) / 0.23;ctx.strokeStyle = e.color;ctx.globalAlpha = 1 - t;ctx.beginPath();ctx.arc(tx, pos.y + side, 2 + t * 15, 0, Math.PI * 2);ctx.stroke();ctx.globalAlpha = 1;
          }
          if (age < 8 / 60) {
            var f = 1 - age * 60 / 8;ctx.fillStyle = '#ffd37f';ctx.beginPath();ctx.moveTo(start, pos.y + side - 6 * f);ctx.lineTo(start + 30 * f, pos.y + side);ctx.lineTo(start, pos.y + side + 6 * f);ctx.fill();
          }
        });
      }
    });
  }
  var palettes = {copper:['#d39169','#eac1a8',2.5,7,9],graphite:['#7d89d8','#dae1ee',3.5,9,12],silicon:['#707594','#999ba0',3,7,9]}, tinted = {};
  function tint(name, color) {
    var c = doc.createElement('canvas');c.width = images[name].width;c.height = images[name].height;
    var g = c.getContext('2d');g.drawImage(images[name], 0, 0);g.globalCompositeOperation = 'source-in';g.fillStyle = color;g.fillRect(0, 0, c.width, c.height);return c;
  }
  function step(dt) {
    elapsed += dt;
    var movement = flow.advance(dt);
    if (movement.arrivals > 0) {arrivals.push({time:elapsed});}
    if (movement.produced.length) {
      serial += movement.produced.length;box.dataset.events = String(serial);
      movement.produced.forEach(function (index) {
        if (index >= shown) return;
        var e = {time:elapsed, index:index, id:flow.state.completed[index]};departures.push({time:elapsed,index:index});
        if (kind === 'turret') {var p = palettes[params.ammo];Object.assign(e, {back:tinted[params.ammo][0], front:tinted[params.ammo][1], color:p[0], speed:p[2], w:p[3]*2, h:p[4]*2});}
        events.push(e);
      });
    }
    events = events.filter(function (e) {return elapsed - e.time < 1;});
    arrivals = arrivals.filter(function (e) {return elapsed - e.time < 0.6;}).slice(-8);
    departures = departures.filter(function (e) {return elapsed - e.time < 0.65;}).slice(-32);
    if (elapsed - lastReadout > 0.2) {lastReadout = elapsed;readout();}
  }
  function shouldRun() { return ready && !failed && valid && !paused && visible && !doc.hidden && box.isConnected && flow && (flow.running() || events.length || arrivals.length || departures.length); }
  function frame(now) {
    raf = 0;if (!shouldRun()) {last = 0;return;}
    var dt = last ? Math.min((now - last) / 1000, 0.1) : 0;last = now;step(dt);draw();raf = root.requestAnimationFrame(frame);
  }
  function sync() {
    label();
    if (!shouldRun()) {if (raf) root.cancelAnimationFrame(raf);raf = 0;last = 0;draw();}
    else if (!raf) {last = 0;raf = root.requestAnimationFrame(frame);}
  }
  toggle.addEventListener('click', function () {paused = !paused;sync();});
  inlet.addEventListener('click', function () {controls.hidden = !controls.hidden;inlet.setAttribute('aria-expanded',String(!controls.hidden));if (!controls.hidden) speed.focus();});
  speed.addEventListener('change', function () {unlimited.checked = false;applySpeed();});
  unlimited.addEventListener('change',applySpeed);
  mode.addEventListener('change',function () {amountLabel.hidden = mode.value !== 'batch';resetFlow();sync();});
  function startBatch() {
    if (!amount.validity.valid || amount.value === '') {controlError.textContent = '本批数量须为 0–1000000 的整数。';controlError.hidden = false;return;}
    controlError.hidden = true;resetFlow();sync();
  }
  amount.addEventListener('change',startBatch);restart.addEventListener('click',startBatch);
  motion.addEventListener('change', function (e) {paused = e.matches;sync();});
  doc.addEventListener('visibilitychange', sync);
  var observer = new IntersectionObserver(function (entries) {visible = entries[0].isIntersecting;sync();});observer.observe(box);
  var resize = new ResizeObserver(layout);resize.observe(box);
  Promise.all(Object.keys(DATA.animation.sprites).map(function (name) {
    return new Promise(function (resolve, reject) {var img = new Image();images[name] = img;img.onload = resolve;img.onerror = reject;img.src = DATA.animation.sprites[name];});
  })).then(function () {
    Object.keys(palettes).forEach(function (k) {tinted[k] = [tint('bullet-back', palettes[k][0]), tint('bullet', palettes[k][1])];});
    ready = true;layout();sync();
  }).catch(function () {failed = true;sync();});
  layout();
  return {
    reset:function () {mode.value = 'continuous';amount.value = '20';amountLabel.hidden = true;controls.hidden = true;inlet.setAttribute('aria-expanded','false');controlError.hidden = true;flow = null;flowKey = '';paused = motion.matches;},
    update:function (p, r) {
      var key = [p.count,r.capacity,p.ammo || 'coal'].join('|');params = p;result = r;valid = true;
      speed.value = p.supply;unlimited.checked = p.supply === '';speed.placeholder = fmt(r.neededInput);
      if (!flow || flowKey !== key) {flowKey = key;resetFlow();}else {flow.state.supply = p.supply === '' ? r.neededInput : Number(p.supply);readout();}
      layout();sync();
    },
    invalid:function () {valid = false;events = [];arrivals = [];departures = [];phase = 0;readout();sync();}
  };
}

  /* Discrete material accounting for the interactive preview, independent of rendering. */
function createMaterialFlow(options) {
  var count = options.count, cost = options.cost, period = options.period;
  var s = {time:0, delivered:0, used:0, output:0, stock:0, credit:0, source:options.amount == null ? Infinity : options.amount,
    supply:options.supply, capacity:count * 10, progress:new Float64Array(count), active:new Uint8Array(count), completed:new Uint32Array(count), cursor:0};
  function advance(dt) {
    var produced = [], arrivals = 0;
    // Fixed maximum step keeps allocation stable across display refresh rates.
    while (dt > 1e-9) {
      var step = Math.min(dt, 1 / 60);dt -= step;s.time += step;
      var room = Math.max(0, s.capacity - s.stock);
      if (room >= 1 && s.source > 0) {
        s.credit += Number.isFinite(s.supply) ? s.supply * step : room;
        var receive = Math.min(Math.floor(s.credit + 1e-9), Math.floor(room), s.source);
        s.stock += receive;s.delivered += receive;s.source -= receive;s.credit -= receive;arrivals += receive;
        if (s.stock >= s.capacity) s.credit = 0;
      } else s.credit = 0;
      if (!(period > 0) || !Number.isFinite(period)) continue;
      for (var n = 0; n < count; n++) {
        var i = (s.cursor + n) % count;
        if (!s.active[i] && s.stock + 1e-9 >= cost) {s.stock = Math.max(0, s.stock - cost);s.active[i] = 1;s.progress[i] = 0;}
        if (s.active[i]) {
          s.progress[i] += step / period;
          if (s.progress[i] >= 1 - 1e-9) {
            s.progress[i] = 0;s.active[i] = 0;s.used += cost;s.output++;s.completed[i]++;produced.push(i);
          }
        }
      }
      s.cursor = (s.cursor + 1) % count;
    }
    return {produced:produced, arrivals:arrivals};
  }
  function busy() {for (var i = 0; i < count; i++) if (s.active[i]) return true;return false;}
  function running() {return (Number.isFinite(period) && period > 0) && (busy() || s.stock + 1e-9 >= cost || (s.source > 0 && s.supply > 0));}
  return {state:s, advance:advance, running:running, busy:busy};
}
if (typeof module !== 'undefined' && module.exports) module.exports = createMaterialFlow;

/* BEGIN MDT ORIGINAL SCENE EMBED V4 */
function mountOriginalScene(title, scene){
  if(doc.querySelector('.mdt-calc'))return;
  var host=doc.querySelector('#mw-content-text .mdtMain');
  if(!host)return;
  var section=el('section','mdt-calc'),heading=el('h2','','交互演算');
  section.dataset.originalScene=scene;heading.id='MDT-calculator';
  section.setAttribute('aria-labelledby',heading.id);
  heading.append(el('span','mdt-calc-version','原版 v160.7 · 实时演算'));
  section.append(heading);
  var descriptions={duo:'选择弹药、冷却液、超速和目标单位,观察双管的实际战斗表现。',
    'graphite-press':'调整供煤、石墨取出速度和超速,观察加工进度与库存变化。',
    'mechanical-drill':'选择矿物、矿层覆盖、供水和超速,观察钻取进度与实际产出。',
    'pneumatic-drill':'选择矿物、矿层覆盖、供水和超速,观察钻取进度与实际产出。'};
  section.append(el('p','mdt-calc-intro',descriptions[scene]));
  var box=el('div','mdt-battle'),button=el('button','','加载原版演算');
  button.type='button';button.setAttribute('aria-expanded','false');
  var status=el('p','mdt-battle-note','点击后加载演算。设置可在演算内折叠。');
  status.setAttribute('role','status');box.append(button,status);section.append(box);
  host.prepend(section);
  var frame,timer,observer,ready=false,inView=true,started=0;
  var bridgeName=scene==='duo'?'mindustryWiki':scene==='graphite-press'?'mindustryFactory':'mindustryDrill';
  function pause(){
    if(!ready||!frame)return;
    try{frame.contentWindow[bridgeName].command('pause','{}');}catch(e){}
  }
  function stopTimer(){if(timer){clearInterval(timer);timer=null;}}
  function cleanup(){stopTimer();if(observer)observer.disconnect();root.removeEventListener('message',onMessage);doc.removeEventListener('visibilitychange',onVisibility);}
  function onVisibility(){if(doc.hidden)pause();}
  function onMessage(event){
    if(!frame||!box.isConnected||event.source!==frame.contentWindow||event.origin!==location.origin)return;
    var data=event.data;
    if(data&&data.type==='mdt-wiki-height'&&Number.isFinite(data.height)){
      frame.style.height=Math.max(240,Math.min(2400,Math.ceil(data.height)))+'px';
    }
  }
  function failed(){
    stopTimer();ready=false;if(frame)frame.remove();frame=null;
    button.hidden=false;button.disabled=false;button.textContent='重新加载原版演算';
    button.setAttribute('aria-expanded','false');status.hidden=false;
    status.textContent='演算加载未完成,请点击重试。';
  }
  function tick(){
    if(!box.isConnected){cleanup();if(frame)frame.remove();return;}
    if(ready)return;
    var boot;
    try{boot=frame.contentDocument.getElementById('boot-status');}catch(e){}
    if(boot&&boot.dataset.state==='ready'){
      ready=true;button.hidden=true;status.hidden=true;
      if(doc.hidden||!inView)pause();
    }else if((boot&&boot.dataset.state==='error')||Date.now()-started>120000)failed();
  }
  button.onclick=function(){
    if(frame)return;
    button.disabled=true;button.setAttribute('aria-expanded','true');
    status.textContent='正在加载原版演算…';
    frame=el('iframe');frame.title=title+' · 原版实时演算';
    frame.id='mdt-original-scene';button.setAttribute('aria-controls',frame.id);
    frame.style.cssText='display:block;width:100%;height:900px;border:0;max-width:100%';
    frame.setAttribute('scrolling','no');
    frame.src='/labs/v160.7/wiki-light-v5/playable/?wiki-lab='+encodeURIComponent(scene);
    box.append(frame);started=Date.now();timer=setInterval(tick,350);
  };
  root.addEventListener('message',onMessage);doc.addEventListener('visibilitychange',onVisibility);
  if('IntersectionObserver' in root){
    observer=new IntersectionObserver(function(entries){
      inView=entries[0].isIntersecting;if(!inView)pause();
    });observer.observe(box);
  }
  doc.querySelectorAll('.article-toc,.floating-contents-links').forEach(function(toc){
    if(!toc.querySelector('a[href="#MDT-calculator"]')){
      var link=el('a','','交互演算');link.href='#MDT-calculator';toc.append(link);
    }
  });
}
/* END MDT ORIGINAL SCENE EMBED V4 */

  function mount() {
    if (!root.mw || mw.config.get('wgAction') !== 'view' || mw.config.get('wgNamespaceNumber') !== 0 ||
      new URLSearchParams(location.search).has('oldid') || doc.querySelector('.diff')) return;
    var title = mw.config.get('wgTitle');
    var originalScenes = {'双管':'duo','石墨压缩机':'graphite-press','机械钻头':'mechanical-drill','气动钻头':'pneumatic-drill'};
    if (originalScenes[title]) {mountOriginalScene(title, originalScenes[title]);return;}
    var kind = title === DATA.factory.title ? 'factory' : title === DATA.turret.title ? 'turret' : null;
    if (!kind || doc.querySelector('.mdt-calc')) return;
    var host = doc.querySelector('#mw-content-text .mdtMain');
    if (!host) return;
    var section = el('section', 'mdt-calc'), heading = el('h2', '', '交互演算');
    heading.id = 'MDT-calculator';section.setAttribute('aria-labelledby', heading.id);
    var badge = el('span', 'mdt-calc-version', '原版 ' + api.version + ' · 公式演算');heading.append(badge);section.append(heading);
    var intro = el('p', 'mdt-calc-intro', kind === 'factory' ? '调整工厂数量与供给,计算稳定运行时的产出和配比。' : '切换弹药与冷却液,比较持续射击时对单个单位的直击伤害。');
    section.append(intro);
    var identity = el('div', 'mdt-calc-identity'), art = el('img');art.src = DATA.images[kind];art.alt = '';art.width = 40;art.height = 40;
    identity.append(art, el('strong', '', title), el('span', '', kind === 'factory' ? '2 煤炭 → 1 石墨 · 基准周期 1.5 秒' : '交替射击 · 每次发射 1 枚子弹'));section.append(identity);
    var preview = kind === 'turret' && DATA.battle ? createTurretBattle(section, kind, title, function (changes) {
      Object.keys(changes).forEach(function (k) { fields[k].value = changes[k]; });update();
    }) : DATA.animation && typeof createBuildingPreview === 'function' ? createBuildingPreview(section, kind, title, function (value) {
      fields.supply.value = value;update();
    }) : null;
    // The original-client turret view owns its own controls and live results.
    if(kind === 'turret' && DATA.battle){
      badge.textContent='原版 ' + api.version + ' · 实时演算';
      intro.textContent='调整弹药、加成和敌方单位,观察原版炮塔的实际战斗表现。';
      host.prepend(section);
      doc.querySelectorAll('.article-toc,.floating-contents-links').forEach(function(toc){
        if(!toc.querySelector('a[href="#MDT-calculator"]')){var a=el('a','','交互演算');a.href='#MDT-calculator';toc.append(a);}
      });
      return;
    }
    var form = el('form', 'mdt-calc-form');form.noValidate = true;form.addEventListener('submit', function (e) { e.preventDefault(); });
    var fields = {};
    function field(key, name, value, min, max, step, hint) {
      var label = el('label', 'mdt-calc-field');label.append(el('span', '', name));
      var input = el('input');input.type = 'number';input.name = key;input.defaultValue = String(value);input.value = value;
      input.min = min;input.max = max;input.step = step;input.inputMode = step === 1 ? 'numeric' : 'decimal';
      input.id = 'mdt-calc-' + key;label.htmlFor = input.id;
      if (hint) { var help = el('small', '', hint);help.id = input.id + '-hint';input.setAttribute('aria-describedby', help.id);label.append(input, help); }
      else label.append(input);
      fields[key] = input;form.append(label);
    }
    function select(key, name, options) {
      var label = el('label', 'mdt-calc-field');label.append(el('span', '', name));var input = el('select');input.name = key;input.id = 'mdt-calc-' + key;label.htmlFor = input.id;
      options.forEach(function (o) { var option = el('option', '', o[1]);option.value = o[0];input.append(option); });
      label.append(input);fields[key] = input;form.append(label);
    }
    field('count', kind === 'factory' ? '工厂数量' : '炮塔数量', 1, 1, 10000, 1);
    if (kind === 'factory') field('efficiency', '运行效率(%)', 100, 0, 100, 1, '不含下方单独计算的供煤限制');
    else {
      select('ammo', '使用弹药', Object.keys(DATA.turret.ammo).map(function (k) { return [k, DATA.turret.ammo[k].title]; }));
      select('coolant', '冷却液', [['none', '不使用冷却液'], ['water', '水(充分供给)'], ['cryofluid', '冷冻液(充分供给)']]);
      field('armor', '目标单位护甲', 0, 0, 1000000, 0.1);
      field('hit', '命中率(%)', 100, 0, 100, 1, '命中率影响伤害,不减少耗弹');
    }
    field('overdrive', '超速倍率', 1, 1, 3, 0.01, '1 表示无超速');
    field('supply', kind === 'factory' ? '总供煤量(个/秒)' : '总供弹量(物品/秒)', '', 0, 10000000, 0.01, '留空表示供给充足;0 表示断供');
    if (kind === 'factory') field('target', '目标石墨产量(个/分钟)', 60, 0, 10000000, 0.1, '反算建筑数,沿用当前效率和超速条件');
    section.append(form);
    var error = el('p', 'mdt-calc-error');error.setAttribute('role', 'status');error.hidden = true;section.append(error);
    var results = el('div', 'mdt-calc-results');results.setAttribute('aria-live', 'polite');results.setAttribute('aria-atomic', 'true');section.append(results);
    var comparison = el('div', 'mdt-calc-comparison');section.append(comparison);
    var actions = el('div', 'mdt-calc-actions'), reset = el('button', '', '恢复默认参数');reset.type = 'button';
    actions.append(reset);section.append(actions);
    var details = el('details', 'mdt-calc-notes');details.append(el('summary', '', '计算条件与数据来源'));
    var note = kind === 'factory' ?
      '按长期平均产量计算,假设产物及时运出,忽略启动、整数批次及运输波动。供煤量为全部工厂合计,假设均匀分配。石墨压缩机不耗电。目标建筑数按当前效率和超速向上取整,供煤不足会单独提示。' :
      '假设目标在射程内、持续锁定、冷却液充分供给。对普通单位按 max(单发伤害 − 护甲, 单发伤害 × 10%) 计算,默认地图及单位属性倍率均为 1。冷却后的装填倍率为 1 + 每 tick 冷却量 × 热容量 × 冷却倍率,再乘弹药装填倍率与超速。供弹量为全部炮塔合计。忽略首发、转向、弹道飞行、状态效果和逐帧取整;结果为长期平均估算。冷却液显示持续装填时的供给预算,断弹或空闲时实际消耗会降低。';
    details.append(el('p', '', note));
    var source = el('p', '', '数据来自官方原版 v160.7;');
    var link = el('a', '', kind === 'factory' ? '查看生产逻辑源码' : '查看装填与冷却源码');
    link.href = 'https://github.com/Anuken/Mindustry/blob/v160.7/core/src/mindustry/' + (kind === 'factory' ? 'world/blocks/production/GenericCrafter.java' : 'world/blocks/defense/turrets/ReloadTurret.java');source.append(link);details.append(source);section.append(details);
    host.prepend(section);
    function card(name, value, unit) { var c = el('div', 'mdt-calc-result');c.append(el('span', '', name), el('strong', '', value), el('small', '', unit));results.append(c); }
    function read() {
      var p = {}, invalid = false;
      Object.keys(fields).forEach(function (k) {
        var input = fields[k], bad = !input.validity.valid || (input.value === '' && k !== 'supply');
        input.setAttribute('aria-invalid', String(bad));if (bad) invalid = true;p[k] = input.value;
      });
      if (invalid) throw new RangeError('请填写有效参数:数量须为正整数,效率和命中率为 0–100%,超速为 1–3 倍,其余参数不能为负。');
      return p;
    }
    function update() {
      results.replaceChildren();comparison.replaceChildren();error.hidden = true;
      try {
        var p = read(), r = kind === 'factory' ? factory(p) : turret(p);
        if (preview) preview.update(p, r);
        if (kind === 'factory') {
          card('实际石墨产量', fmt(r.output * 60), '个/分钟 · ' + fmt(r.output) + ' 个/秒');
          card('实际耗煤', fmt(r.input * 60), '个/分钟 · 满产需 ' + fmt(r.neededInput) + ' 个/秒');
          card('供给利用后的产能', fmt(r.utilization * 100) + '%', '满产 ' + fmt(r.capacity * 60) + ' 石墨/分钟');
          card('运行耗电', fmt(r.power), '电力单位/秒');
          card('目标所需工厂', r.required == null ? '无法达到' : fmt(r.required), '座 · 目标 ' + fmt(Number(p.target)) + ' 石墨/分钟');
          card('目标所需供煤', fmt(r.targetInput), '个/秒 · ' + fmt(r.targetInput * 60) + ' 个/分钟');
          comparison.append(el('p', 'mdt-calc-status', r.limited ? '当前供煤不足,实际产量已按供给上限降低。' : r.capacity === 0 ? '当前效率为 0,工厂停止生产。' : '当前供给可满足所选工厂的满负荷生产。'));
          if (!r.targetPossible) comparison.append(el('p', 'mdt-calc-status', '目标产量需要提高运行效率或增加供煤,单纯增加工厂无法满足。'));
          var bar = el('div', 'mdt-calc-bar');bar.setAttribute('role', 'img');bar.setAttribute('aria-label', '当前可用产能 ' + fmt(r.utilization * 100) + '%');
          var fill = el('span');fill.style.width = (r.utilization * 100) + '%';bar.append(fill);comparison.append(bar);
        } else {
          card('预计直击伤害', fmt(r.dps), '伤害/秒 · 按当前命中率');
          card('实际射速', fmt(r.shots), '发/秒 · 满供给 ' + fmt(r.capacity) + ' 发/秒');
          card('单发护甲后伤害', fmt(r.damage), '伤害/次命中');
          card('实际耗弹', fmt(r.input), '物品/秒 · 满供给需 ' + fmt(r.neededInput));
          card('冷却液供给预算', fmt(r.coolant), '液体/秒 · 持续装填上限');
          card('射程', fmt(r.range), '格 · 冷却装填 ' + fmt(r.multiplier) + ' 倍');
          comparison.append(el('p', 'mdt-calc-status', r.limited ? '当前供弹限制了持续射速,伤害与耗弹已按供给上限降低。' : '当前供弹可满足持续射击;命中率为手动设定值。'));
          comparison.append(el('h3', '', '相同条件下的弹药对比'));
          Object.keys(DATA.turret.ammo).forEach(function (key) {
            var q = Object.assign({}, p, {ammo: key}), v = turret(q), row = el('div', 'mdt-calc-ammo' + (key === p.ammo ? ' is-selected' : ''));
            var image = el('img');image.src = DATA.images[key];image.alt = '';image.width = 20;image.height = 20;
            row.append(image, el('strong', '', DATA.turret.ammo[key].title), el('span', '', fmt(v.dps) + ' 伤害/秒'), el('small', '', fmt(v.input) + ' 物品/秒'));comparison.append(row);
          });
        }
      } catch (e) { error.textContent = e.message;error.hidden = false;if (preview) preview.invalid(); }
    }
    var timer;
    form.addEventListener('input', function () { clearTimeout(timer);timer = setTimeout(update, 120); });
    form.addEventListener('change', function () { clearTimeout(timer);update(); });
    reset.addEventListener('click', function () { clearTimeout(timer);form.reset();if (preview && preview.reset) preview.reset();update(); });update();
    doc.querySelectorAll('.article-toc,.floating-contents-links').forEach(function (toc) {
      if (!toc.querySelector('a[href="#MDT-calculator"]')) { var a = el('a', '', '交互演算');a.href = '#MDT-calculator';toc.append(a); }
    });
  }
  if (root.mw && mw.hook) mw.hook('wikipage.content').add(mount);
  if (doc.readyState === 'loading') doc.addEventListener('DOMContentLoaded', mount);else mount();
}(typeof window !== 'undefined' ? window : globalThis));
/* END MDT CALCULATOR */

/* BEGIN MDT WAVE SEARCH */
(function () {
  'use strict';
  function init() {
    document.querySelectorAll('.mw-parser-output .mdtPanel').forEach(function (panel) {
      var heading = panel.querySelector('h2');
      if (!heading || !heading.textContent.includes('波次数量参考') || panel.querySelector('.mdt-wave-search')) return;
      var table = panel.querySelector('table');
      if (!table) return;
      var rows = new Map();
      table.querySelectorAll('tr').forEach(function (row) {
        var cell = row.querySelector('td');
        if (cell && /^\d+$/.test(cell.textContent.trim())) rows.set(Number(cell.textContent.trim()), row);
      });
      if (!rows.size) return;
      panel.classList.add('mdt-wave-panel');
      var bar = document.createElement('div');
      bar.className = 'mdt-wave-heading';
      var wrapper = heading.closest('.mw-heading') || heading;
      wrapper.parentNode.insertBefore(bar, wrapper);
      bar.appendChild(wrapper);
      var form = document.createElement('form');
      form.className = 'mdt-wave-search';
      form.setAttribute('role', 'search');
      form.setAttribute('aria-label', '查找波次');
      var input = document.createElement('input');
      input.type = 'number'; input.min = '1'; input.step = '1';
      input.placeholder = '输入波次';
      input.setAttribute('aria-label', '波次数');
      input.inputMode = 'numeric'; input.required = true;
      var button = document.createElement('button');
      button.type = 'submit'; button.textContent = '跳转';
      var status = document.createElement('span');
      status.className = 'mdt-wave-status';
      status.setAttribute('role', 'status');
      form.append(input, button, status); bar.appendChild(form);
      input.addEventListener('input', function () {
        status.textContent = ''; input.removeAttribute('aria-invalid');
      });
      var timer;
      form.addEventListener('submit', function (event) {
        event.preventDefault();
        var target = rows.get(Number(input.value));
        if (!target) {
          status.textContent = '表中没有第 ' + input.value + ' 波';
          input.setAttribute('aria-invalid', 'true'); return;
        }
        status.textContent = ''; input.removeAttribute('aria-invalid');
        panel.querySelectorAll('.mdt-wave-selected').forEach(function (row) { row.classList.remove('mdt-wave-selected'); });
        clearTimeout(timer); target.classList.add('mdt-wave-selected');
        target.setAttribute('tabindex', '-1'); target.focus({preventScroll: true});
        target.scrollIntoView({behavior: 'instant', block: 'center'});
        timer = setTimeout(function () { target.classList.remove('mdt-wave-selected'); }, 4000);
      });
    });
  }
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
  else init();
  if (window.mw && mw.hook) mw.hook('wikipage.content').add(init);
}());
/* END MDT WAVE SEARCH */

/* BEGIN MDT CAMPAIGN QUERY LOADER */
(function () {
  function start() {
    if (window.mdtCampaignInitialize) { window.mdtCampaignInitialize(); return; }
    if (!document.querySelector('.mdt-campaign-query') || window.mdtCampaignLoading) return;
    window.mdtCampaignLoading = true;
    var script = document.createElement('script');
    script.src = '/index.php?title=MediaWiki:CampaignQuery.js&action=raw&ctype=text/javascript&v=6';
    script.onerror = function () {
      window.mdtCampaignLoading = false;
      document.querySelectorAll('.mdt-campaign-query').forEach(function (host) {
        var button = document.createElement('button');button.textContent = '重新加载查询工具';button.type = 'button';
        button.onclick = function () { button.remove();start(); };host.appendChild(button);
      });
    };
    document.head.appendChild(script);
  }
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start);else start();
  if (window.mw && mw.hook) mw.hook('wikipage.content').add(start);
}());
/* END MDT CAMPAIGN QUERY LOADER */