UNPKG

silver-mc-java-core

Version:

A library starting minecraft game NW.js and Electron.js

234 lines (188 loc) 9.7 kB
/** * @author Luuxis * @license CC-BY-NC 4.0 - https://creativecommons.org/licenses/by-nc/4.0/ */ import { getPathLibraries, mirrors, getFileFromArchive } from '../../../utils/Index.js'; import download from '../../../utils/Downloader.js'; import neoForgePatcher from '../../patcher.js' import nodeFetch from 'node-fetch' import fs from 'fs' import path from 'path' import { EventEmitter } from 'events'; export default class NeoForgeMC extends EventEmitter { options: any; constructor(options = {}) { super(); this.options = options; } async downloadInstaller(Loader: any) { let build: string; let neoForgeURL: string; let oldAPI: boolean = true; let legacyMetaData = await nodeFetch(Loader.legacyMetaData).then(res => res.json()); let metaData = await nodeFetch(Loader.metaData).then(res => res.json()); let versions = legacyMetaData.versions.filter(version => version.includes(`${this.options.loader.version}-`)); if (!versions.length) { let minecraftVersion = `${this.options.loader.version.split('.')[1]}.${this.options.loader.version.split('.')[2] || 0}`; versions = metaData.versions.filter(version => version.startsWith(minecraftVersion)); oldAPI = false; } if (!versions.length) return { error: `NeoForge doesn't support Minecraft ${this.options.loader.version}` }; if (this.options.loader.build === 'latest' || this.options.loader.build === 'recommended') { build = versions[versions.length - 1]; } else build = versions.find(loader => loader === this.options.loader.build); if (!build) return { error: `NeoForge Loader ${this.options.loader.build} not found, Available builds: ${versions.join(', ')}` }; if (oldAPI) neoForgeURL = Loader.legacyInstall.replaceAll(/\${version}/g, build); else neoForgeURL = Loader.install.replaceAll(/\${version}/g, build); let pathFolder = path.resolve(this.options.path, 'neoForge'); let filePath = path.resolve(pathFolder, `neoForge-${build}-installer.jar`); if (!fs.existsSync(filePath)) { if (!fs.existsSync(pathFolder)) fs.mkdirSync(pathFolder, { recursive: true }); let downloadForge = new download(); downloadForge.on('progress', (downloaded, size) => { this.emit('progress', downloaded, size, `neoForge-${build}-installer.jar`); }); await downloadForge.downloadFile(neoForgeURL, pathFolder, `neoForge-${build}-installer.jar`); } return { filePath, oldAPI }; } async extractProfile(pathInstaller: any) { let neoForgeJSON: any = {} let file: any = await getFileFromArchive(pathInstaller, 'install_profile.json') let neoForgeJsonOrigin = JSON.parse(file); if (!neoForgeJsonOrigin) return { error: { message: 'Invalid neoForge installer' } }; if (neoForgeJsonOrigin.install) { neoForgeJSON.install = neoForgeJsonOrigin.install; neoForgeJSON.version = neoForgeJsonOrigin.versionInfo; } else { neoForgeJSON.install = neoForgeJsonOrigin; let file: any = await getFileFromArchive(pathInstaller, path.basename(neoForgeJSON.install.json)) neoForgeJSON.version = JSON.parse(file); } return neoForgeJSON; } async extractUniversalJar(profile: any, pathInstaller: any, oldAPI: any) { let skipneoForgeFilter = true if (profile.filePath) { let fileInfo = getPathLibraries(profile.path) this.emit('extract', `Extracting ${fileInfo.name}...`); let pathFileDest = path.resolve(this.options.path, 'libraries', fileInfo.path) if (!fs.existsSync(pathFileDest)) fs.mkdirSync(pathFileDest, { recursive: true }); let file: any = await getFileFromArchive(pathInstaller, profile.filePath) fs.writeFileSync(`${pathFileDest}/${fileInfo.name}`, file, { mode: 0o777 }) } else if (profile.path) { let fileInfo = getPathLibraries(profile.path) let listFile: any = await getFileFromArchive(pathInstaller, null, `maven/${fileInfo.path}`) await Promise.all( listFile.map(async (files: any) => { let fileName = files.split('/') this.emit('extract', `Extracting ${fileName[fileName.length - 1]}...`); let file: any = await getFileFromArchive(pathInstaller, files) let pathFileDest = path.resolve(this.options.path, 'libraries', fileInfo.path) if (!fs.existsSync(pathFileDest)) fs.mkdirSync(pathFileDest, { recursive: true }); fs.writeFileSync(`${pathFileDest}/${fileName[fileName.length - 1]}`, file, { mode: 0o777 }) }) ); } else { skipneoForgeFilter = false } if (profile.processors?.length) { let universalPath = profile.libraries.find(v => { return (v.name || '').startsWith(oldAPI ? 'net.neoforged:forge' : 'net.neoforged:neoforge') }) let client: any = await getFileFromArchive(pathInstaller, 'data/client.lzma'); let fileInfo = getPathLibraries(profile.path || universalPath.name, '-clientdata', '.lzma') let pathFile = path.resolve(this.options.path, 'libraries', fileInfo.path) if (!fs.existsSync(pathFile)) fs.mkdirSync(pathFile, { recursive: true }); fs.writeFileSync(`${pathFile}/${fileInfo.name}`, client, { mode: 0o777 }) this.emit('extract', `Extracting ${fileInfo.name}...`); } return skipneoForgeFilter } async downloadLibraries(profile: any, skipneoForgeFilter: any) { let { libraries } = profile.version; let downloader = new download(); let check = 0; let files: any = []; let size = 0; if (profile.install.libraries) libraries = libraries.concat(profile.install.libraries); libraries = libraries.filter((library, index, self) => index === self.findIndex(t => t.name === library.name)) let skipneoForge = [ 'net.minecraftforge:neoforged:', 'net.minecraftforge:minecraftforge:' ] for (let lib of libraries) { if (skipneoForgeFilter && skipneoForge.find(libs => lib.name.includes(libs))) { if (lib.downloads?.artifact?.url == "" || !lib.downloads?.artifact?.url) { this.emit('check', check++, libraries.length, 'libraries'); continue; } } if (lib.rules) { this.emit('check', check++, libraries.length, 'libraries'); continue; } let file = {} let libInfo = getPathLibraries(lib.name); let pathLib = path.resolve(this.options.path, 'libraries', libInfo.path); let pathLibFile = path.resolve(pathLib, libInfo.name); if (!fs.existsSync(pathLibFile)) { let url let sizeFile = 0 let baseURL = `${libInfo.path}/${libInfo.name}`; let response: any = await downloader.checkMirror(baseURL, mirrors) if (response?.status === 200) { size += response.size; sizeFile = response.size; url = response.url; } else if (lib.downloads?.artifact) { url = lib.downloads.artifact.url size += lib.downloads.artifact.size; sizeFile = lib.downloads.artifact.size; } else { url = null } if (url == null || !url) { return { error: `Impossible to download ${libInfo.name}` }; } file = { url: url, folder: pathLib, path: `${pathLib}/${libInfo.name}`, name: libInfo.name, size: sizeFile } files.push(file); } this.emit('check', check++, libraries.length, 'libraries'); } if (files.length > 0) { downloader.on("progress", (DL, totDL) => { this.emit("progress", DL, totDL, 'libraries'); }); await downloader.downloadFileMultiple(files, size, this.options.downloadFileMultiple); } return libraries } async patchneoForge(profile: any, oldAPI: any) { if (profile?.processors?.length) { let patcher: any = new neoForgePatcher(this.options); let config: any = {} patcher.on('patch', data => { this.emit('patch', data); }); patcher.on('error', data => { this.emit('error', data); }); if (!patcher.check(profile)) { config = { java: this.options.loader.config.javaPath, minecraft: this.options.loader.config.minecraftJar, minecraftJson: this.options.loader.config.minecraftJson } await patcher.patcher(profile, config, oldAPI); } } return true } }