Replace AdmZip with node-stream-zip.
This commit is contained in:
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@@ -16,7 +16,8 @@
|
||||
"preLaunchTask": "compile",
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/dist/**/*.js"
|
||||
]
|
||||
],
|
||||
"outputCapture": "std"
|
||||
}
|
||||
]
|
||||
}
|
||||
19
package-lock.json
generated
19
package-lock.json
generated
@@ -67,15 +67,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/adm-zip": {
|
||||
"version": "0.4.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.4.33.tgz",
|
||||
"integrity": "sha512-WM0DCWFLjXtddl0fu0+iN2ZF+qz8RF9RddG5OSy/S90AQz01Fu8lHn/3oTIZDxvG8gVcnBLAHMHOdBLbV6m6Mw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/color-name": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||
@@ -210,11 +201,6 @@
|
||||
"integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==",
|
||||
"dev": true
|
||||
},
|
||||
"adm-zip": {
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz",
|
||||
"integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.12.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
|
||||
@@ -1126,6 +1112,11 @@
|
||||
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
|
||||
"dev": true
|
||||
},
|
||||
"node-stream-zip": {
|
||||
"version": "1.11.2",
|
||||
"resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.11.2.tgz",
|
||||
"integrity": "sha512-cowCX+OyzS3tN2i4BMMFxCr/pE6cQlEMTbVCugmos0TNEJQNtcG04tR41CY8lumO1I7F5GFiLaU4WavomJthaA=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
},
|
||||
"homepage": "https://github.com/dscalzi/Nebula#readme",
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.4.33",
|
||||
"@types/fs-extra": "^9.0.1",
|
||||
"@types/node": "^12.12.43",
|
||||
"@types/triple-beam": "^1.3.1",
|
||||
@@ -38,12 +37,12 @@
|
||||
"typescript": "^3.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"adm-zip": "^0.4.14",
|
||||
"axios": "^0.19.2",
|
||||
"dotenv": "^8.2.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"helios-distribution-types": "^1.0.0-pre.1",
|
||||
"moment": "^2.26.0",
|
||||
"node-stream-zip": "^1.11.2",
|
||||
"toml": "^3.0.0",
|
||||
"triple-beam": "^1.3.0",
|
||||
"winston": "^3.2.1",
|
||||
|
||||
@@ -39,10 +39,10 @@ export class MiscFileStructure extends ModuleStructure {
|
||||
return acc
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||
return name
|
||||
}
|
||||
protected async getModuleUrl(name: string, path: string, stats: Stats): Promise<string> {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import AdmZip from 'adm-zip'
|
||||
import { Stats } from 'fs-extra'
|
||||
import StreamZip from 'node-stream-zip'
|
||||
import toml from 'toml'
|
||||
import { capitalize } from '../../../../../util/stringutils'
|
||||
import { VersionUtil } from '../../../../../util/versionutil'
|
||||
@@ -33,35 +32,60 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
||||
return ForgeModStructure113.isForVersion(version, libraryVersion)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
const fmData = this.getForgeModMetadata(buf, name)
|
||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||
const fmData = await this.getForgeModMetadata(name, path)
|
||||
return this.generateMavenIdentifier(fmData.mods[0].modId, fmData.mods[0].version)
|
||||
}
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return capitalize((this.getForgeModMetadata(buf, name)).mods[0].displayName)
|
||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||
return capitalize((await this.getForgeModMetadata(name, path)).mods[0].displayName)
|
||||
}
|
||||
|
||||
private getForgeModMetadata(buf: Buffer, name: string): ModsToml {
|
||||
private getForgeModMetadata(name: string, path: string): Promise<ModsToml> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.forgeModMetadata, name)) {
|
||||
const zip = new AdmZip(buf)
|
||||
const zipEntries = zip.getEntries()
|
||||
|
||||
const zip = new StreamZip({
|
||||
file: path,
|
||||
storeEntries: true
|
||||
})
|
||||
|
||||
zip.on('error', err => reject(err))
|
||||
zip.on('ready', () => {
|
||||
try {
|
||||
const res = this.processZip(zip, name)
|
||||
zip.close()
|
||||
resolve(res)
|
||||
return
|
||||
} catch(err) {
|
||||
zip.close()
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
resolve(this.forgeModMetadata[name] as ModsToml)
|
||||
return
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
private processZip(zip: StreamZip, name: string): ModsToml {
|
||||
|
||||
// Optifine is a tweak that can be loaded as a forge mod. It does not
|
||||
// appear to contain a mcmod.info class. This a special case we will
|
||||
// account for.
|
||||
if (name.toLowerCase().indexOf('optifine') > -1) {
|
||||
|
||||
// Read zip for changelog.txt
|
||||
let rawChangelog
|
||||
for (const entry of zipEntries) {
|
||||
if (entry.entryName === 'changelog.txt') {
|
||||
rawChangelog = zip.readAsText(entry)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!rawChangelog) {
|
||||
let changelogBuf: Buffer
|
||||
try {
|
||||
changelogBuf = zip.entryDataSync('changelog.txt')
|
||||
} catch(err) {
|
||||
throw new Error('Failed to read OptiFine changelog.')
|
||||
}
|
||||
const info = rawChangelog.split('\n')[0].trim()
|
||||
|
||||
const info = changelogBuf.toString().split('\n')[0].trim()
|
||||
const version = info.split(' ')[1]
|
||||
this.forgeModMetadata[name] = ({
|
||||
modid: 'optifine',
|
||||
@@ -72,20 +96,26 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
||||
return this.forgeModMetadata[name] as ModsToml
|
||||
}
|
||||
|
||||
const raw = zip.readAsText('META-INF/mods.toml')
|
||||
let raw: Buffer | undefined
|
||||
try {
|
||||
raw = zip.entryDataSync('META-INF/mods.toml')
|
||||
} catch(err) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
let createDefault = false
|
||||
|
||||
if (raw) {
|
||||
// Assuming the main mod will be the first entry in this file.
|
||||
try {
|
||||
const parsed = toml.parse(raw) as ModsToml
|
||||
const parsed = toml.parse(raw.toString()) as ModsToml
|
||||
|
||||
// tslint:disable-next-line: no-invalid-template-strings
|
||||
if (parsed.mods[0].version === '${file.jarVersion}') {
|
||||
let version = '0.0.0'
|
||||
const manifest = zip.readAsText('META-INF/MANIFEST.MF')
|
||||
const keys = manifest.split('\n')
|
||||
try {
|
||||
const manifest = zip.entryDataSync('META-INF/MANIFEST.MF')
|
||||
const keys = manifest.toString().split('\n')
|
||||
ForgeModStructure113.logger.debug(keys)
|
||||
for (const key of keys) {
|
||||
const match = ForgeModStructure113.IMPLEMENTATION_VERSION_REGEX.exec(key)
|
||||
@@ -94,6 +124,9 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
||||
}
|
||||
}
|
||||
ForgeModStructure113.logger.debug(`ForgeMod ${name} contains a version wildcard, inferring ${version}`)
|
||||
} catch {
|
||||
ForgeModStructure113.logger.debug(`ForgeMod ${name} contains a version wildcard yet no MANIFEST.MF.. Defaulting to ${version}`)
|
||||
}
|
||||
parsed.mods[0].version = version
|
||||
}
|
||||
|
||||
@@ -120,10 +153,8 @@ export class ForgeModStructure113 extends BaseForgeModStructure {
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return this.forgeModMetadata[name] as ModsToml
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import AdmZip from 'adm-zip'
|
||||
import { Stats } from 'fs-extra'
|
||||
import StreamZip from 'node-stream-zip'
|
||||
import { capitalize } from '../../../../../util/stringutils'
|
||||
import { VersionUtil } from '../../../../../util/versionutil'
|
||||
import { McModInfo } from '../../../../forge/mcmodinfo'
|
||||
@@ -31,35 +30,59 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
||||
return ForgeModStructure17.isForVersion(version, libraryVersion)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
const fmData = this.getForgeModMetadata(buf, name)
|
||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||
const fmData = await this.getForgeModMetadata(name, path)
|
||||
return this.generateMavenIdentifier(fmData.modid, fmData.version)
|
||||
}
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return capitalize((this.getForgeModMetadata(buf, name)).name)
|
||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||
return capitalize((await this.getForgeModMetadata(name, path)).name)
|
||||
}
|
||||
|
||||
private getForgeModMetadata(buf: Buffer, name: string): McModInfo {
|
||||
private getForgeModMetadata(name: string, path: string): Promise<McModInfo> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.forgeModMetadata, name)) {
|
||||
const zip = new AdmZip(buf)
|
||||
const zipEntries = zip.getEntries()
|
||||
|
||||
const zip = new StreamZip({
|
||||
file: path,
|
||||
storeEntries: true
|
||||
})
|
||||
|
||||
zip.on('error', err => reject(err))
|
||||
zip.on('ready', () => {
|
||||
try {
|
||||
const res = this.processZip(zip, name)
|
||||
zip.close()
|
||||
resolve(res)
|
||||
return
|
||||
} catch(err) {
|
||||
zip.close()
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
resolve(this.forgeModMetadata[name] as McModInfo)
|
||||
return
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
private processZip(zip: StreamZip, name: string): McModInfo {
|
||||
// Optifine is a tweak that can be loaded as a forge mod. It does not
|
||||
// appear to contain a mcmod.info class. This a special case we will
|
||||
// account for.
|
||||
if (name.toLowerCase().indexOf('optifine') > -1) {
|
||||
|
||||
// Read zip for changelog.txt
|
||||
let rawChangelog
|
||||
for (const entry of zipEntries) {
|
||||
if (entry.entryName === 'changelog.txt') {
|
||||
rawChangelog = zip.readAsText(entry)
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!rawChangelog) {
|
||||
let changelogBuf: Buffer
|
||||
try {
|
||||
changelogBuf = zip.entryDataSync('changelog.txt')
|
||||
} catch(err) {
|
||||
throw new Error('Failed to read OptiFine changelog.')
|
||||
}
|
||||
const info = rawChangelog.split('\n')[0].trim()
|
||||
|
||||
const info = changelogBuf.toString().split('\n')[0].trim()
|
||||
const version = info.split(' ')[1]
|
||||
this.forgeModMetadata[name] = ({
|
||||
modid: 'optifine',
|
||||
@@ -70,12 +93,11 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
||||
return this.forgeModMetadata[name] as McModInfo
|
||||
}
|
||||
|
||||
let raw
|
||||
for (const entry of zipEntries) {
|
||||
if (entry.entryName === 'mcmod.info') {
|
||||
raw = zip.readAsText(entry)
|
||||
break
|
||||
}
|
||||
let raw: Buffer | undefined
|
||||
try {
|
||||
raw = zip.entryDataSync('mcmod.info')
|
||||
} catch(err) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
let createDefault = false
|
||||
@@ -83,7 +105,7 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
||||
if (raw) {
|
||||
// Assuming the main mod will be the first entry in this file.
|
||||
try {
|
||||
const resolved = JSON.parse(raw) as (McModInfoList | McModInfo[])
|
||||
const resolved = JSON.parse(raw.toString()) as (McModInfoList | McModInfo[])
|
||||
if (Object.prototype.hasOwnProperty.call(resolved, 'modListVersion')) {
|
||||
this.forgeModMetadata[name] = (resolved as McModInfoList).modList[0]
|
||||
} else {
|
||||
@@ -110,7 +132,6 @@ export class ForgeModStructure17 extends BaseForgeModStructure {
|
||||
version: '0.0.0'
|
||||
}) as unknown as McModInfo
|
||||
}
|
||||
}
|
||||
|
||||
return this.forgeModMetadata[name] as McModInfo
|
||||
}
|
||||
|
||||
@@ -34,12 +34,12 @@ export class LibraryStructure extends ModuleStructure {
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||
const inference = this.attemptCrudeInference(name)
|
||||
return this.generateMavenIdentifier(inference.name, inference.version)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||
const inference = this.attemptCrudeInference(name)
|
||||
return inference.name
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AdmZip from 'adm-zip'
|
||||
import StreamZip from 'node-stream-zip'
|
||||
import { Stats } from 'fs-extra'
|
||||
import { Type } from 'helios-distribution-types'
|
||||
import { join } from 'path'
|
||||
@@ -19,12 +19,12 @@ export class LiteModStructure extends ModuleStructure {
|
||||
super(absoluteRoot, relativeRoot, 'litemods', baseUrl, Type.LiteMod)
|
||||
}
|
||||
|
||||
protected async getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
const liteModData = this.getLiteModMetadata(buf, name)
|
||||
protected async getModuleId(name: string, path: string): Promise<string> {
|
||||
const liteModData = await this.getLiteModMetadata(name, path)
|
||||
return this.generateMavenIdentifier(liteModData.name, `${liteModData.version}-${liteModData.mcversion}`)
|
||||
}
|
||||
protected async getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string> {
|
||||
return capitalize(this.getLiteModMetadata(buf, name).name)
|
||||
protected async getModuleName(name: string, path: string): Promise<string> {
|
||||
return capitalize((await this.getLiteModMetadata(name, path)).name)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected async getModuleUrl(name: string, path: string, stats: Stats): Promise<string> {
|
||||
@@ -35,27 +35,53 @@ export class LiteModStructure extends ModuleStructure {
|
||||
return null
|
||||
}
|
||||
|
||||
private getLiteModMetadata(buf: Buffer, name: string): LiteMod {
|
||||
private getLiteModMetadata(name: string, path: string): Promise<LiteMod> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.liteModMetadata, name)) {
|
||||
const zip = new AdmZip(buf)
|
||||
const zipEntries = zip.getEntries()
|
||||
|
||||
let raw
|
||||
for (const entry of zipEntries) {
|
||||
if (entry.entryName === 'litemod.json') {
|
||||
raw = zip.readAsText(entry)
|
||||
break
|
||||
const zip = new StreamZip({
|
||||
file: path,
|
||||
storeEntries: true
|
||||
})
|
||||
|
||||
zip.on('error', err => reject(err))
|
||||
zip.on('ready', () => {
|
||||
try {
|
||||
const res = this.processZip(zip, name)
|
||||
zip.close()
|
||||
resolve(res)
|
||||
return
|
||||
} catch(err) {
|
||||
zip.close()
|
||||
throw err
|
||||
}
|
||||
})
|
||||
|
||||
} else {
|
||||
resolve(this.liteModMetadata[name] as LiteMod)
|
||||
return
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
private processZip(zip: StreamZip, name: string): LiteMod {
|
||||
|
||||
let raw: Buffer | undefined
|
||||
try {
|
||||
raw = zip.entryDataSync('litemod.json')
|
||||
} catch(err) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (raw) {
|
||||
this.liteModMetadata[name] = JSON.parse(raw) as LiteMod
|
||||
this.liteModMetadata[name] = JSON.parse(raw.toString()) as LiteMod
|
||||
} else {
|
||||
throw new Error(`Litemod ${name} does not contain litemod.json file.`)
|
||||
}
|
||||
}
|
||||
|
||||
return this.liteModMetadata[name] as LiteMod
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,16 +29,16 @@ export abstract class ModuleStructure extends BaseModelStructure<Module> {
|
||||
return `generated.${this.type.toLowerCase()}:${name}:${version}@${TypeMetadata[this.type].defaultExtension}`
|
||||
}
|
||||
|
||||
protected async abstract getModuleId(name: string, path: string, stats: Stats, buf: Buffer): Promise<string>
|
||||
protected async abstract getModuleName(name: string, path: string, stats: Stats, buf: Buffer): Promise<string>
|
||||
protected async abstract getModuleId(name: string, path: string): Promise<string>
|
||||
protected async abstract getModuleName(name: string, path: string): Promise<string>
|
||||
protected async abstract getModuleUrl(name: string, path: string, stats: Stats): Promise<string>
|
||||
protected async abstract getModulePath(name: string, path: string, stats: Stats): Promise<string | null>
|
||||
|
||||
protected async parseModule(file: string, filePath: string, stats: Stats): Promise<Module> {
|
||||
const buf = await readFile(filePath)
|
||||
const mdl: Module = {
|
||||
id: await this.getModuleId(file, filePath, stats, buf),
|
||||
name: await this.getModuleName(file, filePath, stats, buf),
|
||||
id: await this.getModuleId(file, filePath),
|
||||
name: await this.getModuleName(file, filePath),
|
||||
type: this.type,
|
||||
required: {
|
||||
value: false,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import AdmZip from 'adm-zip'
|
||||
import { createHash } from 'crypto'
|
||||
import { copy, lstat, mkdirs, pathExists, readFile, remove } from 'fs-extra'
|
||||
import { Module, Type } from 'helios-distribution-types'
|
||||
@@ -59,24 +58,14 @@ export class ForgeGradle2Adapter extends ForgeResolver {
|
||||
}
|
||||
ForgeGradle2Adapter.logger.debug(`Beginning processing of Forge v${this.forgeVersion} (Minecraft ${this.minecraftVersion})`)
|
||||
|
||||
const forgeUniversalBuffer = await readFile(targetLocalPath)
|
||||
const zip = new AdmZip(forgeUniversalBuffer)
|
||||
const zipEntries = zip.getEntries()
|
||||
|
||||
let versionManifest
|
||||
|
||||
for (const entry of zipEntries) {
|
||||
if (entry.entryName === 'version.json') {
|
||||
versionManifest = zip.readAsText(entry)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!versionManifest) {
|
||||
let versionManifestBuf: Buffer
|
||||
try {
|
||||
versionManifestBuf = await this.getVersionManifestFromJar(targetLocalPath)
|
||||
} catch(err) {
|
||||
throw new Error('Failed to find version.json in forge universal jar.')
|
||||
}
|
||||
|
||||
versionManifest = JSON.parse(versionManifest) as VersionManifestFG2
|
||||
const versionManifest = JSON.parse(versionManifestBuf.toString()) as VersionManifestFG2
|
||||
|
||||
const forgeModule: Module = {
|
||||
id: MavenUtil.mavenComponentsToIdentifier(
|
||||
@@ -87,7 +76,7 @@ export class ForgeGradle2Adapter extends ForgeResolver {
|
||||
name: 'Minecraft Forge',
|
||||
type: Type.ForgeHosted,
|
||||
artifact: this.generateArtifact(
|
||||
forgeUniversalBuffer,
|
||||
await readFile(targetLocalPath),
|
||||
await lstat(targetLocalPath),
|
||||
libRepo.getArtifactUrlByComponents(
|
||||
this.baseUrl,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import AdmZip from 'adm-zip'
|
||||
import { ForgeResolver } from '../forge.resolver'
|
||||
import { MinecraftVersion } from '../../../util/MinecraftVersion'
|
||||
import { LoggerUtil } from '../../../util/LoggerUtil'
|
||||
@@ -425,24 +424,14 @@ export class ForgeGradle3Adapter extends ForgeResolver {
|
||||
|
||||
// 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) {
|
||||
let versionManifestBuf: Buffer
|
||||
try {
|
||||
versionManifestBuf = await this.getVersionManifestFromJar(installerPath)
|
||||
} catch(err) {
|
||||
throw new Error('Failed to find version.json in forge installer jar.')
|
||||
}
|
||||
|
||||
versionManifest = JSON.parse(versionManifest) as VersionManifestFG3
|
||||
const versionManifest = JSON.parse(versionManifestBuf.toString()) as VersionManifestFG3
|
||||
|
||||
// Save Version Manifest
|
||||
const versionManifestDest = this.repoStructure.getVersionRepoStruct().getVersionManifest(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import StreamZip from 'node-stream-zip'
|
||||
import { createHash } from 'crypto'
|
||||
import { Stats } from 'fs-extra'
|
||||
import { Artifact } from 'helios-distribution-types'
|
||||
@@ -81,4 +82,24 @@ export abstract class ForgeResolver extends BaseResolver {
|
||||
}
|
||||
}
|
||||
|
||||
protected async getVersionManifestFromJar(jarPath: string): Promise<Buffer>{
|
||||
return new Promise((resolve, reject) => {
|
||||
const zip = new StreamZip({
|
||||
file: jarPath,
|
||||
storeEntries: true
|
||||
})
|
||||
zip.on('ready', () => {
|
||||
try {
|
||||
const data = zip.entryDataSync('version.json')
|
||||
zip.close()
|
||||
resolve(data)
|
||||
} catch(err) {
|
||||
reject(err)
|
||||
}
|
||||
|
||||
})
|
||||
zip.on('error', err => reject(err))
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user