diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 373faef..e4c3232 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -49,7 +49,7 @@ jobs: git push continue-on-error: true - name: publish - uses: JS-DevTools/npm-publish@v1 + uses: JS-DevTools/npm-publish@v3 with: token: ${{ secrets.NPM_TOKEN }} continue-on-error: true diff --git a/locales/version b/locales/version index 2bbb5d8..ee0b85b 100644 --- a/locales/version +++ b/locales/version @@ -1 +1 @@ -4.3.0-beta.2 \ No newline at end of file +4.3.0-beta.3 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 05c4c37..ae04f3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dmclc", - "version": "4.3.0-beta.2", + "version": "4.3.0-beta.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dmclc", - "version": "4.3.0-beta.2", + "version": "4.3.0-beta.3", "license": "MIT", "dependencies": { "compressing": "^1.9.1", diff --git a/package.json b/package.json index 7565162..08621d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dmclc", - "version": "4.3.0-beta.2", + "version": "4.3.0-beta.3", "description": "Dolphin Minecraft Launcher Core", "typings": "./lib/index.d.ts", "module": "./lib/index.js", diff --git a/src/auth/ali_account.ts b/src/auth/ali_account.ts index 3420d2e..3b22f74 100644 --- a/src/auth/ali_account.ts +++ b/src/auth/ali_account.ts @@ -1,7 +1,7 @@ import fs from "fs"; import got from "got"; import { checkFile } from "../utils/check_file.js"; -import { download } from "../utils/downloads.js"; +import { checkAndDownload, download } from "../utils/downloads.js"; import { MinecraftVersion } from "../version.js"; import { YggdrasilAccount } from "./yggdrasil/yggdrasil_account.js"; import { YggdrasilUserData } from "./yggdrasil/yggdrasil_data.js"; @@ -24,10 +24,7 @@ export class AuthlibInjectorAccount extends YggdrasilAccount const obj = await got("https://bmclapi2.bangbang93.com/mirrors/authlib-injector/artifact/latest.json").json(); const sha256 = obj.checksums.sha256; const path = `${versionDir}/authlib-injector-latest.jar`; - if (!fs.existsSync(path) || !await checkFile(path, sha256, "sha256")) { - return await download(obj.download_url, path, this.launcher); - } - return true; + return await checkAndDownload(obj.download_url, path, sha256, this.launcher, "sha256"); } async getLaunchJVMArgs(mc: MinecraftVersion): Promise { diff --git a/src/launcher.ts b/src/launcher.ts index 9e598de..995c3f1 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -45,6 +45,16 @@ export function addExitDelete(file: string) { }); } +export function addExitDeleteDir(dir: string) { + process.addListener("beforeExit", () => { + try { + fs.rmdirSync(dir); + } catch { + + } + }); +} + class LocalizedProgress implements Progress { constructor(private dest: Progress, private t: i18next.TFunction) { @@ -96,7 +106,7 @@ export class Launcher { specialNatives: Record; }; private realRootPath = ""; - static readonly version = "4.3.0-beta.2"; + static readonly version = "4.3.0-beta.3"; /** * Create a new Launcher object. * @throws {@link FormattedError} diff --git a/src/loaders/forgelike/forgelike.ts b/src/loaders/forgelike/forgelike.ts index 4a15f07..f0e82e3 100644 --- a/src/loaders/forgelike/forgelike.ts +++ b/src/loaders/forgelike/forgelike.ts @@ -9,7 +9,7 @@ import { tmpdir } from "os"; import nodePath from "path"; import toml from "toml"; import { parseStringPromise } from "xml2js"; -import { Launcher } from "../../launcher.js"; +import { Launcher, addExitDelete, addExitDeleteDir } from "../../launcher.js"; import { ModDisplayInfo, ModInfo } from "../../mods/mod.js"; import { MCVersion } from "../../schemas.js"; import { merge } from "../../utils/MergeVersionJSONs.js"; @@ -61,8 +61,10 @@ export abstract class ForgeLikeLoader implements Loader>, launcher: Launcher, algorithm = "sha1"): Promise { + const promises: Promise[] = []; + files.forEach((v, k) => { + if (v.a === "no") { + promises.push(download(k, v.b, launcher)); + } else { + promises.push(checkAndDownload(k, v.b, v.a, launcher, algorithm)); + } + }); + return !(await Promise.all(promises)).includes(false); +} + /** * Download multi files. * @throws RequestError @@ -20,7 +41,23 @@ export async function downloadAll(files: Map, launcher: Lau }); return !(await Promise.all(promises)).includes(false); } + +/** + * Download a file after checking hash. + * @throws {@link FormattedError} + * @param url - URL. + * @param filename - File name. + * @param mirror - BMCLAPI mirror. + */ +export async function checkAndDownload(url: string, filename: fs.PathLike, hash: string, launcher: Launcher, algorithm = "sha1"): Promise { + if (!await checkFile(filename, hash, algorithm)) { + return await download(url, filename, launcher); + } + return true; +} + /** + * Download a file. * @throws {@link FormattedError} * @param url - URL. * @param filename - File name. diff --git a/src/version.ts b/src/version.ts index 1d18798..e9cfbc1 100644 --- a/src/version.ts +++ b/src/version.ts @@ -10,14 +10,14 @@ import path from "path"; import { promisify } from "util"; import { Account } from "./auth/account.js"; import { FormattedError } from "./errors/FormattedError.js"; -import { ContentType, ContentVersion } from "./index.js"; +import { ContentType, ContentVersion, Pair } from "./index.js"; import { Launcher } from "./launcher.js"; import { ModrinthContent } from "./mods/download/modrinth/ModrinthContentService.js"; import { ModManager } from "./mods/manage/ModManager.js"; import { Argument, Asset, AssetIndexInfo, AssetsIndex, Library, LibraryArtifact, MCVersion, checkRules } from "./schemas.js"; import { transformURL } from "./utils/TransformURL.js"; import { checkFile } from "./utils/check_file.js"; -import { download, downloadAll } from "./utils/downloads.js"; +import { checkAndDownload, checkAndDownloadAll, download, downloadAll } from "./utils/downloads.js"; import { expandInheritsFrom } from "./utils/expand_inherits_from.js"; import { expandMavenId } from "./utils/maven.js"; @@ -168,16 +168,13 @@ export class MinecraftVersion { */ async completeVersionInstall(): Promise { const promises = []; - if (!fs.existsSync(this.versionJarPath) || - !await checkFile(this.versionJarPath, this.versionObject.downloads.client.sha1)) { - promises.push(download(this.versionObject.downloads.client.url, this.versionJarPath, this.launcher)); - } + promises.push(checkAndDownload(this.versionObject.downloads.client.url, this.versionJarPath, this.versionObject.downloads.client.sha1, this.launcher)); promises.push(this.completeAssets(this.versionObject.assetIndex)); promises.push(this.completeLibraries(this.versionObject.libraries)); return !(await Promise.all(promises)).includes(false); } private async completeAssets (asset: AssetIndexInfo): Promise { - const allDownloads: Map = new Map(); + const allDownloads: Map> = new Map(); const indexPath = `${this.launcher.rootPath}/assets/indexes/${asset.id}.json`; let assetJson; if (!fs.existsSync(indexPath)) { @@ -191,12 +188,9 @@ export class MinecraftVersion { const assetobj: AssetsIndex = JSON.parse(assetJson); for (const assid in assetobj.objects) { const assitem: Asset = assetobj.objects[assid]; - if (!fs.existsSync(`${assetsObjects}/${assitem.hash.slice(0, 2)}/${assitem.hash}`) || - !await checkFile(`${assetsObjects}/${assitem.hash.slice(0, 2)}/${assitem.hash}`, assitem.hash)) { - allDownloads.set(`https://resources.download.minecraft.net/${assitem.hash.slice(0, 2)}/${assitem.hash}`, `${assetsObjects}/${assitem.hash.slice(0, 2)}/${assitem.hash}`); - } + allDownloads.set(`https://resources.download.minecraft.net/${assitem.hash.slice(0, 2)}/${assitem.hash}`, new Pair(assitem.hash, `${assetsObjects}/${assitem.hash.slice(0, 2)}/${assitem.hash}`)); } - return await downloadAll(allDownloads, this.launcher); + return await checkAndDownloadAll(allDownloads, this.launcher); } /** @@ -206,7 +200,7 @@ export class MinecraftVersion { * @internal */ async completeLibraries (liblist: Library[]): Promise { - const allDownloads: Map = new Map(); + const allDownloads: Map> = new Map(); const used = liblist.filter((i) => { return i.rules === undefined || checkRules(i.rules); }); @@ -216,7 +210,7 @@ export class MinecraftVersion { let url: string; if (!("url" in i)) url = "https://libraries.minecraft.net/"; else url = i.url; - allDownloads.set(`${url}${filePath}`, `${this.launcher.rootPath}/libraries/${filePath}`); + allDownloads.set(`${url}${filePath}`, new Pair("no", `${this.launcher.rootPath}/libraries/${filePath}`)); } else { const artifacts: LibraryArtifact[]=[]; if ("artifact" in i.downloads) { @@ -226,13 +220,11 @@ export class MinecraftVersion { artifacts.push(i.downloads.classifiers[i.natives[this.launcher.natives].replaceAll("${arch}", os.arch().includes("64")?"64":"32")]); } for (const artifact of artifacts) { - if(!(fs.existsSync(`${this.launcher.rootPath}/libraries/${artifact.path}`) && await checkFile(`${this.launcher.rootPath}/libraries/${artifact.path}`, artifact.sha1))){ - allDownloads.set(artifact.url, `${this.launcher.rootPath}/libraries/${artifact.path}`); - } + allDownloads.set(artifact.url, new Pair(artifact.sha1, `${this.launcher.rootPath}/libraries/${artifact.path}`)); } } } - return await downloadAll(allDownloads, this.launcher); + return await checkAndDownloadAll(allDownloads, this.launcher); } private getClassPath (versionObject: MCVersion): string[] {