PageSourceSearch

https://ypeng12-noname.hf.space/noname/ui/create/menu/pages/exetensionMenu.js

js ypeng12-noname.hf.space collected 2026-10-03 17:36:32 UTC 109,248 bytes, 2,599 lines download raw bytes

1import { menuxpages, createConfig } from "../index.js";
2import "../../../../../noname.js";
3import { delay } from "../../../../util/index.js";
4import "../../../../util/sandbox.js";
5import "../../../../library/element/index.js";
6import { ui } from "../../../index.js";
7import { lib } from "../../../../library/index.js";
8import { game } from "../../../../game/index.js";
9import { get } from "../../../../get/index.js";
10import { security } from "../../../../util/sandbox/security.js";
11import { Character } from "../../../../library/element/character.js";
12import { _status } from "../../../../status/index.js";
13const extensionMenu = function(connectMenu) {
14  if (connectMenu) {
15    return;
16  }
17  const cacheMenuxpages = menuxpages;
18  var start = cacheMenuxpages.shift();
19  var rightPane = start.lastChild;
20  var clickMode = function() {
21    if (this.mode == "get") {
22      this.update();
23    }
24    var active2 = this.parentNode.querySelector(".active");
25    if (active2 === this) {
26      return;
27    }
28    active2.classList.remove("active");
29    active2.link.remove();
30    active2 = this;
31    this.classList.add("active");
32    if (this.link) {
33      rightPane.appendChild(this.link);
34    } else {
35      this._initLink();
36      rightPane.appendChild(this.link);
37    }
38    updateNodes();
39  };
40  ui.click.extensionTab = function(name) {
41    ui.click.menuTab("扩展");
42    for (var i = 0; i < start.firstChild.childElementCount; i++) {
43      if (start.firstChild.childNodes[i].innerHTML == name) {
44        clickMode.call(start.firstChild.childNodes[i]);
45        break;
46      }
47    }
48  };
49  var updateNodes = function() {
50    for (var i = 0; i < start.firstChild.childNodes.length; i++) {
51      var node = start.firstChild.childNodes[i];
52      if (node.mode == "get") {
53        continue;
54      }
55      if (node.mode == "create") {
56        continue;
57      }
58      if (node.mode && node.mode.startsWith("extension_")) {
59        if (lib.config[node.mode + "_enable"]) {
60          node.classList.remove("off");
61          if (node.link) {
62            node.link.firstChild.classList.add("on");
63          }
64        } else {
65          node.classList.add("off");
66          if (node.link) {
67            node.link.firstChild.classList.remove("on");
68          }
69        }
70      } else {
71        if (lib.config.plays.includes(node.mode)) {
72          node.classList.remove("off");
73          if (node.link) {
74            node.link.firstChild.classList.add("on");
75          }
76        } else {
77          node.classList.add("off");
78          if (node.link) {
79            node.link.firstChild.classList.remove("on");
80          }
81        }
82      }
83    }
84  };
85  var togglePack = function(bool) {
86    var name = this._link.config._name;
87    if (name.startsWith("extension_")) {
88      if (bool) {
89        game.saveConfig(name, true);
90      } else {
91        game.saveConfig(name, false);
92      }
93    } else {
94      name = name.slice(0, name.indexOf("_enable_playpackconfig"));
95      if (bool) {
96        lib.config.plays.add(name);
97      } else {
98        lib.config.plays.remove(name);
99      }
100      game.saveConfig("plays", lib.config.plays);
101    }
102    if (this.onswitch) {
103      this.onswitch(bool);
104    }
105    updateNodes();
106  };
107  var createModeConfig = function(mode, position) {
108    var page = ui.create.div("");
109    page.style.paddingBottom = "10px";
110    let node = ui.create.div(".menubutton.large", mode.startsWith("extension_") ? lib.translate[mode] || mode.slice(10) : lib.translate[`${mode}_play_config`], position, clickMode);
111    if (node.innerHTML.length >= 5) {
112      node.classList.add("smallfont");
113    }
114    node.mode = mode;
115    node.link = page;
116    for (var i in lib.extensionMenu[mode]) {
117      if (i == "game") {
118        continue;
119      }
120      var cfg = get.copy(lib.extensionMenu[mode][i]);
121      var j;
122      if (mode.startsWith("extension_")) {
123        j = mode + "_" + i;
124      } else {
125        j = mode + "_" + i + "_playpackconfig";
126      }
127      cfg._name = j;
128      if (j in lib.config) {
129        cfg.init = lib.config[j];
130      } else {
131        game.saveConfig(j, cfg.init);
132      }
133      if (i == "enable") {
134        cfg.onclick = togglePack;
135      } else if (!lib.extensionMenu[mode][i].onclick) {
136        cfg.onclick = function(result) {
137          var cfg2 = this._link.config;
138          game.saveConfig(cfg2._name, result);
139        };
140      }
141      var cfgnode = createConfig(cfg);
142      if (cfg.onswitch) {
143        cfgnode.onswitch = cfg.onswitch;
144      }
145      page.appendChild(cfgnode);
146    }
147    return node;
148  };
149  let extensionsInMenu = Object.keys(lib.extensionMenu);
150  if (lib.config.extensionSort && Array.isArray(lib.config.extensionSort)) {
151    extensionsInMenu.sort((a, b) => {
152      return lib.config.extensionSort.indexOf(a) - lib.config.extensionSort.indexOf(b);
153    });
154  }
155  for (let i of extensionsInMenu) {
156    if (lib.config.all.stockextension.includes(i) && !lib.config.all.plays.includes(i)) {
157      continue;
158    }
159    if (lib.config.hiddenPlayPack.includes(i)) {
160      continue;
161    }
162    createModeConfig(i, start.firstChild);
163  }
164  (function() {
165    if (!lib.device && !lib.db) {
166      return;
167    }
168    if (lib.config.show_extensionmaker == false) {
169      return;
170    }
171    var page = ui.create.div("#create-extension");
172    var node = ui.create.div(".menubutton.large", "制作扩展", start.firstChild, clickMode);
173    node.mode = "create";
174    game.editExtension = function(name) {
175      node._initLink();
176      game.editExtension(name);
177    };
178    node._initLink = function() {
179      node.link = page;
180      var pageboard = ui.create.div(page);
181      var inputExtLine = ui.create.div(pageboard);
182      inputExtLine.style.transition = "all 0s";
183      inputExtLine.style.padding = "10px";
184      inputExtLine.style.height = "22px";
185      inputExtLine.style.lineHeight = "22px";
186      inputExtLine.style.whiteSpace = "nowrap";
187      inputExtLine.style.overflow = "visible";
188      var inputExtSpan = document.createElement("span");
189      inputExtSpan.innerHTML = "扩展名:";
190      inputExtLine.appendChild(inputExtSpan);
191      var inputExtName = document.createElement("input");
192      inputExtName.type = "text";
193      inputExtName.value = "无名扩展";
194      inputExtName.style.width = "80px";
195      inputExtName.style.textAlign = "center";
196      inputExtLine.appendChild(inputExtName);
197      var buttonConfirmOnclick = function() {
198        buttonConfirm.style.display = "none";
199        inputExtSpan.style.display = "none";
200        inputExtName.style.display = "none";
201        authorExtLine.style.display = "none";
202        introExtLine.style.display = "none";
203        forumExtLine.style.display = "none";
204        diskExtLine.style.display = "none";
205        versionExtLine.style.display = "none";
206        okExtLine.style.display = "none";
207        inputExtLine.style.padding = "10px";
208        buttonRename.style.display = "";
209        buttonSave.style.display = "";
210        buttonReset.style.display = "";
211        buttonExport.style.display = "";
212        inputExtSpan.innerHTML = "扩展名称:";
213        inputExtName.style.width = "100px";
214        inputExtName.style.textAlign = "";
215        dashboard.style.display = "";
216      };
217      var createExtLine = function(str, str2) {
218        var infoExtLine = ui.create.div(pageboard);
219        infoExtLine.style.display = "none";
220        infoExtLine.style.padding = "0 10px 10px 10px";
221        infoExtLine.style.height = "22px";
222        infoExtLine.style.lineHeight = "22px";
223        infoExtLine.style.whiteSpace = "nowrap";
224        infoExtLine.style.overflow = "visible";
225        if (typeof str == "boolean") {
226          var inputConfirm = document.createElement("button");
227          inputConfirm.innerHTML = "确定";
228          inputConfirm.onclick = buttonConfirmOnclick;
229          infoExtLine.appendChild(inputConfirm);
230          return infoExtLine;
231        }
232        var infoExtSpan = document.createElement("span");
233        infoExtSpan.innerHTML = str + ":";
234        infoExtLine.appendChild(infoExtSpan);
235        var infoExtName = document.createElement("input");
236        infoExtName.type = "text";
237        infoExtName.style.width = "100px";
238        infoExtName.value = str2 || "";
239        infoExtLine.appendChild(infoExtName);
240        return infoExtLine;
241      };
242      var authorExtLine = createExtLine("扩展作者", get.connectNickname());
243      var introExtLine = createExtLine("扩展描述");
244      var versionExtLine = createExtLine("扩展版本", "1.0");
245      var diskExtLine = createExtLine("网盘地址");
246      var forumExtLine = createExtLine("讨论地址");
247      var okExtLine = createExtLine(true);
248      game.editExtension = function(name) {
249        page.currentExtension = name || "无名扩展";
250        inputExtName.value = page.currentExtension;
251        if (name && lib.extensionPack[name]) {
252          authorExtLine.querySelector("input").value = lib.extensionPack[name].author || "";
253          introExtLine.querySelector("input").value = lib.extensionPack[name].intro || "";
254          diskExtLine.querySelector("input").value = lib.extensionPack[name].diskURL || "";
255          forumExtLine.querySelector("input").value = lib.extensionPack[name].forumURL || "";
256          versionExtLine.querySelector("input").value = lib.extensionPack[name].version || "";
257        } else {
258          authorExtLine.querySelector("input").value = get.connectNickname() || "";
259          introExtLine.querySelector("input").value = "";
260          diskExtLine.querySelector("input").value = "";
261          forumExtLine.querySelector("input").value = "";
262          versionExtLine.querySelector("input").value = "1.0";
263        }
264        if (name) {
265          inputExtName.disabled = true;
266          buttonConfirm.style.display = "none";
267          inputExtSpan.style.display = "none";
268          inputExtName.style.display = "none";
269          buttonRename.style.display = "";
270          buttonSave.style.display = "";
271          buttonReset.style.display = "";
272          buttonExport.style.display = "";
273        } else {
274          inputExtName.disabled = false;
275          buttonConfirm.style.display = "";
276          inputExtSpan.innerHTML = "扩展名:";
277          inputExtName.style.width = "80px";
278          inputExtName.style.textAlign = "center";
279          inputExtSpan.style.display = "";
280          inputExtName.style.display = "";
281          buttonRename.style.display = "none";
282          buttonSave.style.display = "none";
283          buttonReset.style.display = "none";
284          buttonExport.style.display = "none";
285        }
286        dashboard.style.display = "";
287        exportExtLine.style.display = "none";
288        shareExtLine.style.display = "none";
289        authorExtLine.style.display = "none";
290        introExtLine.style.display = "none";
291        forumExtLine.style.display = "none";
292        diskExtLine.style.display = "none";
293        versionExtLine.style.display = "none";
294        okExtLine.style.display = "none";
295        inputExtLine.style.padding = "10px";
296        dash1.reset(name);
297        dash2.reset(name);
298        dash3.reset(name);
299        dash4.reset(name);
300        dash1.link.classList.remove("active");
301        dash2.link.classList.remove("active");
302        dash3.link.classList.remove("active");
303        dash4.link.classList.remove("active");
304        var active2 = node.parentNode.querySelector(".active");
305        if (active2 === node) {
306          return;
307        }
308        active2.classList.remove("active");
309        active2.link.remove();
310        node.classList.add("active");
311        rightPane.appendChild(node.link);
312      };
313      var processExtension = function(exportext) {
314        if (page.currentExtension) {
315          if (page.currentExtension != inputExtName.value && !exportext) {
316            game.removeExtension(page.currentExtension);
317          }
318        }
319        inputExtName.disabled = true;
320        const waitingImage = Promise.allSettled([...dash1.imagePromises || [], ...dash2.imagePromises || []]);
321        const waitDelay = delay(500);
322        Promise.allSettled([waitingImage, waitDelay]).then(() => {
323          var ext = {};
324          for (var i in dash4.content) {
325            try {
326              if (["arenaReady", "content", "prepare", "precontent"].includes(i)) {
327                ext[i] = security.exec2(`return (${dash4.content[i]});`).return;
328                if (typeof ext[i] != "function") {
329                  throw new Error("err");
330                } else {
331                  ext[i] = ext[i].toString();
332                }
333              } else {
334                ext[i] = security.exec2(dash4.content[i])[i];
335                if (ext[i] == null || typeof ext[i] != "object") {
336                  throw new Error("err");
337                } else {
338                  ext[i] = JSON.stringify(ext[i]);
339                }
340              }
341            } catch (e) {
342              console.log(e);
343              delete ext[i];
344            }
345          }
346          page.currentExtension = inputExtName.value || "无名扩展";
347          var str = '{name:"' + page.currentExtension + '",editable:true,connect:false';
348          for (var i in ext) {
349            str += "," + i + ":" + ext[i];
350          }
351          dash2.content.pack.list = [];
352          for (var i = 0; i < dash2.pile.childNodes.length; i++) {
353            dash2.content.pack.list.push(dash2.pile.childNodes[i].link);
354          }
355          str += ",package:" + get.stringify({
356            //替换die audio,加上扩展名
357            //TODO: 创建扩展这部分更是重量级
358            character: ((pack) => {
359              const { character } = pack;
360              for (const [key, info] of Object.entries(character)) {
361                if (Array.isArray(info)) {
362                  const tag = info[4]?.find((tag2) => /^die:.+$/.test(tag2));
363                  if (tag) {
364                    info[4].remove(tag);
365                    const audio = `die:${typeof game.readFile == "function" ? "ext:" : "db:extension-"}${page.currentExtension}/audio/die/${tag.slice(tag.lastIndexOf("/") + 1)}`;
366                    info[4].push(audio);
367                  }
368                } else if (Array.isArray(info.dieAudios)) {
369                  const { dieAudios } = info;
370                  const tag = dieAudios.find((tag2) => /^ext:.+$/.test(tag2));
371                  if (tag) {
372                    dieAudios.remove(tag);
373                    const audio = `${typeof game.readFile == "function" ? "ext:" : "db:extension-"}${page.currentExtension}/audio/die/${tag.slice(tag.lastIndexOf("/") + 1)}`;
374                    dieAudios.push(audio);
375                  }
376                }
377              }
378              return pack;
379            })(dash1.content.pack),
380            card: dash2.content.pack,
381            skill: dash3.content.pack,
382            intro: introExtLine.querySelector("input").value ?? "",
383            author: authorExtLine.querySelector("input").value ?? "",
384            diskURL: diskExtLine.querySelector("input").value ?? "",
385            forumURL: forumExtLine.querySelector("input").value ?? "",
386            version: versionExtLine.querySelector("input").value ?? ""
387          });
388          var files = { character: [], card: [], skill: [], audio: [] };
389          for (const i2 in dash1.content.image) {
390            files.character.push(i2);
391          }
392          for (const i2 in dash1.content.audio) {
393            files.audio.push("audio/die/" + i2);
394          }
395          for (const i2 in dash2.content.image) {
396            files.card.push(i2);
397          }
398          for (const i2 in dash3.content.audio) {
399            files.skill.push(i2);
400          }
401          str += ",files:" + JSON.stringify(files) + "}";
402          const extension = {
403            "extension.js": `import { lib, game, ui, get, ai, _status } from "noname";
404export const type = "extension";
405export default function(){
406	return ${str} 
407};`,
408            "info.json": JSON.stringify({
409              name: page.currentExtension,
410              intro: introExtLine.querySelector("input").value ?? "",
411              author: authorExtLine.querySelector("input").value ?? "",
412              diskURL: diskExtLine.querySelector("input").value ?? "",
413              forumURL: forumExtLine.querySelector("input").value ?? "",
414              version: versionExtLine.querySelector("input").value ?? ""
415            }),
416            "README.md": ""
417          };
418          for (const id in dash1.content.image) {
419            extension[id] = dash1.content.image[id];
420          }
421          for (const id in dash1.content.audio) {
422            extension["audio/die/" + id] = dash1.content.audio[id];
423          }
424          for (const id in dash2.content.image) {
425            extension[id] = dash2.content.image[id];
426          }
427          if (exportext) {
428            game.importExtension(
429              extension,
430              null,
431              page.currentExtension
432              /* {
433              	intro: introExtLine.querySelector("input").value || "",
434              	author: authorExtLine.querySelector("input").value || "",
435              	netdisk: diskExtLine.querySelector("input").value || "",
436              	forum: forumExtLine.querySelector("input").value || "",
437              	version: versionExtLine.querySelector("input").value || "",
438              } */
439            );
440          } else {
441            game.importExtension(extension, function() {
442              exportExtLine.style.display = "";
443            });
444          }
445        });
446      };
447      var buttonConfirm = document.createElement("button");
448      buttonConfirm.innerHTML = "确定";
449      buttonConfirm.style.marginLeft = "5px";
450      buttonConfirm.onclick = buttonConfirmOnclick;
451      inputExtLine.appendChild(buttonConfirm);
452      var buttonRename = document.createElement("button");
453      buttonRename.innerHTML = "选项";
454      buttonRename.style.marginLeft = "2px";
455      buttonRename.style.marginRight = "2px";
456      buttonRename.style.display = "none";
457      buttonRename.onclick = function() {
458        inputExtSpan.style.display = "";
459        inputExtName.style.display = "";
460        authorExtLine.style.display = "";
461        introExtLine.style.display = "";
462        forumExtLine.style.display = "";
463        diskExtLine.style.display = "";
464        versionExtLine.style.display = "";
465        okExtLine.style.display = "block";
466        inputExtLine.style.padding = "20px 10px 10px 10px";
467        inputExtName.disabled = false;
468        buttonRename.style.display = "none";
469        buttonSave.style.display = "none";
470        buttonReset.style.display = "none";
471        buttonExport.style.display = "none";
472        inputExtSpan.innerHTML = "扩展名称:";
473        inputExtName.style.width = "100px";
474        inputExtName.style.textAlign = "";
475        dashboard.style.display = "none";
476      };
477      inputExtLine.appendChild(buttonRename);
478      var buttonReset = document.createElement("button");
479      buttonReset.innerHTML = "重置";
480      buttonReset.style.marginLeft = "2px";
481      buttonReset.style.marginRight = "2px";
482      buttonReset.style.display = "none";
483      buttonReset.onclick = function() {
484        if (confirm("当前扩展将被清除,是否确定?")) {
485          game.editExtension();
486        }
487      };
488      inputExtLine.appendChild(buttonReset);
489      var buttonSave = document.createElement("button");
490      buttonSave.innerHTML = "保存";
491      buttonSave.style.marginLeft = "2px";
492      buttonSave.style.marginRight = "2px";
493      buttonSave.style.display = "none";
494      buttonSave.onclick = function() {
495        dash1.link.classList.remove("active");
496        dash2.link.classList.remove("active");
497        dash3.link.classList.remove("active");
498        dash4.link.classList.remove("active");
499        processExtension();
500      };
501      inputExtLine.appendChild(buttonSave);
502      var buttonExport = document.createElement("button");
503      buttonExport.innerHTML = "导出";
504      buttonExport.style.marginLeft = "2px";
505      buttonExport.style.marginRight = "2px";
506      buttonExport.style.display = "none";
507      buttonExport.onclick = function() {
508        function oldExport() {
509          processExtension(true);
510          if (lib.config.show_extensionshare) {
511            shareExtLine.style.display = "";
512          }
513        }
514        if (typeof game.readFile == "function" && window.noname_shijianInterfaces && typeof window.noname_shijianInterfaces.shareExtensionWithPassWordAsync == "function" && confirm("是否使用诗笺版自带的导出功能来导出扩展?")) {
515          const extName = inputExtName.value;
516          if (!extName) {
517            alert("未检测到扩展名,将使用无名杀自带的导出功能");
518            oldExport();
519            return;
520          }
521          game.readFile(
522            `extension/${extName}/extension.js`,
523            () => {
524              const pwd = prompt("请输入压缩包密码,不设密码直接点确定");
525              let result;
526              if (pwd === "" || pwd === null) {
527                window.noname_shijianInterfaces.shareExtensionAsync(extName);
528              } else {
529                window.noname_shijianInterfaces.shareExtensionWithPassWordAsync(extName, pwd);
530              }
531            },
532            () => {
533              alert("未检测到扩展文件,将使用无名杀自带的导出功能");
534              oldExport();
535            }
536          );
537        } else {
538          oldExport();
539        }
540      };
541      inputExtLine.appendChild(buttonExport);
542      var exportExtLine = ui.create.div(pageboard);
543      exportExtLine.style.display = "none";
544      exportExtLine.style.width = "calc(100% - 40px)";
545      exportExtLine.style.textAlign = "left";
546      exportExtLine.style.marginBottom = "5px";
547      if (lib.device == "ios") {
548        exportExtLine.innerHTML = '已保存。退出游戏并重新打开后生效<span class="closenode">×</span>';
549        exportExtLine.querySelectorAll("span")[0].onclick = function() {
550          exportExtLine.style.display = "none";
551        };
552      } else {
553        exportExtLine.innerHTML = '重启后生效。<span class="hrefnode">立即重启</span><span class="closenode">×</span>';
554        exportExtLine.querySelectorAll("span")[0].onclick = game.reload;
555        exportExtLine.querySelectorAll("span")[1].onclick = function() {
556          exportExtLine.style.display = "none";
557        };
558      }
559      var shareExtLine = ui.create.div(pageboard);
560      shareExtLine.style.display = "none";
561      shareExtLine.style.width = "calc(100% - 40px)";
562      shareExtLine.style.textAlign = "left";
563      shareExtLine.style.marginBottom = "5px";
564      shareExtLine.innerHTML = '已导出扩展。<span class="hrefnode">分享扩展</span><span class="closenode">×</span>';
565      shareExtLine.querySelectorAll("span")[0].onclick = function() {
566        game.open("https://tieba.baidu.com/f?ie=utf-8&kw=%E6%97%A0%E5%90%8D%E6%9D%80");
567      };
568      shareExtLine.querySelectorAll("span")[1].onclick = function() {
569        shareExtLine.style.display = "none";
570      };
571      var dashboard = ui.create.div(pageboard);
572      var clickDash = function() {
573        ui.create.templayer();
574        pageboard.hide();
575        this.link.show();
576        if (this.link.init) {
577          this.link.init();
578        }
579      };
580      var createDash = function(str1, str2, node2) {
581        var dash = ui.create.div(".menubutton.large.dashboard");
582        dashboard.appendChild(dash);
583        page.appendChild(node2);
584        dash.link = node2;
585        node2.link = dash;
586        dash.listen(clickDash);
587        lib.setScroll(node2);
588        ui.create.div("", str1, dash);
589        ui.create.div("", str2, dash);
590      };
591      var dash1 = (function() {
592        var page2 = ui.create.div(".hidden.menu-buttons");
593        var currentButton = null;
594        page2.init = function() {
595          if (!page2.querySelector(".button.character")) {
596            toggle.classList.add("on");
597            newCharacter.style.display = "";
598          }
599        };
600        var updateButton = function() {
601          var name = page2.querySelector("input.new_name").value;
602          if (!name) {
603            editnode.classList.add("disabled");
604            return;
605          }
606          name = name.split("|");
607          name = name[0];
608          if (currentButton) {
609            if (currentButton.link != name) {
610              if (lib.character[name] || page2.content.pack.character[name]) {
611                editnode.classList.add("disabled");
612                return;
613              }
614            }
615          } else {
616            if (lib.character[name] || page2.content.pack.character[name]) {
617              editnode.classList.add("disabled");
618              return;
619            }
620          }
621          if (!fakeme.image) {
622            if (!page2.content.image[name + ".jpg"]) {
623              editnode.classList.add("disabled");
624              return;
625            }
626          }
627          editnode.classList.remove("disabled");
628        };
629        var clickButton = async function() {
630          if (currentButton == this) {
631            resetEditor();
632            return;
633          }
634          resetEditor();
635          currentButton = this;
636          toggle.classList.add("on");
637          newCharacter.style.display = "";
638          fakeme.classList.add("inited");
639          fakeme.style.backgroundImage = this.style.backgroundImage;
640          if (page2.content.pack.translate[this.link] != this.link) {
641            newCharacter.querySelector(".new_name").value = this.link + "|" + page2.content.pack.translate[this.link];
642          } else {
643            newCharacter.querySelector(".new_name").value = this.link;
644          }
645          var info = page2.content.pack.character[this.link];
646          newCharacter.querySelector(".new_hp").value = get.character(this.link, 2);
647          sexes.value = get.character(this.link, 0);
648          groups.value = get.character(this.link, 1);
649          if (Array.isArray(info[4])) {
650            for (var i2 = 0; i2 < options.childNodes.length - 1; i2++) {
651              const option = options.childNodes[i2].lastChild;
652              if (info[4].includes(option?.name)) {
653                option.checked = true;
654              } else if (option) {
655                option.checked = false;
656              }
657            }
658            for (var i2 = 0; i2 < info[4].length; i2++) {
659              if (info[4][i2].startsWith("des:")) {
660                newCharacter.querySelector(".new_des").value = info[4][i2].slice(4);
661              }
662              if (info[4][i2].startsWith("die:")) {
663                var dieaudionode = newCharacter.querySelector(".die_audio");
664                dieaudionode.file = {
665                  name: info[4][i2].slice(info[4][i2].lastIndexOf("/") + 1)
666                };
667                await new Promise((resolve) => {
668                  if (typeof game.readFile == "function") {
669                    game.readFile(
670                      info[4][i2].slice(4).replace("ext:", "extension/"),
671                      (arraybuffer) => {
672                        dieaudionode.arrayBuffer = arraybuffer;
673                        resolve();
674                      },
675                      () => {
676                        console.warn(`未找到${info[4][i2].slice(4).replace("ext:", "extension/")}阵亡配音`);
677                        resolve();
678                      }
679                    );
680                  } else {
681                    game.getDB("image", info[4][i2].slice(7)).then(
682                      (octetStream) => {
683                        dieaudionode.arrayBuffer = octetStream;
684                        resolve();
685                      },
686                      () => {
687                        console.warn(`未找到${info[4][i2].slice(4)}阵亡配音`);
688                        resolve();
689                      }
690                    );
691                  }
692                });
693              }
694            }
695          } else {
696            const optionMap = /* @__PURE__ */ new Map([
697              ["zhu", "isZhugong"],
698              ["boss", "isBoss"],
699              ["forbidai", "isAiForbidden"],
700              ["hiddenSkill", "hasHiddenSkill"]
701            ]);
702            for (var i2 = 0; i2 < options.childNodes.length - 1; i2++) {
703              const option = options.childNodes[i2].lastChild;
704              if (optionMap.has(option?.name) && info[optionMap.get(option.name)]) {
705                option.checked = true;
706              } else if (option) {
707                option.checked = false;
708              }
709            }
710            const description = info.trashBin?.find((item) => item.startsWith("des:"));
711            if (description) {
712              newCharacter.querySelector(".new_des").value = description.slice(4);
713            }
714            const dieAudios = info.dieAudios || [];
715            for (var i2 = 0; i2 < dieAudios.length; i2++) {
716              var dieaudionode = newCharacter.querySelector(".die_audio");
717              dieaudionode.file = {
718                name: dieAudios[i2].slice(dieAudios[i2].lastIndexOf("/") + 1)
719              };
720              await new Promise((resolve) => {
721                if (typeof game.readFile == "function") {
722                  game.readFile(
723                    dieAudios[i2].replace("ext:", "extension/"),
724                    (arraybuffer) => {
725                      dieaudionode.arrayBuffer = arraybuffer;
726                      resolve();
727                    },
728                    () => {
729                      console.warn(`未找到${dieAudios[i2].replace("ext:", "extension/")}阵亡配音`);
730                      resolve();
731                    }
732                  );
733                } else {
734                  game.getDB("image", dieAudios[i2].slice(3)).then(
735                    (octetStream) => {
736                      dieaudionode.arrayBuffer = octetStream;
737                      resolve();
738                    },
739                    () => {
740                      console.warn(`未找到${dieAudios[i2]}阵亡配音`);
741                      resolve();
742                    }
743                  );
744                }
745              });
746            }
747          }
748          var skills2 = get.character(this.link, 3);
749          for (var i2 = 0; i2 < skills2.length; i2++) {
750            var node2 = document.createElement("button");
751            node2.skill = skills2[i2];
752            node2.onclick = deletenode;
753            node2.innerHTML = lib.translate[skills2[i2]];
754            skillList.firstChild.appendChild(node2);
755          }
756          toggle.innerHTML = "编辑武将 <div>&gt;</div>";
757          editnode.innerHTML = "编辑武将";
758          editnode.classList.remove("disabled");
759          delnode.innerHTML = "删除";
760          delnode.button = this;
761        };
762        var createButton = function(name, image) {
763          var button = ui.create.div(".button.character");
764          button.link = name;
765          button.image = image;
766          button.setBackground(name, "character");
767          button.style.backgroundSize = "cover";
768          button.listen(clickButton);
769          button.classList.add("noclick");
770          button.nodename = ui.create.div(button, ".name", get.verticalStr(page2.content.pack.translate[name]));
771          button.nodename.style.top = "8px";
772          page2.insertBefore(button, page2.childNodes[1]);
773        };
774        page2.reset = function(name) {
775          resetEditor();
776          if (page2.imagePromises == null) {
777            page2.imagePromises = [];
778          } else {
779            page2.imagePromises.length = 0;
780          }
781          var buttons = page2.querySelectorAll(".button.character");
782          var list3 = [];
783          for (var i2 = 0; i2 < buttons.length; i2++) {
784            list3.push(buttons[i2]);
785          }
786          for (var i2 = 0; i2 < list3.length; i2++) {
787            list3[i2].remove();
788          }
789          if (lib.extensionPack[name]) {
790            page2.content.pack = lib.extensionPack[name].character || {
791              character: {},
792              translate: {}
793            };
794            page2.content.image = {};
795            for (const id in page2.content.pack.character) {
796              const file = id + ".jpg";
797              const url = lib.assetURL + "extension/" + name + "/" + file;
798              createButton(id, url);
799              page2.imagePromises.push(
800                game.promises.readFile(url).then((result) => {
801                  page2.content.image[file] = result;
802                }).catch((e) => console.error(e))
803              );
804            }
805          } else {
806            page2.content = {
807              pack: {
808                character: {},
809                translate: {}
810              },
811              image: {},
812              audio: {}
813            };
814            toggle.classList.add("on");
815            newCharacter.style.display = "";
816          }
817        };
818        ui.create.div(".config.more", '<div style="transform:none;margin-right:3px">←</div>返回', page2, function() {
819          ui.create.templayer();
820          page2.hide();
821          pageboard.show();
822        });
823        page2.content = {
824          pack: {
825            character: {},
826            translate: {}
827          },
828          image: {},
829          audio: {}
830        };
831        var newCharacter;
832        var toggle = ui.create.div(".config.more.on", "创建武将 <div>&gt;</div>", page2, function() {
833          this.classList.toggle("on");
834          if (this.classList.contains("on")) {
835            newCharacter.style.display = "";
836          } else {
837            newCharacter.style.display = "none";
838          }
839        });
840        var resetEditor = function() {
841          currentButton = null;
842          toggle.classList.remove("on");
843          newCharacter.style.display = "none";
844          fakeme.classList.remove("inited");
845          delete fakeme.image;
846          delete fakeme.image64;
847          fakeme.style.backgroundImage = "";
848          var inputs = newCharacter.querySelectorAll("input");
849          for (var i2 = 0;
849 i2 < inputs.length; i2++) {
850            inputs[i2].value = "";
851          }
852          inputs = newCharacter.querySelectorAll("textarea");
853          for (var i2 = 0; i2 < inputs.length; i2++) {
854            inputs[i2].value = "";
855          }
856          skillList.firstChild.innerHTML = "";
857          toggle.innerHTML = "创建武将 <div>&gt;</div>";
858          editnode.innerHTML = "创建武将";
859          editnode.classList.add("disabled");
860          delnode.innerHTML = "取消";
861          delete delnode.button;
862        };
863        newCharacter = ui.create.div(".new_character", page2);
864        var fakeme = ui.create.div(".avatar", newCharacter);
865        var input = document.createElement("input");
866        input.type = "file";
867        input.accept = "image/*";
868        input.className = "fileinput";
869        input.onchange = function() {
870          var fileToLoad = input.files[0];
871          if (fileToLoad) {
872            var fileReader = new FileReader();
873            fileReader.onload = function(fileLoadedEvent) {
874              var data = fileLoadedEvent.target.result;
875              fakeme.style.backgroundImage = "url(" + data + ")";
876              fakeme.image64 = data;
877              fakeme.classList.add("inited");
878              var fileReader2 = new FileReader();
879              fileReader2.onload = function(fileLoadedEvent2) {
880                fakeme.image = fileLoadedEvent2.target.result;
881                updateButton();
882              };
883              fileReader2.readAsArrayBuffer(fileToLoad, "UTF-8");
884            };
885            fileReader.readAsDataURL(fileToLoad, "UTF-8");
886          }
887        };
888        fakeme.appendChild(input);
889        ui.create.div(".select_avatar", "选择头像", fakeme);
890        ui.create.div(".indent", '姓名:<input class="new_name" type="text">', newCharacter).style.paddingTop = "8px";
891        ui.create.div(".indent", '介绍:<input class="new_des" type="text">', newCharacter).style.paddingTop = "8px";
892        ui.create.div(".indent", '体力:<input class="new_hp" type="text" placeholder="体/限/甲">', newCharacter).style.paddingTop = "8px";
893        newCharacter.querySelector("input.new_name").onblur = updateButton;
894        var sexes = ui.create.selectlist(
895          [
896            ["male", "男"],
897            ["female", "女"],
898            ["double", "双性"],
899            ["none", "无"]
900          ],
901          null,
902          ui.create.div(".indent", "性别:", newCharacter)
903        );
904        var grouplist = lib.group.map((group, i2) => [lib.group[i2], get.translation(lib.group[i2])]);
905        var groups = ui.create.selectlist(grouplist, null, ui.create.div(".indent", "势力:", newCharacter));
906        var dieaudio = ui.create.div(".die_audio", newCharacter, { textAlign: "left" });
907        var dieaudiolabel = ui.create.node("label", "阵亡配音:", dieaudio);
908        var dieaudioUpload = dieaudio.appendChild(document.createElement("input"));
909        dieaudioUpload.type = "file";
910        dieaudioUpload.accept = "audio/*";
911        dieaudioUpload.style.width = "calc(100% - 100px)";
912        dieaudioUpload.onchange = function() {
913          var fileToLoad = dieaudioUpload.files[0];
914          if (fileToLoad) {
915            console.log(fileToLoad);
916            var fileReader = new FileReader();
917            fileReader.onload = function(fileLoadedEvent) {
918              var data = fileLoadedEvent.target.result;
919              var blob = new Blob([data]);
920              dieaudio.file = fileToLoad;
921              dieaudio.arrayBuffer = data;
922              dieaudio.blob = blob;
923              var new_name = newCharacter.querySelector("input.new_name");
924              dieaudioUpload.style.display = "none";
925              dieaudiopreview.style.display = dieaudiocancel.style.display = "";
926              dieaudiotag.src = window.URL.createObjectURL(blob);
927            };
928            fileReader.readAsArrayBuffer(fileToLoad);
929          }
930        };
931        var dieaudiotag = ui.create.node("audio", dieaudio);
932        var dieaudiopreview = ui.create.node("button", dieaudio, () => {
933          if (dieaudiotag.error) {
934            alert("您使用的客户端不支持预览此音频!");
935          } else {
936            dieaudiotag.play();
937          }
938        });
939        dieaudiopreview.innerHTML = "播放";
940        dieaudiopreview.style.display = "none";
941        var dieaudiocancel = ui.create.node("button", dieaudio, () => {
942          dieaudiopreview.style.display = "none";
943          dieaudiocancel.style.display = "none";
944          if (dieaudio.blob) {
945            window.URL.revokeObjectURL(dieaudio.blob);
946            dieaudiotag.src = null;
947            delete dieaudio.file;
948            delete dieaudio.arrayBuffer;
949            delete dieaudio.blob;
950          }
951          dieaudioUpload.value = "";
952          dieaudioUpload.style.display = "";
953        });
954        dieaudiocancel.innerHTML = "取消";
955        dieaudiocancel.style.display = "none";
956        var options = ui.create.div(".add_skill.options", '<span>主公<input type="checkbox" name="zhu"></span><span>BOSS<input type="checkbox" name="boss"></span><span>仅点将可用<input type="checkbox" name="forbidai"></span><br><span>隐匿技<input type="checkbox" name="hiddenSkill"></span><br>', newCharacter);
957        var addSkill = ui.create.div(".add_skill", "添加技能<br>", newCharacter);
958        var list = [];
959        for (var i in lib.character) {
960          if (lib.character[i][3].length) {
961            list.push([i, lib.translate[i]]);
962          }
963        }
964        if (!list.length) {
965          if (!lib.character["noname_sunce"]) {
966            lib.character["noname_sunce"] = new Character({
967              sex: "male",
968              group: "wu",
969              hp: 4,
970              skills: ["jiang"],
971              isUnseen: true
972            });
973          }
974          if (!lib.translate["noname_sunce"]) {
975            lib.translate["noname_sunce"] = "孙策";
976          }
977          list.push(["noname_sunce", lib.translate["noname_sunce"]]);
978        }
979        list.sort(function(a, b) {
980          a = a[0];
981          b = b[0];
982          var aa = a, bb = b;
983          if (aa.includes("_")) {
984            aa = aa.slice(aa.lastIndexOf("_") + 1);
985          }
986          if (bb.includes("_")) {
987            bb = bb.slice(bb.lastIndexOf("_") + 1);
988          }
989          if (aa != bb) {
990            return aa > bb ? 1 : -1;
991          }
992          return a > b ? 1 : -1;
993        });
994        var list2 = [];
995        var skills = lib.character[list[0][0]].skills.slice();
996        for (const skill of skills) {
997          if (lib.skill[skill]?.derivation) {
998            const derivation = lib.skill[skill]?.derivation;
999            skills[Array.isArray(derivation) ? "addArray" : "add"](derivation);
1000          }
1001        }
1002        for (var i = 0; i < skills.length; i++) {
1003          if (lib.skill[skills[i]] && !lib.skill[skills[i]].sub && lib.translate[skills[i]]) {
1004            list2.push([skills[i], lib.translate[skills[i]]]);
1005          }
1006        }
1007        list.unshift(["current_extension", "此扩展"]);
1008        var selectname = ui.create.selectlist(list, list[1], addSkill);
1009        page2.selectname = selectname;
1010        selectname.onchange = function() {
1011          skillopt.innerHTML = "";
1012          if (this.value == "current_extension") {
1013            for (var i2 in dash3.content.pack.skill) {
1014              var option = document.createElement("option");
1015              option.value = i2;
1016              option.innerHTML = dash3.content.pack.translate[i2];
1017              skillopt.appendChild(option);
1018            }
1019          } else {
1020            var skills2 = lib.character[this.value].skills.slice();
1021            for (const skill of skills2) {
1022              if (lib.skill[skill]?.derivation) {
1023                const derivation = lib.skill[skill]?.derivation;
1024                skills2[Array.isArray(derivation) ? "addArray" : "add"](derivation);
1025              }
1026            }
1027            for (var i2 = 0; i2 < skills2.length; i2++) {
1028              if (lib.skill[skills2[i2]] && !lib.skill[skills2[i2]].sub && lib.translate[skills2[i2]]) {
1029                var option = document.createElement("option");
1030                option.value = skills2[i2];
1031                option.innerHTML = lib.translate[skills2[i2]];
1032                skillopt.appendChild(option);
1033              }
1034            }
1035          }
1036        };
1037        selectname.style.maxWidth = "85px";
1038        var skillopt = ui.create.selectlist(list2, list2[0], addSkill);
1039        skillopt.style.maxWidth = "60px";
1040        page2.skillopt = skillopt;
1041        var addSkillButton = document.createElement("button");
1042        addSkillButton.innerHTML = "添加";
1043        addSkill.appendChild(addSkillButton);
1044        page2.addSkillButton = addSkillButton;
1045        var deletenode = function() {
1046          this.remove();
1047        };
1048        addSkillButton.onclick = function() {
1049          for (var i2 = 0; i2 < skillList.firstChild.childNodes.length; i2++) {
1050            if (skillList.firstChild.childNodes[i2].skill == skillopt.value) {
1051              return alert(selectname.value == "current_extension" ? "此扩展还未添加技能" : "此武将没有技能可添加");
1052            }
1053          }
1054          if (!skillopt.value || skillopt.childElementCount == 0) {
1055            return;
1056          }
1057          var node2 = document.createElement("button");
1058          node2.skill = skillopt.value;
1059          node2.onclick = deletenode;
1060          for (var i2 = 0; i2 < skillopt.childElementCount; i2++) {
1061            if (skillopt.childNodes[i2].value == skillopt.value) {
1062              node2.innerHTML = skillopt.childNodes[i2].innerHTML;
1063              break;
1064            }
1065          }
1066          skillList.firstChild.appendChild(node2);
1067        };
1068        var createSkillButton = document.createElement("button");
1069        createSkillButton.innerHTML = "创建";
1070        createSkillButton.style.marginLeft = "3px";
1071        addSkill.appendChild(createSkillButton);
1072        createSkillButton.onclick = function() {
1073          ui.create.templayer();
1074          page2.hide();
1075          dash3.show();
1076          dash3.fromchar = "add";
1077          dash3.toggle.classList.add("on");
1078          dash3.newSkill.style.display = "";
1079        };
1080        page2.updateSkill = function() {
1081          for (var i2 = 0; i2 < skillList.firstChild.childNodes.length; i2++) {
1082            var node2 = skillList.firstChild.childNodes[i2];
1083            var skill = skillList.firstChild.childNodes[i2].skill;
1084            if (dash3.content.pack.skill[skill]) {
1085              node2.innerHTML = dash3.content.pack.translate[skill];
1086            } else if (lib.skill[skill]) {
1087              node2.innerHTML = lib.translate[skill];
1088            } else {
1089              node2.remove();
1090              i2--;
1091            }
1092          }
1093        };
1094        var skillList = ui.create.div(".skill_list", newCharacter);
1095        ui.create.div(skillList);
1096        var editnode = ui.create.div(".menubutton.large.disabled", "创建武将", ui.create.div(skillList), function() {
1097          let name = page2.querySelector("input.new_name").value;
1098          if (!name) {
1099            alert("请填写武将名\n提示:武将名格式为id+|+中文名,其中id必须惟一");
1100            return;
1101          }
1102          name = name.split("|");
1103          let translate = name[1] || name[0];
1104          name = name[0];
1105          if (currentButton) {
1106            if (currentButton.link != name) {
1107              if (lib.character[name] || page2.content.pack.character[name]) {
1108                alert("武将名与现有武将重复,请更改\n提示:武将名格式为id+|+中文名,其中id必须惟一");
1109                return;
1110              }
1111              page2.content.image[name + ".jpg"] = page2.content.image[currentButton.link + ".jpg"];
1112              delete page2.content.image[currentButton.link + ".jpg"];
1113              delete page2.content.pack.character[currentButton.link];
1114              delete page2.content.pack.translate[currentButton.link];
1115              currentButton.link = name;
1116            }
1117          } else {
1118            if (lib.character[name] || page2.content.pack.character[name]) {
1119              alert("武将名与现有武将重复,请更改\n提示:武将名格式为id+|+中文名,其中id必须惟一");
1120              return;
1121            }
1122          }
1123          if (fakeme.image) {
1124            page2.content.image[name + ".jpg"] = fakeme.image;
1125          } else {
1126            if (!page2.content.image[name + ".jpg"]) {
1127              alert("请选择武将头像");
1128              return;
1129            }
1130          }
1131          let hp = page2.querySelector("input.new_hp").value;
1132          if (["Infinity", "∞", "无限"].includes(hp)) {
1133            hp = Infinity;
1134          } else if (hp.indexOf("/") == -1) {
1135            hp = parseInt(hp) || 1;
1136          }
1137          const skills2 = Array.from(skillList.firstChild.childNodes).map((item) => item.skill);
1138          const oldCharacter = page2.content.pack.character[name] || {};
1139          const bool = !Array.isArray(oldCharacter);
1140          const newCharacter2 = {
1141            sex: sexes.value,
1142            group: groups.value,
1143            hp: get.infoHp(hp),
1144            maxHp: get.infoMaxHp(hp),
1145            hujia: get.infoHujia(hp),
1146            skills: skills2
1147          };
1148          const tags = Array.from(options.childNodes).slice(0, -1).reduce((list3, node2) => {
1149            const child = node2.lastChild;
1150            if (child?.checked) {
1151              list3.push(child.name);
1152            }
1153            return list3;
1154          }, []);
1155          const des = page2.querySelector("input.new_des").value;
1156          if (des) {
1157            tags.add(`des:${des}`);
1158            if (bool) {
1159              oldCharacter.trashBin ??= [];
1160              oldCharacter.trashBin = oldCharacter.trashBin.filter((tag) => !tag.startsWith("des:"));
1161              oldCharacter.trashBin.add(`des:${des}`);
1162            }
1163          } else if (bool && Array.isArray(oldCharacter.trashBin)) {
1164            oldCharacter.trashBin = oldCharacter.trashBin.filter((tag) => !tag.startsWith("des:"));
1165            if (!oldCharacter.trashBin.length) {
1166              delete oldCharacter.trashBin;
1167            }
1168          }
1169          if (tags.includes("zhu")) {
1170            newCharacter2.isZhugong = true;
1171          } else if (bool && "isZhugong" in oldCharacter) {
1172            delete oldCharacter.isZhugong;
1173          }
1174          if (tags.includes("boss")) {
1175            tags.add("bossallowed");
1176            newCharacter2.isBoss = true;
1177            newCharacter2.isBossAllowed = true;
1178          } else if (bool) {
1179            if ("isBoss" in oldCharacter) {
1180              delete oldCharacter.isBoss;
1181            }
1182            if ("isBossAllowed" in oldCharacter) {
1183              delete oldCharacter.isBossAllowed;
1184            }
1185          }
1186          if (tags.includes("forbidai")) {
1187            newCharacter2.isAiForbidden = true;
1188          } else if (bool && "isAiForbidden" in oldCharacter) {
1189            delete oldCharacter.isAiForbidden;
1190          }
1191          if (tags.includes("hiddenSkill")) {
1192            newCharacter2.hasHiddenSkill = true;
1193          } else if (bool && "hasHiddenSkill" in oldCharacter) {
1194            delete oldCharacter.hasHiddenSkill;
1195          }
1196          if (dieaudio.file && dieaudio.arrayBuffer) {
1197            var audioname = name + dieaudio.file.name.slice(dieaudio.file.name.indexOf("."));
1198            const dieAudio = `${typeof game.readFile == "function" ? "ext" : "db"}:audio/die/${audioname}`;
1199            tags.add(`die:${dieAudio}`);
1200            newCharacter2.dieAudios = [];
1201            newCharacter2.dieAudios.add(dieAudio);
1202            page2.content.audio[audioname] = dieaudio.arrayBuffer;
1203          } else if (bool && Array.isArray(oldCharacter.dieAudios)) {
1204            delete oldCharacter.dieAudios;
1205          }
1206          page2.content.pack.translate[name] = translate;
1207          if (!page2.content.pack.character[name]) {
1208            page2.content.pack.character[name] = newCharacter2;
1209          } else if (Array.isArray(page2.content.pack.character[name])) {
1210            page2.content.pack.character[name] = [sexes.value, groups.value, hp, skills2, tags];
1211          } else {
1212            Object.assign(page2.content.pack.character[name], newCharacter2);
1213          }
1214          if (this.innerHTML == "创建武将") {
1215            createButton(name, fakeme.image64);
1216          } else if (currentButton) {
1217            if (fakeme.image64) {
1218              currentButton.image = fakeme.image64;
1219              currentButton.style.backgroundImage = "url(" + fakeme.image64 + ")";
1220            }
1221            currentButton.nodename.innerHTML = get.verticalStr(translate);
1222          }
1223          resetEditor();
1224          dash1.link.classList.add("active");
1225        });
1226        var delnode = ui.create.div(".menubutton.large", "取消", editnode.parentNode, function() {
1227          if (this.innerHTML == "删除") {
1228            this.button.remove();
1229            var name = this.button.link;
1230            delete dash1.content.pack.character[name];
1231            delete dash1.content.pack.translate[name];
1232            delete dash1.content.image[name];
1233            delete dash1.content.audio[name];
1234            dash1.link.classList.add("active");
1235          }
1236          resetEditor();
1237        });
1238        delnode.style.marginLeft = "13px";
1239        return page2;
1240      })();
1241      var dash2 = (function() {
1242        var page2 = ui.create.div(".hidden.menu-buttons");
1243        var currentButton = null;
1244        page2.init = function() {
1245          if (!page2.querySelector(".button.card")) {
1246            toggle.classList.add("on");
1247            newCard.style.display = "";
1248          }
1249        };
1250        var updateButton = function() {
1251          var name = page2.querySelector("input.new_name").value;
1252          if (!name) {
1253            editnode.classList.add("disabled");
1254            return;
1255          }
1256          name = name.split("|");
1257          name = name[0];
1258          if (currentButton) {
1259            if (currentButton.link != name) {
1260              if (lib.card[name] || page2.content.pack.card[name]) {
1261                editnode.classList.add("disabled");
1262                return;
1263              }
1264            }
1265          } else {
1266            if (lib.card[name] || page2.content.pack.card[name]) {
1267              editnode.classList.add("disabled");
1268              return;
1269            }
1270          }
1271          if (!fakeme.image && !fakeme.classList.contains("inited")) {
1272            editnode.classList.add("disabled");
1273            return;
1274          }
1275          editnode.classList.remove("disabled");
1276        };
1277        var clickButton = function() {
1278          if (currentButton == this) {
1279            resetEditor();
1280            return;
1281          }
1282          resetEditor();
1283          currentButton = this;
1284          toggle.classList.add("on");
1285          newCard.style.display = "";
1286          fakeme.classList.add("inited");
1287          delete fakeme.image;
1288          delete fakeme.image64;
1289          if (this.classList.contains("fullskin")) {
1290            fakeme.imagenode.style.backgroundImage = this.imagenode.style.backgroundImage;
1291            fakeme.classList.add("fullskin");
1292          } else {
1293            fakeme.style.backgroundImage = this.style.backgroundImage;
1294            fakeme.classList.remove("fullskin");
1295          }
1296          if (page2.content.pack.translate[this.link] != this.link) {
1297            newCard.querySelector(".new_name").value = this.link + "|" + page2.content.pack.translate[this.link];
1298          } else {
1299            newCard.querySelector(".new_name").value = this.link;
1300          }
1301          newCard.querySelector(".new_description").value = page2.content.pack.translate[this.link + "_info"];
1302          var info = page2.content.pack.card[this.link];
1303          code = "card=" + get.stringify(info);
1304          toggle.innerHTML = "编辑卡牌 <div>&gt;</div>";
1305          editnode.innerHTML = "编辑卡牌";
1306          editnode.classList.remove("disabled");
1307          delnode.innerHTML = "删除";
1308          delnode.button = this;
1309        };
1310        var createButton = function(name, image, fullskin) {
1311          var button2 = ui.create.div(".button.card");
1312          button2.link = name;
1313          button2.image = image;
1314          button2.imagenode = ui.create.div(".image", button2);
1315          if (image) {
1316            if (fullskin) {
1317              button2.imagenode.style.backgroundImage = "url(" + image 
1317+ ")";
1318              button2.style.backgroundImage = "";
1319              button2.style.backgroundSize = "";
1320              button2.classList.add("fullskin");
1321            } else {
1322              button2.style.color = "white";
1323              button2.style.textShadow = "black 0 0 2px";
1324              button2.imagenode.style.backgroundImage = "";
1325              button2.style.backgroundImage = "url(" + image + ")";
1326              button2.style.backgroundSize = "cover";
1327            }
1328          }
1329          button2.listen(clickButton);
1330          button2.classList.add("noclick");
1331          button2.nodename = ui.create.div(button2, ".name", get.verticalStr(page2.content.pack.translate[name]));
1332          page2.insertBefore(button2, page2.childNodes[1]);
1333        };
1334        page2.reset = function(name) {
1335          resetEditor();
1336          if (page2.imagePromises == null) {
1337            page2.imagePromises = [];
1338          } else {
1339            page2.imagePromises.length = 0;
1340          }
1341          var buttons = page2.querySelectorAll(".button.card");
1342          var list2 = [];
1343          for (var i2 = 0; i2 < buttons.length; i2++) {
1344            list2.push(buttons[i2]);
1345          }
1346          for (var i2 = 0; i2 < list2.length; i2++) {
1347            list2[i2].remove();
1348          }
1349          if (lib.extensionPack[name]) {
1350            page2.content.pack = lib.extensionPack[name].card || {
1351              card: {},
1352              translate: {}
1353            };
1354            page2.content.image = {};
1355            if (Array.isArray(page2.content.pack.list)) {
1356              for (var i2 = 0; i2 < page2.content.pack.list.length; i2++) {
1357                var card = page2.content.pack.list[i2];
1358                var node2 = document.createElement("button");
1359                node2.innerHTML = page2.content.pack.translate[card[2]] + " " + lib.translate[card[0]] + card[1];
1360                node2.name = card[2];
1361                node2.link = card;
1362                pile.appendChild(node2);
1363                node2.onclick = function() {
1364                  this.remove();
1365                };
1366              }
1367            }
1368            for (const id in page2.content.pack.card) {
1369              const fullskin = page2.content.pack.card[id].fullskin ? true : false;
1370              const file = id + (fullskin ? ".png" : ".jpg");
1371              const url = lib.assetURL + "extension/" + name + "/" + file;
1372              createButton(id, url, fullskin);
1373              page2.imagePromises.push(
1374                game.promises.readFile(url).then((result) => {
1375                  page2.content.image[file] = result;
1376                }).catch((e) => console.error(e))
1377              );
1378            }
1379          } else {
1380            page2.content = {
1381              pack: {
1382                card: {},
1383                translate: {}
1384              },
1385              image: {}
1386            };
1387            toggle.classList.add("on");
1388            newCard.style.display = "";
1389          }
1390          updatePile();
1391        };
1392        ui.create.div(".config.more.margin-bottom", '<div style="transform:none;margin-right:3px">←</div>返回', page2, function() {
1393          ui.create.templayer();
1394          page2.hide();
1395          pageboard.show();
1396        });
1397        page2.content = {
1398          pack: {
1399            card: {},
1400            translate: {},
1401            list: []
1402          },
1403          image: {}
1404        };
1405        var newCard;
1406        var toggle = ui.create.div(".config.more.on", "创建卡牌 <div>&gt;</div>", page2, function() {
1407          this.classList.toggle("on");
1408          if (this.classList.contains("on")) {
1409            newCard.style.display = "";
1410          } else {
1411            newCard.style.display = "none";
1412          }
1413        });
1414        var resetEditor = function() {
1415          currentButton = null;
1416          toggle.classList.remove("on");
1417          newCard.style.display = "none";
1418          fakeme.classList.remove("inited");
1419          fakeme.classList.add("fullskin");
1420          delete fakeme.image;
1421          delete fakeme.image64;
1422          fakeme.style.backgroundImage = "";
1423          fakeme.imagenode.style.backgroundImage = "";
1424          var inputs = newCard.querySelectorAll("input");
1425          for (var i2 = 0;
1425 i2 < inputs.length; i2++) {
1426            inputs[i2].value = "";
1427          }
1428          toggle.innerHTML = "创建卡牌 <div>&gt;</div>";
1429          editnode.innerHTML = "创建卡牌";
1430          editnode.classList.add("disabled");
1431          delnode.innerHTML = "取消";
1432          delete delnode.button;
1433          code = 'card={\n    \n}\n\n/*\n示例:\ncard={\n    type:"basic",\n    enable:true,\n    filterTarget:true,\n    content:function(){\n        target.draw()\n    },\n    ai:{\n        order:1,\n        result:{\n            target:1\n        }\n    }\n}\n此例的效果为目标摸一张牌\n导出时本段代码中的换行、缩进以及注释将被清除\n*/';
1434        };
1435        newCard = ui.create.div(".new_character", page2);
1436        newCard.style.height = "173px";
1437        var fakeme = ui.create.div(".card.fullskin", newCard);
1438        var input = document.createElement("input");
1439        input.type = "file";
1440        input.accept = "image/*";
1441        input.className = "fileinput";
1442        input.onchange = function() {
1443          var fileToLoad = input.files[0];
1444          if (fileToLoad) {
1445            var fileReader = new FileReader();
1446            var fullimage = fileToLoad.name.includes(".jpg");
1447            fileReader.onload = function(fileLoadedEvent) {
1448              var data = fileLoadedEvent.target.result;
1449              if (fullimage) {
1450                fakeme.imagenode.style.backgroundImage = "";
1451                fakeme.style.backgroundImage = "url(" + data + ")";
1452                fakeme.classList.remove("fullskin");
1453              } else {
1454                fakeme.style.backgroundImage = "";
1455                fakeme.imagenode.style.backgroundImage = "url(" + data + ")";
1456                fakeme.classList.add("fullskin");
1457              }
1458              fakeme.image64 = data;
1459              fakeme.classList.add("inited");
1460              var fileReader2 = new FileReader();
1461              fileReader2.onload = function(fileLoadedEvent2) {
1462                fakeme.image = fileLoadedEvent2.target.result;
1463                updateButton();
1464              };
1465              fileReader2.readAsArrayBuffer(fileToLoad, "UTF-8");
1466            };
1467            fileReader.readAsDataURL(fileToLoad, "UTF-8");
1468          }
1469        };
1470        fakeme.appendChild(input);
1471        fakeme.imagenode = ui.create.div(".image", fakeme);
1472        ui.create.div(".name", "选择背景", fakeme);
1473        ui.create.div(".indent", '名称:<input class="new_name" type="text">', newCard).style.paddingTop = "8px";
1474        ui.create.div(".indent", '描述:<input class="new_description" type="text">', newCard).style.paddingTop = "6px";
1475        newCard.querySelector("input.new_name").onblur = updateButton;
1476        var codeButton = document.createElement("button");
1477        newCard.appendChild(codeButton);
1478        codeButton.innerHTML = "编辑代码";
1479        codeButton.style.left = "123px";
1480        codeButton.style.top = "66px";
1481        codeButton.style.position = "absolute";
1482        var citeButton = document.createElement("button");
1483        newCard.appendChild(citeButton);
1484        citeButton.innerHTML = "引用代码";
1485        citeButton.style.left = "123px";
1486        citeButton.style.top = "90px";
1487        citeButton.style.position = "absolute";
1488        citeButton.onclick = function() {
1489          codeButton.style.display = "none";
1490          citeButton.style.display = "none";
1491          selectname.style.display = "";
1492          confirmcontainer.style.display = "";
1493        };
1494        var list = [];
1495        for (var i in lib.card) {
1496          if (lib.translate[i]) {
1497            list.push([i, lib.translate[i]]);
1498          }
1499        }
1500        list.sort(function(a, b) {
1501          a = a[0];
1502          b = b[0];
1503          var aa = a, bb = b;
1504          if (aa.includes("_")) {
1505            aa = aa.slice(aa.lastIndexOf("_") + 1);
1506          }
1507          if (bb.includes("_")) {
1508            bb = bb.slice(bb.lastIndexOf("_") + 1);
1509          }
1510          if (aa != bb) {
1511            return aa > bb ? 1 : -1;
1512          }
1513          return a > b ? 1 : -1;
1514        });
1515        var selectname = ui.create.selectlist(list, list[0], newCard);
1516        selectname.style.left = "123px";
1517        selectname.style.top = "66px";
1518        selectname.style.position = "absolute";
1519        selectname.style.display = "none";
1520        var confirmcontainer = ui.create.div(newCard);
1521        confirmcontainer.style.left = "123px";
1522        confirmcontainer.style.top = "90px";
1523        confirmcontainer.style.position = "absolute";
1524        confirmcontainer.style.display = "none";
1525        var citeconfirm = document.createElement("button");
1526        citeconfirm.innerHTML = "引用";
1527        confirmcontainer.appendChild(citeconfirm);
1528        citeconfirm.onclick = function() {
1529          codeButton.style.display = "";
1530          citeButton.style.display = "";
1531          selectname.style.display = "none";
1532          confirmcontainer.style.display = "none";
1533          code = "card=" + get.stringify(lib.card[selectname.value]);
1534          codeButton.onclick.call(codeButton);
1535          if (lib.translate[selectname.value + "_info"]) {
1536            newCard.querySelector("input.new_description").value = lib.translate[selectname.value + "_info"];
1537          }
1538        };
1539        let code = "";
1540        var citecancel = document.createElement("button");
1541        citecancel.innerHTML = "取消";
1542        citecancel.style.marginLeft = "3px";
1543        confirmcontainer.appendChild(citecancel);
1544        citecancel.onclick = function() {
1545          codeButton.style.display = "";
1546          citeButton.style.display = "";
1547          selectname.style.display = "none";
1548          confirmcontainer.style.display = "none";
1549        };
1550        codeButton.onclick = function() {
1551          ui.create.editor({
1552            language: "javascript",
1553            value: code,
1554            saveInput: (result) => {
1555              var { card } = security.exec2(result);
1556              if (card == null || typeof card != "object") {
1557                throw new Error("代码格式有错误,请对比示例代码仔细检查");
1558              }
1559              dash2.link.classList.add("active");
1560              code = result;
1561            }
1562          });
1563        };
1564        code = 'card={\n    \n}\n\n/*\n示例:\ncard={\n    type:"basic",\n    enable:true,\n    filterTarget:true,\n    content:function(){\n        target.draw()\n    },\n    ai:{\n        order:1,\n        result:{\n            target:1\n        }\n    }\n}\n此例的效果为目标摸一张牌\n导出时本段代码中的换行、缩进以及注释将被清除\n*/';
1565        var editnode = ui.create.div(".menubutton.large.new_card.disabled", "创建卡牌", newCard, function() {
1566          var name = page2.querySelector("input.new_name").value;
1567          if (!name) {
1568            alert("请填写卡牌名\n提示:卡牌名格式为id+|+中文名,其中id必须惟一");
1569            return;
1570          }
1571          name = name.split("|");
1572          var translate = name[1] || name[0];
1573          var info = page2.querySelector("input.new_description").value;
1574          name = name[0];
1575          if (currentButton) {
1576            if (currentButton.link != name) {
1577              if (lib.card[name] || page2.content.pack.card[name]) {
1578                alert("卡牌名与现有卡牌重复,请更改\n提示:卡牌名格式为id+|+中文名,其中id必须惟一");
1579                return;
1580              }
1581              var extname;
1582              if (currentButton.classList.contains("fullskin")) {
1583                extname = ".png";
1584              } else {
1585                extname = ".jpg";
1586              }
1587              page2.content.image[name + extname] = page2.content.image[currentButton.link + extname];
1588              delete page2.content.image[currentButton.link + extname];
1589              delete page2.content.pack.card[currentButton.link];
1590              delete page2.content.pack.translate[currentButton.link];
1591              delete page2.content.pack.translate[currentButton.link + "_info"];
1592              currentButton.link = name;
1593            }
1594          } else {
1595            if (lib.card[name] || page2.content.pack.card[name]) {
1596              alert("卡牌名与现有卡牌重复,请更改\n提示:卡牌名格式为id+|+中文名,其中id必须惟一");
1597              return;
1598            }
1599          }
1600          if (fakeme.image) {
1601            if (fakeme.classList.contains("fullskin")) {
1602              page2.content.image[name + ".png"] = fakeme.image;
1603              delete page2.content.image[name + ".jpg"];
1604            } else {
1605              page2.content.image[name + ".jpg"] = fakeme.image;
1606              delete page2.content.image[name + ".png"];
1607            }
1608          } else if (!fakeme.classList.contains("inited")) {
1609            alert("请选择一个卡牌背景");
1610            return;
1611          }
1612          page2.content.pack.translate[name] = translate;
1613          page2.content.pack.translate[name + "_info"] = info;
1614          try {
1615            var { card } = security.exec2(code);
1616            if (card == null || typeof card != "object") {
1617              throw new Error("err");
1618            }
1619            page2.content.pack.card[name] = card;
1620          } catch (e) {
1621            page2.content.pack.card[name] = {};
1622          }
1623          if (fakeme.classList.contains("inited")) {
1624            if (fakeme.classList.contains("fullskin")) {
1625              page2.content.pack.card[name].fullskin = true;
1626              delete page2.content.pack.card[name].fullimage;
1627            } else {
1628              page2.content.pack.card[name].fullimage = true;
1629              delete page2.content.pack.card[name].fullskin;
1630            }
1631          }
1632          if (this.innerHTML == "创建卡牌") {
1633            createButton(name, fakeme.image64, fakeme.classList.contains("fullskin"));
1634          } else if (currentButton) {
1635            if (fakeme.image64) {
1636              if (fakeme.classList.contains("fullskin")) {
1637                currentButton.style.color = "";
1638                currentButton.style.textShadow = "";
1639                currentButton.imagenode.style.backgroundImage = "url(" + fakeme.image64 + ")";
1640                currentButton.style.backgroundImage = "";
1641                currentButton.style.backgroundSize = "";
1642                currentButton.classList.add("fullskin");
1643              } else {
1644                currentButton.style.color = "white";
1645                currentButton.style.textShadow = "black 0 0 2px";
1646                currentButton.imagenode.style.backgroundImage = "";
1647                currentButton.style.backgroundImage = "url(" + fakeme.image64 + ")";
1648                currentButton.style.backgroundSize = "cover";
1649                currentButton.classList.remove("fullskin");
1650              }
1651            }
1652            currentButton.nodename.innerHTML = get.verticalStr(translate);
1653          }
1654          resetEditor();
1655          updatePile();
1656          dash2.link.classList.add("active");
1657        });
1658        var delnode = ui.create.div(".menubutton.large.new_card_delete", "取消", editnode.parentNode, function() {
1659          if (this.innerHTML == "删除") {
1660            this.button.remove();
1661            var name = this.button.link;
1662            delete dash2.content.pack.card[name];
1663            delete dash2.content.pack.translate[name];
1664            delete dash2.content.pack.translate[name + "_info"];
1665            delete dash2.content.image[name];
1666            updatePile();
1667            dash2.link.classList.add("active");
1668          }
1669          resetEditor();
1670        });
1671        var editPile;
1672        var toggle2 = ui.create.div(".config.more", "编辑牌堆 <div>&gt;</div>", page2, function() {
1673          this.classList.toggle("on");
1674          if (this.classList.contains("on")) {
1675            editPile.style.display = "";
1676          } else {
1677            editPile.style.display = "none";
1678          }
1679        });
1680        editPile = ui.create.div(".edit_pile", page2);
1681        editPile.style.display = "none";
1682        var cardpileadd = ui.create.div(".config.toggle.cardpilecfg.cardpilecfgadd", editPile);
1683        var pile = ui.create.div(editPile);
1684        page2.pile = pile;
1685        var cardpileaddname = document.createElement("select");
1686        var updatePile = function() {
1687          cardpileaddname.innerHTML = "";
1688          var list2 = [];
1689          var list22 = [];
1690          for (var i2 in page2.content.pack.card) {
1691            list2.push([i2, page2.content.pack.translate[i2]]);
1692            list22.push(i2);
1693          }
1694          if (list2.length) {
1695            toggle2.style.display = "";
1696            if (toggle2.classList.contains("on")) {
1697              editPile.style.display = "";
1698            } else {
1699              editPile.style.display = "none";
1700            }
1701            for (var i2 = 0; i2 < list2.length; i2++) {
1702              var option = document.createElement("option");
1703              option.value = list2[i2][0];
1704              option.innerHTML = list2[i2][1];
1705              cardpileaddname.appendChild(option);
1706            }
1707            for (var i2 = 0; i2 < pile.childNodes.length; i2++) {
1708              if (!list22.includes(pile.childNodes[i2].name)) {
1709                pile.childNodes[i2].remove();
1710                i2--;
1711              }
1712            }
1713          } else {
1714            toggle2.style.display = "none";
1715            editPile.style.display = "none";
1716            pile.innerHTML = "";
1717          }
1718        };
1719        updatePile();
1720        cardpileadd.appendChild(cardpileaddname);
1721        cardpileaddname.style.width = "75px";
1722        cardpileaddname.style.marginRight = "2px";
1723        cardpileaddname.style.marginLeft = "-1px";
1724        var cardpileaddsuit = ui.create.selectlist(
1725          [
1726            ["heart", "红桃"],
1727            ["diamond", "方片"],
1728            ["club", "梅花"],
1729            ["spade", "黑桃"]
1730          ],
1731          null,
1732          cardpileadd
1733        );
1734        cardpileaddsuit.style.width = "53px";
1735        cardpileaddsuit.style.marginRight = "2px";
1736        var cardpileaddnumber = ui.create.selectlist([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], null, cardpileadd);
1737        cardpileaddnumber.style.width = "43px";
1738        cardpileaddnumber.style.marginRight = "2px";
1739        var button = document.createElement("button");
1740        button.innerHTML = "确定";
1741        button.style.width = "40px";
1742        button.onclick = function() {
1743          var card = [cardpileaddsuit.value, cardpileaddnumber.value, cardpileaddname.value];
1744          var node2 = document.createElement("button");
1745          node2.innerHTML = page2.content.pack.translate[card[2]] + " " + lib.translate[card[0]] + card[1];
1746          node2.name = card[2];
1747          node2.link = card;
1748          pile.appendChild(node2);
1749          node2.onclick = function() {
1750            this.remove();
1751          };
1752        };
1753        cardpileadd.appendChild(button);
1754        cardpileadd.style.whiteSpace = "nowrap";
1755        cardpileadd.style.position = "relative";
1756        cardpileadd.style.right = "-4px";
1757        return page2;
1758      })();
1759      var dash3 = (function() {
1760        var page2 = ui.create.div(".hidden.menu-buttons.new_skill");
1761        var updateButton = function() {
1762          var name = page2.querySelector("input.new_name").value;
1763          if (!name) {
1764            editnode.classList.add("disabled");
1765            return;
1766          }
1767          name = name.split("|");
1768          name = name[0];
1769          if (currentButton) {
1770            if (currentButton.link != name) {
1771              if (lib.skill[name] || page2.content.pack.skill[name]) {
1772                editnode.classList.add("disabled");
1773                return;
1774              }
1775            }
1776          } else {
1777            if (lib.skill[name] || page2.content.pack.skill[name]) {
1778              editnode.classList.add("disabled");
1779              return;
1780            }
1781          }
1782          editnode.classList.remove("disabled");
1783        };
1784        page2.init = function() {
1785          if (!page2.querySelector(".menubutton:not(.large)")) {
1786            toggle.classList.add("on");
1787            newSkill.style.display = "";
1788          }
1789        };
1790        page2.reset = function(name) {
1791          resetEditor();
1792          var buttons = page2.querySelectorAll(".menubutton:not(.large)");
1793          var list4 = [];
1794          for (var i2 = 0; i2 < buttons.length; i2++) {
1795            list4.push(buttons[i2]);
1796          }
1797          for (var i2 = 0; i2 < list4.length; i2++) {
1798            list4[i2].remove();
1799          }
1800          if (lib.extensionPack[name]) {
1801            page2.content.pack = lib.extensionPack[name].skill || {
1802              skill: {},
1803              translate: {}
1804            };
1805            page2.content.audio = {};
1806            for (var i2 in page2.content.pack.skill) {
1807              createButton(i2);
1808            }
1809            dash1.updateSkill();
1810          } else {
1811            page2.content = {
1812              pack: {
1813                skill: {},
1814                translate: {}
1815              },
1816              audio: {}
1817            };
1818            toggle.classList.add("on");
1819            newSkill.style.display = "";
1820          }
1821        };
1822        ui.create.div(".config.more.margin-bottom", '<div style="transform:none;margin-right:3px">←</div>返回', page2, function() {
1823          ui.create.templayer();
1824          page2.hide();
1825          if (page2.fromchar) {
1826            dash1.show();
1827            delete page2.fromchar;
1828          } else {
1829            pageboard.show();
1830          }
1831        });
1832        var currentButton = null;
1833        var clickButton = function() {
1834          if (currentButton == this) {
1835            resetEditor();
1836            return;
1837          }
1838          resetEditor();
1839          currentButton = this;
1840          toggle.classList.add("on");
1841          newSkill.style.display = "";
1842          if (page2.content.pack.translate[this.link] != this.link) {
1843            newSkill.querySelector(".new_name").value = this.link + "|" + page2.content.pack.translate[this.link];
1844          } else {
1845            newSkill.querySelector(".new_name").value = this.link;
1846          }
1847          newSkill.querySelector(".new_description").value = page2.content.pack.translate[this.link + "_info"];
1848          var info = page2.content.pack.skill[this.link];
1849          code = "skill=" + // 需要考虑getter和setter以及Symbol
1850          (() => {
1851            const obj = Object.defineProperty(get.copy(info), "_priority", {
1852              enumerable: false,
1853              writable: true,
1854              configurable: true
1855            });
1856            let str = "{\n";
1857            const indent = "    ";
1858            for (const key in obj) {
1859              const descriptor = Object.getOwnPropertyDescriptor(obj, key);
1860              if (descriptor?.get || descriptor?.set) {
1861                if (descriptor.get) {
1862                  str += indent + get.stringify(descriptor.get, 1) + ",\n";
1863                }
1864                if (descriptor.set) {
1865                  str += indent + get.stringify(descriptor.set, 1) + ",\n";
1866                }
1867              } else {
1868                let keyString = (/[^a-zA-Z]/.test(key) ? `"${key}"` : key) + ": ";
1869                if (get.is.functionMethod(obj, key)) {
1870                  keyString = "";
1871                }
1872                str += indent + keyString + get.stringify(obj[key], 1) + ",\n";
1873              }
1874            }
1875            Object.getOwnPropertySymbols(obj).forEach((symbol) => {
1876              str += `${indent}[${String(symbol)}]: ${get.stringify(obj[symbol], 1)},
1877`;
1878            });
1879            str += "}";
1880            return str;
1881          })();
1882          toggle.innerHTML = "编辑技能 <div>&gt;</div>";
1883          editnode.innerHTML = "编辑技能";
1884          editnode.classList.remove("disabled");
1885          delnode.button = this;
1886          delnode.innerHTML = "删除";
1887        };
1888        var createButton = function(name) {
1889          var button = ui.create.div(".menubutton");
1890          button.link = name;
1891          button.innerHTML = page2.content.pack.translate[name];
1892          button.listen(clickButton);
1893          page2.insertBefore(button, page2.childNodes[1]);
1894        };
1895        var newSkill;
1896        var toggle = ui.create.div(".config.more.on", "创建技能 <div>&gt;</div>", page2, function() {
1897          this.classList.toggle("on");
1898          if (this.classList.contains("on")) {
1899            newSkill.style.display = "";
1900          } else {
1901            newSkill.style.display = "none";
1902          }
1903        });
1904        page2.toggle = toggle;
1905        var resetEditor = function() {
1906          currentButton = null;
1907          toggle.classList.remove("on");
1908          newSkill.style.display = "none";
1909          var inputs = newSkill.querySelectorAll("input");
1910          for (var i2 = 0; i2 < inputs.length; i2++) {
1911            inputs[i2].value = "";
1912          }
1913          var inputs = newSkill.querySelectorAll("textarea");
1914          for (var i2 = 0; i2 < inputs.length; i2++) {
1915            inputs[i2].value = "";
1916          }
1917          toggle.innerHTML = "创建技能 <div>&gt;</div>";
1918          editnode.innerHTML = "创建技能";
1919          editnode.classList.add("disabled");
1920          delnode.innerHTML = "取消";
1921          delete delnode.button;
1922          code = 'skill={\n    \n}\n\n/*\n示例:\nskill={\n    trigger:{player:"phaseJieshuBegin"},\n    frequent:true,\n    content:function(){\n        player.draw()\n    }\n}\n此例为闭月代码\n导出时本段代码中的换行、缩进以及注释将被清除\n*/';
1923          if (page2.fromchar == "add") {
1924            page2.fromchar = true;
1925          }
1926        };
1927        newSkill = ui.create.div(".new_character.new_skill", page2);
1928        page2.newSkill = newSkill;
1929        var namenode = ui.create.div(".config", '名称:<input class="new_name" type="text" style="width:120px"></input>', newSkill);
1930        var descnode = ui.create.div(".config", '描述:<input class="new_description" type="text" style="width:120px"></input>', newSkill);
1931        namenode.querySelector("input.new_name").onblur = updateButton;
1932        var commandline = ui.create.div(".config", newSkill);
1933        var editbutton = document.createElement("button");
1934        editbutton.innerHTML = "编辑代码";
1935        commandline.appendChild(editbutton);
1936        editbutton.onclick = function() {
1937          ui.create.editor({
1938            language: "javascript",
1939            value: code,
1940            saveInput: (result) => {
1941              const { skill } = security.exec2(result);
1942              if (skill == null || typeof skill != "object") {
1943                throw new Error("代码格式有错误,请对比示例代码仔细检查");
1944              }
1945              dash3.link.classList.add("active");
1946              code = result;
1947            }
1948          });
1949        };
1950        let code = 'skill={\n    \n}\n\n/*\n示例:\nskill={\n    trigger:{player:"phaseJieshuBegin"},\n    frequent:true,\n    content:function(){\n        player.draw()\n    }\n}\n此例为闭月代码\n导出时本段代码中的换行、缩进以及注释将被清除\n*/';
1951        var citebutton = document.createElement("button");
1952        citebutton.innerHTML = "引用代码";
1953        commandline.appendChild(citebutton);
1954        citebutton.onclick = function() {
1955          editbutton.style.display = "none";
1956          citebutton.style.display = "none";
1957          selectname.style.display = "";
1958          skillopt.style.display = "";
1959          addSkillButton.style.display = "";
1960          cancelSkillButton.style.display = "";
1961        };
1962        var list = [];
1963        for (var i in lib.character) {
1964          if (lib.character[i][3].length) {
1965            list.push([i, lib.translate[i]]);
1966          }
1967        }
1968        if (!list.length) {
1969          if (!lib.character["noname_sunce"]) {
1970            lib.character["noname_sunce"] = new Character({
1971              sex: "male",
1972              group: "wu",
1973              hp: 4,
1974              skills: ["jiang"],
1975              isUnseen: true
1976            });
1977          }
1978          if (!lib.translate["noname_sunce"]) {
1979            lib.translate["noname_sunce"] = "孙策";
1980          }
1981          list.push(["noname_sunce", lib.translate["noname_sunce"]]);
1982        }
1983        list.sort(function(a, b) {
1984          a = a[0];
1985          b = b[0];
1986          var aa = a, bb = b;
1987          if (aa.includes("_")) {
1988            aa = aa.slice(aa.lastIndexOf("_") + 1);
1989          }
1990          if (bb.includes("_")) {
1991            bb = bb.slice(bb.lastIndexOf("_") + 1);
1992          }
1993          if (aa != bb) {
1994            return aa > bb ? 1 : -1;
1995          }
1996          return a > b ? 1 : -1;
1997        });
1998        list.push(["others", "其它"]);
1999        var list2 = [];
2000        var skills = lib.character[list[0][0]][3];
2001        for (var i = 0; i < skills.length; i++) {
2002          list2.push([skills[i], lib.translate[skills[i]]]);
2003        }
2004        var selectname = ui.create.selectlist(list, list[0], commandline);
2005        var list3 = [];
2006        for (var i in lib.skill) {
2007          if (i != "global" && !get.is.empty(lib.skill[i]) && !lib.skilllist.includes(i)) {
2008            list3.push(i);
2009          }
2010        }
2011        list3.sort(function(a, b) {
2012          return a > b ? 1 : -1;
2013        });
2014        selectname.onchange = function() {
2015          var skills2;
2016          skillopt.innerHTML = "";
2017          if (this.value == "others") {
2018            skills2 = list3;
2019            for (var i2 = 0; i2 < skills2.length; i2++) {
2020              var option = document.createElement("option");
2021              option.value = skills2[i2];
2022              option.innerHTML = skills2[i2];
2023              skillopt.appendChild(option);
2024            }
2025          } else {
2026            skills2 = lib.character[this.value][3];
2027            for (var i2 = 0; i2 < skills2.length; i2++) {
2028              var option = document.createElement("option");
2029              option.value = skills2[i2];
2030              option.innerHTML = lib.translate[skills2[i2]];
2031              skillopt.appendChild(option);
2032            }
2033          }
2034        };
2035        selectname.style.display = "none";
2036        selectname.style.maxWidth = "80px";
2037        var skillopt = ui.create.selectlist(list2, list2[0], commandline);
2038        skillopt.style.display = "none";
2039        skillopt.style.maxWidth = "60px";
2040        var addSkillButton = document.createElement("button");
2041        addSkillButton.style.display = "none";
2042        addSkillButton.innerHTML = "引用";
2043        commandline.appendChild(addSkillButton);
2044        addSkillButton.onclick = function() {
2045          editbutton.style.display = "";
2046          citebutton.style.display = "";
2047          selectname.style.display = "none";
2048          skillopt.style.display = "none";
2049          addSkillButton.style.display = "none";
2050          cancelSkillButton.style.display = "none";
2051          code = "skill=" + // 需要考虑getter和setter以及Symbol
2052          (() => {
2053            const obj = Object.defineProperty(get.copy(lib.skill[skillopt.value]), "_priority", {
2054              enumerable: false,
2055              writable: true,
2056              configurable: true
2057            });
2058            let str = "{\n";
2059            const indent = "    ";
2060            for (const key in obj) {
2061              const descriptor = Object.getOwnPropertyDescriptor(obj, key);
2062              if (descriptor?.get || descriptor?.set) {
2063                if (descriptor.get) {
2064                  str += indent + get.stringify(descriptor.get, 1) + ",\n";
2065                }
2066                if (descriptor.set) {
2067                  str += indent + get.stringify(descriptor.set, 1) + ",\n";
2068                }
2069              } else {
2070                let keyString = (/[^a-zA-Z]/.test(key) ? `"${key}"` : key) + ": ";
2071                if (get.is.functionMethod(obj, key)) {
2072                  keyString = "";
2073                }
2074                str += indent + keyString + get.stringify(obj[key], 1) + ",\n";
2075              }
2076            }
2077            Object.getOwnPropertySymbols(obj).forEach((symbol) => {
2078              str += `${indent}[${String(symbol)}]: ${get.stringify(obj[symbol], 1)},
2079`;
2080            });
2081            str += "}";
2082            return str;
2083          })();
2084          editbutton.onclick.call(editbutton);
2085          if (lib.translate[skillopt.value + "_info"]) {
2086            newSkill.querySelector("input.new_description").value = lib.translate[skillopt.value + "_info"];
2087          }
2088        };
2089        var cancelSkillButton = document.createElement("button");
2090        cancelSkillButton.style.display = "none";
2091        cancelSkillButton.innerHTML = "取消";
2092        commandline.appendChild(cancelSkillButton);
2093        cancelSkillButton.onclick = function() {
2094          editbutton.style.display = "";
2095          citebutton.style.display = "";
2096          selectname.style.display = "none";
2097          skillopt.style.display = "none";
2098          addSkillButton.style.display = "none";
2099          cancelSkillButton.style.display = "none";
2100        };
2101        var editnode = ui.create.div(
2102          ".menubutton.large.new_skill.disabled",
2103          "创建技能",
2104          function() {
2105            var name = page2.querySelector("input.new_name").value;
2106            if (!name) {
2107              alert("请填写技能名\n提示:技能名格式为id+|+中文名,其中id必须惟一");
2108              return;
2109            }
2110            name = name.split("|");
2111            var translate = name[1] || name[0];
2112            var info = page2.querySelector("input.new_description").value;
2113            name = name[0];
2114            if (currentButton) {
2115              if (currentButton.link != name) {
2116                if (lib.skill[name] || page2.content.pack.skill[name]) {
2117                  alert("技能名与现有技能重复,请更改\n提示:技能名格式为id+|+中文名,其中id必须惟一");
2118                  return;
2119                }
2120                delete page2.content.pack.skill[currentButton.link];
2121                delete page2.content.pack.translate[currentButton.link];
2122                delete page2.content.pack.translate[currentButton.link + "_info"];
2123                currentButton.link = name;
2124              }
2125            } else {
2126              if (lib.skill[name] || page2.content.pack.skill[name]) {
2127                alert("技能名与现有技能重复,请更改\n提示:技能名格式为id+|+中文名,其中id必须惟一");
2128                return;
2129              }
2130            }
2131            page2.content.pack.translate[name] = translate;
2132            page2.content.pack.translate[name + "_info"] = info;
2133            try {
2134              var { skill } = security.exec2(code);
2135              if (skill == null || typeof skill != "object") {
2136                throw new Error("err");
2137              }
2138              page2.content.pack.skill[name] = skill;
2139            } catch (e) {
2140              page2.content.pack.skill[name] = {};
2141            }
2142            dash1.selectname.value = "current_extension";
2143            dash1.selectname.onchange.call(dash1.selectname);
2144            if (this.innerHTML == "创建技能") {
2145              createButton(name);
2146              if (page2.fromchar == "add") {
2147                ui.create.templayer();
2148                page2.hide();
2149                dash1.show();
2150                dash1.skillopt.value = name;
2151                dash1.addSkillButton.onclick();
2152                delete page2.fromchar;
2153              }
2154            } else if (currentButton) {
2155              currentButton.innerHTML = translate;
2156            }
2157            resetEditor();
2158            dash3.link.classList.add("active");
2159            dash1.updateSkill();
2160          },
2161          newSkill
2162        );
2163        var delnode = ui.create.div(".menubutton.large.new_card_delete", "取消", editnode.parentNode, function() {
2164          if (this.innerHTML == "删除") {
2165            this.button.remove();
2166            var name = this.button.link;
2167            delete dash3.content.pack.skill[name];
2168            delete dash3.content.pack.translate[name];
2169            delete dash3.content.pack.translate[name + "_info"];
2170            dash3.link.classList.add("active");
2171            if (get.is.empty(dash3.content.pack.skill)) {
2172              dash1.selectname.value = dash1.selectname.childNodes[1].value;
2173            }
2174            dash1.selectname.onchange.call(dash1.selectname);
2175            dash1.updateSkill();
2176            resetEditor();
2177          } else if (page2.fromchar == "add") {
2178            ui.create.templayer();
2179            page2.hide();
2180            dash1.show();
2181            delete page2.fromchar;
2182            setTimeout(resetEditor, 600);
2183          } else {
2184            resetEditor();
2185          }
2186        });
2187        page2.content = {
2188          pack: {
2189            skill: {},
2190            translate: {}
2191          },
2192          audio: {}
2193        };
2194        return page2;
2195      })();
2196      var dash4 = (function() {
2197        var page2 = ui.create.div(".hidden.menu-buttons");
2198        ui.create.div(".config.more.margin-bottom", '<div style="transform:none;margin-right:3px">←</div>返回', page2, function() {
2199          ui.create.templayer();
2200          page2.hide();
2201          pageboard.show();
2202        });
2203        page2.reset = function(name) {
2204          page2.content = {};
2205          if (lib.extensionPack[name]) {
2206            for (var i in lib.extensionPack[name].code) {
2207              switch (typeof lib.extensionPack[name].code[i]) {
2208                case "function":
2209                  page2.content[i] = lib.extensionPack[name].code[i].toString();
2210                  break;
2211                case "object":
2212                  page2.content[i] = i + "=" + get.stringify(lib.extensionPack[name].code[i]);
2213                  break;
2214              }
2215            }
2216          }
2217        };
2218        var dashes = {};
2219        var createCode = function(shortName, fullName, link, defaultCode) {
2220          var dash = ui.create.div(".menubutton.large.dashboard");
2221          dashes[link] = dash;
2222          page2.appendChild(dash);
2223          dash.listen(() => {
2224            ui.create.editor({
2225              language: "javascript",
2226              value: page2.content[link] || defaultCode,
2227              saveInput: (result) => {
2228                if (["arenaReady", "content", "prepare", "precontent"].includes(link)) {
2229                  var { func } = security.exec2(`func = ${result}`);
2230                  if (typeof func != "function") {
2231                    throw new Error("代码格式有错误,请对比示例代码仔细检查");
2232                  }
2233                } else if (link == "config") {
2234                  var { config } = security.exec2(result);
2235                  if (config == null || typeof config != "object") {
2236                    throw new Error("代码格式有错误,请对比示例代码仔细检查");
2237                  }
2238                } else if (link == "help") {
2239                  var { help } = security.exec2(result);
2240                  if (help == null || typeof help != "object") {
2241                    throw new Error("代码格式有错误,请对比示例代码仔细检查");
2242                  }
2243                }
2244                dash4.link.classList.add("active");
2245                page2.content[link] = result;
2246              }
2247            });
2248          });
2249          dash.link = link;
2250          ui.create.div("", shortName, dash);
2251          ui.create.div("", fullName, dash);
2252          page2.content[link] = defaultCode;
2253        };
2254        page2.content = {};
2255        createCode("辅", "辅助代码", "arenaReady", "function(){\n    \n}\n\n/*\n函数执行时机为游戏界面创建之后\n导出时本段代码中的换行、缩进以及注释将被清除\n*/");
2256        createCode("主", "主代码", "content", "function(config,pack){\n    \n}\n\n/*\n函数执行时机为游戏数据加载之后、界面加载之前\n参数1扩展选项(见选项代码);参数2为扩展定义的武将、卡牌和技能等(可在此函数中修改)\n导出时本段代码中的换行、缩进以及注释将被清除\n*/");
2257        createCode("预", "预备代码", "prepare", "function(){\n    \n}\n\n/*\n函数执行时机为游戏扩展全部加载之后\n导出时本段代码中的换行、缩进以及注释将被清除\n*/");
2258        createCode("启", "启动代码", "precontent", "function(config){\n    \n}\n\n/*\n函数执行时机为游戏数据加载之前,联机模式亦可加载\n除添加模式外请慎用\n导出时本段代码中的换行、缩进以及注释将被清除\n*/");
2259        createCode("选", "选项代码", "config", 'config={\n    \n}\n\n/*\n示例:\nconfig={\n    switcher_example:{\n        name:"示例列表选项",\n        init:"3",\n     	  item:{"1":"一","2":"二","3":"三"}\n    },\n    toggle_example:{\n        name:"示例开关选项",\n        init:true\n    }\n}\n此例中传入的主代码函数的默认参数为{switcher_example:"3",toggle_example:true}\n导出时本段代码中的换行、缩进以及注释将被清除\n*/');
2260        createCode("帮", "帮助代码", "help", 'help={\n    \n}\n\n/*\n示例:\nhelp={\n    "帮助条目":"<ul><li>列表1-条目1<li>列表1-条目2</ul><ol><li>列表2-条目1<li>列表2-条目2</ul>"\n}\n帮助内容将显示在菜单-选项-帮助中\n导出时本段代码中的换行、缩进以及注释将被清除\n*/');
2261        return page2;
2262      })();
2263      createDash("将", "编辑武将", dash1);
2264      createDash("卡", "编辑卡牌", dash2);
2265      createDash("技", "编辑技能", dash3);
2266      createDash("码", "编辑代码", dash4);
2267    };
2268    if (!get.config("menu_loadondemand")) {
2269      node._initLink();
2270    }
2271  })();
2272  (function() {
2273    var page = ui.create.div("");
2274    var node = ui.create.div(".menubutton.large", "获取扩展", start.firstChild, clickMode);
2275    node.mode = "get";
2276    var _thisUpdate = false;
2277    node.update = function() {
2278      _thisUpdate = true;
2279    };
2280    node._initLink = function() {
2281      node.link = page;
2282      page.listen(function() {
2283        if (!page.currenttimeout) {
2284          var active2 = page.querySelector(".videonode.current");
2285          if (active2) {
2286            active2.classList.remove("current");
2287          }
2288        }
2289      });
2290      var importextensionexpanded = false;
2291      page.style.paddingBottom = "10px";
2292      var importExtension;
2293      var extensionNode = ui.create.div(".config.more", "导入扩展 <div>&gt;</div>", page, function() {
2294        if (importextensionexpanded) {
2295          this.classList.remove("on");
2296          importExtension.style.display = "none";
2297        } else {
2298          this.classList.add("on");
2299          importExtension.style.display = "";
2300        }
2301        importextensionexpanded = !importextensionexpanded;
2302      });
2303      importExtension = ui.create.div(".new_character.export.import", page);
2304      importExtension.style.marginLeft = "5px";
2305      importExtension.style.marginTop = "5px";
2306      importExtension.style.marginBottom = "5px";
2307      importExtension.style.display = "none";
2308      importExtension.style.width = "100%";
2309      importExtension.style.textAlign = "left";
2310      ui.create.div("", '<input type="file" accept="application/zip" style="width:153px"><button>确定</button>', importExtension);
2311      ui.create.div(".config", "修改下载地址", page, function() {
2312        alert("您可以在“设置→通用→获取扩展地址”中,修改下载扩展时所采用的地址。");
2313      });
2314      var extensionURL;
2315      var source = lib.config.extension_sources, index = lib.config.extension_source;
2316      if (source && source[index]) {
2317        extensionURL = source[index];
2318      } else {
2319        extensionURL = lib.updateURL.replace(/noname/g, "noname-extension") + "/master/";
2320      }
2321      var reloadnode = ui.create.div(".config.toggle.pointerdiv", "重新启动", page, game.reload);
2322      reloadnode.style.display = "none";
2323      var placeholder = ui.create.div(".config.toggle", page);
2324      placeholder.style.height = 0;
2325      placeholder.style.marginTop = "5px";
2326      importExtension.firstChild.lastChild.onclick = function() {
2327        const fileToLoad = this.previousSibling.files[0];
2328        if (!fileToLoad) {
2329          return;
2330        }
2331        new Promise((resolve, reject) => {
2332          const fileReader = new FileReader();
2333          fileReader.onerror = reject;
2334          fileReader.onload = resolve;
2335          fileReader.readAsArrayBuffer(fileToLoad, "UTF-8");
2336        }).then(async (progressEvent) => {
2337          if (await game.importExtension(progressEvent.target.result, () => {
2338            extensionNode.innerHTML = "导入成功,3秒后将重启";
2339            new Promise((resolve) => setTimeout(resolve, 1e3)).then(() => {
2340              extensionNode.innerHTML = "导入成功,2秒后将重启";
2341              return new Promise((resolve) => setTimeout(resolve, 1e3));
2342            }).then(() => {
2343              extensionNode.innerHTML = "导入成功,1秒后将重启";
2344              return new Promise((resolve) => setTimeout(resolve, 1e3));
2345            }).then(game.reload);
2346          }) !== false) {
2347            importExtension.style.display = "none";
2348          }
2349        });
2350      };
2351      var clickExtension = function() {
2352        var active2 = this.parentNode.querySelector(".videonode.current");
2353        if (active2 && active2 != this) {
2354          active2.classList.remove("current");
2355        }
2356        this.classList.add("current");
2357        clearTimeout(page.currenttimeout);
2358        page.currenttimeout = setTimeout(function() {
2359          delete page.currenttimeout;
2360        }, 200);
2361      };
2362      var downloadExtension = function(e) {
2363        if (this.innerHTML != "下载扩展" && this.innerHTML != "更新扩展") {
2364          return;
2365        }
2366        this.classList.remove("update");
2367        if (e) {
2368          e.stopPropagation();
2369        }
2370        node.updated = true;
2371        var that = this;
2372        var list = [];
2373        var size = parseFloat(this.info.size) || 0;
2374        if (size) {
2375          if (this.info.size.includes("MB")) {
2376            size *= 1024 * 1024;
2377          } else if (this.info.size.includes("KB")) {
2378            size *= 1024;
2379          }
2380        }
2381        this.innerHTML = "<span>正在下载</span><div>正在下载</div>";
2382        this.classList.add("nopointer");
2383        this.classList.add("button-downloading");
2384        var progress = ui.create.div(".button-progress", this);
2385        ui.create.div(progress);
2386        var url = extensionURL + this.info.name + ".zip";
2387        var onprogress = function(byte, total) {
2388          if (total) {
2389            size = total;
2390          }
2391          if (byte == -1) {
2392            byte = size;
2393          }
2394          progress.firstChild.style.width = Math.round(100 * byte / size) + "%";
2395        };
2396        var files = this.info.files || [];
2397        for (var i = 0; i < files.length; i++) {
2398          files[i] = "extension/" + that.info.name + "/" + files[i];
2399        }
2400        game.checkFileList(files, function() {
2401          files.unshift("extension/" + that.info.name + "/extension.js");
2402          for (var i2 = 0; i2 < files.length; i2++) {
2403            files[i2] = extensionURL + that.info.name + "/" + files[i2].slice(10 + that.info.name.length + 1);
2404          }
2405          var n1 = 0, n2 = files.length;
2406          game.multiDownload(
2407            files,
2408            function() {
2409              n1++;
2410              onprogress(n1, n2);
2411            },
2412            function(e2) {
2413              game.print("下载失败:" + e2.source);
2414            },
2415            function() {
2416              onprogress(-1);
2417              _status.importingExtension = true;
2418              window.game = game;
2419              lib.init.js(
2420                lib.assetURL + "extension/" + that.info.name,
2421                "extension",
2422                function() {
2423                  if (!lib.config.dev) {
2424                    delete window.game;
2425                  }
2426                  if (game.importedPack) {
2427                    var extname = game.importedPack.name;
2428                    if (lib.config.extensions.includes(extname)) {
2429                      game.removeExtension(extname, true);
2430                    }
2431                    lib.config.extensions.add(extname);
2432                    game.saveConfig("extensions", lib.config.extensions);
2433                    game.saveConfig("extension_" + extname + "_enable", true);
2434                    game.saveConfig("extension_" + extname + "_version", that.info.version);
2435                    for (var i3 in game.importedPack.config) {
2436                      if (game.importedPack.config[i3] && "init" in game.importedPack.config[i3]) {
2437                        game.saveConfig("extension_" + extname + "_" + i3, game.importedPack.config[i3].init);
2438                      }
2439                    }
2440                    reloadnode.style.display = "";
2441                    that.childNodes[0].innerHTML = "安装成功";
2442                    that.childNodes[1].innerHTML = "安装成功";
2443                    that.classList.remove("active");
2444                    that.classList.remove("highlight");
2445                    delete game.importedPack;
2446                  } else {
2447                    that.innerHTML = "安装失败";
2448                    that.classList.add("nopointer");
2449                  }
2450                  _status.importingExtension = false;
2451                },
2452                function() {
2453                  that.innerHTML = "下载失败";
2454                  that.classList.add("nopointer");
2455                  _status.importingExtension = false;
2456                }
2457              );
2458            },
2459            function(current) {
2460              return "extension/" + current.slice(extensionURL.length);
2461            }
2462          );
2463        });
2464      };
2465      node.update = function() {
2466        if (this.updated) {
2467          return;
2468        }
2469        var toremove = [];
2470        for (var i = 0; i < page.childElementCount; i++) {
2471          if (page.childNodes[i].classList.contains("menubutton") || page.childNodes[i].classList.contains("loading")) {
2472            toremove.push(page.childNodes[i]);
2473          }
2474        }
2475        for (var i = 0; i < toremove.length; i++) {
2476          toremove[i].remove();
2477        }
2478        var loading = ui.create.div(".loading.config.toggle", "载入中...", page);
2479        var loaded = function() {
2480          var list = [];
2481          var extension = window.extension;
2482          for (var i2 in extension) {
2483            extension[i2].name = i2;
2484            list.push(extension[i2]);
2485          }
2486          list.randomSort();
2487          delete window.extension;
2488          loading.style.display = "none";
2489          for (var i2 = 0; i2 < list.length; i2++) {
2490            var node2 = ui.create.div(".videonode.menubutton.extension.large", page, clickExtension);
2491            ui.create.div(".caption", list[i2].name, node2);
2492            ui.create.div(".text.author", "作者:" + list[i2].author + "<span>(" + list[i2].size + ")</span>", node2);
2493            ui.create.div(".text", "更新日期:" + list[i2].date, node2);
2494            ui.create.div(".text", list[i2].intro, node2);
2495            var download = ui.create.div(".menubutton.text.active", "下载扩展", node2.firstChild, {
2496              zIndex: "5"
2497            });
2498            if (game.download) {
2499              if (list[i2].netdisk) {
2500                var linknode = ui.create.div(".text", node2);
2501                ui.create.node(
2502                  "span.hrefnode",
2503                  "网盘链接",
2504                  function() {
2505                    game.open(this.link);
2506                  },
2507                  linknode
2508                ).link = list[i2].netdisk;
2509                if (list[i2].forum) {
2510                  ui.create.node("span", linknode).style.marginRight = "10px";
2511                  ui.create.node(
2512                    "span.hrefnode",
2513                    "参与讨论",
2514                    function() {
2515                      game.open(this.link);
2516                    },
2517                    linknode
2518                  ).link = list[i2].forum;
2519                }
2520              } else if (list[i2].forum) {
2521                var linknode = ui.create.div(".text", node2);
2522                ui.create.node(
2523                  "span.hrefnode",
2524                  "参与讨论",
2525                  function() {
2526                    game.open(this.link);
2527                  },
2528                  linknode
2529                ).link = list[i2].forum;
2530              }
2531              download.listen(downloadExtension);
2532              if (lib.config.extensions.includes(list[i2].name)) {
2533                download.classList.remove("active");
2534                if (lib.extensionPack[list[i2].name] && lib.extensionPack[list[i2].name].version == list[i2].version) {
2535                  download.classList.add("transparent2");
2536                  download.classList.remove("active");
2537                  download.innerHTML = "已安装";
2538                } else if (lib.config["extension_" + list[i2].name + "_version"] != list[i2].version) {
2539                  download.innerHTML = "更新扩展";
2540                  download.classList.add("highlight");
2541                  download.classList.add("update");
2542                } else {
2543                  download.classList.add("transparent2");
2544                  download.classList.remove("active");
2545                  download.innerHTML = "已安装";
2546                }
2547              }
2548              download.info = list[i2];
2549            } else {
2550              if (list[i2].forum) {
2551                var linknode = ui.create.div(".text", node2);
2552                ui.create.node("span", linknode);
2553                ui.create.node(
2554                  "span.hrefnode",
2555                  "参与讨论",
2556                  function() {
2557                    game.open(this.link);
2558                  },
2559                  linknode
2560                ).link = list[i2].forum;
2561              }
2562              download.listen(function() {
2563                game.open(this.link);
2564              });
2565              download.link = list[i2].netdisk;
2566            }
2567          }
2568        };
2569        window.extension = {};
2570        fetch(`${extensionURL}catalog.js`, {
2571          referrerPolicy: "no-referrer"
2572        }).then((response) => response.text()).then(security.eval).then(loaded).catch((reason) => {
2573          console.log(reason);
2574          delete window.extension;
2575          loading.innerHTML = "连接失败:" + (reason instanceof Error ? reason.message : 
2575String(reason));
2576        });
2577      };
2578      if (_thisUpdate) {
2579        node.update();
2580      }
2581    };
2582    if (!get.config("menu_loadondemand")) {
2583      node._initLink();
2584    }
2585  })();
2586  var active = start.firstChild.querySelector(".active");
2587  if (!active) {
2588    active = start.firstChild.firstChild;
2589    active.classList.add("active");
2590  }
2591  if (!active.link) {
2592    active._initLink();
2593  }
2594  rightPane.appendChild(active.link);
2595  updateNodes();
2596};
2597export {
2598  extensionMenu
2599};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.