UNPKG

silver-mc-java-core

Version:

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

266 lines (214 loc) 9.68 kB
/** * @author Luuxis * @license CC-BY-NC 4.0 - https://creativecommons.org/licenses/by-nc/4.0/ */ import { EventEmitter } from 'events'; import path from 'path'; import fs from 'fs'; import { spawn } from 'child_process'; import jsonMinecraft from './Minecraft/Minecraft-Json.js'; import librariesMinecraft from './Minecraft/Minecraft-Libraries.js'; import assetsMinecraft from './Minecraft/Minecraft-Assets.js'; import loaderMinecraft from './Minecraft/Minecraft-Loader.js'; import javaMinecraft from './Minecraft/Minecraft-Java.js'; import bundleMinecraft from './Minecraft/Minecraft-Bundle.js'; import argumentsMinecraft from './Minecraft/Minecraft-Arguments.js'; import { isold } from './utils/Index.js'; import Downloader from './utils/Downloader.js'; type loader = { path?: string, type?: string, build?: string, enable?: boolean } type screen = { width?: number, height?: number, fullscreen?: boolean } type memory = { min?: string, max?: string } type javaOPTS = { path?: string, version?: number, type?: string } type LaunchOPTS = { url: string | null, authenticator: any, timeout?: number, path: string, version: string, instance?: string, detached?: boolean, downloadFileMultiple?: number, intelEnabledMac?: boolean, loader: loader, mcp: any, verify: boolean, ignored: string[], JVM_ARGS: string[], GAME_ARGS: string[], java: javaOPTS, screen: screen, memory: memory }; export default class Launch extends EventEmitter { options: LaunchOPTS; async Launch(opt: LaunchOPTS) { const defaultOptions: LaunchOPTS = { url: null, authenticator: null, timeout: 10000, path: '.Minecraft', version: 'latest_release', instance: null, detached: false, intelEnabledMac: false, downloadFileMultiple: 5, loader: { path: './loader', type: null, build: 'latest', enable: false, }, mcp: null, verify: false, ignored: [], JVM_ARGS: [], GAME_ARGS: [], java: { path: null, version: null, type: 'jre', }, screen: { width: null, height: null, fullscreen: false, }, memory: { min: '1G', max: '2G' }, ...opt, }; this.options = defaultOptions; this.options.path = path.resolve(this.options.path).replace(/\\/g, '/'); if (this.options.mcp) { if (this.options.instance) this.options.mcp = `${this.options.path}/instances/${this.options.instance}/${this.options.mcp}` else this.options.mcp = path.resolve(`${this.options.path}/${this.options.mcp}`).replace(/\\/g, '/') } if (this.options.loader.type) { this.options.loader.type = this.options.loader.type.toLowerCase() this.options.loader.build = this.options.loader.build.toLowerCase() } if (!this.options.authenticator) return this.emit("error", { error: "Authenticator not found" }); if (this.options.downloadFileMultiple < 1) this.options.downloadFileMultiple = 1 if (this.options.downloadFileMultiple > 30) this.options.downloadFileMultiple = 30 if (typeof this.options.loader.path !== 'string') this.options.loader.path = `./loader/${this.options.loader.type}`; this.start(); } async start() { let data: any = await this.DownloadGame(); if (data.error) return this.emit('error', data); let { minecraftJson, minecraftLoader, minecraftVersion, minecraftJava } = data; let minecraftArguments: any = await new argumentsMinecraft(this.options).GetArguments(minecraftJson, minecraftLoader); if (minecraftArguments.error) return this.emit('error', minecraftArguments); let loaderArguments: any = await new loaderMinecraft(this.options).GetArguments(minecraftLoader, minecraftVersion); if (loaderArguments.error) return this.emit('error', loaderArguments); let Arguments: any = [ ...minecraftArguments.jvm, ...minecraftArguments.classpath, ...loaderArguments.jvm, minecraftArguments.mainClass, ...minecraftArguments.game, ...loaderArguments.game ] let java: any = this.options.java.path ? this.options.java.path : minecraftJava.path; let logs = this.options.instance ? `${this.options.path}/instances/${this.options.instance}` : this.options.path; if (!fs.existsSync(logs)) fs.mkdirSync(logs, { recursive: true }); let argumentsLogs: string = Arguments.join(' ') argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator?.access_token, '????????') argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator?.client_token, '????????') argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator?.uuid, '????????') argumentsLogs = argumentsLogs.replaceAll(this.options.authenticator?.xboxAccount?.xuid, '????????') argumentsLogs = argumentsLogs.replaceAll(`${this.options.path}/`, '') this.emit('data', `Launching with arguments ${argumentsLogs}`); let minecraftDebug = spawn(java, Arguments, { cwd: logs, detached: this.options.detached }) minecraftDebug.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))) minecraftDebug.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))) minecraftDebug.on('close', (code) => this.emit('close', 'Minecraft closed')) } async DownloadGame() { let InfoVersion = await new jsonMinecraft(this.options).GetInfoVersion(); let loaderJson: any = null; if (InfoVersion.error) return InfoVersion let { json, version } = InfoVersion; let libraries = new librariesMinecraft(this.options) let bundle = new bundleMinecraft(this.options) let java = new javaMinecraft(this.options) java.on('progress', (progress: any, size: any, element: any) => { this.emit('progress', progress, size, element) }); java.on('extract', (progress: any) => { this.emit('extract', progress) }); let gameLibraries: any = await libraries.Getlibraries(json); let gameAssetsOther: any = await libraries.GetAssetsOthers(this.options.url); let gameAssets: any = await new assetsMinecraft(this.options).GetAssets(json); let gameJava: any = this.options.java.path ? { files: [] } : await java.getJavaFiles(json); if (gameJava.error) return gameJava let filesList: any = await bundle.checkBundle([...gameLibraries, ...gameAssetsOther, ...gameAssets, ...gameJava.files]); if (filesList.length > 0) { let downloader = new Downloader(); let totsize = await bundle.getTotalSize(filesList); downloader.on("progress", (DL: any, totDL: any, element: any) => { this.emit("progress", DL, totDL, element); }); downloader.on("speed", (speed: any) => { this.emit("speed", speed); }); downloader.on("estimated", (time: any) => { this.emit("estimated", time); }); downloader.on("error", (e: any) => { this.emit("error", e); }); await downloader.downloadFileMultiple(filesList, totsize, this.options.downloadFileMultiple, this.options.timeout); } if (this.options.loader.enable === true) { let loaderInstall = new loaderMinecraft(this.options) loaderInstall.on('extract', (extract: any) => { this.emit('extract', extract); }); loaderInstall.on('progress', (progress: any, size: any, element: any) => { this.emit('progress', progress, size, element); }); loaderInstall.on('check', (progress: any, size: any, element: any) => { this.emit('check', progress, size, element); }); loaderInstall.on('patch', (patch: any) => { this.emit('patch', patch); }); let jsonLoader = await loaderInstall.GetLoader(version, this.options.java.path ? this.options.java.path : gameJava.path) .then((data: any) => data) .catch((err: any) => err); if (jsonLoader.error) return jsonLoader; loaderJson = jsonLoader; } if (this.options.verify) await bundle.checkFiles([...gameLibraries, ...gameAssetsOther, ...gameAssets, ...gameJava.files]); let natives = await libraries.natives(gameLibraries); if (natives.length === 0) json.nativesList = false; else json.nativesList = true; if (isold(json)) new assetsMinecraft(this.options).copyAssets(json); return { minecraftJson: json, minecraftLoader: loaderJson, minecraftVersion: version, minecraftJava: gameJava } } }