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