Skip to content

Commit

Permalink
fix(install): add ModLoader for legacy Forge versions
Browse files Browse the repository at this point in the history
  • Loading branch information
skjsjhb committed Feb 27, 2025
1 parent 400e08e commit 2140a77
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 5 deletions.
26 changes: 23 additions & 3 deletions src/main/api/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { containers } from "@/main/container/manage";
import { games } from "@/main/game/manage";
import { fabricInstaller } from "@/main/install/fabric";
import { forgeInstaller } from "@/main/install/forge";
import { forgeCompat } from "@/main/install/forge-compat";
import { neoforgedInstaller } from "@/main/install/neoforged";
import { quiltInstaller } from "@/main/install/quilt";
import { smelt, type SmeltInstallInit } from "@/main/install/smelt";
Expand Down Expand Up @@ -54,6 +55,7 @@ ipcMain.on("installGame", async (e, gameId) => {
let p = vanillaProfile;

let forgeInstallerPath: string | null = null;
let forgeModLoaderPath: string | null = null;
let forgeInstallerInit: SmeltInstallInit | null = null;
let forgeInstallAction: ForgeInstallActionType = "none";

Expand Down Expand Up @@ -103,6 +105,9 @@ ipcMain.on("installGame", async (e, gameId) => {
const installerType = forgeInstaller.getInstallType(gameVersion);
forgeInstallerPath = await forgeInstaller.downloadInstaller(loaderVersion, installerType, { onProgress });

const modLoaderUrl = await forgeCompat.getModLoaderUrl(gameVersion);
forgeModLoaderPath = modLoaderUrl && await forgeCompat.downloadModLoader(modLoaderUrl);

if (installerType === "installer") {
const legacyProfileId = await smeltLegacy.dumpContent(forgeInstallerPath, c);
if (legacyProfileId) {
Expand All @@ -116,7 +121,16 @@ ipcMain.on("installGame", async (e, gameId) => {
}
} else {
forgeInstallAction = "merge";
p = vanillaProfile;
if (modLoaderUrl) {
// There exists a bug with ModLoader which makes it incompatible with the directory structure
// This cannot be fixed even with VENV
// We're using a patch named DAMT: https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/mods-discussion/1291855-a-custom-tweaker-for-using-older-modloaders-in-the
await forgeCompat.patchProfile(c, gameVersion);
p = await profileLoader.fromContainer(gameVersion, c);
} else {
p = vanillaProfile;
}

}
}

Expand All @@ -136,10 +150,16 @@ ipcMain.on("installGame", async (e, gameId) => {
c
);

await smeltLegacy.mergeClient(forgeInstallerPath!, c.client(p.version || p.id));
game.launchHint.venv = true;
const clientPath = c.client(p.version || p.id);

if (forgeModLoaderPath) {
await smeltLegacy.mergeClient(forgeModLoaderPath, clientPath);
}

await smeltLegacy.mergeClient(forgeInstallerPath!, clientPath);
}

game.launchHint.venv = await forgeCompat.shouldUseVenv(gameVersion);
await fs.remove(forgeInstallerPath!);
}

Expand Down
49 changes: 49 additions & 0 deletions src/main/install/forge-compat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { Container } from "@/main/container/spec";
import { paths } from "@/main/fs/paths";
import { dlx } from "@/main/net/dlx";
import type { Library } from "@/main/profile/version-profile";
import { unwrapESM } from "@/main/util/module";
import fs from "fs-extra";
import { nanoid } from "nanoid";

async function loadCompat() {
return await unwrapESM(import("@/refs/legacy-forge-compat.json"));
}

async function shouldUseVenv(v: string): Promise<boolean> {
return (await loadCompat()).venv.includes(v);
}

async function getModLoaderUrl(v: string): Promise<string> {
return (await loadCompat() as any)["mod-loader"][v] ?? "";
}

async function downloadModLoader(url: string): Promise<string> {
console.debug(`Fetching ModLoader from ${url}`);
const fp = paths.temp.to(`mod-loader-${nanoid()}.jar`);
await dlx.getAll([{ url, path: fp }]);
return fp;
}

async function getModLoaderDamtLibrary(): Promise<Library> {
return (await loadCompat())["damt"];
}

async function getModLoaderDamtArg(): Promise<string> {
return (await loadCompat())["damt-arg"];
}

async function patchProfile(container: Container, id: string) {
console.debug(`Patching ${id} with DAMT...`);
const prof = await fs.readJSON(container.profile(id));
prof.libraries.push(await getModLoaderDamtLibrary());
prof.minecraftArguments += (" " + await getModLoaderDamtArg());
await fs.writeJSON(container.profile(id), prof);
}

export const forgeCompat = {
shouldUseVenv,
getModLoaderUrl,
downloadModLoader,
patchProfile
};
5 changes: 5 additions & 0 deletions src/main/install/forge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ async function syncVersions(): Promise<string[]> {
async function queryLoaderVersions(gameVersion: string, control?: ProgressController): Promise<string[]> {
control?.onProgress?.(progress.indefinite("forge.download"));

// This is the only except in versioning
if (gameVersion === "1.4") {
gameVersion = "1.4.0";
}

const versions = await syncVersions();

// Versions of Forge are named in the format `<gameVersion>-<suffix>`
Expand Down
4 changes: 2 additions & 2 deletions src/main/install/smelt-legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import StreamZip from "node-stream-zip";
import child_process from "node:child_process";
import path from "node:path";
import { pEvent } from "p-event";
import { COMPRESSION_LEVEL, zip } from "zip-a-folder";
import { zip } from "zip-a-folder";

async function dumpContent(installer: string, container: Container): Promise<string> {
let zip: StreamZip.StreamZipAsync | null = null;
Expand Down Expand Up @@ -143,7 +143,7 @@ async function mergeClient(src: string, fp: string): Promise<void> {

await fs.remove(path.join(workDir, "META-INF")); // Drop signatures
await fs.remove(fp);
await zip(workDir, fp, { compression: COMPRESSION_LEVEL.uncompressed });
await zip(workDir, fp);
await fs.remove(workDir);
}

Expand Down
33 changes: 33 additions & 0 deletions src/refs/legacy-forge-compat.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"mod-loader": {
"1.2.4": "https://github.com/skjsjhb/ModLoader-Binaries/releases/download/1.0/ModLoader.1.2.4.zip",
"1.2.3": "https://github.com/skjsjhb/ModLoader-Binaries/releases/download/1.0/ModLoader.1.2.3.zip",
"1.1": "https://github.com/skjsjhb/ModLoader-Binaries/releases/download/1.0/ModLoader.1.1.zip"
},
"damt": {
"name": "damt:damt:0.1",
"downloads": {
"artifact": {
"url": "https://github.com/skjsjhb/ModLoader-Binaries/releases/download/1.0/damt-0.1.jar"
}
}
},
"damt-arg": "--tweakClass damt.ModLoaderTweaker",
"venv": [
"1.5.1",
"1.5",
"1.4.7",
"1.4.6",
"1.4.5",
"1.4.4",
"1.4.3",
"1.4.2",
"1.4.1",
"1.4",
"1.3.2",
"1.2.5",
"1.2.4",
"1.2.3",
"1.1"
]
}

0 comments on commit 2140a77

Please sign in to comment.