diff --git a/.vscode/launch.json b/.vscode/launch.json index 4d659ac..3639121 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,9 +10,8 @@ "name": "Launch Program", "program": "${workspaceFolder}\\src\\index.ts", "args": [ - "test", - "1.12.2", - "14.23.5.2847" + "g", + "distro" ], "preLaunchTask": "compile", "outFiles": [ diff --git a/src/index.ts b/src/index.ts index 33d860f..387b525 100644 --- a/src/index.ts +++ b/src/index.ts @@ -217,7 +217,8 @@ const testCommand: yargs.CommandModule = { handler: async (argv) => { console.debug(`Invoked test with mcVer ${argv.mcVer} forgeVer ${argv.forgeVer}`) console.log(process.cwd()) - const resolver = ResolverRegistry.getForgeResolver('1.12.2', '14.23.5.2847', getRoot(), '', getBaseURL()) + const resolver = ResolverRegistry.getForgeResolver(argv.mcVer as string, + argv.forgeVer as string, getRoot(), '', getBaseURL()) if (resolver != null) { const mdl = await resolver.getModule() console.log(inspect(mdl, false, null, true)) diff --git a/src/model/forge/versionmanifest.ts b/src/model/forge/versionmanifest.ts index bbf54f3..b029c16 100644 --- a/src/model/forge/versionmanifest.ts +++ b/src/model/forge/versionmanifest.ts @@ -14,7 +14,8 @@ export interface VersionManifest { url?: string, checksums?: string[], serverreq?: boolean, - clientreq?: boolean + clientreq?: boolean, + comment?: string }> } diff --git a/src/model/struct/model/server.struct.ts b/src/model/struct/model/server.struct.ts index 73b4687..b767f3f 100644 --- a/src/model/struct/model/server.struct.ts +++ b/src/model/struct/model/server.struct.ts @@ -103,7 +103,7 @@ export class ServerStructure extends BaseModelStructure { const forgeResolver = ResolverRegistry.getForgeResolver( match[2], serverMeta.forgeVersion, - dirname(this.absoluteRoot), + dirname(this.containerDirectory), '', this.baseUrl ) diff --git a/src/model/struct/repo/repo.struct.ts b/src/model/struct/repo/repo.struct.ts index 954f98a..eb6d5c4 100644 --- a/src/model/struct/repo/repo.struct.ts +++ b/src/model/struct/repo/repo.struct.ts @@ -43,4 +43,8 @@ export class RepoStructure extends BaseFileStructure { return join(this.absoluteRoot, 'temp') } + public getWorkDirectory() { + return join(this.absoluteRoot, 'work') + } + } diff --git a/src/resolver/forge/adapter/forge113.resolver.ts b/src/resolver/forge/adapter/forge113.resolver.ts index 9e59f1f..fc8abc4 100644 --- a/src/resolver/forge/adapter/forge113.resolver.ts +++ b/src/resolver/forge/adapter/forge113.resolver.ts @@ -1,4 +1,9 @@ +import { spawn } from 'child_process' +import { copy, mkdirs, pathExists, remove, writeFile } from 'fs-extra' +import { basename, join } from 'path' import { Module } from '../../../model/spec/module' +import { ForgeRepoStructure } from '../../../model/struct/repo/forgerepo.struct' +import { JavaUtil } from '../../../util/javautil' import { ForgeResolver } from '../forge.resolver' export class Forge113Adapter extends ForgeResolver { @@ -18,11 +23,62 @@ export class Forge113Adapter extends ForgeResolver { } public async getModule(): Promise { - return null as unknown as Module + await this.process() + return {} as unknown as Module } public isForVersion(version: string): boolean { return Forge113Adapter.isForVersion(version) } + private async process() { + const forgeRepo = this.repoStructure.getForgeRepoStruct() + const installerPath = forgeRepo.getLocalForge(this.artifactVersion, 'installer') + console.debug(`Checking for forge installer at ${installerPath}..`) + if (!await forgeRepo.artifactExists(installerPath)) { + console.debug(`Forge installer not found locally, initializing download..`) + await forgeRepo.downloadArtifactByComponents( + this.REMOTE_REPOSITORY, + ForgeRepoStructure.FORGE_GROUP, + ForgeRepoStructure.FORGE_ARTIFACT, + this.artifactVersion, 'installer', 'jar' + ) + } else { + console.debug('Using locally discovered forge installer.') + } + console.debug(`Beginning processing of Forge v${this.forgeVersion} (Minecraft ${this.minecraftVersion})`) + + const workDir = this.repoStructure.getWorkDirectory() + if (await pathExists(workDir)) { + await remove(workDir) + } + + await mkdirs(workDir) + + const workingInstaller = join(workDir, basename(installerPath)) + + await copy(installerPath, workingInstaller) + + // Required for the installer to function. + await writeFile(join(workDir, 'launcher_profiles.json'), JSON.stringify({})) + + console.debug(`Spawning forge installer`) + + } + + private executeInstaller(installerExec: string) { + return new Promise((resolve, reject) => { + const child = spawn(JavaUtil.getJavaExecutable(), [ + '-jar', + installerExec + ]) + child.stdout.on('data', (data) => console.log('[Forge Installer]', data.toString('utf8'))) + child.stderr.on('data', (data) => console.error('[Forge Installer]', data.toString('utf8'))) + child.on('close', (code, signal) => { + console.log('[Forge Installer]', 'Exited with code', code) + resolve() + }) + }) + } + } diff --git a/src/resolver/forge/adapter/forge18.resolver.ts b/src/resolver/forge/adapter/forge18.resolver.ts index 8019609..37adbd9 100644 --- a/src/resolver/forge/adapter/forge18.resolver.ts +++ b/src/resolver/forge/adapter/forge18.resolver.ts @@ -14,7 +14,7 @@ import { ForgeResolver } from '../forge.resolver' export class Forge18Adapter extends ForgeResolver { public static isForVersion(version: string) { - return Forge18Adapter.isVersionAcceptable(version, [8, 9, 10, 11, 12]) + return Forge18Adapter.isVersionAcceptable(version, [7, 8, 9, 10, 11, 12]) } constructor( @@ -37,8 +37,7 @@ export class Forge18Adapter extends ForgeResolver { public async getForgeByVersion() { const forgeRepo = this.repoStructure.getForgeRepoStruct() - const artifactVersion = `${this.minecraftVersion}-${this.forgeVersion}` - const targetLocalPath = forgeRepo.getLocalForge(artifactVersion, 'universal') + const targetLocalPath = forgeRepo.getLocalForge(this.artifactVersion, 'universal') console.debug(`Checking for forge version at ${targetLocalPath}..`) if (!await forgeRepo.artifactExists(targetLocalPath)) { console.debug(`Forge not found locally, initializing download..`) @@ -46,7 +45,7 @@ export class Forge18Adapter extends ForgeResolver { this.REMOTE_REPOSITORY, ForgeRepoStructure.FORGE_GROUP, ForgeRepoStructure.FORGE_ARTIFACT, - artifactVersion, 'universal', 'jar') + this.artifactVersion, 'universal', 'jar') } else { console.debug('Using locally discovered forge.') } @@ -75,7 +74,7 @@ export class Forge18Adapter extends ForgeResolver { id: MavenUtil.mavenComponentsToIdentifier( ForgeRepoStructure.FORGE_GROUP, ForgeRepoStructure.FORGE_ARTIFACT, - artifactVersion, 'universal' + this.artifactVersion, 'universal' ), name: 'Minecraft Forge', type: Type.ForgeHosted, @@ -86,7 +85,7 @@ export class Forge18Adapter extends ForgeResolver { this.baseUrl, ForgeRepoStructure.FORGE_GROUP, ForgeRepoStructure.FORGE_ARTIFACT, - artifactVersion, 'universal' + this.artifactVersion, 'universal' ) ), subModules: [] diff --git a/src/resolver/forge/forge.resolver.ts b/src/resolver/forge/forge.resolver.ts index 49f99ba..41343c5 100644 --- a/src/resolver/forge/forge.resolver.ts +++ b/src/resolver/forge/forge.resolver.ts @@ -6,6 +6,7 @@ export abstract class ForgeResolver extends BaseResolver { protected readonly REMOTE_REPOSITORY = 'https://files.minecraftforge.net/maven/' protected repoStructure: RepoStructure + protected artifactVersion: string constructor( absoluteRoot: string, @@ -16,6 +17,55 @@ export abstract class ForgeResolver extends BaseResolver { ) { super(absoluteRoot, relativeRoot, baseUrl) this.repoStructure = new RepoStructure(absoluteRoot, relativeRoot) + this.artifactVersion = this.inferArtifactVersion() + } + + // Coverage is not 100% but that doesnt matter. + // It's enough and you should always use the latest version anyway. + public inferArtifactVersion() { + const version = `${this.minecraftVersion}-${this.forgeVersion}` + + const ver = this.forgeVersion.split('.') + const major = Number(ver[0]) + if ([12, 11, 10].indexOf(major) > -1) { + const minor = Number(ver[1]) + const revision = Number(ver[2]) + const extra = Number(ver[3]) + + if (major === 10) { + if (minor === 13 && revision >= 2 && extra >= 1300) { + return `${version}-1.7.10` + } + } else + if (major === 11) { + if (minor === 15) { + if (revision === 1 && extra >= 1890) { + return `${version}-1.8.9` + } else + if (revision === 0 && extra <= 1654) { + return `${version}-1.8.8` + } + } else + if (minor === 14 && revision === 0 && extra <= 1295) { + return `${version}-1.8` + } + } else + if (major === 12) { + if (minor === 17 && revision === 0 && extra <= 1936) { + return `${version}-1.9.4` + } else + if (minor === 16) { + if (revision === 0 && extra <= 1885) { + return `${version}-1.9` + } else + if (revision === 1 && extra === 1938) { + return `${version}-1.9.0` + } + } + } + + } + return version } } diff --git a/src/util/PackXZExtractWrapper.ts b/src/util/PackXZExtractWrapper.ts index 273874f..69164fb 100644 --- a/src/util/PackXZExtractWrapper.ts +++ b/src/util/PackXZExtractWrapper.ts @@ -1,12 +1,9 @@ import { spawn } from 'child_process' import { join } from 'path' +import { JavaUtil } from './javautil' export class PackXZExtractWrapper { - public static getJavaExecutable() { - return process.env.JAVA_EXECUTABLE as string - } - public static getPackXZExtract() { return join(process.cwd(), 'libraries', 'java', 'PackXZExtract.jar') } @@ -25,7 +22,7 @@ export class PackXZExtractWrapper { private static execute(command: string, paths: string[]) { return new Promise((resolve, reject) => { - const child = spawn(PackXZExtractWrapper.getJavaExecutable(), [ + const child = spawn(JavaUtil.getJavaExecutable(), [ '-jar', PackXZExtractWrapper.getPackXZExtract(), command, diff --git a/src/util/javautil.ts b/src/util/javautil.ts new file mode 100644 index 0000000..a6bef2d --- /dev/null +++ b/src/util/javautil.ts @@ -0,0 +1,7 @@ +export class JavaUtil { + + public static getJavaExecutable() { + return process.env.JAVA_EXECUTABLE as string + } + +} diff --git a/src/util/versionutil.ts b/src/util/versionutil.ts index efb2c06..4cdcf5a 100644 --- a/src/util/versionutil.ts +++ b/src/util/versionutil.ts @@ -17,7 +17,7 @@ export class VersionUtil { } } } - return null + throw new Error(`${version} is not a valid minecraft version!`) } }