From 1736441591099f1e2a6e0bab396edd4e989bdf10 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 15 Jul 2022 09:13:08 +0800 Subject: [PATCH] perf(install): perform better fabric install Fixed #140 --- src/modules/commons/Constants.ts | 2 +- src/modules/pff/get/FabricGet.ts | 181 ------------------ .../pff/get/{QuiltGet.ts => FabricLikeGet.ts} | 17 +- src/modules/pff/install/FabricInstall.ts | 109 ----------- src/modules/pff/modpack/InstallModpack.ts | 28 +-- src/renderer/InstallCore.tsx | 86 ++------- src/renderer/Renderer.tsx | 2 - 7 files changed, 36 insertions(+), 389 deletions(-) delete mode 100644 src/modules/pff/get/FabricGet.ts rename src/modules/pff/get/{QuiltGet.ts => FabricLikeGet.ts} (60%) delete mode 100644 src/modules/pff/install/FabricInstall.ts diff --git a/src/modules/commons/Constants.ts b/src/modules/commons/Constants.ts index d928f810..09b9323d 100644 --- a/src/modules/commons/Constants.ts +++ b/src/modules/commons/Constants.ts @@ -27,7 +27,7 @@ export const FORGE_VERSIONS_MANIFEST = "https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"; export const FABRIC_META_ROOT = "https://meta.fabricmc.net/v2"; - +export const QUILT_META_ROOT = "https://meta.quiltmc.org/v3"; // MD5 of the following text (excluding quotes): "The developer of Alicorn Launcher is really a cute filly!" export const CODE_32_SPECIAL = "61096da20861084f1e6a442d939717a8"; diff --git a/src/modules/pff/get/FabricGet.ts b/src/modules/pff/get/FabricGet.ts deleted file mode 100644 index 932026ce..00000000 --- a/src/modules/pff/get/FabricGet.ts +++ /dev/null @@ -1,181 +0,0 @@ -import fs from "fs-extra"; -import { basicHash } from "../../commons/BasicHash"; -import { Pair } from "../../commons/Collections"; -import { FABRIC_META_ROOT } from "../../commons/Constants"; -import { isNull, safeGet } from "../../commons/Null"; -import { MinecraftContainer } from "../../container/MinecraftContainer"; -import { DownloadMeta } from "../../download/AbstractDownloader"; -import { wrappedDownloadFile } from "../../download/DownloadWrapper"; -import { xgot } from "../../download/GotWrapper"; -import { JAR_SUFFIX } from "../../launch/NativesLint"; - -// Alicorn LIKE Fabric! -// Good Fabric! Noble Fabric! Excellent Fabric! - -const FABRIC_VERSIONS_ROOT = FABRIC_META_ROOT + "/versions"; - -const FABRIC_VERSIONS_GAME = FABRIC_VERSIONS_ROOT + "/game"; -export const FABRIC_VERSIONS_LOADER = FABRIC_VERSIONS_ROOT + "/loader"; -const FABRIC_VERSIONS_INSTALLER = FABRIC_VERSIONS_ROOT + "/installer"; - -const FABRIC_INSTALLER_MANIFEST_CACHE_KEY = "FabricInstallerManifestCache"; -const FABRIC_LOADER_MANIFEST_CACHE_KEY = "FabricLoaderManifestCache"; - -export async function getLatestFabricInstallerAndLoader( - filter = FabricFilter.STABLE -): Promise> { - return ( - (await _getLatestFabricInstallerAndLoader(filter, false)) || - (await _getLatestFabricInstallerAndLoader(filter, true)) - ); -} - -export async function prefetchFabricManifest(): Promise { - await _getLatestFabricInstallerAndLoader(FabricFilter.STABLE, false, true); -} - -// Get Fabric installer and loader -// Please notice that Fabric doesn't care about mojang version! -async function _getLatestFabricInstallerAndLoader( - filter = FabricFilter.STABLE, - noMirror = false, - noTimeout = false -): Promise> { - let installerURL = ""; - let loaderVersion = ""; - try { - let jInstaller; - - if ( - // @ts-ignore - window[FABRIC_INSTALLER_MANIFEST_CACHE_KEY] !== undefined && - // @ts-ignore - Object.keys(window[FABRIC_INSTALLER_MANIFEST_CACHE_KEY]).length > 0 - ) { - // @ts-ignore - jInstaller = window[FABRIC_INSTALLER_MANIFEST_CACHE_KEY]; - } else { - jInstaller = await xgot(FABRIC_VERSIONS_INSTALLER, noMirror, noTimeout); - - // @ts-ignore - window[FABRIC_INSTALLER_MANIFEST_CACHE_KEY] = jInstaller; - } - if (jInstaller instanceof Array) { - for (const i of jInstaller) { - const url = safeGet(i, ["url"], ""); - if (!isNull(url)) { - if ( - filter === FabricFilter.ANY || - safeGet(i, ["stable"], false) === true - ) { - installerURL = String(url || ""); - break; - } - } - } - } - } catch {} - - try { - let jLoader; - - if ( - // @ts-ignore - window[FABRIC_LOADER_MANIFEST_CACHE_KEY] !== undefined && - // @ts-ignore - Object.keys(window[FABRIC_LOADER_MANIFEST_CACHE_KEY]).length > 0 - ) { - // @ts-ignore - jLoader = window[FABRIC_LOADER_MANIFEST_CACHE_KEY]; - } else { - jLoader = await xgot(FABRIC_VERSIONS_LOADER, noMirror, noTimeout); - - // @ts-ignore - window[FABRIC_LOADER_MANIFEST_CACHE_KEY] = jLoader; - } - - if (jLoader instanceof Array) { - for (const l of jLoader) { - const version = safeGet(l, ["version"]); - if (!isNull(version)) { - if ( - filter === FabricFilter.ANY || - safeGet(l, ["stable"], false) === true - ) { - loaderVersion = String(version || ""); - break; - } - } - } - } - } catch {} - - return new Pair(installerURL, loaderVersion); -} - -export function generateFabricJarName(id: string): string { - return `fabric-installer-${id}` + JAR_SUFFIX; -} - -export async function removeFabricInstaller( - url: string, - container: MinecraftContainer -): Promise { - try { - await fs.remove( - container.getTempFileStorePath( - generateFabricJarName(basicHash(url).slice(0, 8)) - ) - ); - } catch { - return; - } -} - -export async function getFabricInstaller( - url: string, - container: MinecraftContainer -): Promise { - try { - const meta = new DownloadMeta( - url, - container.getTempFileStorePath( - generateFabricJarName(basicHash(url).slice(0, 8)) - ), - "" - ); - - return (await wrappedDownloadFile(meta, true)) === 1; - } catch { - return false; - } -} - -export async function canSupportGame( - version: string, - filter: FabricFilter = FabricFilter.STABLE -): Promise { - try { - const gJson = await xgot(FABRIC_VERSIONS_GAME, true); - if (gJson instanceof Array) { - for (const c of gJson) { - if (safeGet(c, ["version"]) === version) { - if ( - filter === FabricFilter.ANY || - safeGet(c, ["stable"], false) === true - ) { - return true; - } - } - } - } - return false; - } catch { - return false; - } -} - -enum FabricFilter { - STABLE, - ANY, -} diff --git a/src/modules/pff/get/QuiltGet.ts b/src/modules/pff/get/FabricLikeGet.ts similarity index 60% rename from src/modules/pff/get/QuiltGet.ts rename to src/modules/pff/get/FabricLikeGet.ts index d97bf9fd..e3e522b3 100644 --- a/src/modules/pff/get/QuiltGet.ts +++ b/src/modules/pff/get/FabricLikeGet.ts @@ -5,23 +5,24 @@ import { MinecraftContainer } from "../../container/MinecraftContainer"; import { xgot } from "../../download/GotWrapper"; import { downloadProfile } from "./MojangCore"; -const QUILT_ROOT = "https://meta.quiltmc.org/v3/versions/loader/"; - -function genQuiltName(mcv: string, ld: string): string { - return `quilt-loader-${ld}-${mcv}`; +const API_SUBFOLDER = "/versions/loader/"; +function genFabricLikeName(type: string, mcv: string, ld: string): string { + return `${type}-${ld}-${mcv}`; } -export async function getQuiltProfile( +export async function getFabricLikeProfile( + root: string, + type: string, mcv: string, c: MinecraftContainer ): Promise { try { - const loaders = await xgot(QUILT_ROOT + mcv); + const loaders = await xgot(root + API_SUBFOLDER + mcv); const loaderName = (loaders as Array<{ loader: { version: string } }>)[0] .loader.version; - const ver = genQuiltName(mcv, loaderName); + const ver = genFabricLikeName(type, mcv, loaderName); await downloadProfile( - QUILT_ROOT + mcv + "/" + loaderName + "/profile/json", + root + API_SUBFOLDER + mcv + "/" + loaderName + "/profile/json", c, ver ); diff --git a/src/modules/pff/install/FabricInstall.ts b/src/modules/pff/install/FabricInstall.ts deleted file mode 100644 index 57ca539c..00000000 --- a/src/modules/pff/install/FabricInstall.ts +++ /dev/null @@ -1,109 +0,0 @@ -import childProcess from "child_process"; -import fs from "fs-extra"; -import { basicHash } from "../../commons/BasicHash"; -import { MinecraftContainer } from "../../container/MinecraftContainer"; -import { addDoing } from "../../download/DownloadWrapper"; -import { xgot } from "../../download/GotWrapper"; -import { ensureLibraries } from "../../launch/Ensurance"; -import { GameProfile } from "../../profile/GameProfile"; -import { convertLibsByName } from "../../profile/LibrariesConvert"; -import { - FABRIC_VERSIONS_LOADER, - generateFabricJarName, -} from "../get/FabricGet"; -import { makeTempLP } from "./ForgeInstall"; - -const JAR_ARG = "-jar"; -const PROFILE_JSON_SUFFIX = "/profile/json"; - -export async function performFabricInstall( - jExecutable: string, - fbURL: string, - fbv: string, - mcv: string, - container: MinecraftContainer -): Promise { - try { - let failBit = true; - try { - await makeTempLP(container); - // Fabric has less libraries, much faster than Forge! - await ensureFabricLibrariesOL(mcv, fbv, container); - await bootFabricInstaller(jExecutable, fbURL, fbv, mcv, container); - await fs.ensureDir(container.getModsRoot()); - } catch (e) { - console.log(e); - failBit = false; - } - return failBit; - } catch (e) { - console.log(e); - return false; - } -} - -function bootFabricInstaller( - jExecutable: string, - fbURL: string, - fbv: string, - mcv: string, - container: MinecraftContainer -) { - const fArg = [ - "client", - "-dir", - container.resolvePath(), - "-mcversion", - mcv, - "-loader", - fbv, - ]; - const fbJar = container.getTempFileStorePath( - generateFabricJarName(basicHash(fbURL).slice(0, 8)) - ); - return new Promise((resolve, reject) => { - try { - const prc = childProcess.spawn( - jExecutable, - [JAR_ARG, fbJar].concat(fArg), - { - cwd: container.resolvePath(), - } - ); - prc.on("close", (code) => { - if (code === 0) { - resolve(); - } - reject(); - }); - prc.on("error", () => { - prc.kill("SIGKILL"); - reject(); - }); - prc.stdout?.on("data", (d) => { - addDoing(d.toString()); - }); - prc.stderr?.on("data", (d) => { - addDoing(d.toString()); - }); - } catch (e) { - console.log(e); - reject(e); - } - }); -} - -async function ensureFabricLibrariesOL( - mcv: string, - fbv: string, - container: MinecraftContainer -): Promise { - const url = FABRIC_VERSIONS_LOADER + `/${mcv}/${fbv}` + PROFILE_JSON_SUFFIX; - try { - const profJ = await xgot(url); - const gp = new GameProfile(convertLibsByName(Object.assign({}, profJ))); - await ensureLibraries(gp, container); - } catch { - return; - } -} diff --git a/src/modules/pff/modpack/InstallModpack.ts b/src/modules/pff/modpack/InstallModpack.ts index ab86bede..7576e958 100644 --- a/src/modules/pff/modpack/InstallModpack.ts +++ b/src/modules/pff/modpack/InstallModpack.ts @@ -4,17 +4,14 @@ import path from "path"; import { tr } from "../../../renderer/Translator"; import { basicHash } from "../../commons/BasicHash"; import { Pair } from "../../commons/Collections"; +import { FABRIC_META_ROOT } from "../../commons/Constants"; import { isFileExist } from "../../commons/FileUtil"; -import { isNull, safeGet } from "../../commons/Null"; +import { safeGet } from "../../commons/Null"; import { MinecraftContainer } from "../../container/MinecraftContainer"; import { addDoing } from "../../download/DownloadWrapper"; import { getDefaultJavaHome, getJavaRunnable } from "../../java/JavaInfo"; import { ProfileType } from "../../profile/WhatProfile"; -import { - getFabricInstaller, - getLatestFabricInstallerAndLoader, - removeFabricInstaller, -} from "../get/FabricGet"; +import { getFabricLikeProfile } from "../get/FabricLikeGet"; import { generateForgeInstallerName, getForgeInstaller, @@ -22,7 +19,6 @@ import { removeForgeInstaller, } from "../get/ForgeGet"; import { downloadProfile, getProfileURLById } from "../get/MojangCore"; -import { performFabricInstall } from "../install/FabricInstall"; import { performForgeInstall } from "../install/ForgeInstall"; import { fetchSelectedMod, setPffFlag } from "../virtual/PffWrapper"; import { @@ -184,31 +180,19 @@ export async function deployModLoader( } case ProfileType.FABRIC: default: { - const u = (await getLatestFabricInstallerAndLoader()).getFirstValue(); - if (isNull(u)) { - throw "Could not fetch installer: No such installer!"; - } - if (!(await getFabricInstaller(u, container))) { - await removeFabricInstaller(u, container); - throw "Failed to fetch installer!"; - } - const jr = await getJavaRunnable(getDefaultJavaHome()); await Promise.allSettled( mcVersions.map((mcVersion) => { return (async () => { if ( - !(await performFabricInstall( - jr, - u, - version, + !(await getFabricLikeProfile( + FABRIC_META_ROOT, + "fabric-loader", mcVersion, container )) ) { - await removeFabricInstaller(u, container); throw "Could not perform install!"; } - await removeFabricInstaller(u, container); })(); }) ); diff --git a/src/renderer/InstallCore.tsx b/src/renderer/InstallCore.tsx index ab401908..206c609b 100644 --- a/src/renderer/InstallCore.tsx +++ b/src/renderer/InstallCore.tsx @@ -17,7 +17,12 @@ import { import { EventEmitter } from "events"; import React, { useEffect, useRef, useState } from "react"; import { throttle } from "throttle-debounce"; -import { ALICORN_SEPARATOR, ReleaseType } from "../modules/commons/Constants"; +import { + ALICORN_SEPARATOR, + FABRIC_META_ROOT, + QUILT_META_ROOT, + ReleaseType, +} from "../modules/commons/Constants"; import { isNull } from "../modules/commons/Null"; import { scanCoresInAllMountedContainers } from "../modules/container/ContainerScanner"; import { @@ -31,12 +36,7 @@ import { unsubscribeDoing, } from "../modules/download/DownloadWrapper"; import { getDefaultJavaHome, getJavaRunnable } from "../modules/java/JavaInfo"; -import { - canSupportGame, - getFabricInstaller, - getLatestFabricInstallerAndLoader, - removeFabricInstaller, -} from "../modules/pff/get/FabricGet"; +import { getFabricLikeProfile } from "../modules/pff/get/FabricLikeGet"; import { generateForgeInstallerName, getForgeInstaller, @@ -48,8 +48,6 @@ import { getAllMojangCores, getProfileURLById, } from "../modules/pff/get/MojangCore"; -import { getQuiltProfile } from "../modules/pff/get/QuiltGet"; -import { performFabricInstall } from "../modules/pff/install/FabricInstall"; import { performForgeInstall } from "../modules/pff/install/ForgeInstall"; import { loadProfile } from "../modules/profile/ProfileLoader"; import { ProfileType, whatProfile } from "../modules/profile/WhatProfile"; @@ -86,8 +84,6 @@ export function InstallCore(): JSX.Element { const [baseMojangVersionFabric, setBaseMojangVersionFabric] = useState(""); const [detectedForgeVersion, setDetectedForgeVersion] = useState(""); - const [detectedFabricVersion, setDetectedFabricVersion] = - useState(""); const [selectedMojangContainer, setMojangContainer] = useState(""); const [selectedForgeContainer, setForgeContainer] = useState(""); const [selectedFabricContainer, setFabricContainer] = useState(""); @@ -143,20 +139,6 @@ export function InstallCore(): JSX.Element { } })(); }, [baseMojangVersionForge]); - useEffect(() => { - void (async () => { - if (!(await canSupportGame(baseMojangVersionFabric))) { - if (mounted.current) { - setDetectedFabricVersion(""); - } - return; - } - const d = (await getLatestFabricInstallerAndLoader()).getSecondValue(); - if (mounted.current) { - setDetectedFabricVersion(d); - } - })(); - }, [baseMojangVersionFabric]); useEffect(() => { void (async () => { const aCores = await filterFabricCores(); @@ -584,11 +566,6 @@ export function InstallCore(): JSX.Element { {tr("InstallCore.InstallFabricInstr")} - - {tr("InstallCore.FabricVersion") + - " " + - (detectedFabricVersion || tr("InstallCore.Unknown"))} -
{ clearDoing(); setChangePageWarn(true); setOperating(true); setFailed(false); - setProgressMsg( - "Resloving Fabric installer and loader info..." - ); - const u = ( - await getLatestFabricInstallerAndLoader() - ).getFirstValue(); - const fbv = detectedFabricVersion; const mcv = baseMojangVersionFabric; const ct = getContainer(selectedFabricContainer); - if (isNull(u)) { - if (mounted.current) { - setFailedMsg("Invalid Fabric info received."); - setOperating(false); - setChangePageWarn(false); - setFailed(true); - } - return; - } - const [stat2, fbapi] = await Promise.allSettled([ + const [stat2, qtapi] = await Promise.allSettled([ (async () => { setProgressMsg( tr( @@ -676,21 +634,12 @@ export function InstallCore(): JSX.Element { `MCV=${mcv}` ) ); - if (!(await getFabricInstaller(u, ct))) { - return false; - } - setProgressMsg( - tr("InstallCore.Progress.ExecutingFabric") - ); - const s0 = await performFabricInstall( - await getJavaRunnable(getDefaultJavaHome()), - u, - fbv, + return await getFabricLikeProfile( + FABRIC_META_ROOT, + "fabric-loader", mcv, ct ); - await removeFabricInstaller(u, ct); - return s0; })(), pffInstall( "@Modrinth:P7dR8mSH", @@ -709,8 +658,8 @@ export function InstallCore(): JSX.Element { setFailedMsg(tr("InstallCore.Progress.CouldNotExecute")); } return; - } else if (!fbapi) { - submitWarn(tr("InstallCore.Fabric.FabricAPIFailed")); + } else if (!qtapi) { + submitWarn(tr("InstallCore.Quilt.QuiltAPIFailed")); } updateFabricCores(!updateFabricCoresBit); setProgressMsg("Done! Cleaning up files..."); @@ -800,7 +749,12 @@ export function InstallCore(): JSX.Element { `MCV=${mcv}` ) ); - return await getQuiltProfile(mcv, ct); + return await getFabricLikeProfile( + QUILT_META_ROOT, + "quilt-loader", + mcv, + ct + ); })(), pffInstall( "@Modrinth:qvIfYCYJ", diff --git a/src/renderer/Renderer.tsx b/src/renderer/Renderer.tsx index 75b87b3d..74a797a7 100644 --- a/src/renderer/Renderer.tsx +++ b/src/renderer/Renderer.tsx @@ -26,7 +26,6 @@ import { initConcurrentDownloader } from "../modules/download/Concurrent"; import { initDownloadWrapper } from "../modules/download/DownloadWrapper"; import { loadAllMirrors, loadMirror } from "../modules/download/Mirror"; import { loadJDT, preCacheJavaInfo } from "../modules/java/JavaInfo"; -import { prefetchFabricManifest } from "../modules/pff/get/FabricGet"; import { prefetchForgeManifest } from "../modules/pff/get/ForgeGet"; import { prefetchMojangVersions } from "../modules/pff/get/MojangCore"; import { initForgeInstallModule } from "../modules/pff/install/ForgeInstall"; @@ -274,7 +273,6 @@ try { await Promise.allSettled([ updPm, prefetchForgeManifest(), - prefetchFabricManifest(), prefetchMojangVersions(), ]); const t4 = new Date();