From 8aee01bc4eeda5dc919d61489954485ffcca0cd5 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Thu, 14 Jul 2022 17:57:39 +0800 Subject: [PATCH 01/23] fix(launch): fix auth fail when launch during keep --- src/renderer/ReadyToLaunch.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/renderer/ReadyToLaunch.tsx b/src/renderer/ReadyToLaunch.tsx index b7c041ff..5c8efde4 100644 --- a/src/renderer/ReadyToLaunch.tsx +++ b/src/renderer/ReadyToLaunch.tsx @@ -198,8 +198,11 @@ export const LAST_CRASH_KEY = "ReadyToLaunch.LastCrash"; export function ReadyToLaunch(): JSX.Element { const [coreProfile, setProfile] = useState(new GameProfile({})); const [profileLoadedBit, setLoaded] = useState(0); - let { id, container, server } = - useParams<{ id: string; container: string; server?: string }>(); + let { id, container, server } = useParams<{ + id: string; + container: string; + server?: string; + }>(); id = decodeURIComponent(id); container = decodeURIComponent(container); server = server ? decodeURIComponent(server) : undefined; @@ -845,6 +848,7 @@ async function startBoot( console.log("Token valid, skipped auth."); } } else { + account = new MicrosoftAccount(""); // Use the latest data console.log( "MS account auth job has been done by ReadyBoom. Skipped." ); From 931b3d3dec8e820758911db3de0cef1fc21f05aa Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Thu, 14 Jul 2022 23:44:46 +0800 Subject: [PATCH 02/23] #139 feat(*): add basic quilt support --- resources/shared/defaults/Equish.lang | 18 ++- resources/shared/defaults/PonyCN.lang | 28 +++- resources/shared/defaults/PonyTW.lang | 24 +++- resources/shared/img/Quilt.svg | 1 + src/modules/container/MinecraftContainer.ts | 4 + src/modules/modx/ModInfo.ts | 1 + src/modules/pff/get/QuiltGet.ts | 33 +++++ src/modules/pff/modpack/InstallModpack.ts | 3 +- src/modules/pff/modrinth/Get.ts | 16 ++- src/modules/pff/virtual/ModDefine.ts | 4 +- src/modules/pff/virtual/PffWrapper.ts | 9 +- src/modules/pff/virtual/Resolver.ts | 38 +++-- src/modules/profile/WhatProfile.ts | 5 + src/renderer/Icons.ts | 1 + src/renderer/InstallCore.tsx | 148 ++++++++++++++++++-- src/renderer/LaunchPad.tsx | 4 + src/renderer/PffFront.tsx | 8 +- 17 files changed, 293 insertions(+), 52 deletions(-) create mode 100644 resources/shared/img/Quilt.svg create mode 100644 src/modules/pff/get/QuiltGet.ts diff --git a/resources/shared/defaults/Equish.lang b/resources/shared/defaults/Equish.lang index 646f494c..9ca07645 100644 --- a/resources/shared/defaults/Equish.lang +++ b/resources/shared/defaults/Equish.lang @@ -266,6 +266,10 @@ Forge Mods are supported. Fabric Mods are supported. +# CoreInfo.Introduction.Quilt + +Quilt Mods are supported. + # CoreInfo.Introduction.Installer It's a modpack installer! @@ -1014,7 +1018,7 @@ Retrofit (Fabric) # InstallCore.InstallFabricInstr -@HTMLRetrofit an installed Minecraft core to a Fabric core. Both of then will be available. With this you can play Fabric mods. +@HTMLRetrofit an installed Minecraft core to a Fabric core. Both of them will be available. With this you can play Fabric mods. # InstallCore.InstallIris @@ -1028,6 +1032,18 @@ Install Iris Install To +# InstallCore.InstallQuilt + +Retrofit (Quilt) + +# InstallCore.InstallQuiltInstr + +@HTMLRetrofit an installed Minecraft core to a Quilt core. Both of them will be available. With this you can play Quilt mods. + +# InstallCore.QuiltBaseVersion + +Install To + # InstallCore.TargetContainer Target Container diff --git a/resources/shared/defaults/PonyCN.lang b/resources/shared/defaults/PonyCN.lang index 997624d7..a48d4d92 100644 --- a/resources/shared/defaults/PonyCN.lang +++ b/resources/shared/defaults/PonyCN.lang @@ -278,6 +278,10 @@ Alicorn 无法读/写 {Target},请检查此目录的权限,相关操作已 此核心可以加载 Fabric Mod +# CoreInfo.Introduction.Quilt + +此核心可以加载 Quilt Mod + # CoreInfo.Introduction.Installer 这不是核心,这是一个整合包安装器 @@ -1047,6 +1051,10 @@ Pff 正安装 Mod…… 安装 Fabric API 失败,许多 Fabric Mod 需要它。\n前往 Pff,输入 fabric-api 重新进行安装。 +# InstallCore.Fabric.FabricAPIFailed + +安装 Quilt API 失败,许多 Quilt Mod 需要它。\n前往 Pff,输入 qsl 重新进行安装。 + # InstallCore.Progress.CouldNotExecute 没能执行安装程序…… @@ -1089,7 +1097,7 @@ Pff 正安装 Mod…… # InstallCore.InstallMinecraft -添加新的核心 +添加核心 # InstallCore.InstallMinecraftInstr @@ -1097,7 +1105,7 @@ Pff 正安装 Mod…… # InstallCore.InstallForge -改装已有核心(Forge) +改装核心(Forge) # InstallCore.InstallForgeInstr @@ -1105,7 +1113,7 @@ Pff 正安装 Mod…… # InstallCore.InstallFabric -改装已有核心(Fabric) +改装核心(Fabric) # InstallCore.InstallFabricInstr @@ -1123,6 +1131,18 @@ Pff 正安装 Mod…… 安装到此 Fabric 上 +# InstallCore.InstallQuilt + +改装核心(Quilt) + +# InstallCore.InstallQuiltInstr + +@HTML为已有的 Minecraft 核心进行改装并安装 Quilt,它可以支持部分 Fabric Mod 和 Forge Mod。\n注意:你必须安装了对应版本的 Minecraft 核心才可以进行改装!\nQuilt 尚在开发中,请注意可能存在的风险及漏洞! + +# InstallCore.QuiltBaseVersion + +目标 Minecraft 版本号 + # InstallCore.TargetContainer 目标容器 @@ -3408,7 +3428,7 @@ END # Instruction.InstallCore.1 -使用 <添加新的核心> 来安装新的 Minecraft 原版核心。@5.40 +使用 <添加核心> 来安装新的 Minecraft 原版核心。@5.40 # Instruction.InstallCore.2 diff --git a/resources/shared/defaults/PonyTW.lang b/resources/shared/defaults/PonyTW.lang index f442306d..a32a0921 100644 --- a/resources/shared/defaults/PonyTW.lang +++ b/resources/shared/defaults/PonyTW.lang @@ -278,6 +278,10 @@ Alicorn 無法讀/寫 {Target},請檢查此目錄的權限,相關操作已 此核心可以加載 Fabric Mod +# CoreInfo.Introduction.Quilt + +此核心可以加載 Quilt Mod + # CoreInfo.Introduction.Installer 這不是核心,這是一個整合包安裝器 @@ -1089,7 +1093,7 @@ Pff 正安裝 Mod…… # InstallCore.InstallMinecraft -添加新的核心 +添加核心 # InstallCore.InstallMinecraftInstr @@ -1097,7 +1101,7 @@ Pff 正安裝 Mod…… # InstallCore.InstallForge -改裝已有核心(Forge) +改裝核心(Forge) # InstallCore.InstallForgeInstr @@ -1105,7 +1109,7 @@ Pff 正安裝 Mod…… # InstallCore.InstallFabric -改裝已有核心(Fabric) +改裝核心(Fabric) # InstallCore.InstallFabricInstr @@ -1123,6 +1127,18 @@ Pff 正安裝 Mod…… 安裝到此 Fabric 上 +# InstallCore.InstallQuilt + +改裝核心(Quilt) + +# InstallCore.InstallQuiltInstr + +@HTML為已有的 Minecraft 核心進行改裝並安裝 Quilt,它可以支持部分 Fabric Mod 和 Forge Mod。 \n注意:你必須安裝了對應版本的 Minecraft 核心才可以進行改裝! \nQuilt 尚在開發中,請注意可能存在的風險及漏洞! + +# InstallCore.QuiltBaseVersion + +目標 Minecraft 版本號 + # InstallCore.TargetContainer 目標容器 @@ -3408,7 +3424,7 @@ END # Instruction.InstallCore.1 -使用 <添加新的核心> 來安裝新的 Minecraft 原版核心。@5.40 +使用 <添加核心> 來安裝新的 Minecraft 原版核心。@5.40 # Instruction.InstallCore.2 diff --git a/resources/shared/img/Quilt.svg b/resources/shared/img/Quilt.svg new file mode 100644 index 00000000..93d24d4f --- /dev/null +++ b/resources/shared/img/Quilt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/modules/container/MinecraftContainer.ts b/src/modules/container/MinecraftContainer.ts index c635a140..22a08cb5 100644 --- a/src/modules/container/MinecraftContainer.ts +++ b/src/modules/container/MinecraftContainer.ts @@ -91,6 +91,10 @@ export class MinecraftContainer { return path.resolve(this.getVersionRoot(id), id + ".json"); } + getClientPath(id: string): string { + return path.resolve(this.getVersionRoot(id), id + ".jar"); + } + getLibraryPath(libPath: string): string { return path.resolve(this.librariesBase, libPath); } diff --git a/src/modules/modx/ModInfo.ts b/src/modules/modx/ModInfo.ts index ba8c5be9..1e6b7aef 100644 --- a/src/modules/modx/ModInfo.ts +++ b/src/modules/modx/ModInfo.ts @@ -27,6 +27,7 @@ export interface ModInfo { enum ModLoader { FORGE = "Forge", FABRIC = "Fabric", + QUILT = "Quilt", UNKNOWN = "Unknown", } diff --git a/src/modules/pff/get/QuiltGet.ts b/src/modules/pff/get/QuiltGet.ts new file mode 100644 index 00000000..d97bf9fd --- /dev/null +++ b/src/modules/pff/get/QuiltGet.ts @@ -0,0 +1,33 @@ +// For Quilt, we only needs to download profile and that's all. + +import { copy } from "fs-extra"; +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}`; +} + +export async function getQuiltProfile( + mcv: string, + c: MinecraftContainer +): Promise { + try { + const loaders = await xgot(QUILT_ROOT + mcv); + const loaderName = (loaders as Array<{ loader: { version: string } }>)[0] + .loader.version; + const ver = genQuiltName(mcv, loaderName); + await downloadProfile( + QUILT_ROOT + mcv + "/" + loaderName + "/profile/json", + c, + ver + ); + await copy(c.getClientPath(mcv), c.getClientPath(ver)); // Yeah, that's all, quite easy. + return true; + } catch { + return false; + } +} diff --git a/src/modules/pff/modpack/InstallModpack.ts b/src/modules/pff/modpack/InstallModpack.ts index 86f432c2..ab86bede 100644 --- a/src/modules/pff/modpack/InstallModpack.ts +++ b/src/modules/pff/modpack/InstallModpack.ts @@ -28,6 +28,7 @@ import { fetchSelectedMod, setPffFlag } from "../virtual/PffWrapper"; import { AbstractModResolver, CurseforgeModResolver, + ModLoaderType, ModrinthModResolver, } from "../virtual/Resolver"; import { ModpackModel, SimpleFile, transformManifest5 } from "./CFModpackModel"; @@ -243,7 +244,7 @@ async function installSingleMod( fid: string | number, container: MinecraftContainer, gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise { let mr: AbstractModResolver; if (typeof aid === "number" || typeof fid === "number") { diff --git a/src/modules/pff/modrinth/Get.ts b/src/modules/pff/modrinth/Get.ts index 34ba45e0..32947da3 100644 --- a/src/modules/pff/modrinth/Get.ts +++ b/src/modules/pff/modrinth/Get.ts @@ -1,6 +1,7 @@ import { isNull, safeGet } from "../../commons/Null"; import { pgot } from "../../download/GotWrapper"; import { ModArtifact, ModMeta } from "../virtual/ModDefine"; +import { ModLoaderType } from "../virtual/Resolver"; export async function searchMetaBySlug( slug: string, @@ -71,12 +72,11 @@ export async function lookupModMetaInfo( const rs = (await pgot(ACCESS_URL, timeout)) as any; // For other values const slug = String(rs["slug"]); const t = await getModMetaBySlug(slug, apiBase, timeout); // Only for support versions - if (t === undefined) { - return t; - } + const sv = t ? t.supportVersions : []; // Empty means everything + // Sometimes Modrinth return null for its existed names... return { id: String(rs["id"]), - supportVersions: t.supportVersions, + supportVersions: sv, thumbNail: String(rs["icon_url"] || ""), slug: slug, provider: "Modrinth", @@ -107,7 +107,11 @@ export async function getVersionListForMod( return; } let m = 0; + if (l.includes("quilt")) { + m += 8; + } if (l.includes("fabric")) { + // Also accept quilt m += 1; } if (l.includes("forge")) { @@ -125,7 +129,7 @@ export async function getVersionListForMod( } p.push({ id: String(c["id"]), - modLoader: m === 1 ? "Fabric" : "Forge", // 3 is preserved, currently we haven't found a Forge and Fabric compatible mod + modLoader: m === 1 ? "Fabric" : m === 8 ? "Quilt" : "Forge", gameVersion: c["game_versions"] || [], fileName: f[0]["filename"], hash: safeGet(f[0], ["hashes", "sha1"], undefined) as @@ -144,7 +148,7 @@ export async function getVersionListForMod( export function findCompatibleArtifact( versions: ModArtifact[], gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): ModArtifact | undefined { for (const a of versions) { if (a.modLoader === modLoader && a.gameVersion.includes(gameVersion)) { diff --git a/src/modules/pff/virtual/ModDefine.ts b/src/modules/pff/virtual/ModDefine.ts index dfed841c..9d69a7c3 100644 --- a/src/modules/pff/virtual/ModDefine.ts +++ b/src/modules/pff/virtual/ModDefine.ts @@ -1,3 +1,5 @@ +import { ModLoaderType } from "./Resolver"; + export interface ModMeta { provider: "Modrinth" | "Curseforge" | "CursePlusPlus"; // ...CPP stands for a browser-based Curseforge API @@ -9,7 +11,7 @@ export interface ModMeta { } export interface ModArtifact { - modLoader: "Fabric" | "Forge"; + modLoader: ModLoaderType; id: string; gameVersion: string[]; downloadUrl: string; diff --git a/src/modules/pff/virtual/PffWrapper.ts b/src/modules/pff/virtual/PffWrapper.ts index 4813e62f..25710e77 100644 --- a/src/modules/pff/virtual/PffWrapper.ts +++ b/src/modules/pff/virtual/PffWrapper.ts @@ -9,6 +9,7 @@ import { AbstractModResolver, CurseforgeModResolver, CursePlusPlusModResolver, + ModLoaderType, ModResolver, ModrinthModResolver, } from "./Resolver"; @@ -18,7 +19,7 @@ const SLUG_SCOPE_REGEX = /(?<=@)(curseforge|modrinth|curseplusplus)(?=:.+?)/i; export async function fetchModByName( slug: string, gameVersion: string, - modLoader: "Fabric" | "Forge", + modLoader: ModLoaderType, container: MinecraftContainer ): Promise { // slug can be '@Provider:Slug' @@ -53,6 +54,10 @@ export async function fetchModByName( await c.setSelected(sid, undefined); // Set id } await c.resolveMod(); + if (c.cachedMeta?.id === sid) { + sx = c; + break; + } if (!sx) { sx = c; // Find the first as the best } @@ -98,7 +103,7 @@ export async function fetchModByName( export async function fetchSelectedMod( rsv: ModResolver, gameVersion: string, - modLoader: "Fabric" | "Forge", + modLoader: ModLoaderType, container: MinecraftContainer ): Promise { const lf = await loadLockfile(container); diff --git a/src/modules/pff/virtual/Resolver.ts b/src/modules/pff/virtual/Resolver.ts index c15e1671..3ccf1966 100644 --- a/src/modules/pff/virtual/Resolver.ts +++ b/src/modules/pff/virtual/Resolver.ts @@ -30,12 +30,9 @@ export interface ModResolver { searchMods(num: number): Promise; getArtifactFor( gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise; - canSupport( - gameVersion: string, - modLoader: "Fabric" | "Forge" - ): Promise; + canSupport(gameVersion: string, modLoader: ModLoaderType): Promise; setSelected( mainId: string | undefined, artifactId: string | undefined @@ -64,11 +61,11 @@ export abstract class AbstractModResolver implements ModResolver { abstract searchMods(num: number): Promise; abstract getArtifactFor( gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise; abstract canSupport( gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise; abstract setSelected( mainId: string | undefined, @@ -133,7 +130,7 @@ export class CurseforgeModResolver extends AbstractModResolver { } async getArtifactFor( gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise { if (this.cachedArtifact) { return this.cachedArtifact; @@ -168,10 +165,7 @@ export class CurseforgeModResolver extends AbstractModResolver { } throw "Failed to lookup artifact!"; } - canSupport( - gameVersion: string, - modLoader: "Fabric" | "Forge" - ): Promise { + canSupport(gameVersion: string, modLoader: ModLoaderType): Promise { if (!this.insideCachedAddonInfo) { throw "Must resolve first!"; } @@ -241,7 +235,7 @@ export class CursePlusPlusModResolver extends AbstractModResolver { } async getArtifactFor( gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise { if (this.cachedArtifact) { return this.cachedArtifact; @@ -262,10 +256,7 @@ export class CursePlusPlusModResolver extends AbstractModResolver { } throw "Check compatibility first!"; } - canSupport( - gameVersion: string, - modLoader: "Fabric" | "Forge" - ): Promise { + canSupport(gameVersion: string, modLoader: ModLoaderType): Promise { if (this.cachedArtifactGroup === null) { throw "Must resolve first!"; } @@ -329,7 +320,7 @@ export class ModrinthModResolver extends AbstractModResolver { } async getArtifactFor( gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise { if (this.cachedArtifact) { return this.cachedArtifact; @@ -357,7 +348,7 @@ export class ModrinthModResolver extends AbstractModResolver { } async canSupport( gameVersion: string, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): Promise { if (!this.mainId) { throw "Must resolve first!"; @@ -410,7 +401,12 @@ function transformAddonInfoToMeta(aInfo: AddonInfo): ModMeta { }; } -export function modLoaderOf(type: number): "Forge" | "Fabric" { +export type ModLoaderType = "Forge" | "Fabric" | "Quilt"; + +export function modLoaderOf(type: number): ModLoaderType { + if (type === 8) { + return "Quilt"; + } if (type === 4) { return "Fabric"; } @@ -419,7 +415,7 @@ export function modLoaderOf(type: number): "Forge" | "Fabric" { function transformFileInfoToArtifact( file: File, - modLoader: "Fabric" | "Forge" + modLoader: ModLoaderType ): ModArtifact { return { downloadUrl: file.downloadUrl, diff --git a/src/modules/profile/WhatProfile.ts b/src/modules/profile/WhatProfile.ts index b2b62687..223d7830 100644 --- a/src/modules/profile/WhatProfile.ts +++ b/src/modules/profile/WhatProfile.ts @@ -2,6 +2,7 @@ import { isNull } from "../commons/Null"; const FABRIC_NAME = /fabric/i; const FORGE_NAME = /forge/i; +const QUILT_NAME = /quilt/i; const MOJANG_NAME_RELEASE = /^[0-9]+?\.[0-9]+?(\.)?[0-9]*$/i; const MOJANG_NAME_SNAPSHOT = /^[0-9]+?w[0-9]+?[a-z]+$/i; const LEGACY_VERSIONS = /^1\.([0-9]|1[0-2])([-.a-z].*?)?$/i; @@ -29,6 +30,9 @@ export function whatProfile(id: string): ProfileType { if (FORGE_NAME.test(id)) { return ProfileType.FORGE; } + if (QUILT_NAME.test(id)) { + return ProfileType.QUILT; + } if (INSTALLER.test(id)) { return ProfileType.INSTALLER; } @@ -41,6 +45,7 @@ export enum ProfileType { FABRIC = "Fabric", UNIVERSAL = "Universal", INSTALLER = "Installer", + QUILT = "Quilt", } export function isLegacy(obj: Record): boolean { diff --git a/src/renderer/Icons.ts b/src/renderer/Icons.ts index 8e98b7aa..cd90bc8a 100644 --- a/src/renderer/Icons.ts +++ b/src/renderer/Icons.ts @@ -7,5 +7,6 @@ export enum Icons { CONTAINER_ASC = "img/EnderChest.gif", CONTAINER_MCX = "img/Chest.gif", PROFILE_IRIS = "img/Iris.webp", + PROFILE_QUILT = "img/Quilt.svg", ALEX = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAIAElEQVR42uWa728URRjH968wanznj5DoC9BASIopJFKgHFIbCUmlNQVLGhoDoqRa0rQaAgJFDRoSEuGNJmITrVrPKIgmGo0EXlg1/CYkBIwoUOUtL9b7Pt3v9NnnZq/X2722XDf5ZmZndu/2+5lnZnd2Nggm2K4dXBaK9tWHRflCerb/8ZIKUm6XD+bGNLC0OF9IR/oWllTqTZslgIvvLpL0r0M5Z3Rwd1tMmQFQZgng9P4lkl451OyMfrS7PabsAESGYZYgBEAEhObf394UEyFkEQEwDLMEIQAiIDR/sKc5JkLIJAJiAFQ3QHnVAUSGHQDVDVA+JQAgAaC6A/YB4PLPH1QdACQAVHfAPgBc+unDKgMwg57u/1DVAZhBT/d/qOoAXH/XdwEVBQTgUxYAXH/XdwEVBQTgUyYA9ODHVrddoJTS/r8e/NjqtguUUtkhTqM0afu8Sz23Rd9xGpwv5e9rczq0bZ93qee26DtOg/Ol/P0g0UjChXMMsGaSoLlyTxShLNFIwoVzDLBmkqC5ck8UoSwodeHWKMz/8/uwKNbSBGZa3oLRUcbfLHXh1ijMX/8tL4q1NIGZlrdgdJQ5ALZV2bdZxjzN3z5/NLx68mORHhTdb+hWNpB83cK2qr0D6A3G/z33bcljYq1sIPm6RRALadPKyMPonTt3wgfXPyTmb1/6QfIoQ51+Kiw1JmjAOh8L6cgMWxnby40PBIX/CuZvX+BMIo8y1OnHZd9t044XOrKQd7c5try0csGkmC3o1umvwtFzx5x5SS8cD2+d+UbyBOU16ukWsf2CeJvjqC6tfPFHaWnb2iy3UeEgWqOebhHbly5g+jzDXMzScJSOHvtcRDiE5SAkjPR6ULVji+3zDHMxSxBRevP4sIhwCMtBSBjp9aBqx5bYkx5DX0eAky5TcIrMT3Rb5HjBByl1wQx9HQFOukzBKTI/0W2RY05UVrS9sOSxUGvOnDkxTfRc0ZPvDnfuai96L0AAnUvnltSEvz/UHVJnj74nDYD0mXkPB1DqLSsAWgDA8M8EQP4uAcDHYeSrAYDmkW5aPDeAZgwAN5gWpMeGLLtAJgAc0YgqLuK1NU+G/S2Lwxcbn5B9gGA68N0eUe8XPSJ3bnQ+6iwA+zTonXeY2+jr+b5w79E3Q93i/H2Uy3+ba0c564OhoUBUTovzx2Fy69MLBACkzTO/OTdf4EA4Vl8AL3DP3o0xAIwCfSfg8XbuAeM07wBQ+W5nHv9j/5vnoG5SALRRGiSMpHoAEgCeFpIL3Nc5Pm9QzwDWEA1TbMEYABVlupVtBLB80gAo3RdpcLIAuoe2uW4CCBDNx7pMdJ6+aG0cxyLtf6Ml3LV7vQh5dK+33+mStFRdRQAY4jvbGkTI23o7aNkW0gAYqmL+yx5vSPsAOIAFXT1xJCZGFVSqbrB3YwBNuNXV1YUUDb767CIRW14f09DQEFMsAgopTWtT2lwMwFC8T2sATK05/RiuQbCOadkAVqxYEVIw2NLSEra2toqQR5k+ZtWqVeHatWtFyFsAtvWtIdtldIszz3MJQJslgOu/Dsn+jT++LsxKByXVj+oVAYDa29vDrq4uEfK2vghAPt4FeOHsCtpMDIA5Xh+rz4ExGkV6fWQcwui541J+7eQn4ej578fhjAxPHgBb2gdAR4EFcO/Ce8L76+9z6er+XAyAHhNQh2N8x8uxn70SOwd1MKglAKLJGPZhnHVukjaZCIAJqLm52XWBDRs2iNgFUMfjGhsbw6amJhHyOvyRwhilzXJfD4CQrddwIJqDUWllmrz8SzGAQhnq/i7kD2x+LoAmBWDdunVFEYCyyQCwfZ63s9gY4Dnejhssp3GaFZORUdaxnuVQ2QDq6+tDCmbR8lu2bBEhjzJ9zPLly8NcLidC3vc4irvHtqaFMaFM7gL5ZABWqBPjUV93AFQX0FFQEYDp2jo6Oio7cWAgCAYHJcXkh9PgzKbDM36D+VOnJOUMcHYCKEQATRNEJu8DZvymuoA1X5sA2tqCYNOmce3YMQYB0uXQ/v1j6ukZ112/rVwZBJ2dY+rrG5vhHTkSBIcPj+1Dug4iCKgmIkADgHkanZUA0PIwOVsiYOtTjwYHnl8i2rWmLuAzPoR9iPUsf6tzjVNNAsATnqSqvGYBdNQ94gUgmm0AtEkLQHePmgRgW1kDsONDTY4BFoAeA2x09LbmnGoaQNJdoCYBUDCF0Eb60rJ5Qe/qBU4sn1YAaRdXZfXIs/xd9mSHk6Voujzl7wvSAtBLaBUBgPkIxLS8L8gCANYS7fJ32QYIoJBOy/uC1ABg3vMBRNkApvp9gf1+AN8UcPFUL6vr5XW98KFfkLL1Sy2j4Rwc4yY+0/2+wK4ec2XZri4nfl+gDPL7gaKl8VLr/3hfwI0zQkYCZ4u6LuvZogUAU0hhkKvLZS2vm/V/3xcg3vV/RIAGgPcF2PR0udoA9NI5vzDxhb8PQOr1fwsAxrHpFyZTBaCS7wvSrv/jQYkb5wOMAD4pYqvabDHt9wVp1/+TAOi5QlUBpP2+IGn9n2b18rhv/R+zxRkDoJLvC7RBrAHq9X+WY/0/CcCVM58GN/88IUL+6oXh4L8bI5JyX+dZlzmASr8vmGj9P6nOFwFsZcmr9wU6OjKPgLTfFxSt8EYGYTapzkZAUiuXqststpj2+wK99u9MqvV/DcHVFeQbBHUE6PcFdgzIdLqc9vsCGGNft2v83k9gPAB87wtQV877gv8BjY2wPg7jcKEAAAAASUVORK5CYII=", } diff --git a/src/renderer/InstallCore.tsx b/src/renderer/InstallCore.tsx index 99b6487e..0e0ecee7 100644 --- a/src/renderer/InstallCore.tsx +++ b/src/renderer/InstallCore.tsx @@ -12,7 +12,7 @@ import { Tab, Tabs, ThemeProvider, - Typography + Typography, } from "@mui/material"; import { EventEmitter } from "events"; import React, { useEffect, useRef, useState } from "react"; @@ -22,32 +22,33 @@ import { isNull } from "../modules/commons/Null"; import { scanCoresInAllMountedContainers } from "../modules/container/ContainerScanner"; import { getAllMounted, - getContainer + getContainer, } from "../modules/container/ContainerUtil"; import { clearDoing, getDoing, subscribeDoing, - unsubscribeDoing + unsubscribeDoing, } from "../modules/download/DownloadWrapper"; import { getDefaultJavaHome, getJavaRunnable } from "../modules/java/JavaInfo"; import { canSupportGame, getFabricInstaller, getLatestFabricInstallerAndLoader, - removeFabricInstaller + removeFabricInstaller, } from "../modules/pff/get/FabricGet"; import { generateForgeInstallerName, getForgeInstaller, getForgeVersionByMojang, - removeForgeInstaller + removeForgeInstaller, } from "../modules/pff/get/ForgeGet"; import { downloadProfile, getAllMojangCores, - getProfileURLById + 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"; @@ -61,7 +62,7 @@ import { pffInstall } from "./PffFront"; import { ALICORN_DEFAULT_THEME_DARK, ALICORN_DEFAULT_THEME_LIGHT, - isBgDark + isBgDark, } from "./Renderer"; import { useFormStyles } from "./Stylex"; import { tr } from "./Translator"; @@ -98,6 +99,9 @@ export function InstallCore(): JSX.Element { const [updateFabricCoresBit, updateFabricCores] = useState(false); const [selectedIrisBase, setSelectedIrisBase] = useState(""); const [selectedIrisContainer, setSelectedIrisContainer] = useState(""); + const [selectedQuiltContainer, setQuiltContainer] = useState(""); + const [baseMojangVersionQuilt, setBaseMojangVersionQuilt] = + useState(""); function setProgressMsg(msg: string): void { // Binding if (mounted.current) { @@ -153,7 +157,6 @@ export function InstallCore(): JSX.Element { } })(); }, [baseMojangVersionFabric]); - useEffect(() => { void (async () => { const aCores = await filterFabricCores(); @@ -233,7 +236,6 @@ export function InstallCore(): JSX.Element { } /> - @@ -270,6 +272,24 @@ export function InstallCore(): JSX.Element { } /> + + + + + + + {tr("InstallCore.InstallQuilt")} + + + + } + /> {/* Mojang */} @@ -791,6 +811,116 @@ export function InstallCore(): JSX.Element { + {/* Quilt */} + + + + {tr("InstallCore.InstallQuiltInstr")} + +
+ + + {tr("InstallCore.QuiltBaseVersion")} + + + +
+ +
+
diff --git a/src/renderer/LaunchPad.tsx b/src/renderer/LaunchPad.tsx index 09ccee8c..5111fedd 100644 --- a/src/renderer/LaunchPad.tsx +++ b/src/renderer/LaunchPad.tsx @@ -591,6 +591,8 @@ function getDescriptionFor(type: string): string { return tr("CoreInfo.Introduction.Installer"); case "FABRIC": return tr("CoreInfo.Introduction.Fabric"); + case "QUILT": + return tr("CoreInfo.Introduction.Quilt"); default: return ""; } @@ -622,6 +624,8 @@ function getIconForProfile(p: SimplifiedCoreInfo): string { return Icons.PROFILE_FABRIC; case "Installer": return Icons.PROFILE_INSTALLER; + case "Quilt": + return Icons.PROFILE_QUILT; case "Universal": default: return Icons.PROFILE_UNKNOWN; diff --git a/src/renderer/PffFront.tsx b/src/renderer/PffFront.tsx index 0f977464..dad09f3c 100644 --- a/src/renderer/PffFront.tsx +++ b/src/renderer/PffFront.tsx @@ -63,7 +63,6 @@ export function PffFront(): JSX.Element { name = name ? decodeURIComponent(name) : undefined; loader = decodeURIComponent(loader); autostart = autostart ? decodeURIComponent(autostart) : undefined; - const [isRunning, setRunning] = useState(autostart === "1"); const [val, setVal] = useState(0); const [info, setInfo] = useState(""); @@ -148,7 +147,7 @@ export function PffFront(): JSX.Element { getContainer(container), version, emitter.current, - loader === "Forge" ? 1 : 4 + loader === "Forge" ? 1 : loader === "Quilt" ? 8 : 4 ); } }) @@ -174,7 +173,7 @@ export function PffFront(): JSX.Element { getContainer(container), version, emitter.current, - loader === "Forge" ? 1 : 4 + loader === "Forge" ? 1 : loader === "Quilt" ? 8 : 4 ); } }) @@ -388,6 +387,8 @@ export function PffFront(): JSX.Element { ? ModLoader.FORGE : loader === "Fabric" ? ModLoader.FABRIC + : loader === "Quilt" + ? ModLoader.QUILT : ModLoader.UNKNOWN } mcversion={version} @@ -634,6 +635,7 @@ export async function pffInstall( name = name.slice(0, -1); } const ml = modLoaderOf(modLoader); + const idx = `[${name}] `; if (!ml) { if (!optional) { From 2c9b83f48ec7633d273b005856f83ef87648f223 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Thu, 14 Jul 2022 23:49:07 +0800 Subject: [PATCH 03/23] chore(pff): remove unnecessary if --- src/renderer/PffFront.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/renderer/PffFront.tsx b/src/renderer/PffFront.tsx index dad09f3c..03c49662 100644 --- a/src/renderer/PffFront.tsx +++ b/src/renderer/PffFront.tsx @@ -637,13 +637,8 @@ export async function pffInstall( const ml = modLoaderOf(modLoader); const idx = `[${name}] `; - if (!ml) { - if (!optional) { - emitter.emit( - PFF_MSG_GATE, - `[${name}] ` + tr("PffFront.UnsupportedLoader") - ); - } + if (!optional) { + emitter.emit(PFF_MSG_GATE, `[${name}] ` + tr("PffFront.UnsupportedLoader")); } setPffFlag("1"); emitter.emit(PFF_MSG_GATE, idx + tr("PffFront.Loading")); From 84170897647d4397c408663599229b2603dbd7d0 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 15 Jul 2022 08:58:43 +0800 Subject: [PATCH 04/23] security(*): fix alert --- src/renderer/Instruction.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/renderer/Instruction.tsx b/src/renderer/Instruction.tsx index 1169ccc3..a8d47561 100644 --- a/src/renderer/Instruction.tsx +++ b/src/renderer/Instruction.tsx @@ -90,7 +90,11 @@ function InstructionInside(props: { borderStyle: "solid", }} > - + Date: Fri, 15 Jul 2022 09:00:14 +0800 Subject: [PATCH 05/23] perf(ui): sort core installation --- src/renderer/InstallCore.tsx | 180 +++++++++++++++++------------------ 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/src/renderer/InstallCore.tsx b/src/renderer/InstallCore.tsx index 0e0ecee7..ab401908 100644 --- a/src/renderer/InstallCore.tsx +++ b/src/renderer/InstallCore.tsx @@ -261,12 +261,12 @@ export function InstallCore(): JSX.Element { - {tr("InstallCore.InstallIris")} + {tr("InstallCore.InstallQuilt")} @@ -279,12 +279,12 @@ export function InstallCore(): JSX.Element { - {tr("InstallCore.InstallQuilt")} + {tr("InstallCore.InstallIris")} @@ -726,93 +726,8 @@ export function InstallCore(): JSX.Element { - {/* Iris */} - - - - {tr("InstallCore.InstallIrisInstr")} - -
- - - {tr("InstallCore.IrisBaseVersion")} - - - -
- -
-
{/* Quilt */} - + {tr("InstallCore.InstallQuiltInstr")} @@ -921,6 +836,91 @@ export function InstallCore(): JSX.Element { + {/* Iris */} + + + + {tr("InstallCore.InstallIrisInstr")} + +
+ + + {tr("InstallCore.IrisBaseVersion")} + + + +
+ +
+
From 1736441591099f1e2a6e0bab396edd4e989bdf10 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 15 Jul 2022 09:13:08 +0800 Subject: [PATCH 06/23] 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(); From 3a6b730cd45c99066cb29a204636270cc982950b Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 15 Jul 2022 09:27:14 +0800 Subject: [PATCH 07/23] #139 feat(pff): run check for quilt --- src/modules/modx/ModDynLoad.ts | 19 ++++++++++++++++--- src/modules/modx/ModInfo.ts | 16 ++++++++++++++-- src/modules/pff/modrinth/Get.ts | 8 +++++++- src/renderer/PffFront.tsx | 14 +++++++++----- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/modules/modx/ModDynLoad.ts b/src/modules/modx/ModDynLoad.ts index 325fb04b..b1702692 100644 --- a/src/modules/modx/ModDynLoad.ts +++ b/src/modules/modx/ModDynLoad.ts @@ -6,7 +6,7 @@ import { FileOperateReport, LaunchTracker } from "../launch/LaunchTracker"; import { JAR_SUFFIX } from "../launch/NativesLint"; import { GameProfile } from "../profile/GameProfile"; import { ProfileType } from "../profile/WhatProfile"; -import { loadModInfo, ModInfo, ModLoader } from "./ModInfo"; +import { loadModInfo, ModInfo, ModLoader, modLoaderOfStr } from "./ModInfo"; import { canModVersionApply, gatherVersionInfo } from "./ModVersionUtil"; // How we manage mods: // Before launch: @@ -71,11 +71,11 @@ async function moveModsTo( } mi.mcversion = mi.mcversion || "*"; // Fallback if ( - mi.loader?.toString() !== type.toString() || + !chkModLoader(mi.loader, modLoaderOfStr(type)) || !canModVersionApply( mi.mcversion || "", mcVersion, - mi.loader === ModLoader.FABRIC + mi.loader !== ModLoader.FORGE ) ) { toProcess.push(mi); @@ -197,3 +197,16 @@ async function scanModsList( tracker.mods(tFile); } } + +export function chkModLoader( + mod: ModLoader | undefined, + loader: ModLoader | undefined +): boolean { + if (mod === loader) { + return true; + } + if (mod === ModLoader.FABRIC && loader === ModLoader.QUILT) { + return true; + } + return false; +} diff --git a/src/modules/modx/ModInfo.ts b/src/modules/modx/ModInfo.ts index 1e6b7aef..61b77524 100644 --- a/src/modules/modx/ModInfo.ts +++ b/src/modules/modx/ModInfo.ts @@ -24,14 +24,26 @@ export interface ModInfo { description?: string; } -enum ModLoader { +export enum ModLoader { FORGE = "Forge", FABRIC = "Fabric", QUILT = "Quilt", UNKNOWN = "Unknown", } -export { ModLoader }; +export function modLoaderOfStr(org: string): ModLoader { + if (org === "Quilt") { + return ModLoader.QUILT; + } + if (org === "Fabric") { + return ModLoader.FABRIC; + } + if (org === "Forge") { + return ModLoader.FORGE; + } + return ModLoader.UNKNOWN; +} + // Load mod info export async function loadModInfo( modJar: string, diff --git a/src/modules/pff/modrinth/Get.ts b/src/modules/pff/modrinth/Get.ts index 32947da3..e139a900 100644 --- a/src/modules/pff/modrinth/Get.ts +++ b/src/modules/pff/modrinth/Get.ts @@ -1,5 +1,7 @@ import { isNull, safeGet } from "../../commons/Null"; import { pgot } from "../../download/GotWrapper"; +import { chkModLoader } from "../../modx/ModDynLoad"; +import { modLoaderOfStr } from "../../modx/ModInfo"; import { ModArtifact, ModMeta } from "../virtual/ModDefine"; import { ModLoaderType } from "../virtual/Resolver"; @@ -151,8 +153,12 @@ export function findCompatibleArtifact( modLoader: ModLoaderType ): ModArtifact | undefined { for (const a of versions) { - if (a.modLoader === modLoader && a.gameVersion.includes(gameVersion)) { + if ( + chkModLoader(modLoaderOfStr(a.modLoader), modLoaderOfStr(modLoader)) && + a.gameVersion.includes(gameVersion) + ) { return a; } } + return undefined; } diff --git a/src/renderer/PffFront.tsx b/src/renderer/PffFront.tsx index 03c49662..3df03898 100644 --- a/src/renderer/PffFront.tsx +++ b/src/renderer/PffFront.tsx @@ -29,8 +29,8 @@ import { getBoolean } from "../modules/config/ConfigSupport"; import { getContainer as _getContainer } from "../modules/container/ContainerUtil"; import { MinecraftContainer } from "../modules/container/MinecraftContainer"; import { configureModDepChain, UnmetDepUnit } from "../modules/modx/ModDeps"; -import { loadMetas } from "../modules/modx/ModDynLoad"; -import { ModInfo, ModLoader } from "../modules/modx/ModInfo"; +import { chkModLoader, loadMetas } from "../modules/modx/ModDynLoad"; +import { ModInfo, ModLoader, modLoaderOfStr } from "../modules/modx/ModInfo"; import { canModVersionApply } from "../modules/modx/ModVersionUtil"; import { loadLockfile, @@ -467,8 +467,12 @@ function SinglePffModDisplay(props: { }): JSX.Element { const [showDesc, setShowDesc] = useState(false); const isCompatible = - props.meta.selectedArtifact.gameVersion.includes(props.version) && - props.loader === props.meta.selectedArtifact.modLoader; + (props.meta.selectedArtifact.gameVersion.length === 0 || + props.meta.selectedArtifact.gameVersion.includes(props.version)) && + chkModLoader( + modLoaderOfStr(props.loader), + modLoaderOfStr(props.meta.selectedArtifact.modLoader) + ); return ( Date: Fri, 15 Jul 2022 09:40:19 +0800 Subject: [PATCH 08/23] fix(pff): fix compatible check --- src/renderer/PffFront.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/renderer/PffFront.tsx b/src/renderer/PffFront.tsx index 3df03898..e8e8d01e 100644 --- a/src/renderer/PffFront.tsx +++ b/src/renderer/PffFront.tsx @@ -470,9 +470,10 @@ function SinglePffModDisplay(props: { (props.meta.selectedArtifact.gameVersion.length === 0 || props.meta.selectedArtifact.gameVersion.includes(props.version)) && chkModLoader( - modLoaderOfStr(props.loader), - modLoaderOfStr(props.meta.selectedArtifact.modLoader) + modLoaderOfStr(props.meta.selectedArtifact.modLoader), + modLoaderOfStr(props.loader) ); + return ( Date: Wed, 20 Jul 2022 06:41:15 +0000 Subject: [PATCH 09/23] chore(deps): bump terser from 5.10.0 to 5.14.2 Bumps [terser](https://github.com/terser/terser) from 5.10.0 to 5.14.2. - [Release notes](https://github.com/terser/terser/releases) - [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md) - [Commits](https://github.com/terser/terser/commits) --- updated-dependencies: - dependency-name: terser dependency-type: indirect ... Signed-off-by: dependabot[bot] --- yarn.lock | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/yarn.lock b/yarn.lock index 39ac441e..29e5622e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -465,7 +465,7 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/gen-mapping@^0.3.2": +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== @@ -475,15 +475,23 @@ "@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/resolve-uri@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.3.tgz#b80093f4edbb5490c49746231513669c8f518acb" - integrity sha512-fuIOnc81C5iRNevb/XPiM8Khp9bVjreydRQ37rt0C/dY0PAW1DRvEM3WrKX/5rStS5lbgwS0FCgqSndh9tvK5w== + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" @@ -1140,12 +1148,7 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.4.1: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - -acorn@^8.7.1: +acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1: version "8.7.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== @@ -4602,11 +4605,6 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -4822,12 +4820,13 @@ terser-webpack-plugin@^5.1.3: terser "^5.7.2" terser@^5.7.2: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== + version "5.14.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10" + integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA== dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" commander "^2.20.0" - source-map "~0.7.2" source-map-support "~0.5.20" text-table@^0.2.0: From bcca4668c920d5253033f5bd0415500a0a64e8aa Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Wed, 20 Jul 2022 19:28:42 +0800 Subject: [PATCH 10/23] feat(user): add boss key --- resources/shared/defaults/PonyCN.lang | 8 ++++++++ resources/shared/defaults/alicorn.config.json | 3 ++- src/main/Background.ts | 14 ++++++++++++++ src/modules/access/BossKey.ts | 16 ++++++++++++++++ src/modules/launch/MinecraftBootstrap.ts | 6 ++++++ src/renderer/Options.tsx | 7 +++++++ src/renderer/Renderer.tsx | 3 ++- 7 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/modules/access/BossKey.ts diff --git a/resources/shared/defaults/PonyCN.lang b/resources/shared/defaults/PonyCN.lang index a48d4d92..fc4288ee 100644 --- a/resources/shared/defaults/PonyCN.lang +++ b/resources/shared/defaults/PonyCN.lang @@ -2223,6 +2223,14 @@ Mod 动态加载 不使用 Mojang 提供的 Log4j 配置文件以在启动疑难解答中获得更清晰的日志 - 副作用是输出到文件的日志会很混乱 +# Options.bosskey.title + +老板键 ^ + +# Options.bosskey.desc + +我们一直在努力为每个人争取正当、公平的玩游戏的权利,不受任何监管或制约。\n尽管如此,仍然有些人听不进去,所以这是留给你的小礼物~\n在此设置一个快捷键,此后按下它可随时隐藏 Alicorn,终止 Minecraft。\n(快捷键格式类似 Ctrl+B+S 或者 F6) + # CrashReportDisplay.BaseInfo 基本信息 diff --git a/resources/shared/defaults/alicorn.config.json b/resources/shared/defaults/alicorn.config.json index 006b8b41..2e020f50 100644 --- a/resources/shared/defaults/alicorn.config.json +++ b/resources/shared/defaults/alicorn.config.json @@ -69,5 +69,6 @@ "pff.upgrade-mode": "Override", "cx.shared-root": "", "interactive.cadance": false, - "interactive.boticorn": false + "interactive.boticorn": false, + "bosskey": "" } diff --git a/src/main/Background.ts b/src/main/Background.ts index 935cd3a1..e4313150 100644 --- a/src/main/Background.ts +++ b/src/main/Background.ts @@ -2,6 +2,7 @@ import { app, BrowserWindow, dialog, + globalShortcut, ipcMain, safeStorage, screen, @@ -306,6 +307,14 @@ export function registerBackgroundListeners(): void { }); } ); + ipcMain.on("toggleWindow", () => { + const win = getMainWindow(); + if (win?.isVisible()) { + win.hide(); + } else { + win?.show(); + } + }); ipcMain.on("hideWindow", () => { getMainWindow()?.hide(); }); @@ -364,4 +373,9 @@ export function registerBackgroundListeners(): void { e.returnValue = ""; } }); + ipcMain.on("registerHotKey", (e, k) => { + globalShortcut.register(k, () => { + getMainWindow()?.webContents.send("HotKey-" + k); + }); + }); } diff --git a/src/modules/access/BossKey.ts b/src/modules/access/BossKey.ts new file mode 100644 index 00000000..c6dee28b --- /dev/null +++ b/src/modules/access/BossKey.ts @@ -0,0 +1,16 @@ +// Quickly kill Minecraft and hide Alicorn with just one hot key. + +import { ipcRenderer } from "electron"; +import { getString } from "../config/ConfigSupport"; +import { stopAllMinecraft } from "../launch/MinecraftBootstrap"; + +export function registerBossKey(): void { + const k = getString("bosskey"); + if (k.length > 0) { + ipcRenderer.send("registerHotKey", k); + ipcRenderer.on("HotKey-" + k, () => { + stopAllMinecraft(); + ipcRenderer.send("toggleWindow"); + }); + } +} diff --git a/src/modules/launch/MinecraftBootstrap.ts b/src/modules/launch/MinecraftBootstrap.ts index 5985c676..47cb1a41 100644 --- a/src/modules/launch/MinecraftBootstrap.ts +++ b/src/modules/launch/MinecraftBootstrap.ts @@ -142,3 +142,9 @@ export function runMinecraft( export function stopMinecraft(runID: string): void { POOL.get(runID)?.kill(); } + +export function stopAllMinecraft(): void { + for (const v of POOL.values()) { + v.kill(); + } +} diff --git a/src/renderer/Options.tsx b/src/renderer/Options.tsx index 19aa272c..ff646d5f 100644 --- a/src/renderer/Options.tsx +++ b/src/renderer/Options.tsx @@ -30,6 +30,7 @@ import { InsertPhoto, Inventory2, Iso, + Keyboard, LockOpen, LockReset, Memory, @@ -230,6 +231,12 @@ export function OptionsPage(): JSX.Element { bindConfig={"interactive.assistant?"} reload /> + } + type={ConfigType.STR} + bindConfig={"bosskey"} + reload + /> } type={ConfigType.BOOL} diff --git a/src/renderer/Renderer.tsx b/src/renderer/Renderer.tsx index 74a797a7..8b3ecd15 100644 --- a/src/renderer/Renderer.tsx +++ b/src/renderer/Renderer.tsx @@ -7,6 +7,7 @@ import React from "react"; import { createRoot } from "react-dom/client"; import { HashRouter } from "react-router-dom"; import pkg from "../../package.json"; +import { registerBossKey } from "../modules/access/BossKey"; import { reloadAccounts } from "../modules/auth/AccountUtil"; import { prepareAJ } from "../modules/auth/AJHelper"; import { prepareND } from "../modules/auth/NDHelper"; @@ -217,7 +218,7 @@ try { void todayPing(); void startCadanceProc(); void initBoticorn(); - + registerBossKey(); // Heavy works and minor works await Promise.allSettled([initVF(), preCacheJavaInfo()]); const t2 = new Date(); From 0670862f85765a589326b5f4f698247819f0b052 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Wed, 20 Jul 2022 22:12:05 +0800 Subject: [PATCH 11/23] perf(auth): add timeout show for ms browser --- src/main/Background.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/Background.ts b/src/main/Background.ts index e4313150..7300a3f0 100644 --- a/src/main/Background.ts +++ b/src/main/Background.ts @@ -202,6 +202,11 @@ export function registerBackgroundListeners(): void { mode: "system", }); } */ + setTimeout(() => { + if (!loginWindow?.isVisible()) { + loginWindow?.show(); + } + }, 5000); // Easy everyone, don't get panic! await loginWindow.loadURL(LOGIN_START); return new Promise((resolve) => { loginWindow?.on("close", () => { From da3fae581f4e19651bcca51487cef6e9ece4656c Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Wed, 20 Jul 2022 22:15:32 +0800 Subject: [PATCH 12/23] fix(auth): fix wrong window open --- src/main/Background.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/Background.ts b/src/main/Background.ts index 7300a3f0..d19d6885 100644 --- a/src/main/Background.ts +++ b/src/main/Background.ts @@ -203,7 +203,11 @@ export function registerBackgroundListeners(): void { }); } */ setTimeout(() => { - if (!loginWindow?.isVisible()) { + if ( + loginWindow && + !loginWindow?.isDestroyed() && + !loginWindow?.isVisible() + ) { loginWindow?.show(); } }, 5000); // Easy everyone, don't get panic! @@ -226,7 +230,7 @@ export function registerBackgroundListeners(): void { sCode = decodeURIComponent( (url.match(CODE_REGEX) || [])[0] || "" ); - loginWindow?.close(); + loginWindow?.destroy(); loginWindow = null; if (t) { clearTimeout(t); @@ -248,7 +252,7 @@ export function registerBackgroundListeners(): void { ); } console.log("Error occurred. Closing login window."); - loginWindow?.close(); + loginWindow?.destroy(); loginWindow = null; if (t) { clearTimeout(t); @@ -260,7 +264,7 @@ export function registerBackgroundListeners(): void { "Not a callback URL, but quiet required, resolving." ); resolve(""); - loginWindow?.close(); + loginWindow?.destroy(); loginWindow = null; return; } @@ -277,7 +281,6 @@ export function registerBackgroundListeners(): void { if (res.response === 1) { sCode = "USER PROVIDE"; try { - loginWindow?.close(); loginWindow?.destroy(); } catch {} loginWindow = null; From fd86a93a74ddc884982d2fd934c028b8fb77896a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Jul 2022 21:05:03 +0000 Subject: [PATCH 13/23] chore(deps): bump undici from 5.6.0 to 5.8.0 Bumps [undici](https://github.com/nodejs/undici) from 5.6.0 to 5.8.0. - [Release notes](https://github.com/nodejs/undici/releases) - [Commits](https://github.com/nodejs/undici/compare/v5.6.0...v5.8.0) --- updated-dependencies: - dependency-name: undici dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a9e467ff..cabbf259 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "sudo-prompt": "^9.2.1", "throttle-debounce": "^5.0.0", "toml": "^3.0.0", - "undici": "^5.6.0", + "undici": "^5.8.0", "uuid": "^8.3.2", "ws": "^8.8.0" } diff --git a/yarn.lock b/yarn.lock index 39ac441e..61a23984 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4968,10 +4968,10 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undici@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.6.0.tgz#3fd695d4454970bae3d151326ee4ab645b8d1962" - integrity sha512-mc+8SY1fXubTrdx4CXDkeFFGV8lI3Tq4I/70U1V8Z6g4iscGII0uLO7CPnDt56bXEbvaKwo2T2+VrteWbZiXiQ== +undici@^5.8.0: + version "5.8.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.8.0.tgz#dec9a8ccd90e5a1d81d43c0eab6503146d649a4f" + integrity sha512-1F7Vtcez5w/LwH2G2tGnFIihuWUlc58YidwLiCv+jR2Z50x0tNXpRRw7eOIJ+GvqCqIkg9SB7NWAJ/T9TLfv8Q== unique-string@^1.0.0: version "1.0.0" From cd22cb2ac46c6593e0286f731d373d4b5fee8354 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Sat, 23 Jul 2022 14:57:14 +0800 Subject: [PATCH 14/23] fix(auth): fix ms logout problem --- src/main/Background.ts | 46 ++++++++++++++++++++++++++++ src/modules/auth/MicrosoftAccount.ts | 2 +- src/renderer/ReadyToLaunch.tsx | 18 ++++++----- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/main/Background.ts b/src/main/Background.ts index d19d6885..19826623 100644 --- a/src/main/Background.ts +++ b/src/main/Background.ts @@ -20,10 +20,14 @@ import { getMainWindow, getMainWindowUATrimmed } from "./Bootstrap"; import { closeDM, getDMWindow } from "./DisplayManager"; const LOGIN_START = "https://login.live.com/oauth20_authorize.srf?client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf"; +const LOGOUT_START = + "https://login.live.com/oauth20_logout.srf?client_id=00000000402b5328&response_type=code&scope=service%3A%3Auser.auth.xboxlive.com%3A%3AMBI_SSL&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf"; let loginWindow: BrowserWindow | null = null; +let logoutWindow: BrowserWindow | null = null; const CODE_REGEX = /(?<=\?code=)[^&]+/gi; const ERROR_REGEX = /(?<=\?error=)[^&]+/gi; const ERROR_DESCRIPTION = /(?<=&error_description=)[^&]+/gi; +const LOGOUT_OK_HEAD = "https://login.live.com/oauth20_desktop.srf"; export function registerBackgroundListeners(): void { bindCurseListeners(); @@ -386,4 +390,46 @@ export function registerBackgroundListeners(): void { getMainWindow()?.webContents.send("HotKey-" + k); }); }); + ipcMain.handle( + "msLogout", + async (_e, proxy: string, key = "alicorn_ms_login_initial") => { + return new Promise((res, rej) => { + try { + void (async () => { + const { width, height } = screen.getPrimaryDisplay().workAreaSize; + logoutWindow = + logoutWindow || + new BrowserWindow({ + frame: false, + width: Math.floor(width * 0.6), + height: Math.floor(height * 0.6), + show: false, + backgroundColor: "#fff", + webPreferences: { + partition: "persist:" + key, + spellcheck: false, + }, + }); + logoutWindow.webContents.setUserAgent(getMainWindowUATrimmed()); + if (proxy.trim().length > 0) { + await logoutWindow.webContents.session.setProxy({ + proxyRules: proxy, + }); + } + await logoutWindow.loadURL(LOGOUT_START); + logoutWindow.webContents.on("did-navigate", () => { + if ( + logoutWindow?.webContents.getURL().startsWith(LOGOUT_OK_HEAD) + ) { + logoutWindow.destroy(); + res(); + } + }); + })(); + } catch { + rej(); + } + }); + } + ); } diff --git a/src/modules/auth/MicrosoftAccount.ts b/src/modules/auth/MicrosoftAccount.ts index 73a3347f..97d7e6a8 100644 --- a/src/modules/auth/MicrosoftAccount.ts +++ b/src/modules/auth/MicrosoftAccount.ts @@ -184,7 +184,7 @@ function saveAccessToken(v: string): void { // Only in remote! async function browserGetCode(quiet = false): Promise { const LOGIN_WINDOW_KEY = - window.localStorage.getItem("MS.LoginWindowKey") || + // window.localStorage.getItem("MS.LoginWindowKey") || "alicorn_ms_login_initial"; console.log("Building login window..."); const r = await ipcRenderer.invoke( diff --git a/src/renderer/ReadyToLaunch.tsx b/src/renderer/ReadyToLaunch.tsx index 5c8efde4..991095e3 100644 --- a/src/renderer/ReadyToLaunch.tsx +++ b/src/renderer/ReadyToLaunch.tsx @@ -43,6 +43,7 @@ import { } from "@mui/material"; import { makeStyles } from "@mui/styles"; import copy from "copy-to-clipboard"; +import { ipcRenderer } from "electron"; import EventEmitter from "events"; import os from "os"; import React, { useEffect, useMemo, useRef, useState } from "react"; @@ -1345,22 +1346,23 @@ function AccountChoose(props: { className={btnClasses.btn} disabled={msLogout === "ReadyToLaunch.MSLogoutRunning"} onClick={() => { - void (() => { + void (async () => { // @ts-ignore window[SESSION_ACCESSDATA_CACHED_KEY] = false; setMSLogout("ReadyToLaunch.MSLogoutRunning"); - window.localStorage.setItem( + /* window.localStorage.setItem( "MS.LoginWindowKey", "alicorn_ms_login_" + new Date().getTime() - ); + ); */ dropAccountPromise(); - localStorage.setItem(MS_LAST_USED_REFRESH_KEY, ""); - localStorage.setItem(MS_LAST_USED_ACTOKEN_KEY, ""); - localStorage.setItem(MS_LAST_USED_UUID_KEY, ""); - localStorage.setItem(MS_LAST_USED_USERNAME_KEY, ""); - localStorage.setItem(MS_LAST_USED_XUID_KEY, ""); + localStorage.removeItem(MS_LAST_USED_REFRESH_KEY); + localStorage.removeItem(MS_LAST_USED_ACTOKEN_KEY); + localStorage.removeItem(MS_LAST_USED_UUID_KEY); + localStorage.removeItem(MS_LAST_USED_USERNAME_KEY); + localStorage.removeItem(MS_LAST_USED_XUID_KEY); localStorage.removeItem(ACCOUNT_EXPIRES_KEY); // Reset time localStorage.removeItem(ACCOUNT_LAST_REFRESHED_KEY); + await ipcRenderer.invoke("msLogout"); if (mounted.current) { setMSLogout("ReadyToLaunch.MSLogoutDone"); } From 78e95d8e2f1500b0f4d147856f33c129c0dc59c0 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Thu, 28 Jul 2022 21:24:30 +0800 Subject: [PATCH 15/23] fix(ui): fix possible wrong locale --- src/main/Background.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/Background.ts b/src/main/Background.ts index 19826623..4b15408d 100644 --- a/src/main/Background.ts +++ b/src/main/Background.ts @@ -307,7 +307,7 @@ export function registerBackgroundListeners(): void { console.log("Config reloaded."); }); ipcMain.on("getLocale", (e) => { - e.returnValue = app.getLocale(); + e.returnValue = app.getLocale().toLowerCase(); }); ipcMain.handle( "isReachable", From 3bd7a87e0d25cf8691d5997a3c28a7927c360ede Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Wed, 10 Aug 2022 16:36:20 +0800 Subject: [PATCH 16/23] chore(*): cumulative update --- package.json | 1 - src/renderer/App.tsx | 12 ++---------- src/renderer/UpdateHint.tsx | 2 +- yarn.lock | 5 ----- 4 files changed, 3 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index a9e467ff..76625cf2 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "copy-to-clipboard": "^3.3.1", "crypto-js": "^4.1.1", "fs-extra": "^10.1.0", - "hotkeys-js": "^3.9.4", "iconv-lite": "^0.6.3", "is-reachable": "^5.2.1", "js-base64": "^3.7.2", diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 46372903..cd159ce3 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -50,7 +50,6 @@ import { } from "@mui/material"; import { makeStyles } from "@mui/styles"; import { ipcRenderer } from "electron"; -import hotkeys from "hotkeys-js"; import React, { useEffect, useRef, useState } from "react"; import { Route } from "react-router-dom"; import pkg from "../../package.json"; @@ -891,16 +890,9 @@ function Echo(): JSX.Element { const [open, setOpen] = useState(false); const [input, setInput] = useState(""); useEffect(() => { - if (getBoolean("features.echo")) { - hotkeys("t", () => { - if (!open) { - setOpen(true); - } - }); + if (!open) { + setOpen(true); } - return () => { - hotkeys.unbind("t"); - }; }, []); return ( diff --git a/src/renderer/UpdateHint.tsx b/src/renderer/UpdateHint.tsx index 4dfc6aff..b2ba753e 100644 --- a/src/renderer/UpdateHint.tsx +++ b/src/renderer/UpdateHint.tsx @@ -31,7 +31,7 @@ export function UpdateHint(): JSX.Element { > {">>"} - {" "} + {pkg.updatorVersion} diff --git a/yarn.lock b/yarn.lock index 39ac441e..b3c9fb80 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2892,11 +2892,6 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== -hotkeys-js@^3.9.4: - version "3.9.4" - resolved "https://registry.yarnpkg.com/hotkeys-js/-/hotkeys-js-3.9.4.tgz#ce1aa4c3a132b6a63a9dd5644fc92b8a9b9cbfb9" - integrity sha512-2zuLt85Ta+gIyvs4N88pCYskNrxf1TFv3LR9t5mdAZIX8BcgQQ48F2opUptvHa6m8zsy5v/a0i9mWzTrlNWU0Q== - htmlparser2@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" From 16c2d22f6755e2a281483f8b9cb9b323c5c73298 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 12 Aug 2022 19:35:50 +0800 Subject: [PATCH 17/23] feat(launch): add nvidia prime support --- resources/shared/defaults/Equish.lang | 16 ++++++++++++++++ resources/shared/defaults/PonyCN.lang | 8 ++++++++ resources/shared/defaults/PonyTW.lang | 16 ++++++++++++++++ resources/shared/defaults/alicorn.config.json | 3 ++- src/modules/launch/MinecraftBootstrap.ts | 9 +++++++++ src/renderer/Options.tsx | 8 ++++++++ 6 files changed, 59 insertions(+), 1 deletion(-) diff --git a/resources/shared/defaults/Equish.lang b/resources/shared/defaults/Equish.lang index 9ca07645..72ba24fc 100644 --- a/resources/shared/defaults/Equish.lang +++ b/resources/shared/defaults/Equish.lang @@ -2124,6 +2124,22 @@ Disable Log4j Configuration Disable Log4j configuration provided by Mojang. +# Options.bosskey.title + +Boss Key ^ + +# Options.bosskey.desc + +Set a keyboard shortcut here. When your boss is around, press this to hide Alicorn and quit Minecraft.\n(Format e.g. Alt+B) + +# Options.nvidia-prime.title + +NVIDIA Prime + +# Options.nvidia-prime.desc + +Run Minecraft on NVIDIA dGPU.\nIt only works with dual graphics cards when NVIDIA is not the output card. + # CrashReportDisplay.BaseInfo Base Information diff --git a/resources/shared/defaults/PonyCN.lang b/resources/shared/defaults/PonyCN.lang index fc4288ee..b49c4f0e 100644 --- a/resources/shared/defaults/PonyCN.lang +++ b/resources/shared/defaults/PonyCN.lang @@ -2231,6 +2231,14 @@ Mod 动态加载 我们一直在努力为每个人争取正当、公平的玩游戏的权利,不受任何监管或制约。\n尽管如此,仍然有些人听不进去,所以这是留给你的小礼物~\n在此设置一个快捷键,此后按下它可随时隐藏 Alicorn,终止 Minecraft。\n(快捷键格式类似 Ctrl+B+S 或者 F6) +# Options.nvidia-prime.title + +启用 NVIDIA Prime + +# Options.nvidia-prime.desc + +在主要显卡上运行 Minecraft。\n仅适用于双显卡计算机,且当前输出显卡不是 NVIDIA 显卡。 + # CrashReportDisplay.BaseInfo 基本信息 diff --git a/resources/shared/defaults/PonyTW.lang b/resources/shared/defaults/PonyTW.lang index a32a0921..ab42087f 100644 --- a/resources/shared/defaults/PonyTW.lang +++ b/resources/shared/defaults/PonyTW.lang @@ -2219,6 +2219,22 @@ Mod 動態加載 不使用 Mojang 提供的 Log4j 配置文件以在啟動疑難解答中獲得更清晰的日誌 - 副作用是輸出到文件的日誌會很混亂 +# Options.bosskey.title + +老闆鍵 ^ + +# Options.bosskey.desc + +我們一直在努力為每個人爭取正當、公平的玩遊戲的權利,不受任何監管或製約。 \n儘管如此,仍然有些人聽不進去,所以這是留給你的小禮物~\n在此設置一個快捷鍵,此後按下它可隨時隱藏 Alicorn,終止 Minecraft。 \n(快捷鍵格式類似 Ctrl+B+S 或者 F6) + +# Options.nvidia-prime.title + +啟用 NVIDIA Prime + +# Options.nvidia-prime.desc + +在主要顯卡上運行 Minecraft。 \n僅適用於雙顯卡計算機,且當前輸出顯卡不是 NVIDIA 顯卡。 + # CrashReportDisplay.BaseInfo 基本信息 diff --git a/resources/shared/defaults/alicorn.config.json b/resources/shared/defaults/alicorn.config.json index 2e020f50..ce75452d 100644 --- a/resources/shared/defaults/alicorn.config.json +++ b/resources/shared/defaults/alicorn.config.json @@ -70,5 +70,6 @@ "cx.shared-root": "", "interactive.cadance": false, "interactive.boticorn": false, - "bosskey": "" + "bosskey": "", + "nvidia-prime": true } diff --git a/src/modules/launch/MinecraftBootstrap.ts b/src/modules/launch/MinecraftBootstrap.ts index 47cb1a41..d72877dc 100644 --- a/src/modules/launch/MinecraftBootstrap.ts +++ b/src/modules/launch/MinecraftBootstrap.ts @@ -2,6 +2,7 @@ import { ChildProcess, exec, spawn } from "child_process"; import EventEmitter from "events"; import os from "os"; import { PROCESS_END_GATE, PROCESS_LOG_GATE } from "../commons/Constants"; +import { getBoolean } from "../config/ConfigSupport"; import { MinecraftContainer } from "../container/MinecraftContainer"; import { restoreMods } from "../modx/ModDynLoad"; @@ -41,6 +42,14 @@ class RunningMinecraft { this.process = spawn(this.executable, this.args, { cwd: this.isolateRoot || this.container.rootDir, detached: true, // Won't close after launcher closed + env: getBoolean("nvidia-prime") + ? { + ...process.env, + __NV_PRIME_RENDER_OFFLOAD: "1", + __VK_LAYER_NV_optimus: "NVIDIA_only", + __GLX_VENDOR_LIBRARY_NAME: "nvidia", + } + : undefined, }); } catch (e) { console.log(e); diff --git a/src/renderer/Options.tsx b/src/renderer/Options.tsx index ff646d5f..dae984fc 100644 --- a/src/renderer/Options.tsx +++ b/src/renderer/Options.tsx @@ -25,6 +25,7 @@ import { ExtensionOff, Favorite, FirstPage, + GraphicEq, Home, Inbox, InsertPhoto, @@ -37,6 +38,7 @@ import { MonitorHeart, Mouse, Numbers, + Output, Palette, PermContactCalendar, Public, @@ -426,6 +428,12 @@ export function OptionsPage(): JSX.Element { bindConfig={"para-gc"} choices={["pure", "g1", "z", "aggressive", "sd"]} /> + } + type={ConfigType.BOOL} + bindConfig={"nvidia-prime"} + onlyOn={"linux"} + /> } type={ConfigType.STR} From ab15fd119bed4b93638a2e9f2f8b333ce845e9d0 Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 12 Aug 2022 19:43:46 +0800 Subject: [PATCH 18/23] remove(*): removed unused echo feature --- src/modules/selfupdate/Echo.ts | 47 ------------------------------ src/renderer/App.tsx | 52 ---------------------------------- src/renderer/ReadyToLaunch.tsx | 49 +++++++++++--------------------- src/renderer/Renderer.tsx | 10 +------ src/renderer/Welcome.tsx | 17 +---------- 5 files changed, 19 insertions(+), 156 deletions(-) delete mode 100644 src/modules/selfupdate/Echo.ts diff --git a/src/modules/selfupdate/Echo.ts b/src/modules/selfupdate/Echo.ts deleted file mode 100644 index 0cd0fe59..00000000 --- a/src/modules/selfupdate/Echo.ts +++ /dev/null @@ -1,47 +0,0 @@ -const ECHO_ENDPOINT = "https://echo.thatrarityegmc.workers.dev/"; - -export function sendEcho(e: string): void { - console.log("SEND"); - fetch(ECHO_ENDPOINT, { - headers: { - "X-Alicorn-Echo-Type": "SEND", - "X-Alicorn-Echo-Text": encodeURIComponent(e.trim().slice(-100)), - }, - }) - .then(() => {}) - .catch((e) => { - console.log(e); - }); -} - -let WEB_ECHOS: string[] = []; - -export async function updateWebEchos(): Promise { - try { - const ret = await fetch(ECHO_ENDPOINT, { - headers: { - "X-Alicorn-Echo-Type": "GET", - }, - }); - if (ret.ok) { - const dt = await ret.json(); - const keys = Object.values(dt); - WEB_ECHOS = keys.map((s) => { - return String(s); - }); - localStorage.setItem("Echo.Web", JSON.stringify(WEB_ECHOS)); - console.log(`Updated echo data, ${WEB_ECHOS.length} items in all.`); - } - } catch {} -} - -export function getEchos(): string[] { - try { - if (WEB_ECHOS.length > 0) { - return WEB_ECHOS; - } - return (WEB_ECHOS = JSON.parse(localStorage.getItem("Echo.Web") || "[]")); - } catch { - return []; - } -} diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index cd159ce3..c8f22228 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -64,7 +64,6 @@ import { saveGDT } from "../modules/container/ContainerUtil"; import { saveVF } from "../modules/container/ValidateRecord"; import { handleDnD } from "../modules/dnd/DnDCenter"; import { saveJDT } from "../modules/java/JavaInfo"; -import { sendEcho } from "../modules/selfupdate/Echo"; import { waitUpdateFinished } from "../modules/selfupdate/Updator"; import { saveServers } from "../modules/server/ServerFiles"; import { ContainerManager } from "./ContainerManager"; @@ -238,7 +237,6 @@ export function App(): JSX.Element { no={tr("System.JumpPageWarn.No")} /> - ); } - -function Echo(): JSX.Element { - const [open, setOpen] = useState(false); - const [input, setInput] = useState(""); - useEffect(() => { - if (!open) { - setOpen(true); - } - }, []); - - return ( - - { - setOpen(false); - }} - > - - {tr("Echo.Title")} - {tr("Echo.Hint")} - { - setInput(e.target.value); - }} - /> - - - - - - - ); -} diff --git a/src/renderer/ReadyToLaunch.tsx b/src/renderer/ReadyToLaunch.tsx index 991095e3..2ae7465f 100644 --- a/src/renderer/ReadyToLaunch.tsx +++ b/src/renderer/ReadyToLaunch.tsx @@ -10,7 +10,7 @@ import { Person, RssFeed, SportsScore, - ViewModule, + ViewModule } from "@mui/icons-material"; import { Box, @@ -39,7 +39,7 @@ import { TextField, ThemeProvider, Tooltip, - Typography, + Typography } from "@mui/material"; import { makeStyles } from "@mui/styles"; import copy from "copy-to-clipboard"; @@ -52,7 +52,7 @@ import { Account } from "../modules/auth/Account"; import { AccountType, getPresentAccounts, - querySkinFor, + querySkinFor } from "../modules/auth/AccountUtil"; import { prefetchData } from "../modules/auth/AJHelper"; import { AuthlibAccount } from "../modules/auth/AuthlibAccount"; @@ -65,7 +65,7 @@ import { MS_LAST_USED_REFRESH_KEY, MS_LAST_USED_USERNAME_KEY, MS_LAST_USED_UUID_KEY, - MS_LAST_USED_XUID_KEY, + MS_LAST_USED_XUID_KEY } from "../modules/auth/MicrosoftAccount"; import { Nide8Account } from "../modules/auth/Nide8Account"; import { uniqueHash } from "../modules/commons/BasicHash"; @@ -73,13 +73,13 @@ import { Pair } from "../modules/commons/Collections"; import { PROCESS_END_GATE, PROCESS_LOG_GATE, - ReleaseType, + ReleaseType } from "../modules/commons/Constants"; import { isNull } from "../modules/commons/Null"; import { getBoolean, getNumber, - getString, + getString } from "../modules/config/ConfigSupport"; import { getContainer } from "../modules/container/ContainerUtil"; import { MinecraftContainer } from "../modules/container/MinecraftContainer"; @@ -87,7 +87,7 @@ import { killEdge, runEdge } from "../modules/cutie/BootEdge"; import { acquireCode, deactiveCode } from "../modules/cutie/Hoofoff"; import { getWrapperStatus, - WrapperStatus, + WrapperStatus } from "../modules/download/DownloadWrapper"; import { getAllJava, @@ -97,7 +97,7 @@ import { getLegacyJDK, getNewJDK, parseJavaInfo, - parseJavaInfoRaw, + parseJavaInfoRaw } from "../modules/java/JavaInfo"; import { autoMemory } from "../modules/launch/ArgsGenerator"; import { @@ -106,12 +106,12 @@ import { ensureClient, ensureLibraries, ensureLog4jFile, - ensureNatives, + ensureNatives } from "../modules/launch/Ensurance"; import { launchProfile, markSafeLaunch, - shouldSafeLaunch, + shouldSafeLaunch } from "../modules/launch/LaunchTool"; import { LaunchTracker } from "../modules/launch/LaunchTracker"; import { stopMinecraft } from "../modules/launch/MinecraftBootstrap"; @@ -119,22 +119,21 @@ import { prepareModsCheckFor } from "../modules/modx/ModDynLoad"; import { GameProfile } from "../modules/profile/GameProfile"; import { isProfileIsolated, - loadProfile, + loadProfile } from "../modules/profile/ProfileLoader"; import { dropAccountPromise, - waitMSAccountReady, + waitMSAccountReady } from "../modules/readyboom/AccountMaster"; import { setLastUsed, - waitProfileReady, + waitProfileReady } from "../modules/readyboom/PrepareProfile"; import { getMachineUniqueID } from "../modules/security/Unique"; -import { getEchos } from "../modules/selfupdate/Echo"; import { initLocalYggdrasilServer, ROOT_YG_URL, - skinTypeFor, + skinTypeFor } from "../modules/skin/LocalYggdrasilServer"; import { jumpTo, setChangePageWarn, triggerSetPage } from "./GoTo"; import { Icons } from "./Icons"; @@ -144,7 +143,7 @@ import { YNDialog } from "./OperatingHint"; import { ALICORN_DEFAULT_THEME_DARK, ALICORN_DEFAULT_THEME_LIGHT, - isBgDark, + isBgDark } from "./Renderer"; import { SkinDisplay2D, SkinDisplay3D } from "./SkinDisplay"; import { addStatistics } from "./Statistics"; @@ -152,13 +151,13 @@ import { AlicornTheme, fullWidth, useFormStyles, - useInputStyles, + useInputStyles } from "./Stylex"; import { randsl, tr } from "./Translator"; import { HOOFOFF_CENTRAL, NETWORK_PORT, - QUERY_PORT, + QUERY_PORT } from "./utilities/CutieConnect"; import { SpecialKnowledge } from "./Welcome"; import { toReadableType, YggdrasilForm } from "./YggdrasilAccountManager"; @@ -1876,20 +1875,6 @@ function WaitingText(): JSX.Element { const [hint, setHint] = useState(randsl("ReadyToLaunch.WaitingText")); useEffect(() => { const timer = setInterval(() => { - if (getBoolean("features.echo")) { - const echos = getEchos(); - if (Math.random() > 0.6) { - if (echos.length > 0) { - setHint( - tr( - "Echo.Format", - `Text=${echos[Math.floor(Math.random() * echos.length)]}` - ) - ); - return; - } - } - } setHint(randsl("ReadyToLaunch.WaitingText")); }, 5000); return () => { diff --git a/src/renderer/Renderer.tsx b/src/renderer/Renderer.tsx index 8b3ecd15..90cb9854 100644 --- a/src/renderer/Renderer.tsx +++ b/src/renderer/Renderer.tsx @@ -17,7 +17,7 @@ import { getNumber, getString, loadConfig, - saveDefaultConfig, + saveDefaultConfig } from "../modules/config/ConfigSupport"; import { getActualDataPath } from "../modules/config/DataSupport"; import { loadGDT } from "../modules/container/ContainerUtil"; @@ -34,7 +34,6 @@ import { setupMSAccountRefreshService } from "../modules/readyboom/AccountMaster import { setupHotProfilesService } from "../modules/readyboom/PrepareProfile"; import { initEncrypt } from "../modules/security/Encrypt"; import { getMachineUniqueID } from "../modules/security/Unique"; -import { updateWebEchos } from "../modules/selfupdate/Echo"; import { todayPing } from "../modules/selfupdate/Ping"; import { checkUpdate, initUpdator } from "../modules/selfupdate/Updator"; import { loadServers } from "../modules/server/ServerFiles"; @@ -264,13 +263,6 @@ try { console.log("Skipped update checking due to user settings."); } })(); - - if (getBoolean("features.echo")) { - setInterval(() => { - void updateWebEchos(); - }, 600000); - void updateWebEchos(); - } await Promise.allSettled([ updPm, prefetchForgeManifest(), diff --git a/src/renderer/Welcome.tsx b/src/renderer/Welcome.tsx index 66cc42db..75edc14f 100644 --- a/src/renderer/Welcome.tsx +++ b/src/renderer/Welcome.tsx @@ -6,10 +6,9 @@ import { getBoolean } from "../modules/config/ConfigSupport"; import { getContainer } from "../modules/container/ContainerUtil"; import { isProfileIsolated, - loadProfile, + loadProfile } from "../modules/profile/ProfileLoader"; import { whatProfile } from "../modules/profile/WhatProfile"; -import { getEchos } from "../modules/selfupdate/Echo"; import { jumpTo, triggerSetPage } from "./GoTo"; import { ShiftEle } from "./Instruction"; import { markTime, markUsed, SimplifiedCoreInfo } from "./LaunchPad"; @@ -161,20 +160,6 @@ function subscribeEcho( return () => { const i = setInterval(() => { setRefresh((o) => !o); - if (getBoolean("features.echo")) { - const echos = getEchos(); - if (Math.random() > 0.6) { - if (echos.length > 0) { - setTip( - tr( - "Echo.Format", - `Text=${echos[Math.floor(Math.random() * echos.length)]}` - ) - ); - return; - } - } - } setTip(null); }, 5000); return () => { From 32e6561254d169dfd5e8f3b112d42deae1ceabfe Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 12 Aug 2022 20:34:02 +0800 Subject: [PATCH 19/23] feat(*): add installer for gnu --- makesh.js | 19 +++++++++++++------ resources/build/_install.sh | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 resources/build/_install.sh diff --git a/makesh.js b/makesh.js index 402f56d1..886ab98d 100644 --- a/makesh.js +++ b/makesh.js @@ -1,12 +1,19 @@ // Inject alicorn.sh for GNU/Linux // eslint-disable-next-line @typescript-eslint/no-var-requires const fs = require("fs"); -const START_SH = "#!/bin/sh\ncd `dirname $0`\n./Alicorn"; -fs.writeFile( - "./out/Alicorn-linux-x64/alicorn.sh", - START_SH, - { mode: "0777" }, +fs.copyFile( + "./resources/build/install.sh", + "./out/Alicorn-linux-x64/install.sh", () => { - console.log("Shell launcher emitted."); + fs.chmod("./out/Alicorn-linux-x64/install.sh", 0o755, () => { + console.log("Shell installer emitted."); + }); + } +); +fs.copyFile( + "./resources/build/icon.png", + "./out/Alicorn-linux-x64/Alicorn.png", + () => { + console.log("Icon emitted."); } ); diff --git a/resources/build/_install.sh b/resources/build/_install.sh new file mode 100644 index 00000000..fcab1cb1 --- /dev/null +++ b/resources/build/_install.sh @@ -0,0 +1,15 @@ +#!/bin/sh +echo "Installing Alicorn, just a second..." +USERNAME=`whoami` +DESTFILE="/home/$USERNAME/.local/share/applications/alicorn.desktop" +rm -f $DESTFILE +cd `dirname $0` +MYDIR=`pwd` +chmod +x "Alicorn" +for LN in '[Desktop Entry]' 'Type=Application' 'Version=1.0' 'Name=Alicorn' 'Comment=A cute custom Minecraft launcher for everypony!' "Path=$MYDIR" "Exec=$MYDIR/Alicorn" "Icon=$MYDIR/Alicorn.png" 'Terminal=false' +do + echo $LN >> $DESTFILE +done + +echo "Installation complete, starting for you..." +./Alicorn \ No newline at end of file From f4ad59bbb42d6a911d81bf1deff7c3ee550069ed Mon Sep 17 00:00:00 2001 From: Andy-K-Sparklight Date: Fri, 12 Aug 2022 20:34:27 +0800 Subject: [PATCH 20/23] perf(*): make config dir start with dot --- src/main/Bootstrap.ts | 2 ++ src/modules/config/ConfigSupport.ts | 31 +++++++++++++++++++++++++++-- src/modules/config/DataSupport.ts | 2 +- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/Bootstrap.ts b/src/main/Bootstrap.ts index a74c8f7e..ec02b31e 100644 --- a/src/main/Bootstrap.ts +++ b/src/main/Bootstrap.ts @@ -7,6 +7,7 @@ import { getNumber, getString, loadConfigSync, + movOldConfigFolderSync, } from "../modules/config/ConfigSupport"; import { setBeacon } from "../modules/selfupdate/Beacon"; import { registerBackgroundListeners } from "./Background"; @@ -173,6 +174,7 @@ async function whenAppReady() { function main() { console.log("Loading config..."); + movOldConfigFolderSync(); loadConfigSync(); if (!getBoolean("hardware-acc") && !getBoolean("features.skin-view-3d")) { // If 3D enabled then we should use hardware acc diff --git a/src/modules/config/ConfigSupport.ts b/src/modules/config/ConfigSupport.ts index 76b3bf8e..304a38a0 100644 --- a/src/modules/config/ConfigSupport.ts +++ b/src/modules/config/ConfigSupport.ts @@ -1,5 +1,12 @@ import { ipcRenderer } from "electron"; -import fs from "fs-extra"; +import fs, { + move, + moveSync, + remove, + removeSync, + stat, + statSync, +} from "fs-extra"; import os from "os"; import path from "path"; import { DEFAULTS_ROOT } from "./DataSupport"; @@ -7,7 +14,7 @@ import { getBasePath } from "./PathSolve"; const CONFIG_FILE = path.resolve( os.homedir(), - "alicorn", + ".alicorn", "alicorn.config.json" ); @@ -147,3 +154,23 @@ export async function saveAndReloadMain(): Promise { await saveConfig(); ipcRenderer.send("reloadConfig"); } + +export function movOldConfigFolderSync(): void { + const oldDir = path.resolve(os.homedir(), "alicorn"); + const newDir = path.resolve(os.homedir(), ".alicorn"); + try { + const sto = statSync(oldDir); + try { + const stn = statSync(newDir); + if (stn.isDirectory()) { + // Already exists + return; + } + } catch {} + if (sto.isDirectory()) { + removeSync(newDir); + moveSync(oldDir, newDir); + console.log("Old config path detected, moved to new path."); + } + } catch {} +} diff --git a/src/modules/config/DataSupport.ts b/src/modules/config/DataSupport.ts index ea76603f..36ecb2df 100644 --- a/src/modules/config/DataSupport.ts +++ b/src/modules/config/DataSupport.ts @@ -4,7 +4,7 @@ import path from "path"; import { copyFileStream, isFileExist } from "../commons/FileUtil"; import { getBasePath } from "./PathSolve"; -const DATA_ROOT = path.resolve(os.homedir(), "alicorn"); +const DATA_ROOT = path.resolve(os.homedir(), ".alicorn"); export const DEFAULTS_ROOT = path.resolve(getBasePath(), "defaults"); export async function loadData(dataPath: string): Promise { From 6f57be37645e12e690a2b8d22f477471993f7657 Mon Sep 17 00:00:00 2001 From: Annie K Rarity Sparklight Date: Mon, 15 Aug 2022 20:19:58 +0800 Subject: [PATCH 21/23] fix(config): auto select path for different os --- src/modules/config/ConfigSupport.ts | 18 ++++-------------- src/modules/config/DataSupport.ts | 4 ++-- src/modules/config/OSDirSupport.ts | 11 +++++++++++ 3 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 src/modules/config/OSDirSupport.ts diff --git a/src/modules/config/ConfigSupport.ts b/src/modules/config/ConfigSupport.ts index 304a38a0..acf7dc05 100644 --- a/src/modules/config/ConfigSupport.ts +++ b/src/modules/config/ConfigSupport.ts @@ -1,22 +1,12 @@ import { ipcRenderer } from "electron"; -import fs, { - move, - moveSync, - remove, - removeSync, - stat, - statSync, -} from "fs-extra"; +import fs, { moveSync, removeSync, statSync } from "fs-extra"; import os from "os"; import path from "path"; import { DEFAULTS_ROOT } from "./DataSupport"; +import { getOSSpecificDataDir } from "./OSDirSupport"; import { getBasePath } from "./PathSolve"; -const CONFIG_FILE = path.resolve( - os.homedir(), - ".alicorn", - "alicorn.config.json" -); +const CONFIG_FILE = path.resolve(getOSSpecificDataDir(), "alicorn.config.json"); const DEFAULT_CONFIG_FILE = path.resolve( getBasePath(), @@ -157,7 +147,7 @@ export async function saveAndReloadMain(): Promise { export function movOldConfigFolderSync(): void { const oldDir = path.resolve(os.homedir(), "alicorn"); - const newDir = path.resolve(os.homedir(), ".alicorn"); + const newDir = path.resolve(getOSSpecificDataDir()); try { const sto = statSync(oldDir); try { diff --git a/src/modules/config/DataSupport.ts b/src/modules/config/DataSupport.ts index 36ecb2df..f4deace6 100644 --- a/src/modules/config/DataSupport.ts +++ b/src/modules/config/DataSupport.ts @@ -1,10 +1,10 @@ import fs from "fs-extra"; -import os from "os"; import path from "path"; import { copyFileStream, isFileExist } from "../commons/FileUtil"; +import { getOSSpecificDataDir } from "./OSDirSupport"; import { getBasePath } from "./PathSolve"; -const DATA_ROOT = path.resolve(os.homedir(), ".alicorn"); +const DATA_ROOT = path.resolve(getOSSpecificDataDir()); export const DEFAULTS_ROOT = path.resolve(getBasePath(), "defaults"); export async function loadData(dataPath: string): Promise { diff --git a/src/modules/config/OSDirSupport.ts b/src/modules/config/OSDirSupport.ts new file mode 100644 index 00000000..dbf55fd4 --- /dev/null +++ b/src/modules/config/OSDirSupport.ts @@ -0,0 +1,11 @@ +import os from "os"; +import path from "path"; + +export function getOSSpecificDataDir(): string { + switch (os.platform()) { + case "win32": + return path.join(os.homedir(), "AppData", "Local", "Alicorn"); + default: + return path.join(os.homedir(), ".alicorn"); + } +} From 3544d9f5e899f5fdff3ce8b32d7a979b0e09b1f4 Mon Sep 17 00:00:00 2001 From: Annie K Rarity Sparklight Date: Mon, 15 Aug 2022 20:22:04 +0800 Subject: [PATCH 22/23] remove(beacon): removed beacon --- src/modules/selfupdate/Beacon.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/modules/selfupdate/Beacon.ts b/src/modules/selfupdate/Beacon.ts index 29d4190e..1cadd6ed 100644 --- a/src/modules/selfupdate/Beacon.ts +++ b/src/modules/selfupdate/Beacon.ts @@ -1,13 +1,12 @@ -import { app } from "electron"; import fs from "fs-extra"; import os from "os"; import path from "path"; // Place a symlink at ~/alicorn, so that our bootstrap in packs can find it export async function setBeacon(): Promise { + // No longer using, use this to remove files for our users. try { const target = path.join(os.homedir(), "alicorn-is-here"); - await fs.outputFile(target, app.getPath("exe")); - console.log("Beacon set!"); + await fs.remove(target); } catch (e) { console.log(e); } From 8497486fe3a4a03761d56f6a12b7f1ca7b60fb18 Mon Sep 17 00:00:00 2001 From: Annie K Rarity Sparklight Date: Mon, 15 Aug 2022 20:28:37 +0800 Subject: [PATCH 23/23] release(*): bump core 50 as new av sunset --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a0b6345a..99177513 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "private": true, - "appVersion": "Harmony", + "appVersion": "Sunset", "version": "1.0.0", - "updatorVersion": 49, + "updatorVersion": 50, "scripts": { "lc": "yarn lcd", "df": "yarn dev-full",