feat: add support for installing modpacks from a link or a file in modrinth format
This commit is contained in:
parent
01ba9f44bf
commit
2cf9f73ce9
14 changed files with 375 additions and 37 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -145,6 +145,7 @@ tests/temp
|
|||
tests/vanilla/*
|
||||
tests/modloaders/forge/*
|
||||
tests/modloaders/neoforge/*
|
||||
tests/modloaders/fabric/*
|
||||
|
||||
# Test files
|
||||
handler.js
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import path from "path";
|
||||
import { isNeeded } from "../utils/rules";
|
||||
import { Argument, Version } from "../utils/types";
|
||||
import { Argument, Version, Config } from "../utils/types";
|
||||
import { getLibraries } from "./libraries";
|
||||
import { version as packageVersion } from "../../package.json";
|
||||
import { getArgument } from "./log4j";
|
||||
import { Config } from "../launcher/instance";
|
||||
|
||||
// Fill templates
|
||||
function fillArguments(
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import path from "path";
|
||||
import { downloadFile, fetchJson } from "../utils/fetch";
|
||||
import { getTempFolder } from "../utils/temp";
|
||||
import { LauncherProfiles, logger, Modloader, FabricInstallerMeta } from "../utils/types";
|
||||
import { LauncherProfiles, logger, Modloader, FabricInstallerMeta, ModloaderConfig } from "../utils/types";
|
||||
import fs from "fs/promises";
|
||||
import { spawn } from "child_process";
|
||||
import { version as packageVersion } from "../../package.json";
|
||||
import { ensureDir, exists, readJson } from "../utils/fs";
|
||||
import { InstallError } from "../utils/errors";
|
||||
import AdmZip from "adm-zip";
|
||||
import { Config } from "../launcher/instance";
|
||||
|
||||
const versionWithDoubleName = ["1.9.4", "1.9.0", "1.8.9", "1.8.8", "1.8", "1.7.10"]
|
||||
export function fixVersionWithDoubleName(version: string, modloader: Modloader) {
|
||||
|
|
@ -20,10 +19,6 @@ export function fixVersionWithDoubleName(version: string, modloader: Modloader)
|
|||
return modLoaderVersion
|
||||
}
|
||||
|
||||
export interface ModloaderConfig extends Config {
|
||||
modloader: Modloader
|
||||
}
|
||||
|
||||
export function getVersionId(config: ModloaderConfig) {
|
||||
return `${config.version}-${config.modloader.name}-${config.modloader.version}`
|
||||
}
|
||||
|
|
@ -66,7 +61,7 @@ async function downloadJar(
|
|||
path: filePath,
|
||||
});
|
||||
} else if (config.modloader.name === "fabric") {
|
||||
const fabricInstaller = (await fetchJson<FabricInstallerMeta>("https://meta.fabricmc.net/v2/versions/installer")).find(i => i.stable)
|
||||
const fabricInstaller = (await fetchJson<FabricInstallerMeta[]>("https://meta.fabricmc.net/v2/versions/installer")).find(i => i.stable)
|
||||
if (!fabricInstaller) {
|
||||
throw new Error("Couldn't download fabric installer")
|
||||
}
|
||||
|
|
@ -194,7 +189,6 @@ export async function installForge(
|
|||
}
|
||||
|
||||
const versionId = getVersionId(config)
|
||||
console.log(versionId)
|
||||
|
||||
if (isModernForge(config.version)) {
|
||||
// Modern forge (version >= 1.12.2)
|
||||
|
|
@ -312,6 +306,5 @@ export async function installFabric(config: ModloaderConfig, logger: logger) {
|
|||
|
||||
const versionId = getVersionId(config)
|
||||
await ensureDir(path.join(config.paths.versions, versionId))
|
||||
console.log(path.join(config.paths.versions, originalVersionId, `${originalVersionId}.json`), path.join(config.paths.versions, versionId, `${versionId}.json`))
|
||||
await fs.cp(path.join(fakeLauncher, "versions", originalVersionId, `${originalVersionId}.json`), path.join(config.paths.versions, versionId, `${versionId}.json`))
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
export { offlineAuth } from "./auth";
|
||||
export { Instance, defineConfig } from "./instance";
|
||||
export { RuntimeManager, getJavaComponent } from "./java";
|
||||
export { RuntimeManager, getJavaComponent } from "./java";
|
||||
export { importModrinthModpack } from "./modrinth"
|
||||
|
|
@ -1,28 +1,14 @@
|
|||
import { EventEmitter } from "node:stream";
|
||||
import { Auth, InstanceEvents, logger, Modloader, Paths, ProcessArgs, ProcessRam, Version } from "../utils/types";
|
||||
import { BaseConfig, Config, InstanceEvents, logger, PoolFile, Version, ModloaderConfig } from "../utils/types";
|
||||
import path from "node:path";
|
||||
import fs from "fs/promises"
|
||||
import { argumentsGenerator, AssetsDownloader, launch, LibrariesDownloader, NativesDownloader, version } from "../core";
|
||||
import { ConfigError, InstallError, LaunchError } from "../utils/errors";
|
||||
import { checkJava } from "./java";
|
||||
import { fixVersionWithDoubleName, installFabric, installForge, ModloaderConfig } from "../core/modloaders";
|
||||
import { fixVersionWithDoubleName, installFabric, installForge } from "../core/modloaders";
|
||||
import { ChildProcessWithoutNullStreams } from "node:child_process";
|
||||
import { prepareManifest } from "../core/mergeManifests";
|
||||
|
||||
export interface BaseConfig {
|
||||
version: string;
|
||||
auth: Auth;
|
||||
paths: Paths
|
||||
javaExecutable: string
|
||||
modloader?: Modloader;
|
||||
args?: ProcessArgs;
|
||||
ram?: { max?: string; min?: string }
|
||||
}
|
||||
|
||||
export interface Config extends BaseConfig {
|
||||
paths: Required<Paths>
|
||||
args: Required<ProcessArgs>
|
||||
ram: Required<ProcessRam>
|
||||
}
|
||||
import { DownloadPool } from "../utils/fetch";
|
||||
|
||||
export function defineConfig(logger: logger, ...layers: Partial<BaseConfig>[]) {
|
||||
let config: Partial<BaseConfig> = {} as Partial<BaseConfig>;
|
||||
|
|
@ -45,6 +31,10 @@ export function defineConfig(logger: logger, ...layers: Partial<BaseConfig>[]) {
|
|||
|
||||
config.ram = { max: config.ram?.max ?? "2G", min: config.ram?.min ?? "2G" };
|
||||
|
||||
if (!config.files) {
|
||||
config.files = []
|
||||
}
|
||||
|
||||
return config as Config
|
||||
}
|
||||
|
||||
|
|
@ -198,6 +188,38 @@ export class Instance extends EventEmitter<InstanceEvents> {
|
|||
throw new InstallError("An error occured while installing the modloader", "install-modloader", this.config, this.logger, { cause: error })
|
||||
}
|
||||
}
|
||||
|
||||
if (this.config.files.length > 0) {
|
||||
this.log("install-modpack", "Downloading modpack's files")
|
||||
try {
|
||||
const files = this.config.files.map<PoolFile>(f => {
|
||||
return { url: f.url, path: path.join(this.config.paths.instance, f.path), size: f.size }
|
||||
})
|
||||
const pool = new DownloadPool(files, { pQueueOptions: { concurrency: 5 }, overwrite: false })
|
||||
pool.on("completed", () => {
|
||||
this.emit(
|
||||
"progress",
|
||||
"modpack-files",
|
||||
pool.done,
|
||||
pool.total,
|
||||
pool.doneSize,
|
||||
pool.totalSize,
|
||||
);
|
||||
});
|
||||
await pool.run();
|
||||
} catch (error) {
|
||||
throw new InstallError("An error occured while downloading modpack's files", "install-modpack", this.config, this.logger, { cause: error })
|
||||
}
|
||||
}
|
||||
|
||||
if (this.config.overridesPath) {
|
||||
this.log("install-modpack", "Copying modpack's overrides")
|
||||
try {
|
||||
await fs.cp(this.config.overridesPath, this.config.paths.instance, {recursive: true})
|
||||
} catch (error) {
|
||||
throw new InstallError("An error occured while copying modpack's overrides", "install-modpack", this.config, this.logger, { cause: error })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async launch(): Promise<ChildProcessWithoutNullStreams> {
|
||||
|
|
|
|||
47
src/launcher/modrinth.ts
Normal file
47
src/launcher/modrinth.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import path from "node:path";
|
||||
import { downloadFile } from "../utils/fetch";
|
||||
import { getTempFolder } from "../utils/temp";
|
||||
import { unzipAll } from "../utils/unzip";
|
||||
import { ensureDir, exists, readJson } from "../utils/fs";
|
||||
import { Modloader, ModrinthManifest, BaseConfig, PoolFile } from "../utils/types";
|
||||
|
||||
function getModloader(manifest: ModrinthManifest): Modloader {
|
||||
if (manifest.dependencies["fabric-loader"]) {
|
||||
return { name: "fabric", version: manifest.dependencies["fabric-loader"] }
|
||||
} else if (manifest.dependencies["forge"]) {
|
||||
return { name: "forge", version: manifest.dependencies["forge"] }
|
||||
} else if (manifest.dependencies["neoforge"]) {
|
||||
return { name: "neoforge", version: manifest.dependencies["neoforge"] }
|
||||
} else {
|
||||
throw new Error("Unknown modloader")
|
||||
}
|
||||
}
|
||||
|
||||
export async function importModrinthModpack(source: string, sourceType: "url" | "file"): Promise<Partial<BaseConfig>> {
|
||||
const tempFolder = await getTempFolder("modrinth")
|
||||
|
||||
if (sourceType === "url") {
|
||||
const outputFile = path.join(tempFolder, "pack.mrpack")
|
||||
await downloadFile({ path: outputFile, url: source })
|
||||
source = outputFile
|
||||
}
|
||||
|
||||
if (!await exists(source)) {
|
||||
throw new Error("Couldn't find modpack file")
|
||||
}
|
||||
|
||||
await ensureDir(path.join(tempFolder, "pack"))
|
||||
|
||||
await unzipAll(source, path.join(tempFolder, "pack"), [], "overwrite")
|
||||
|
||||
const manifest = await readJson<ModrinthManifest>(path.join(tempFolder, "pack", "modrinth.index.json"))
|
||||
|
||||
return {
|
||||
version: manifest.dependencies.minecraft,
|
||||
modloader: getModloader(manifest),
|
||||
files: manifest.files.map<PoolFile>(f => {
|
||||
return { url: f.downloads[0], path: f.path, size: f.fileSize }
|
||||
}),
|
||||
overridesPath: path.join(tempFolder, "pack", "overrides")
|
||||
}
|
||||
}
|
||||
|
|
@ -253,4 +253,49 @@ export type FabricInstallerMeta = {
|
|||
maven: string,
|
||||
version: string,
|
||||
stable: boolean
|
||||
}[]
|
||||
}
|
||||
|
||||
export type ModrinthManifestFile = {
|
||||
path: string,
|
||||
hashes : {sha1: string, sha512: string},
|
||||
env: {client: string, server: string},
|
||||
downloads: string[],
|
||||
fileSize: number
|
||||
}
|
||||
|
||||
export type ModrinthManifest = {
|
||||
formatVersion: number,
|
||||
game: string,
|
||||
versionId: string,
|
||||
name: string,
|
||||
files: ModrinthManifestFile[],
|
||||
dependencies: {
|
||||
minecraft: string,
|
||||
"fabric-loader": string
|
||||
forge: string,
|
||||
neoforge: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface BaseConfig {
|
||||
version: string;
|
||||
auth: Auth;
|
||||
paths: Paths
|
||||
javaExecutable: string
|
||||
modloader?: Modloader;
|
||||
args?: ProcessArgs;
|
||||
ram?: { max?: string; min?: string },
|
||||
files?: PoolFile[],
|
||||
overridesPath?: string
|
||||
}
|
||||
|
||||
export interface Config extends BaseConfig {
|
||||
paths: Required<Paths>
|
||||
args: Required<ProcessArgs>
|
||||
ram: Required<ProcessRam>
|
||||
files: PoolFile[]
|
||||
}
|
||||
|
||||
export interface ModloaderConfig extends Config {
|
||||
modloader: Modloader
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ export async function unzipAll(from: string, to: string, filters: string[], mode
|
|||
}
|
||||
if (shouldSkip) continue;
|
||||
if (!await exists(path.join(to, entry.entryName)) || mode === "overwrite") {
|
||||
zip.extractEntryTo(entry.entryName, to);
|
||||
zip.extractEntryTo(entry.entryName, to, true, mode === "overwrite");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ import path from "path"
|
|||
import { Browser, BrowserWindow } from 'happy-dom';
|
||||
import PQueue from 'p-queue';
|
||||
|
||||
// Use "java" tests if you don't want tests to download java by themselves, you will need to provide binaries path :
|
||||
// pnpm run test /path/to/java8/bin/java /path/to/java21/bin/java
|
||||
|
||||
const importantVersions = ["1.7.10", "1.12.2", "1.16.5", "1.18.2", "1.20.1", "1.21.1", "1.21.11"]
|
||||
const modpacksUrls = ["https://cdn.modrinth.com/data/1KVo5zza/versions/FbnAVst2/Fabulously.Optimized-v12.0.7.mrpack", "https://cdn.modrinth.com/data/4BV47HRn/versions/krFPoaLH/Better%20MC%20%5BFORGE%5D%20BMC4%20v43.mrpack"]
|
||||
|
||||
const java8 = process.argv[2]
|
||||
const java21 = process.argv[3]
|
||||
|
|
@ -45,14 +49,16 @@ async function fExists(path) {
|
|||
const tempFolder = import.meta.dirname
|
||||
|
||||
if (await fExists(path.join(tempFolder, "vanilla"))) { await fs.rm(path.join(tempFolder, "vanilla"), { recursive: true }) }
|
||||
if (await fExists(path.join(tempFolder, "modrinth"))) { await fs.rm(path.join(tempFolder, "modrinth"), { recursive: true }) }
|
||||
if (await fExists(path.join(tempFolder, "modloaders/forge"))) { await fs.rm(path.join(tempFolder, "modloaders/forge"), { recursive: true }) }
|
||||
if (await fExists(path.join(tempFolder, "modloaders/neoforge"))) { await fs.rm(path.join(tempFolder, "modloaders/neoforge"), { recursive: true }) }
|
||||
if (await fExists(path.join(tempFolder, "modloaders/fabric"))) { await fs.rm(path.join(tempFolder, "modloaders/fabric"), { recursive: true }) }
|
||||
|
||||
await fs.mkdir(path.join(tempFolder, "vanilla"), {recursive: true})
|
||||
await fs.mkdir(path.join(tempFolder, "modloaders/forge"), {recursive: true})
|
||||
await fs.mkdir(path.join(tempFolder, "modloaders/neoforge"), {recursive: true})
|
||||
await fs.mkdir(path.join(tempFolder, "modloaders/fabric"), {recursive: true})
|
||||
await fs.mkdir(path.join(tempFolder, "vanilla"), { recursive: true })
|
||||
await fs.mkdir(path.join(tempFolder, "modrinth"), { recursive: true })
|
||||
await fs.mkdir(path.join(tempFolder, "modloaders/forge"), { recursive: true })
|
||||
await fs.mkdir(path.join(tempFolder, "modloaders/neoforge"), { recursive: true })
|
||||
await fs.mkdir(path.join(tempFolder, "modloaders/fabric"), { recursive: true })
|
||||
|
||||
// Forge
|
||||
{
|
||||
|
|
@ -89,7 +95,7 @@ await fs.mkdir(path.join(tempFolder, "modloaders/fabric"), {recursive: true})
|
|||
const parsedVersion = v.split(".")
|
||||
const start = `1.${parsedVersion[0]}.${parsedVersion[1]}`
|
||||
return start
|
||||
})).map(arr => arr[arr.length-1])
|
||||
})).map(arr => arr[arr.length - 1])
|
||||
|
||||
for (const neoForgeVersion of versions) {
|
||||
const parsedVersion = neoForgeVersion.split(".")
|
||||
|
|
@ -155,4 +161,23 @@ await fs.mkdir(path.join(tempFolder, "modloaders/fabric"), {recursive: true})
|
|||
console.log(`Done vanilla ${v.id}`)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Modrinth modpacks
|
||||
{
|
||||
modpacksUrls.forEach(async (url) => {
|
||||
const modpackId = url.split("/").pop().replace(".mrpack", "")
|
||||
let result = ""
|
||||
if (java) {
|
||||
const template = await fs.readFile(path.join(tempFolder, "modrinth-java.test.ts.template"), { encoding: "utf-8" })
|
||||
// TODO: use java version based on modpack's minecraft version
|
||||
result = template.replaceAll("${modpack_url}", url).replaceAll("${modpack_id}", modpackId).replaceAll("${java}", java21)
|
||||
} else {
|
||||
const template = await fs.readFile(path.join(tempFolder, "modrinth.test.ts.template"), { encoding: "utf-8" })
|
||||
// Same but inside tests
|
||||
result = template.replaceAll("${modpack_url}", url).replaceAll("${modpack_id}", modpackId)
|
||||
}
|
||||
await fs.writeFile(path.join(tempFolder, `modrinth/modrinth-${modpackId}.test.ts`), result)
|
||||
console.log(`Done modrinth ${modpackId}`)
|
||||
})
|
||||
}
|
||||
50
tests/modrinth-java.test.ts.template
Normal file
50
tests/modrinth-java.test.ts.template
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import { test } from "vitest";
|
||||
import { Instance, offlineAuth, RuntimeManager, getJavaComponent, importModrinthModpack } from "../../dist/index.js";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
|
||||
const gameRoot = path.join(import.meta.dirname, "..", "temp");
|
||||
// await fs.rm(gameRoot, { recursive: true, force: true });
|
||||
// await fs.mkdir(gameRoot, { recursive: true });
|
||||
|
||||
test("launch game", { timeout: 0, tags: ["full", "modrinth"] }, async () => {
|
||||
const javaManager = new RuntimeManager(path.join(gameRoot, "java"));
|
||||
javaManager.on("progress", console.log)
|
||||
// const java = await javaManager.use(await getJavaComponent("${version}"))
|
||||
|
||||
const instance = new Instance({
|
||||
auth: offlineAuth("player"),
|
||||
paths: { root: gameRoot, instance: path.join(gameRoot, "instances", "${modpack_id}") },
|
||||
javaExecutable: "${java}",
|
||||
ram: {max:"4G",min:"4G"}
|
||||
},
|
||||
await importModrinthModpack("${modpack_url}", "url")
|
||||
);
|
||||
|
||||
instance.on("progress", console.log);
|
||||
instance.on("log", (step, msg) => {
|
||||
console.log(`[${step}] ${msg}`)
|
||||
})
|
||||
|
||||
await instance.install();
|
||||
const p = await instance.launch();
|
||||
|
||||
p.stdout.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
p.stderr.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
await new Promise<void>((res) => {
|
||||
p.on("error", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
res();
|
||||
});
|
||||
p.on("close", () => {
|
||||
console.log("closed");
|
||||
res();
|
||||
});
|
||||
});
|
||||
});
|
||||
50
tests/modrinth.test.ts.template
Normal file
50
tests/modrinth.test.ts.template
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import { test } from "vitest";
|
||||
import { Instance, offlineAuth, RuntimeManager, getJavaComponent, importModrinthModpack } from "../../../dist/index.js";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
|
||||
const gameRoot = path.join(import.meta.dirname, "..", "temp");
|
||||
// await fs.rm(gameRoot, { recursive: true, force: true });
|
||||
// await fs.mkdir(gameRoot, { recursive: true });
|
||||
|
||||
test("launch game", { timeout: 0, tags: ["full", "modrinth"] }, async () => {
|
||||
const javaManager = new RuntimeManager(path.join(gameRoot, "java"));
|
||||
javaManager.on("progress", console.log)
|
||||
const java = await javaManager.use(await getJavaComponent("${version}"))
|
||||
|
||||
const instance = new Instance({
|
||||
auth: offlineAuth("player"),
|
||||
paths: { root: gameRoot, instance: path.join(gameRoot, "instances", "${modpack_id}") },
|
||||
javaExecutable: java,
|
||||
ram: {max:"4G",min:"4G"}
|
||||
},
|
||||
await importModrinthModpack("${modpack_url}", "url")
|
||||
);
|
||||
|
||||
instance.on("progress", console.log);
|
||||
instance.on("log", (step, msg) => {
|
||||
console.log(`[${step}] ${msg}`)
|
||||
})
|
||||
|
||||
await instance.install();
|
||||
const p = await instance.launch();
|
||||
|
||||
p.stdout.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
p.stderr.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
await new Promise<void>((res) => {
|
||||
p.on("error", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
res();
|
||||
});
|
||||
p.on("close", () => {
|
||||
console.log("closed");
|
||||
res();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { test } from "vitest";
|
||||
import { Instance, offlineAuth, RuntimeManager, getJavaComponent, importModrinthModpack } from "../../dist/index.js";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
|
||||
const gameRoot = path.join(import.meta.dirname, "..", "temp");
|
||||
// await fs.rm(gameRoot, { recursive: true, force: true });
|
||||
// await fs.mkdir(gameRoot, { recursive: true });
|
||||
|
||||
test("launch game", { timeout: 0, tags: ["full", "modrinth"] }, async () => {
|
||||
const javaManager = new RuntimeManager(path.join(gameRoot, "java"));
|
||||
javaManager.on("progress", console.log)
|
||||
// const java = await javaManager.use(await getJavaComponent("${version}"))
|
||||
|
||||
const instance = new Instance({
|
||||
auth: offlineAuth("player"),
|
||||
paths: { root: gameRoot, instance: path.join(gameRoot, "instances", "Better%20MC%20%5BFORGE%5D%20BMC4%20v43") },
|
||||
javaExecutable: "/nix/store/wrf2p3qb5sycka2y4nnl7pdm8h6zpcin-openjdk-21.0.10+7/bin/java",
|
||||
ram: {max:"4G",min:"4G"}
|
||||
},
|
||||
await importModrinthModpack("https://cdn.modrinth.com/data/4BV47HRn/versions/krFPoaLH/Better%20MC%20%5BFORGE%5D%20BMC4%20v43.mrpack", "url")
|
||||
);
|
||||
|
||||
instance.on("progress", console.log);
|
||||
instance.on("log", (step, msg) => {
|
||||
console.log(`[${step}] ${msg}`)
|
||||
})
|
||||
|
||||
await instance.install();
|
||||
const p = await instance.launch();
|
||||
|
||||
p.stdout.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
p.stderr.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
await new Promise<void>((res) => {
|
||||
p.on("error", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
res();
|
||||
});
|
||||
p.on("close", () => {
|
||||
console.log("closed");
|
||||
res();
|
||||
});
|
||||
});
|
||||
});
|
||||
50
tests/modrinth/modrinth-Fabulously.Optimized-v12.0.7.test.ts
Normal file
50
tests/modrinth/modrinth-Fabulously.Optimized-v12.0.7.test.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import { test } from "vitest";
|
||||
import { Instance, offlineAuth, RuntimeManager, getJavaComponent, importModrinthModpack } from "../../dist/index.js";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
|
||||
const gameRoot = path.join(import.meta.dirname, "..", "temp");
|
||||
// await fs.rm(gameRoot, { recursive: true, force: true });
|
||||
// await fs.mkdir(gameRoot, { recursive: true });
|
||||
|
||||
test("launch game", { timeout: 0, tags: ["full", "modrinth"] }, async () => {
|
||||
const javaManager = new RuntimeManager(path.join(gameRoot, "java"));
|
||||
javaManager.on("progress", console.log)
|
||||
// const java = await javaManager.use(await getJavaComponent("${version}"))
|
||||
|
||||
const instance = new Instance({
|
||||
auth: offlineAuth("player"),
|
||||
paths: { root: gameRoot, instance: path.join(gameRoot, "instances", "Fabulously.Optimized-v12.0.7") },
|
||||
javaExecutable: "/nix/store/wrf2p3qb5sycka2y4nnl7pdm8h6zpcin-openjdk-21.0.10+7/bin/java",
|
||||
ram: {max:"4G",min:"4G"}
|
||||
},
|
||||
await importModrinthModpack("/home/heroz/Downloads/Fabulously.Optimized-v12.0.7.mrpack", "file")
|
||||
);
|
||||
|
||||
instance.on("progress", console.log);
|
||||
instance.on("log", (step, msg) => {
|
||||
console.log(`[${step}] ${msg}`)
|
||||
})
|
||||
|
||||
await instance.install();
|
||||
const p = await instance.launch();
|
||||
|
||||
p.stdout.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
p.stderr.on("data", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
});
|
||||
|
||||
await new Promise<void>((res) => {
|
||||
p.on("error", (d: Buffer) => {
|
||||
console.log(d.toString());
|
||||
res();
|
||||
});
|
||||
p.on("close", () => {
|
||||
console.log("closed");
|
||||
res();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -18,6 +18,11 @@ export default defineConfig({
|
|||
name: 'forge',
|
||||
description: 'Only forge and neoforge tests from full test suite',
|
||||
concurrent: false
|
||||
},
|
||||
{
|
||||
name: 'modrinth',
|
||||
description: 'Only tests that uses populars modrinth modpacks',
|
||||
concurrent: false
|
||||
}
|
||||
],
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue