Add support for processing 1.12.2 Forge compiled with Forge Gradle 3 (#8).
Changed the resolver names to match the Forge Gradle versions, since that software version determines the structure of the jar file and how it needs to be parsed. Refactored the ForgeGradle3 resolver to conditionally execute the installer only when we need artifacts generated by the installer. This allows the new 1.12.2 builds to be processed without running the installer. Changed the VersionSegemented interface to accept a libraryVersion, so we can segment within a minecraft version. This change is pending verification with Helios.
This commit is contained in:
38
package-lock.json
generated
38
package-lock.json
generated
@@ -103,9 +103,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "12.12.42",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.42.tgz",
|
||||
"integrity": "sha512-R/9QdYFLL9dE9l5cWWzWIZByVGFd7lk7JVOJ7KD+E1SJ4gni7XJRLz9QTjyYQiHIqEAgku9VgxdLjMlhhUaAFg==",
|
||||
"version": "12.12.43",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.43.tgz",
|
||||
"integrity": "sha512-KUyZdkGCnVPuXfsKmDUu2XLui65LZIJ2s0M57noy5e+ixUT2oK33ep7zlvgzI8LElcWqbf8AR+o/3GqAPac2zA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yargs": {
|
||||
@@ -124,12 +124,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.0.2.tgz",
|
||||
"integrity": "sha512-ER3bSS/A/pKQT/hjMGCK8UQzlL0yLjuCZ/G8CDFJFVTfl3X65fvq2lNYqOG8JPTfrPa2RULCdwfOyFjZEMNExQ==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.1.0.tgz",
|
||||
"integrity": "sha512-D52KwdgkjYc+fmTZKW7CZpH5ZBJREJKZXRrveMiRCmlzZ+Rw9wRVJ1JAmHQ9b/+Ehy1ZeaylofDB9wwXUt83wg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@typescript-eslint/experimental-utils": "3.0.2",
|
||||
"@typescript-eslint/experimental-utils": "3.1.0",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"regexpp": "^3.0.0",
|
||||
"semver": "^7.3.2",
|
||||
@@ -137,33 +137,33 @@
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.0.2.tgz",
|
||||
"integrity": "sha512-4Wc4EczvoY183SSEnKgqAfkj1eLtRgBQ04AAeG+m4RhTVyaazxc1uI8IHf0qLmu7xXe9j1nn+UoDJjbmGmuqXQ==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.1.0.tgz",
|
||||
"integrity": "sha512-Zf8JVC2K1svqPIk1CB/ehCiWPaERJBBokbMfNTNRczCbQSlQXaXtO/7OfYz9wZaecNvdSvVADt6/XQuIxhC79w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.3",
|
||||
"@typescript-eslint/typescript-estree": "3.0.2",
|
||||
"@typescript-eslint/typescript-estree": "3.1.0",
|
||||
"eslint-scope": "^5.0.0",
|
||||
"eslint-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.0.2.tgz",
|
||||
"integrity": "sha512-80Z7s83e8QXHNUspqVlWwb4t5gdz/1bBBmafElbK1wwAwiD/yvJsFyHRxlEpNrt4rdK6eB3p+2WEFkEDHAKk9w==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.1.0.tgz",
|
||||
"integrity": "sha512-NcDSJK8qTA2tPfyGiPes9HtVKLbksmuYjlgGAUs7Ld2K0swdWibnCq9IJx9kJN8JJdgUJSorFiGaPHBgH81F/Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/eslint-visitor-keys": "^1.0.0",
|
||||
"@typescript-eslint/experimental-utils": "3.0.2",
|
||||
"@typescript-eslint/typescript-estree": "3.0.2",
|
||||
"@typescript-eslint/experimental-utils": "3.1.0",
|
||||
"@typescript-eslint/typescript-estree": "3.1.0",
|
||||
"eslint-visitor-keys": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/typescript-estree": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.0.2.tgz",
|
||||
"integrity": "sha512-cs84mxgC9zQ6viV8MEcigfIKQmKtBkZNDYf8Gru2M+MhnA6z9q0NFMZm2IEzKqAwN8lY5mFVd1Z8DiHj6zQ3Tw==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.1.0.tgz",
|
||||
"integrity": "sha512-+4nfYauqeQvK55PgFrmBWFVYb6IskLyOosYEmhH3mSVhfBp9AIJnjExdgDmKWoOBHRcPM8Ihfm2BFpZf0euUZQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "^4.1.1",
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.4.33",
|
||||
"@types/fs-extra": "^9.0.1",
|
||||
"@types/node": "^12.12.42",
|
||||
"@types/node": "^12.12.43",
|
||||
"@types/yargs": "^15.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^3.0.2",
|
||||
"@typescript-eslint/parser": "^3.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^3.1.0",
|
||||
"@typescript-eslint/parser": "^3.1.0",
|
||||
"eslint": "^7.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "^3.9.3"
|
||||
|
||||
@@ -16,7 +16,7 @@ export abstract class BaseForgeModStructure extends ModuleStructure implements V
|
||||
super(absoluteRoot, relativeRoot, 'forgemods', baseUrl, Type.ForgeMod)
|
||||
}
|
||||
|
||||
public abstract isForVersion(version: MinecraftVersion): boolean
|
||||
public abstract isForVersion(version: MinecraftVersion, libraryVersion: string): boolean
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected async getModuleUrl(name: string, path: string, stats: Stats): Promise<string> {
|
||||
|
||||
@@ -11,7 +11,8 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
||||
|
||||
public static readonly IMPLEMENTATION_VERSION_REGEX = /^Implementation-Version: (.+)[\r\n]/
|
||||
|
||||
public static isForVersion(version: MinecraftVersion): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public static isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
return VersionUtil.isVersionAcceptable(version, [13, 14, 15])
|
||||
}
|
||||
|
||||
@@ -25,8 +26,8 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
||||
super(absoluteRoot, relativeRoot, baseUrl)
|
||||
}
|
||||
|
||||
public isForVersion(version: MinecraftVersion): boolean {
|
||||
return ForgeModStructure113.isForVersion(version)
|
||||
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
return ForgeModStructure113.isForVersion(version, libraryVersion)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
|
||||
@@ -9,7 +9,8 @@ import { MinecraftVersion } from '../../../../../util/MinecraftVersion'
|
||||
|
||||
export class ForgeModStructure17 extends BaseForgeModStructure {
|
||||
|
||||
public static isForVersion(version: MinecraftVersion): boolean {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public static isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
return VersionUtil.isVersionAcceptable(version, [7, 8, 9, 10, 11, 12])
|
||||
}
|
||||
|
||||
@@ -23,8 +24,8 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
||||
super(absoluteRoot, relativeRoot, baseUrl)
|
||||
}
|
||||
|
||||
public isForVersion(version: MinecraftVersion): boolean {
|
||||
return ForgeModStructure17.isForVersion(version)
|
||||
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
return ForgeModStructure17.isForVersion(version, libraryVersion)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
|
||||
@@ -50,6 +50,7 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
||||
if (options.forgeVersion != null) {
|
||||
const fms = VersionSegmentedRegistry.getForgeModStruct(
|
||||
minecraftVersion,
|
||||
options.forgeVersion,
|
||||
absoluteServerRoot,
|
||||
relativeServerRoot,
|
||||
this.baseUrl
|
||||
@@ -123,6 +124,7 @@ export class ServerStructure extends BaseModelStructure<Server> {
|
||||
|
||||
const forgeModStruct = VersionSegmentedRegistry.getForgeModStruct(
|
||||
minecraftVersion,
|
||||
serverMeta.forgeVersion,
|
||||
absoluteServerRoot,
|
||||
relativeServerRoot,
|
||||
this.baseUrl
|
||||
|
||||
@@ -50,20 +50,24 @@ export abstract class BaseMavenRepo extends BaseFileStructure {
|
||||
|
||||
private async downloadArtifactBase(url: string, relative: string): Promise<void> {
|
||||
const resolvedURL = resolveURL(url, relative).toString()
|
||||
console.debug(`Downloading ${resolvedURL}..`)
|
||||
return this.downloadArtifactDirect(resolvedURL, relative)
|
||||
}
|
||||
|
||||
public async downloadArtifactDirect(url: string, path: string): Promise<void> {
|
||||
console.debug(`Downloading ${url}..`)
|
||||
const response = await axios({
|
||||
method: 'get',
|
||||
url: resolvedURL,
|
||||
url,
|
||||
responseType: 'stream'
|
||||
})
|
||||
const localPath = resolve(this.containerDirectory, relative)
|
||||
const localPath = resolve(this.containerDirectory, path)
|
||||
await mkdirs(dirname(localPath))
|
||||
const writer = createWriteStream(localPath)
|
||||
response.data.pipe(writer)
|
||||
// tslint:disable-next-line: no-shadowed-variable
|
||||
return new Promise((resolve, reject) => {
|
||||
writer.on('finish', () => {
|
||||
console.debug(`Completed download of ${resolvedURL}.`)
|
||||
console.debug(`Completed download of ${url}.`)
|
||||
resolve()
|
||||
})
|
||||
writer.on('error', reject)
|
||||
|
||||
@@ -12,6 +12,6 @@ export abstract class BaseResolver implements Resolver, VersionSegmented {
|
||||
) {}
|
||||
|
||||
public abstract getModule(): Promise<Module>
|
||||
public abstract isForVersion(version: MinecraftVersion): boolean
|
||||
public abstract isForVersion(version: MinecraftVersion, libraryVersion: string): boolean
|
||||
|
||||
}
|
||||
|
||||
@@ -15,12 +15,13 @@ type ArrayElement<A> = A extends readonly (infer T)[] ? T : never
|
||||
|
||||
export class ForgeGradle2Adapter extends ForgeResolver {
|
||||
|
||||
public static isForVersion(version: MinecraftVersion): boolean {
|
||||
public static isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
if(version.getMinor() === 12 && !VersionUtil.isOneDotTwelveFG2(libraryVersion)) {
|
||||
return false
|
||||
}
|
||||
return VersionUtil.isVersionAcceptable(version, [7, 8, 9, 10, 11, 12])
|
||||
}
|
||||
|
||||
protected readonly MOJANG_REMOTE_REPOSITORY = 'https://libraries.minecraft.net/'
|
||||
|
||||
constructor(
|
||||
absoluteRoot: string,
|
||||
relativeRoot: string,
|
||||
@@ -35,8 +36,8 @@ export class ForgeGradle2Adapter extends ForgeResolver {
|
||||
return this.getForgeByVersion()
|
||||
}
|
||||
|
||||
public isForVersion(version: MinecraftVersion): boolean {
|
||||
return ForgeGradle2Adapter.isForVersion(version)
|
||||
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
return ForgeGradle2Adapter.isForVersion(version, libraryVersion)
|
||||
}
|
||||
|
||||
public async getForgeByVersion(): Promise<Module> {
|
||||
|
||||
@@ -1,21 +1,40 @@
|
||||
import { spawn } from 'child_process'
|
||||
import { copy, lstat, mkdirs, move, pathExists, readFile, remove, writeFile } from 'fs-extra'
|
||||
import { Module, Type } from 'helios-distribution-types'
|
||||
import { basename, dirname, join } from 'path'
|
||||
import { VersionManifestFG3 } from '../../../model/forge/VersionManifestFG3'
|
||||
import { LibRepoStructure } from '../../../model/struct/repo/librepo.struct'
|
||||
import { JavaUtil } from '../../../util/javautil'
|
||||
import { MavenUtil } from '../../../util/maven'
|
||||
import { VersionUtil } from '../../../util/versionutil'
|
||||
import AdmZip from 'adm-zip'
|
||||
import { ForgeResolver } from '../forge.resolver'
|
||||
import { MinecraftVersion } from '../../../util/MinecraftVersion'
|
||||
import { VersionUtil } from '../../../util/versionutil'
|
||||
import { Module, Type } from 'helios-distribution-types'
|
||||
import { LibRepoStructure } from '../../../model/struct/repo/librepo.struct'
|
||||
import { pathExists, remove, mkdirs, copy, writeFile, readFile, lstat, move, writeJson } from 'fs-extra'
|
||||
import { join, basename, dirname } from 'path'
|
||||
import { spawn } from 'child_process'
|
||||
import { JavaUtil } from '../../../util/javautil'
|
||||
import { VersionManifestFG3 } from '../../../model/forge/VersionManifestFG3'
|
||||
import { MavenUtil } from '../../../util/maven'
|
||||
import { createHash } from 'crypto'
|
||||
|
||||
interface GeneratedFile {
|
||||
name: string
|
||||
group: string
|
||||
artifact: string
|
||||
version: string
|
||||
classifiers: string[] | [undefined]
|
||||
skipIfNotPresent?: boolean
|
||||
}
|
||||
|
||||
export class ForgeGradle3Adapter extends ForgeResolver {
|
||||
|
||||
public static isForVersion(version: MinecraftVersion): boolean {
|
||||
return VersionUtil.isVersionAcceptable(version, [13, 14, 15])
|
||||
private static readonly WILDCARD_MCP_VERSION = '${mcpVersion}'
|
||||
|
||||
public static isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
if(version.getMinor() === 12 && VersionUtil.isOneDotTwelveFG2(libraryVersion)) {
|
||||
return false
|
||||
}
|
||||
return VersionUtil.isVersionAcceptable(version, [12, 13, 14, 15])
|
||||
}
|
||||
|
||||
private generatedFiles: GeneratedFile[] | undefined
|
||||
private wildcardsInUse: string[] | undefined
|
||||
|
||||
constructor(
|
||||
absoluteRoot: string,
|
||||
relativeRoot: string,
|
||||
@@ -24,18 +43,95 @@ export class ForgeGradle3Adapter extends ForgeResolver {
|
||||
forgeVersion: string
|
||||
) {
|
||||
super(absoluteRoot, relativeRoot, baseUrl, minecraftVersion, forgeVersion)
|
||||
this.configure()
|
||||
}
|
||||
|
||||
private configure(): void {
|
||||
// Configure for 13, 14, 15
|
||||
if(VersionUtil.isVersionAcceptable(this.minecraftVersion, [13, 14, 15])) {
|
||||
this.generatedFiles = [
|
||||
{
|
||||
name: 'base jar',
|
||||
group: LibRepoStructure.FORGE_GROUP,
|
||||
artifact: LibRepoStructure.FORGE_ARTIFACT,
|
||||
version: this.artifactVersion,
|
||||
classifiers: [undefined]
|
||||
},
|
||||
{
|
||||
name: 'universal jar',
|
||||
group: LibRepoStructure.FORGE_GROUP,
|
||||
artifact: LibRepoStructure.FORGE_ARTIFACT,
|
||||
version: this.artifactVersion,
|
||||
classifiers: ['universal']
|
||||
},
|
||||
{
|
||||
name: 'client jar',
|
||||
group: LibRepoStructure.FORGE_GROUP,
|
||||
artifact: LibRepoStructure.FORGE_ARTIFACT,
|
||||
version: this.artifactVersion,
|
||||
classifiers: ['client']
|
||||
},
|
||||
{
|
||||
name: 'client slim',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: this.minecraftVersion.toString(),
|
||||
classifiers: [
|
||||
'slim',
|
||||
'slim-stable'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'client data',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: this.minecraftVersion.toString(),
|
||||
classifiers: ['data'],
|
||||
skipIfNotPresent: true
|
||||
},
|
||||
{
|
||||
name: 'client extra',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: this.minecraftVersion.toString(),
|
||||
classifiers: [
|
||||
'extra',
|
||||
'extra-stable'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'client srg',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: `${this.minecraftVersion}-${ForgeGradle3Adapter.WILDCARD_MCP_VERSION}`,
|
||||
classifiers: ['srg']
|
||||
}
|
||||
]
|
||||
this.wildcardsInUse = [
|
||||
ForgeGradle3Adapter.WILDCARD_MCP_VERSION
|
||||
]
|
||||
return
|
||||
}
|
||||
|
||||
// Configure for 12
|
||||
if(VersionUtil.isVersionAcceptable(this.minecraftVersion, [12])) {
|
||||
// NOTHING TO CONFIGURE
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
public async getModule(): Promise<Module> {
|
||||
return this.process()
|
||||
}
|
||||
|
||||
public isForVersion(version: MinecraftVersion): boolean {
|
||||
return ForgeGradle3Adapter.isForVersion(version)
|
||||
public isForVersion(version: MinecraftVersion, libraryVersion: string): boolean {
|
||||
return ForgeGradle3Adapter.isForVersion(version, libraryVersion)
|
||||
}
|
||||
|
||||
private async process(): Promise<Module> {
|
||||
const libRepo = this.repoStructure.getLibRepoStruct()
|
||||
|
||||
// Get Installer
|
||||
const installerPath = libRepo.getLocalForge(this.artifactVersion, 'installer')
|
||||
console.debug(`Checking for forge installer at ${installerPath}..`)
|
||||
if (!await libRepo.artifactExists(installerPath)) {
|
||||
@@ -51,6 +147,18 @@ export class ForgeGradle3Adapter extends ForgeResolver {
|
||||
}
|
||||
console.debug(`Beginning processing of Forge v${this.forgeVersion} (Minecraft ${this.minecraftVersion})`)
|
||||
|
||||
if(this.generatedFiles != null && this.generatedFiles.length > 0) {
|
||||
// Run installer
|
||||
return this.processWithInstaller(installerPath)
|
||||
} else {
|
||||
// Installer not required
|
||||
return this.processWithoutInstaller(installerPath)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async processWithInstaller(installerPath: string): Promise<Module> {
|
||||
|
||||
const workDir = this.repoStructure.getWorkDirectory()
|
||||
if (await pathExists(workDir)) {
|
||||
await remove(workDir)
|
||||
@@ -94,129 +202,67 @@ export class ForgeGradle3Adapter extends ForgeResolver {
|
||||
await remove(workDir)
|
||||
|
||||
return forgeModule
|
||||
|
||||
}
|
||||
|
||||
private async processLibraries(manifest: VersionManifestFG3): Promise<Module[]> {
|
||||
private async processVersionManifest(): Promise<[VersionManifestFG3, Module]> {
|
||||
const workDir = this.repoStructure.getWorkDirectory()
|
||||
const versionRepo = this.repoStructure.getVersionRepoStruct()
|
||||
const versionName = versionRepo.getFileName(this.minecraftVersion, this.forgeVersion)
|
||||
const versionManifestPath = join(workDir, 'versions', versionName, `${versionName}.json`)
|
||||
|
||||
const libDir = join(this.repoStructure.getWorkDirectory(), 'libraries')
|
||||
const libRepo = this.repoStructure.getLibRepoStruct()
|
||||
const versionManifestBuf = await readFile(versionManifestPath)
|
||||
const versionManifest = JSON.parse(versionManifestBuf.toString()) as VersionManifestFG3
|
||||
|
||||
const mdls: Module[] = []
|
||||
|
||||
for (const entry of manifest.libraries) {
|
||||
const artifact = entry.downloads.artifact
|
||||
if (artifact.url) {
|
||||
|
||||
const targetLocalPath = join(libDir, artifact.path)
|
||||
|
||||
if (!await pathExists(targetLocalPath)) {
|
||||
throw new Error(`Expected library ${entry.name} not found!`)
|
||||
}
|
||||
|
||||
const components = MavenUtil.getMavenComponents(entry.name)
|
||||
|
||||
mdls.push({
|
||||
id: entry.name,
|
||||
name: `Minecraft Forge (${components.artifact})`,
|
||||
type: Type.Library,
|
||||
artifact: this.generateArtifact(
|
||||
await readFile(targetLocalPath),
|
||||
await lstat(targetLocalPath),
|
||||
libRepo.getArtifactUrlByComponents(
|
||||
this.baseUrl,
|
||||
components.group,
|
||||
components.artifact,
|
||||
components.version,
|
||||
components.classifier,
|
||||
components.extension
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
const destination = libRepo.getArtifactByComponents(
|
||||
components.group,
|
||||
components.artifact,
|
||||
components.version,
|
||||
components.classifier,
|
||||
components.extension
|
||||
)
|
||||
|
||||
await move(targetLocalPath, destination, {overwrite: true})
|
||||
|
||||
}
|
||||
const versionManifestModule: Module = {
|
||||
id: this.artifactVersion,
|
||||
name: 'Minecraft Forge (version.json)',
|
||||
type: Type.VersionManifest,
|
||||
artifact: this.generateArtifact(
|
||||
versionManifestBuf,
|
||||
await lstat(versionManifestPath),
|
||||
versionRepo.getVersionManifestURL(this.baseUrl, this.minecraftVersion, this.forgeVersion)
|
||||
)
|
||||
}
|
||||
|
||||
return mdls
|
||||
const destination = versionRepo.getVersionManifest(
|
||||
this.minecraftVersion,
|
||||
this.forgeVersion
|
||||
)
|
||||
|
||||
await move(versionManifestPath, destination, {overwrite: true})
|
||||
|
||||
return [versionManifest, versionManifestModule]
|
||||
}
|
||||
|
||||
private async processForgeModule(versionManifest: VersionManifestFG3): Promise<Module> {
|
||||
|
||||
const libDir = join(this.repoStructure.getWorkDirectory(), 'libraries')
|
||||
const mcpVersion = this.getMCPVersion(versionManifest.arguments.game)
|
||||
|
||||
if(this.wildcardsInUse) {
|
||||
if(this.wildcardsInUse.indexOf(ForgeGradle3Adapter.WILDCARD_MCP_VERSION) > -1) {
|
||||
|
||||
const mcpVersion = this.getMCPVersion(versionManifest.arguments.game)
|
||||
if(mcpVersion == null) {
|
||||
throw new Error('MCP Version not found.. did forge change their format?')
|
||||
}
|
||||
|
||||
this.generatedFiles = this.generatedFiles!.map(f => {
|
||||
if(f.version.indexOf(ForgeGradle3Adapter.WILDCARD_MCP_VERSION) > -1) {
|
||||
return {
|
||||
...f,
|
||||
version: f.version.replace(ForgeGradle3Adapter.WILDCARD_MCP_VERSION, mcpVersion)
|
||||
}
|
||||
}
|
||||
return f
|
||||
})
|
||||
|
||||
const generatedFiles = [
|
||||
{
|
||||
name: 'base jar',
|
||||
group: LibRepoStructure.FORGE_GROUP,
|
||||
artifact: LibRepoStructure.FORGE_ARTIFACT,
|
||||
version: this.artifactVersion,
|
||||
classifiers: [undefined]
|
||||
},
|
||||
{
|
||||
name: 'universal jar',
|
||||
group: LibRepoStructure.FORGE_GROUP,
|
||||
artifact: LibRepoStructure.FORGE_ARTIFACT,
|
||||
version: this.artifactVersion,
|
||||
classifiers: ['universal']
|
||||
},
|
||||
{
|
||||
name: 'client jar',
|
||||
group: LibRepoStructure.FORGE_GROUP,
|
||||
artifact: LibRepoStructure.FORGE_ARTIFACT,
|
||||
version: this.artifactVersion,
|
||||
classifiers: ['client']
|
||||
},
|
||||
{
|
||||
name: 'client slim',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: this.minecraftVersion.toString(),
|
||||
classifiers: [
|
||||
'slim',
|
||||
'slim-stable'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'client data',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: this.minecraftVersion.toString(),
|
||||
classifiers: ['data'],
|
||||
skipIfNotPresent: true
|
||||
},
|
||||
{
|
||||
name: 'client extra',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: this.minecraftVersion.toString(),
|
||||
classifiers: [
|
||||
'extra',
|
||||
'extra-stable'
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'client srg',
|
||||
group: LibRepoStructure.MINECRAFT_GROUP,
|
||||
artifact: LibRepoStructure.MINECRAFT_CLIENT_ARTIFACT,
|
||||
version: `${this.minecraftVersion}-${mcpVersion}`,
|
||||
classifiers: ['srg']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const mdls: Module[] = []
|
||||
|
||||
for (const entry of generatedFiles) {
|
||||
for (const entry of this.generatedFiles!) {
|
||||
|
||||
const targetLocations: string[] = []
|
||||
let located = false
|
||||
@@ -286,34 +332,58 @@ export class ForgeGradle3Adapter extends ForgeResolver {
|
||||
return forgeModule
|
||||
}
|
||||
|
||||
private async processVersionManifest(): Promise<[VersionManifestFG3, Module]> {
|
||||
const workDir = this.repoStructure.getWorkDirectory()
|
||||
const versionRepo = this.repoStructure.getVersionRepoStruct()
|
||||
const versionName = versionRepo.getFileName(this.minecraftVersion, this.forgeVersion)
|
||||
const versionManifestPath = join(workDir, 'versions', versionName, `${versionName}.json`)
|
||||
private async processLibraries(manifest: VersionManifestFG3): Promise<Module[]> {
|
||||
|
||||
const versionManifestBuf = await readFile(versionManifestPath)
|
||||
const versionManifest = JSON.parse(versionManifestBuf.toString()) as VersionManifestFG3
|
||||
const libDir = join(this.repoStructure.getWorkDirectory(), 'libraries')
|
||||
const libRepo = this.repoStructure.getLibRepoStruct()
|
||||
|
||||
const versionManifestModule: Module = {
|
||||
id: this.artifactVersion,
|
||||
name: 'Minecraft Forge (version.json)',
|
||||
type: Type.VersionManifest,
|
||||
artifact: this.generateArtifact(
|
||||
versionManifestBuf,
|
||||
await lstat(versionManifestPath),
|
||||
versionRepo.getVersionManifestURL(this.baseUrl, this.minecraftVersion, this.forgeVersion)
|
||||
)
|
||||
const mdls: Module[] = []
|
||||
|
||||
for (const entry of manifest.libraries) {
|
||||
const artifact = entry.downloads.artifact
|
||||
if (artifact.url) {
|
||||
|
||||
const targetLocalPath = join(libDir, artifact.path)
|
||||
|
||||
if (!await pathExists(targetLocalPath)) {
|
||||
throw new Error(`Expected library ${entry.name} not found!`)
|
||||
}
|
||||
|
||||
const components = MavenUtil.getMavenComponents(entry.name)
|
||||
|
||||
mdls.push({
|
||||
id: entry.name,
|
||||
name: `Minecraft Forge (${components.artifact})`,
|
||||
type: Type.Library,
|
||||
artifact: this.generateArtifact(
|
||||
await readFile(targetLocalPath),
|
||||
await lstat(targetLocalPath),
|
||||
libRepo.getArtifactUrlByComponents(
|
||||
this.baseUrl,
|
||||
components.group,
|
||||
components.artifact,
|
||||
components.version,
|
||||
components.classifier,
|
||||
components.extension
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
const destination = libRepo.getArtifactByComponents(
|
||||
components.group,
|
||||
components.artifact,
|
||||
components.version,
|
||||
components.classifier,
|
||||
components.extension
|
||||
)
|
||||
|
||||
await move(targetLocalPath, destination, {overwrite: true})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const destination = this.repoStructure.getVersionRepoStruct().getVersionManifest(
|
||||
this.minecraftVersion,
|
||||
this.forgeVersion
|
||||
)
|
||||
return mdls
|
||||
|
||||
await move(versionManifestPath, destination, {overwrite: true})
|
||||
|
||||
return [versionManifest, versionManifestModule]
|
||||
}
|
||||
|
||||
private executeInstaller(installerExec: string): Promise<void> {
|
||||
@@ -342,4 +412,169 @@ export class ForgeGradle3Adapter extends ForgeResolver {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
private async processWithoutInstaller(installerPath: string): Promise<Module> {
|
||||
|
||||
// Extract version.json from installer.
|
||||
|
||||
const forgeInstallerBuffer = await readFile(installerPath)
|
||||
const zip = new AdmZip(forgeInstallerBuffer)
|
||||
const zipEntries = zip.getEntries()
|
||||
|
||||
let versionManifest
|
||||
|
||||
for (const entry of zipEntries) {
|
||||
if (entry.entryName === 'version.json') {
|
||||
versionManifest = zip.readAsText(entry)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!versionManifest) {
|
||||
throw new Error('Failed to find version.json in forge installer jar.')
|
||||
}
|
||||
|
||||
versionManifest = JSON.parse(versionManifest) as VersionManifestFG3
|
||||
|
||||
// Save Version Manifest
|
||||
const versionManifestDest = this.repoStructure.getVersionRepoStruct().getVersionManifest(
|
||||
this.minecraftVersion,
|
||||
this.forgeVersion
|
||||
)
|
||||
await mkdirs(dirname(versionManifestDest))
|
||||
await writeJson(versionManifestDest, versionManifest, { spaces: 4 })
|
||||
|
||||
const libRepo = this.repoStructure.getLibRepoStruct()
|
||||
const universalLocalPath = libRepo.getLocalForge(this.artifactVersion, 'universal')
|
||||
console.debug(`Checking for Forge Universal jar at ${universalLocalPath}..`)
|
||||
|
||||
const forgeMdl = versionManifest.libraries.find(val => val.name.startsWith('net.minecraftforge:forge:'))
|
||||
|
||||
if(forgeMdl == null) {
|
||||
throw new Error('Forge entry not found in version.json!')
|
||||
}
|
||||
|
||||
let forgeUniversalBuffer
|
||||
|
||||
// Check for local universal jar.
|
||||
if (await libRepo.artifactExists(universalLocalPath)) {
|
||||
const localUniBuf = await readFile(universalLocalPath)
|
||||
const sha1 = createHash('sha1').update(localUniBuf).digest('hex')
|
||||
if(sha1 !== forgeMdl.downloads.artifact.sha1) {
|
||||
console.debug('SHA-1 of local universal jar does not match version.json entry.')
|
||||
console.debug('Redownloading Forge Universal jar..')
|
||||
} else {
|
||||
console.debug('Using locally discovered forge.')
|
||||
forgeUniversalBuffer = localUniBuf
|
||||
}
|
||||
} else {
|
||||
console.debug('Forge Universal jar not found locally, initializing download..')
|
||||
}
|
||||
|
||||
// Download if local is missing or corrupt
|
||||
if(!forgeUniversalBuffer) {
|
||||
await libRepo.downloadArtifactByComponents(
|
||||
this.REMOTE_REPOSITORY,
|
||||
LibRepoStructure.FORGE_GROUP,
|
||||
LibRepoStructure.FORGE_ARTIFACT,
|
||||
this.artifactVersion, 'universal', 'jar')
|
||||
forgeUniversalBuffer = await readFile(universalLocalPath)
|
||||
}
|
||||
|
||||
console.debug(`Beginning processing of Forge v${this.forgeVersion} (Minecraft ${this.minecraftVersion})`)
|
||||
|
||||
const forgeModule: Module = {
|
||||
id: MavenUtil.mavenComponentsToIdentifier(
|
||||
LibRepoStructure.FORGE_GROUP,
|
||||
LibRepoStructure.FORGE_ARTIFACT,
|
||||
this.artifactVersion, 'universal'
|
||||
),
|
||||
name: 'Minecraft Forge',
|
||||
type: Type.ForgeHosted,
|
||||
artifact: this.generateArtifact(
|
||||
forgeUniversalBuffer,
|
||||
await lstat(universalLocalPath),
|
||||
libRepo.getArtifactUrlByComponents(
|
||||
this.baseUrl,
|
||||
LibRepoStructure.FORGE_GROUP,
|
||||
LibRepoStructure.FORGE_ARTIFACT,
|
||||
this.artifactVersion, 'universal'
|
||||
)
|
||||
),
|
||||
subModules: []
|
||||
}
|
||||
|
||||
// Attach Version Manifest module.
|
||||
forgeModule.subModules?.push({
|
||||
id: this.artifactVersion,
|
||||
name: 'Minecraft Forge (version.json)',
|
||||
type: Type.VersionManifest,
|
||||
artifact: this.generateArtifact(
|
||||
await readFile(versionManifestDest),
|
||||
await lstat(versionManifestDest),
|
||||
this.repoStructure.getVersionRepoStruct().getVersionManifestURL(
|
||||
this.baseUrl, this.minecraftVersion, this.forgeVersion)
|
||||
)
|
||||
})
|
||||
|
||||
for(const lib of versionManifest.libraries) {
|
||||
if (lib.name.startsWith('net.minecraftforge:forge:')) {
|
||||
// We've already processed forge.
|
||||
continue
|
||||
}
|
||||
console.debug(`Processing ${lib.name}..`)
|
||||
|
||||
const extension = 'jar'
|
||||
const localPath = libRepo.getArtifactById(lib.name, extension)
|
||||
|
||||
let queueDownload = !await libRepo.artifactExists(localPath)
|
||||
let libBuf
|
||||
|
||||
if (!queueDownload) {
|
||||
libBuf = await readFile(localPath)
|
||||
const sha1 = createHash('sha1').update(libBuf).digest('hex')
|
||||
if (sha1 !== lib.downloads.artifact.sha1) {
|
||||
console.debug('Hashes do not match, redownloading..')
|
||||
queueDownload = true
|
||||
}
|
||||
} else {
|
||||
console.debug('Not found locally, downloading..')
|
||||
queueDownload = true
|
||||
}
|
||||
|
||||
if (queueDownload) {
|
||||
await libRepo.downloadArtifactDirect(lib.downloads.artifact.url, lib.downloads.artifact.path)
|
||||
libBuf = await readFile(localPath)
|
||||
} else {
|
||||
console.debug('Using local copy.')
|
||||
}
|
||||
|
||||
const stats = await lstat(localPath)
|
||||
|
||||
const mavenComponents = MavenUtil.getMavenComponents(lib.name)
|
||||
const properId = MavenUtil.mavenComponentsToIdentifier(
|
||||
mavenComponents.group, mavenComponents.artifact, mavenComponents.version,
|
||||
mavenComponents.classifier, extension
|
||||
)
|
||||
|
||||
forgeModule.subModules?.push({
|
||||
id: properId,
|
||||
name: `Minecraft Forge (${mavenComponents?.artifact})`,
|
||||
type: Type.Library,
|
||||
artifact: this.generateArtifact(
|
||||
libBuf as Buffer,
|
||||
stats,
|
||||
libRepo.getArtifactUrlByComponents(
|
||||
this.baseUrl,
|
||||
mavenComponents.group, mavenComponents.artifact,
|
||||
mavenComponents.version, mavenComponents.classifier, extension
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return forgeModule
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { MinecraftVersion } from '../../util/MinecraftVersion'
|
||||
|
||||
export abstract class ForgeResolver extends BaseResolver {
|
||||
|
||||
protected readonly MOJANG_REMOTE_REPOSITORY = 'https://libraries.minecraft.net/'
|
||||
protected readonly REMOTE_REPOSITORY = 'https://files.minecraftforge.net/maven/'
|
||||
|
||||
protected repoStructure: RepoStructure
|
||||
|
||||
@@ -2,6 +2,6 @@ import { MinecraftVersion } from './MinecraftVersion'
|
||||
|
||||
export interface VersionSegmented {
|
||||
|
||||
isForVersion(version: MinecraftVersion): boolean
|
||||
isForVersion(version: MinecraftVersion, libraryVersion: string): boolean
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export class VersionSegmentedRegistry {
|
||||
baseURL: string
|
||||
): ForgeResolver {
|
||||
for (const impl of VersionSegmentedRegistry.FORGE_ADAPTER_IMPL) {
|
||||
if (impl.isForVersion(minecraftVersion)) {
|
||||
if (impl.isForVersion(minecraftVersion, forgeVersion)) {
|
||||
return new impl(absoluteRoot, relativeRoot, baseURL, minecraftVersion, forgeVersion)
|
||||
}
|
||||
}
|
||||
@@ -35,12 +35,13 @@ export class VersionSegmentedRegistry {
|
||||
|
||||
public static getForgeModStruct(
|
||||
minecraftVersion: MinecraftVersion,
|
||||
forgeVersion: string,
|
||||
absoluteRoot: string,
|
||||
relativeRoot: string,
|
||||
baseUrl: string
|
||||
): BaseForgeModStructure {
|
||||
for (const impl of VersionSegmentedRegistry.FORGEMOD_STRUCT_IML) {
|
||||
if (impl.isForVersion(minecraftVersion)) {
|
||||
if (impl.isForVersion(minecraftVersion, forgeVersion)) {
|
||||
return new impl(absoluteRoot, relativeRoot, baseUrl)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,19 @@ export class VersionUtil {
|
||||
return false
|
||||
}
|
||||
|
||||
public static isOneDotTwelveFG2(libraryVersion: string): boolean {
|
||||
const maxFG2 = [14, 23, 5, 2847]
|
||||
const verSplit = libraryVersion.split('.').map(v => Number(v))
|
||||
|
||||
for(let i=0; i<maxFG2.length; i++) {
|
||||
if(verSplit[i] > maxFG2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public static isPromotionVersion(version: string): boolean {
|
||||
return VersionUtil.PROMOTION_TYPE.indexOf(version.toLowerCase()) > -1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user