diff --git a/noname/game/index.js b/noname/game/index.js index 96ef20db8..74b898be0 100644 --- a/noname/game/index.js +++ b/noname/game/index.js @@ -2229,18 +2229,72 @@ export class Game { } } alert(`导入失败:\n${JSON.stringify(error, null, "\t")}`); + console.error(error); }; try { zip.load(data); - // alert(zip.file('文件夹/加扩展.js').asText()) - const str = zip.file("extension.js").asText(); - if (str === "" || undefined) throw "你导入的不是扩展!请选择正确的文件"; + let extensionFile = zip.file("extension.js"); + let isTsFile = false; + // 未找到extension.js + if (!extensionFile) { + extensionFile = zip.file("extension.ts"); + if (!extensionFile) throw new Error("未找到extension.js"); + isTsFile = true; + } + /** @type { string } */ + // @ts-ignore + let str = extensionFile.asText(); + if (str === "" || str === undefined) throw "你导入的不是扩展!请选择正确的文件"; + // 编译ts扩展 + if (isTsFile) { + if (typeof globalThis.ts === 'undefined') { + await lib.init.promises.js('game', 'typescript'); + } + /** + * @type {typeof import('typescript')} + */ + const ts = globalThis.ts; + str = ts.transpile(str, { + module: ts.ModuleKind.ES2015, + //@todo: ES2019 -> ES2020 + target: ts.ScriptTarget.ES2019, + inlineSourceMap: true, + resolveJsonModule: true, + esModuleInterop: true, + }, 'extension.ts'); + } _status.importingExtension = true; - eval(str); - await Promise.allSettled(_status.extensionLoading); - delete _status.extensionLoading; + try { + // 导入普通扩展 + eval(str); + // esm扩展可以不写game.impoprt或许会导致_status.extensionLoading不存在 + if (Array.isArray(_status.extensionLoading)) { + await Promise.allSettled(_status.extensionLoading); + delete _status.extensionLoading; + } + } catch (error) { + // 是模块扩展 + if ( + // @ts-ignore + error.message === 'Cannot use import statement outside a module' || + // @ts-ignore + error.message === 'await is only valid in async functions and the top level bodies of modules' + ) { + // 改为用info.json判断扩展名 + const infoFile = zip.file("info.json"); + if (!infoFile) throw new Error("未找到info.json,导入模块化扩展必须加入info.json!"); + const info = JSON.parse(infoFile.asText()); + if (typeof info.name == 'string') { + await game.import('extension', () => { + return Object.assign(info, { + config: {}, + }); + }); + } + } + } _status.importingExtension = false; - if (!game.importedPack) throw "err"; + if (!game.importedPack) throw "此压缩包不是一个扩展"; const extensionName = game.importedPack.name; if (lib.config.all.plays.includes(extensionName)) throw "禁止安装游戏原生扩展"; const extensions = lib.config.extensions; @@ -2260,7 +2314,6 @@ export class Game { fileList = Object.keys(files) .filter((key) => !files[key].dir && !hiddenFileFlags.includes(key[0])) .reverse(); - //alert(filelist) //电脑端 //具备nodeJS环境 if (lib.node && lib.node.fs) { @@ -2286,14 +2339,14 @@ export class Game { ) ).then(writeFile); return fileName.length - ? game + ? game.promises .createDir(`extension/${extensionName}/${fileName.join("/")}`) .then(() => letGo(`${fileName.join("/")}/${name}`)) : letGo(name); } finishLoad(); }; - game.ensureDirectory(`extension/${extensionName}`).then(writeFile).catch(UHP); + game.promises.ensureDirectory(`extension/${extensionName}`).then(writeFile).catch(UHP); } else new Promise((resolve, reject) => window.resolveLocalFileSystemURL(nonameInitialized, resolve, reject) @@ -2351,7 +2404,7 @@ export class Game { ) .then(writeFile); return fileName.length - ? game + ? game.promises .createDir(`extension/${extensionName}/${fileName.join("/")}`) .then(() => letGo(`${fileName.join("/")}/${name}`)) : letGo(name); @@ -4960,10 +5013,13 @@ export class Game { * @param { string } extensionName */ hasExtension(extensionName) { - if (typeof lib.config[`extension_${extensionName}_enable`] != "boolean") { - game.saveExtensionConfig(extensionName, "enable", true); + if (this.hasExtensionInstalled(extensionName)) { + if (typeof lib.config[`extension_${extensionName}_enable`] != "boolean") { + game.saveExtensionConfig(extensionName, "enable", true); + } + return lib.config[`extension_${extensionName}_enable`] === true; } - return this.hasExtensionInstalled(extensionName) && lib.config[`extension_${extensionName}_enable`]; + return false; } /** * @param { string } extensionName diff --git a/noname/game/promises.js b/noname/game/promises.js index 6659b8187..a79a407d3 100644 --- a/noname/game/promises.js +++ b/noname/game/promises.js @@ -67,7 +67,7 @@ export class GamePromises { } /** * @param {string} filename - * @returns {Promise} + * @returns {Promise} */ readFile(filename) { return new Promise((resolve, reject) => { diff --git a/noname/init/node.js b/noname/init/node.js index c1a9b75ce..7331b4b2e 100644 --- a/noname/init/node.js +++ b/noname/init/node.js @@ -184,9 +184,12 @@ export function nodeReady() { game.createDir = (directory, successCallback, errorCallback) => { const target = lib.node.path.join(__dirname, directory); if (lib.node.fs.existsSync(target)) { - if (typeof errorCallback == "function") { - errorCallback(new Error(`${target}已存在`)); - } + // 修改逻辑,路径存在且是文件才会报错 + if (!lib.node.fs.lstatSync(target).isDirectory()){ + if (typeof errorCallback == "function") errorCallback(new Error(`${target}文件已存在`)); + else if (typeof successCallback == "function") successCallback(); + } + else if (typeof successCallback == "function") successCallback(); } else if (checkVersion(process.versions.node, "10.12.0") > -1) { lib.node.fs.mkdir(target, { recursive: true }, (e) => { if (e) { diff --git a/noname/library/index.js b/noname/library/index.js index 538d57d88..7977ceb56 100644 --- a/noname/library/index.js +++ b/noname/library/index.js @@ -124,6 +124,9 @@ export class Library { onload = []; onload2 = []; onprepare = []; + /** + * @type { Function[] | undefined } + */ arenaReady = []; onfree = []; inpile = []; diff --git a/noname/library/update.js b/noname/library/update.js index ebc22697f..bba8b98d3 100644 --- a/noname/library/update.js +++ b/noname/library/update.js @@ -1,4 +1,4 @@ -import { ui, game } from "../../noname.js"; +import { ui, game, lib } from "../../noname.js"; // https://github.com/libccy/noname/archive/refs/tags/v1.10.10.zip @@ -21,9 +21,12 @@ if (localStorage.getItem("noname_authorization")) { defaultHeaders["Authorization"] = `token ${localStorage.getItem("noname_authorization")}`; } +/** + * 获取github授权的token + */ export async function gainAuthorization() { if (!localStorage.getItem("noname_authorization") && !sessionStorage.getItem("noname_authorization")) { - const result = await game.promises.prompt("请输入您github的token以解除访问每小时60次的限制"); + const result = await game.promises.prompt("请输入您github的token以解除访问每小时60次的限制(可不输入)"); if (typeof result == "string") { localStorage.setItem("noname_authorization", result); defaultHeaders["Authorization"] = `token ${localStorage.getItem("noname_authorization")}`; @@ -42,11 +45,17 @@ const defaultResponse = async (/** @type {Response} */ response) => { // @ts-ignore console.log(`限制重置时间`, new Date(reset * 1000).toLocaleString()); if ( - Number(remaining) === 0 && - !sessionStorage.getItem("noname_authorization") && - confirm(`您达到了每小时${limit}次的访问限制,是否输入您github的token以获取更高的请求总量限制`) + ( + Number(remaining) === 0 && + !sessionStorage.getItem("noname_authorization") && + confirm(`您达到了每小时${limit}次的访问限制,是否输入您github账号的token以获取更高的请求总量限制`) + ) || ( + response.status === 401 && + (localStorage.removeItem("noname_authorization"), true) && + (alert(`身份验证凭证错误,是否重新输入您github账号的token以获取更高的请求总量限制`), true) + ) ) { - await gainAuthorization(); + return gainAuthorization(); } }; @@ -85,9 +94,10 @@ export function parseSize(limit) { /** * 对比版本号 - * @param { string } ver1 - * @param { string } ver2 - * @returns { -1 | 0 | 1 } + * @param { string } ver1 版本号1 + * @param { string } ver2 版本号2 + * @returns { -1 | 0 | 1 } -1为ver1 < ver2, 0为ver1 == ver2, 1为ver1 > ver2 + * @throws {Error} */ export function checkVersion(ver1, ver2) { if (typeof ver1 !== "string") ver1 = String(ver1); @@ -164,9 +174,9 @@ export function checkVersion(ver1, ver2) { * ``` */ export async function getRepoTags(options = { username: "libccy", repository: "noname" }) { - if (!localStorage.getItem("noname_authorization")) { - await gainAuthorization(); - } + // if (!localStorage.getItem("noname_authorization")) { + // await gainAuthorization(); + // } const { username = "libccy", repository = "noname", accessToken } = options; const headers = Object.assign({}, defaultHeaders); if (accessToken) { @@ -199,9 +209,9 @@ export async function getRepoTags(options = { username: "libccy", repository: "n */ export async function getRepoTagDescription(tagName, options = { username: "libccy", repository: "noname" }) { - if (!localStorage.getItem("noname_authorization")) { - await gainAuthorization(); - } + // if (!localStorage.getItem("noname_authorization")) { + // await gainAuthorization(); + // } const { username = "libccy", repository = "noname", accessToken } = options; const headers = Object.assign({}, defaultHeaders); if (accessToken) { @@ -243,7 +253,7 @@ export async function getRepoTagDescription(tagName, options = { username: "libc /** * - * 获取仓库指定分支和指定目录内的所有文件和目录 + * 获取仓库指定分支和指定(单个)目录内的所有文件和目录 * @param { string } [path = ''] 路径名称(可放参数) * @param { string } [branch = ''] 仓库分支名称 * @param { Object } options @@ -263,9 +273,9 @@ export async function getRepoFilesList( branch, options = { username: "libccy", repository: "noname" } ) { - if (!localStorage.getItem("noname_authorization")) { - await gainAuthorization(); - } + // if (!localStorage.getItem("noname_authorization")) { + // await gainAuthorization(); + // } const { username = "libccy", repository = "noname", accessToken } = options; const headers = Object.assign({}, defaultHeaders); if (accessToken) { @@ -301,6 +311,9 @@ export async function getRepoFilesList( /** * * 获取仓库指定分支和指定目录内的所有文件(包含子目录的文件) + * + * **注意: 此api可能会大幅度消耗请求次数,请谨慎使用** + * * @param { string } [path = ''] 路径名称(可放参数) * @param { string } [branch = ''] 仓库分支名称 * @param { Object } options @@ -320,6 +333,9 @@ export async function flattenRepositoryFiles( branch, options = { username: "libccy", repository: "noname" } ) { + if (!localStorage.getItem("noname_authorization")) { + await gainAuthorization(); + } /** * @type { { download_url: string, name: string, path: string, sha: string, size: number, type: 'file' }[] } */ @@ -350,7 +366,7 @@ export async function flattenRepositoryFiles( } /** - * 请求一个文件而不是直接储存为文件 + * 请求一个文件而不是直接储存为文件,这样可以省内存空间 * @param { string } url * @param { (receivedBytes: number, total?:number, filename?: string) => void } [onProgress] * @param { RequestInit } [options={}] @@ -520,18 +536,15 @@ export function createProgress(title, max, fileName, value) { } /** - * Retrieves the latest version tag from a GitHub repository, excluding a specific tag. - * This function fetches the list of tags from the GitHub repository specified by - * the owner and repository name, then returns the latest tag name that is not “v1998”. - * @param {string} owner - The username or organization name on GitHub that owns the repository. - * @param {string} repo - The name of the repository from which to fetch tags. - * @returns {Promise} A promise that resolves with the name of the latest version tag, - * or rejects with an error if the operation fails. - * @throws {Error} Will throw an error if the fetch operation fails or if no valid tags are found. + * 从GitHub存储库检索最新版本(tag),不包括特定tag。 + * + * 此函数从GitHub存储库中获取由所有者和存储库名称指定的tags列表,然后返回不是“v1998”的最新tag名称。 + * @param {string} owner GitHub上拥有存储库的用户名或组织名称。 + * @param {string} repo 要从中提取tag的存储库的名称。 + * @returns {Promise} 以最新版本tag的名称解析的promise,或者如果操作失败则以错误拒绝。 + * @throws {Error} 如果获取操作失败或找不到有效tag,将抛出错误。 */ export async function getLatestVersionFromGitHub(owner = "libccy", repo = "noname") { - if (!localStorage.getItem("noname_authorization")) await gainAuthorization(); - const tags = await getRepoTags({ username: owner, repository: repo, @@ -539,18 +552,24 @@ export async function getLatestVersionFromGitHub(owner = "libccy", repo = "nonam for (const tag of tags) { const tagName = tag.name; - if (tagName !== "v1998") return tagName; + if (tagName === "v1998") continue; + try { + checkVersion(tagName, lib.version); + return tagName; + } catch { + // 非标准版本号 + } } throw new Error("No valid tags found in the repository"); } /** - * Fetches trees from a GitHub repository within specified directories. - * @param {string[]} directories - The list of directories to fetch the trees from. - * @param {string} version - The version or branch to fetch the trees from. - * @param {string} owner - The owner of the GitHub repository. - * @param {string} repo - The name of the GitHub repository. + * 从指定目录中的GitHub存储库中获取树 + * @param {string[]} directories 要从中获取树的目录列表 + * @param {string} version 从中获取树的版本或分支。 + * @param {string} [owner = 'libccy'] GitHub上拥有存储库的用户名或组织名称。 + * @param {string} [repo = 'noname'] GitHub存储库的名称 * @returns {Promise<{ * path: string; * mode: string; @@ -562,7 +581,7 @@ export async function getLatestVersionFromGitHub(owner = "libccy", repo = "nonam * @throws {Error} Will throw an error if unable to fetch the repository tree from GitHub. */ export async function getTreesFromGithub(directories, version, owner = "libccy", repo = "noname") { - if (!localStorage.getItem("noname_authorization")) await gainAuthorization(); + // if (!localStorage.getItem("noname_authorization")) await gainAuthorization(); const treesResponse = await fetch( `https://api.github.com/repos/${owner}/${repo}/git/trees/${version}?recursive=1`, @@ -570,7 +589,7 @@ export async function getTreesFromGithub(directories, version, owner = "libccy", headers: defaultHeaders, } ); - + await defaultResponse(treesResponse); if (!treesResponse.ok) throw new Error(`Failed to fetch the GitHub repository tree: HTTP status ${treesResponse.status}`); /** diff --git a/noname/status/index.js b/noname/status/index.js index c41646590..4acb7f2f1 100644 --- a/noname/status/index.js +++ b/noname/status/index.js @@ -41,37 +41,41 @@ export class status { prehidden_skills = []; postReconnect = {}; /** - * @type { string | void } + * @type { string | undefined } */ extension = undefined; /** - * @type { boolean | void } + * @type { boolean | undefined } */ dragged = undefined; /** - * @type { boolean | void } + * @type { boolean | undefined } */ touchconfirmed = undefined; /** - * @type { boolean | void } + * @type { boolean | undefined } */ connectMode = undefined; /** - * @type { boolean | void } + * @type { boolean | undefined } */ importingExtension = undefined; /** - * @type { Promise[] | void } + * @type { Promise[] | undefined } */ extensionLoaded = undefined; /** - * @type { Promise[] | void } + * @type { Promise[] | undefined } */ extensionLoading = undefined; /** - * @type { { [key: string]: Promise[] } | void } + * @type { { [key: string]: Promise[] } | undefined } */ importing = undefined; + /** + * @type { Function | boolean | undefined } + */ + new_tutorial = undefined; } export let _status = new status(); diff --git a/noname/ui/click/index.js b/noname/ui/click/index.js index 4655a7863..c87c1d0cd 100644 --- a/noname/ui/click/index.js +++ b/noname/ui/click/index.js @@ -13,6 +13,10 @@ export class Click { * @type {(arg0: string) => void} */ menuTab; + /** + * @type {() => void} + */ + configMenu; identitycircle() { var list = []; this.classList.toggle("transparent"); diff --git a/noname/ui/create/index.js b/noname/ui/create/index.js index 1cd3e635d..109b031a1 100644 --- a/noname/ui/create/index.js +++ b/noname/ui/create/index.js @@ -2558,12 +2558,12 @@ export class Create { lib.status.date = new Date(); lib.status.dateDelayed = 0; - while (lib.arenaReady.length) { - lib.arenaReady.shift()(); - } + // @ts-ignore + while (lib.arenaReady.length) lib.arenaReady.shift()(); delete lib.arenaReady; - if (lib.config.auto_check_update) { - setTimeout(function () { + if (lib.config.auto_check_update && !sessionStorage.getItem("auto_check_update")) { + setTimeout(() => { + sessionStorage.setItem("auto_check_update", '1'); game.checkForUpdate(false); }, 3000); } @@ -2574,7 +2574,7 @@ export class Create { game.saveConfig("asset_version", "无"); } else { var func = function () { - if (confirm("是否下载图片和字体素材?(约175MB)")) { + if (confirm("是否下载图片和字体素材?(约386.6MB)")) { if (!ui.arena.classList.contains("menupaused")) { ui.click.configMenu(); ui.click.menuTab("其它"); diff --git a/noname/ui/create/menu/pages/exetensionMenu.js b/noname/ui/create/menu/pages/exetensionMenu.js index bac3d6b05..4d670eef6 100644 --- a/noname/ui/create/menu/pages/exetensionMenu.js +++ b/noname/ui/create/menu/pages/exetensionMenu.js @@ -2632,9 +2632,9 @@ export const extensionMenu = function (connectMenu) { fileReader.onerror = reject; fileReader.onload = resolve; fileReader.readAsArrayBuffer(fileToLoad, "UTF-8"); - }).then((progressEvent) => { + }).then(async (progressEvent) => { if ( - game.importExtension(progressEvent.target.result, () => { + await game.importExtension(progressEvent.target.result, () => { extensionNode.innerHTML = "导入成功,3秒后将重启"; new Promise((resolve) => setTimeout(resolve, 1000)) .then(() => { diff --git a/noname/ui/create/menu/pages/otherMenu.js b/noname/ui/create/menu/pages/otherMenu.js index 07e96dbd2..a36c1c323 100644 --- a/noname/ui/create/menu/pages/otherMenu.js +++ b/noname/ui/create/menu/pages/otherMenu.js @@ -14,12 +14,9 @@ import { ui, game, get, ai, lib, _status } from "../../../../../noname.js"; import { parseSize, checkVersion, - getRepoTags, getRepoTagDescription, - flattenRepositoryFiles, request, createProgress, - gainAuthorization, getLatestVersionFromGitHub, getTreesFromGithub, } from "../../../../library/update.js"; @@ -56,6 +53,9 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM saveButton.style.display = "none"; saveButton.style.transition = "opacity 0.3s"; + /** + * @this { HTMLDivElement } + */ var clickMode = function () { if (this.classList.contains("off")) return; var active = this.parentNode.querySelector(".active"); @@ -166,79 +166,17 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM checkDevVersionButton.disabled = true; checkVersionButton.disabled = true; - function refresh() { + const refresh = () => { checkVersionButton.disabled = false; checkVersionButton.innerHTML = "检查游戏更新"; checkDevVersionButton.disabled = false; checkDevVersionButton.innerHTML = "更新到开发版"; } - if (!dev) { - getRepoTags() - .then((tags) => tags.filter((tag) => tag.name != "v1998")[0]) - .then((tag) => { - game.saveConfig("check_version", tag.name.slice(1)); - if (typeof lib.config["version_description_" + tag.name] == "object") { - /** @type { ReturnType } */ - const description = lib.config["version_description_" + tag.name]; - return description; - } else return getRepoTagDescription(tag.name); - }) - .then((description) => { - // 保存版本信息 - if (typeof lib.config["version_description_" + description.name] != "object") { - game.saveConfig("version_description_" + description.name, description); - } - const versionResult = checkVersion(lib.version, description.name); - if (versionResult === 0) { - // forcecheck: 为false的时候是自动检测更新的调用 - if (forcecheck === false || !confirm("版本已是最新,是否强制更新?")) { - refresh(); - return; - } - } - const str = - versionResult > 0 - ? `有新版本${description.name}可用,是否下载?` - : `本地版本${lib.version}高于或等于github版本${description.name},是否强制下载?`; - const str2 = description.body; - if (navigator.notification && navigator.notification.confirm) { - navigator.notification.confirm( - str2, - function (index) { - if (index == 1) { - download(description); - } else refresh(); - }, - str, - ["确定", "取消"] - ); - } else { - if (confirm(str + "\n" + str2)) { - download(description); - } else refresh(); - } - }) - .catch((e) => { - alert("获取更新失败: " + e); - refresh(); - }); - } else { - if (confirm("将要直接下载dev版本的完整包,是否继续?")) { - download({ - name: "noname-PR-Branch", - assets: [], - zipball_url: - "https://ghproxy.cc/https://github.com/libccy/noname/archive/PR-Branch.zip", - }); - } else { - refresh(); - } - } /** * @param {{ assets: any; author?: { login: string; avatar_url: string; html_url: string; }; body?: string; html_url?: string; name: any; published_at?: string; zipball_url: any; }} description */ - function download(description) { + const download = description => { const progress = createProgress( "正在更新" + description.name, 1, @@ -333,7 +271,7 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM .then(() => { cp.exec( `start /b ${__dirname}\\noname-server.exe -platform=electron`, - () => {} + () => { } ); function loadURL() { let myAbortController = @@ -385,6 +323,69 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM throw e; }); } + + if (!dev) { + getLatestVersionFromGitHub() + .then(tagName => { + game.saveConfig("check_version", tagName.slice(1)); + if (typeof lib.config[`version_description_${tagName}`] == "object") { + /** @type { ReturnType } */ + const description = lib.config[`version_description_${tagName}`]; + return description; + } + else return getRepoTagDescription(tagName); + }) + .then(description => { + // 保存版本信息 + if (typeof lib.config["version_description_" + description.name] != "object") { + game.saveConfig("version_description_" + description.name, description); + } + const versionResult = checkVersion(lib.version, description.name); + if (versionResult === 0) { + // forcecheck: 为false的时候是自动检测更新的调用 + if (forcecheck === false || !confirm("版本已是最新,是否强制更新?")) { + refresh(); + return; + } + } + const str = + versionResult > 0 + ? `有新版本${description.name}可用,是否下载?` + : `本地版本${lib.version}高于或等于github版本${description.name},是否强制下载?`; + const str2 = description.body; + if (navigator.notification && navigator.notification.confirm) { + navigator.notification.confirm( + str2, + function (index) { + if (index == 1) { + download(description); + } else refresh(); + }, + str, + ["确定", "取消"] + ); + } else { + if (confirm(str + "\n" + str2)) { + download(description); + } else refresh(); + } + }) + .catch((e) => { + alert("获取更新失败: " + e); + refresh(); + }); + } else { + if (confirm("将要直接下载dev版本的完整包,是否继续?")) { + download({ + name: "noname-PR-Branch", + assets: [], + zipball_url: + "https://ghproxy.cc/https://github.com/libccy/noname/archive/PR-Branch.zip", + }); + } else { + refresh(); + } + } } }; @@ -392,21 +393,21 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM if (checkAssetButton.disabled) { return; } else if (game.download) { - if ( - !localStorage.getItem("noname_authorization") && - !sessionStorage.getItem("noname_authorization") - ) { - if ( - confirm( - "素材更新或许会直接超过每小时的访问限制,是否输入您github的token以解除访问每小时60次的限制?" - ) - ) - await gainAuthorization(); - } + // if ( + // !localStorage.getItem("noname_authorization") && + // !sessionStorage.getItem("noname_authorization") + // ) { + // if ( + // confirm( + // "素材更新或许会直接超过每小时的访问限制,是否输入您github的token以解除访问每小时60次的限制?" + // ) + // ) + // await gainAuthorization(); + // } checkAssetButton.innerHTML = "正在检查更新"; checkAssetButton.disabled = true; - function refresh() { + const refresh = () => { checkAssetButton.innerHTML = "检查素材更新"; checkAssetButton.disabled = false; } @@ -415,8 +416,14 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM if (lib.config.asset_font) assetDirectories.push("font"); if (lib.config.asset_audio) assetDirectories.push("audio"); if (lib.config.asset_image) assetDirectories.push("image"); - const version = await getLatestVersionFromGitHub(); - const files = await getTreesFromGithub(assetDirectories, version); + const version = await getLatestVersionFromGitHub().catch(e => { + refresh(); + throw e; + }); + const files = await getTreesFromGithub(assetDirectories, version).catch(e => { + refresh(); + throw e; + }); assetDirectories.forEach((assetDirectory, index) => { const arr = files[index]; @@ -432,18 +439,28 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM * @param { (value: T) => Promise } predicate */ const asyncFilter = async (arr, predicate) => { - const results = await Promise.all(arr.map(predicate)); + //将arr每10个分为一个数组,分别使用Promise.all + /** @type { boolean[] } */ + const results = []; + for (let i = 0; i < arr.length; i += 10) { + const pushArr = arr.slice(i, i + 10); + results.push( + ...await Promise.all(pushArr.map(predicate)) + ); + } return arr.filter((_v, index) => results[index]); }; - const result = await asyncFilter(files.flat(), async (v) => { - return v.size != (await game.promises.readFile(v.path)).length; - }).then((arr) => arr.map((v) => v.path)); + const result = await asyncFilter(files.flat(), async v => { + return game.promises.readFile(v.path).then(data => { + return v.size != data.byteLength; + }) + }).then(arr => arr.map((v) => v.path)); console.log("需要更新的文件有:", result); game.print("需要更新的文件有:", result); const finish = async () => { - await lib.init.promises.js("game", "asset.js"); + await lib.init.promises.js("game", "asset"); if (Array.isArray(window.noname_asset_list)) { game.saveConfig("asset_version", window.noname_asset_list[0]); delete window.noname_asset_list; @@ -460,7 +477,7 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM */ let unZipProgress; request( - "api.unitedrhythmized.club/noname", + "https://api.unitedrhythmized.club/noname", (receivedBytes, total, filename) => { if (typeof filename == "string") { progress.setFileName(filename);