feat: add support for older forge (down to 1.7.10)
This commit is contained in:
parent
8e6408fb7b
commit
8bcf3680c0
5 changed files with 127 additions and 56 deletions
|
|
@ -163,7 +163,7 @@ export async function generateLaunchArguments(
|
|||
} else {
|
||||
console.log(versionManifest.minecraftArguments)
|
||||
game = fillArguments(
|
||||
versionManifest.minecraftArguments,
|
||||
versionManifest.minecraftArguments!,
|
||||
versionManifest,
|
||||
assetsPath,
|
||||
instancePath,
|
||||
|
|
|
|||
|
|
@ -9,12 +9,25 @@ export function getLibraries(versionManifest: Version, librariesRoot: string) {
|
|||
for (const key in versionManifest.libraries) {
|
||||
if (Object.prototype.hasOwnProperty.call(versionManifest.libraries, key)) {
|
||||
const library = versionManifest.libraries[key];
|
||||
if (isNeeded(library) && library.downloads.artifact) {
|
||||
libs.push({
|
||||
url: library.downloads.artifact.url,
|
||||
path: path.join(librariesRoot, library.downloads.artifact.path),
|
||||
size: library.downloads.artifact.size,
|
||||
});
|
||||
if (library.downloads) {
|
||||
if (isNeeded(library) && library.downloads.artifact) {
|
||||
libs.push({
|
||||
url: library.downloads.artifact.url,
|
||||
path: path.join(librariesRoot, library.downloads.artifact.path),
|
||||
size: library.downloads.artifact.size,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// forge lib ?
|
||||
if (!library.rules && !library.downloads && !library.natives) {
|
||||
const parsedLib = library.name.split(":")
|
||||
const libPath = path.join(parsedLib[0].replaceAll(".", "/"), parsedLib[1], parsedLib[2], `${parsedLib[1]}-${parsedLib[2]}.jar`)
|
||||
libs.push({
|
||||
url: "",
|
||||
path: path.join(librariesRoot, libPath),
|
||||
size: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,36 +3,62 @@ import { Version } from "../utils/types";
|
|||
export function mergeManifests(base: Version, layer: Version) {
|
||||
// Copy needed properties to base
|
||||
// Those properties should be enough for forge at least
|
||||
base.mainClass = layer.mainClass;
|
||||
const result = { ...base }
|
||||
result.libraries = [];
|
||||
result.mainClass = layer.mainClass;
|
||||
console.log(base)
|
||||
|
||||
const librariesHashes = base.libraries.filter(lib => lib.downloads.artifact).map(
|
||||
(lib) => {
|
||||
return lib.downloads.artifact.sha1
|
||||
},
|
||||
);
|
||||
// const librariesNames = base.libraries.map(
|
||||
// (lib) => {
|
||||
// return lib.name
|
||||
// },
|
||||
// );
|
||||
|
||||
for (const lib of layer.libraries) {
|
||||
if (!librariesHashes.includes(lib.downloads.artifact.sha1)) // remove duplicates
|
||||
base.libraries.push(lib);
|
||||
// for (const lib of layer.libraries) {
|
||||
// // remove duplicates
|
||||
// if (!librariesNames.includes(lib.name)) {
|
||||
// base.libraries.push(lib);
|
||||
// }
|
||||
// }
|
||||
|
||||
for (const bLib of base.libraries) {
|
||||
let isInLayer = false
|
||||
for (const lLib of layer.libraries) {
|
||||
const lId = lLib.name.split(":")[1]
|
||||
const bId = bLib.name.split(":")[1]
|
||||
|
||||
if (lId === bId) {
|
||||
isInLayer = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!isInLayer) {
|
||||
result.libraries.push(bLib)
|
||||
}
|
||||
}
|
||||
|
||||
for (const lLib of layer.libraries) {
|
||||
result.libraries.push(lLib)
|
||||
}
|
||||
|
||||
// modern versions
|
||||
if (layer.arguments && base.arguments) {
|
||||
if (layer.arguments && result.arguments) {
|
||||
if (layer.arguments.game) {
|
||||
for (const arg of layer.arguments.game) {
|
||||
base.arguments.game.push(arg);
|
||||
result.arguments.game.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (layer.arguments.jvm) {
|
||||
for (const arg of layer.arguments.jvm) {
|
||||
base.arguments.jvm.push(arg);
|
||||
result.arguments.jvm.push(arg);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// older versions
|
||||
base.minecraftArguments = layer.minecraftArguments
|
||||
result.minecraftArguments = layer.minecraftArguments
|
||||
}
|
||||
|
||||
return base;
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,18 @@ import { LauncherProfiles, Modloader, Version } from "../utils/types";
|
|||
import fs from "fs/promises";
|
||||
import { execSync, spawn } from "child_process";
|
||||
import { version as packageVersion } from "../../package.json";
|
||||
import { readJson } from "../utils/fs";
|
||||
import { ensureDir, readJson } from "../utils/fs";
|
||||
import { InstallError } from "../utils/errors";
|
||||
import AdmZip from "adm-zip";
|
||||
|
||||
const versionWithDoubleName = ["1.9.4", "1.9.0", "1.8.9", "1.8.8", "1.8", "1.7.10"]
|
||||
function fixVersionWithDoubleName(version: string, modloader: Modloader) {
|
||||
if (versionWithDoubleName.includes(version)) {
|
||||
// these versions have a different file name on forge's maven
|
||||
modloader.version = modloader.version + `-${version}`
|
||||
}
|
||||
return modloader
|
||||
}
|
||||
|
||||
async function downloadJar(
|
||||
minecraftVersion: string,
|
||||
|
|
@ -15,6 +25,7 @@ async function downloadJar(
|
|||
destination: string,
|
||||
) {
|
||||
let filePath = "";
|
||||
modloader = fixVersionWithDoubleName(minecraftVersion, modloader)
|
||||
try {
|
||||
if (modloader.name === "forge") {
|
||||
if (type === "universal") {
|
||||
|
|
@ -58,17 +69,18 @@ export function runForgeInstaller(
|
|||
javaExecutable: string,
|
||||
forgeInstallerPath: string,
|
||||
fakeLauncher: string,
|
||||
installType: "Client" | "Server"
|
||||
) {
|
||||
console.log(execSync(`${javaExecutable} -version`).toString());
|
||||
console.log(
|
||||
`[nlk ${packageVersion}] Running forge installer : "${javaExecutable} -jar ${forgeInstallerPath} --installClient ${path.join(fakeLauncher)}"`,
|
||||
`[nlk ${packageVersion}] Running forge installer : "${javaExecutable} -jar ${forgeInstallerPath} --install${installType} ${path.join(fakeLauncher)}"`,
|
||||
);
|
||||
const forgeInstaller = spawn(javaExecutable, [
|
||||
"-jar",
|
||||
forgeInstallerPath,
|
||||
"--installClient",
|
||||
`--install${installType}`,
|
||||
path.join(fakeLauncher),
|
||||
]);
|
||||
], { cwd: fakeLauncher });
|
||||
|
||||
forgeInstaller.stdout.on("data", (data: Buffer) =>
|
||||
console.log(data.toString()),
|
||||
|
|
@ -112,34 +124,36 @@ export async function installForge(
|
|||
versionsPath: string
|
||||
) {
|
||||
const tempFolder = await getTempFolder("forge");
|
||||
// Download and extract installer file
|
||||
const forgeInstallerPath = await downloadJar(
|
||||
versionManifest.id,
|
||||
modloader,
|
||||
"installer",
|
||||
tempFolder,
|
||||
);
|
||||
|
||||
const fakeLauncher = path.join(tempFolder, "fakeLauncher");
|
||||
|
||||
await fs.mkdir(fakeLauncher);
|
||||
await fs.writeFile(path.join(fakeLauncher, "launcher_profiles.json"), `{"profiles":{}}`);
|
||||
|
||||
const modernInstaller = isModernForge(versionManifest.id)
|
||||
|
||||
await runForgeInstaller(javaExecutable, forgeInstallerPath, fakeLauncher, modernInstaller ? "Client" : "Server");
|
||||
|
||||
// Copy libraries and versions files
|
||||
for (const file of await fs.readdir(path.join(fakeLauncher, "libraries"))) {
|
||||
await fs.cp(
|
||||
path.join(fakeLauncher, "libraries", file),
|
||||
path.join(librariesPath, file),
|
||||
{
|
||||
recursive: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (isModernForge(versionManifest.id)) {
|
||||
// Download and extract installer file
|
||||
const forgeInstallerPath = await downloadJar(
|
||||
versionManifest.id,
|
||||
modloader,
|
||||
"installer",
|
||||
tempFolder,
|
||||
);
|
||||
|
||||
const fakeLauncher = path.join(tempFolder, "fakeLauncher");
|
||||
|
||||
await fs.mkdir(fakeLauncher);
|
||||
await fs.writeFile(path.join(fakeLauncher, "launcher_profiles.json"), "{}");
|
||||
|
||||
await runForgeInstaller(javaExecutable, forgeInstallerPath, fakeLauncher);
|
||||
|
||||
// Copy libraries and versions files
|
||||
for (const file of await fs.readdir(path.join(fakeLauncher, "libraries"))) {
|
||||
await fs.cp(
|
||||
path.join(fakeLauncher, "libraries", file),
|
||||
path.join(librariesPath, file),
|
||||
{
|
||||
recursive: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Modern forge (version >= 1.12.2)
|
||||
const fakeLauncherProfiles = await readJson<LauncherProfiles>(
|
||||
path.join(fakeLauncher, "launcher_profiles.json"),
|
||||
);
|
||||
|
|
@ -152,5 +166,23 @@ export async function installForge(
|
|||
path.join(versionsPath, originalVersionId),
|
||||
{ recursive: true },
|
||||
);
|
||||
} else {
|
||||
// Older versions (from 1.5.2 to 1.12.2, even older versions are not supported)
|
||||
//await runForgeInstaller(javaExecutable, forgeInstallerPath, fakeLauncher, "Server");
|
||||
|
||||
const universalPath = path.join(fakeLauncher, `forge-${versionManifest.id}-${modloader.version}-universal.jar`)
|
||||
|
||||
// Copy forge jar
|
||||
await ensureDir(path.join(root, "libraries", "net", "minecraftforge", "forge", `${versionManifest.id}-${modloader.version}`), true)
|
||||
await fs.cp(
|
||||
universalPath,
|
||||
path.join(root, "libraries", "net", "minecraftforge", "forge", `${versionManifest.id}-${modloader.version}`, `forge-${versionManifest.id}-${modloader.version}.jar`),
|
||||
{ recursive: true },
|
||||
);
|
||||
|
||||
// Copy version json
|
||||
const zip = new AdmZip(universalPath)
|
||||
zip.extractEntryTo("version.json", path.join(versionsPath, `${versionManifest.id}-forge-${modloader.version}`))
|
||||
await fs.rename(path.join(versionsPath, `${versionManifest.id}-forge-${modloader.version}`, "version.json"), path.join(versionsPath, `${versionManifest.id}-forge-${modloader.version}`, `${versionManifest.id}-forge-${modloader.version}.json`))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,13 +93,13 @@ type Rules = {
|
|||
|
||||
export type Argument =
|
||||
| {
|
||||
rules: Rules[];
|
||||
value: string[] | string;
|
||||
}
|
||||
rules: Rules[];
|
||||
value: string[] | string;
|
||||
}
|
||||
| string;
|
||||
|
||||
export type Library = {
|
||||
downloads: {
|
||||
downloads?: {
|
||||
artifact: {
|
||||
path: string;
|
||||
sha1: string;
|
||||
|
|
@ -120,7 +120,7 @@ export type Version = {
|
|||
game: Argument[];
|
||||
jvm: Argument[];
|
||||
};
|
||||
minecraftArguments: string;
|
||||
minecraftArguments?: string;
|
||||
assetIndex: {
|
||||
id: string;
|
||||
sha1: string;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue