UNPKG

@origami-minecraft/devbuilds

Version:

Origami is a terminal-first Minecraft launcher that supports authentication, installation, and launching of Minecraft versions โ€” with built-in support for Microsoft accounts, mod loaders, profile management, and more. Designed for power users, modders, an

530 lines โ€ข 22 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Runtime = void 0; // runtime.ts const inquirer_1 = __importDefault(require("inquirer")); const chalk_1 = __importDefault(require("chalk")); const figlet_1 = __importDefault(require("figlet")); const gradient = __importStar(require("gradient-string")); const handler_1 = require("./handler"); const fs_1 = require("fs"); const data_manager = __importStar(require("../../tools/data_manager")); const path_1 = __importDefault(require("path")); const readline_1 = __importDefault(require("readline")); const common_1 = require("../../utils/common"); const fs_extra_1 = require("fs-extra"); const origami_1 = require("../../../cli/origami"); const java_1 = __importDefault(require("../../../java")); const install_1 = require("../install/packs/install"); const manager_1 = __importDefault(require("../install/packs/manager")); const account_1 = require("../account"); const create_1 = require("../account/auth_types/create"); const prompts_1 = require("@inquirer/prompts"); if (!process.stdin.isTTY) { handler_1.logger.error(`Umm... is this terminal asleep? I can't reach it (no TTY ๐Ÿ˜ข)`); process.exit(1); } class Runtime { handler = new handler_1.Handler(); version; constructor() { this.version = this.getVersion(); } async start() { console.clear(); await this.showLicenseAgreement(); console.clear(); await this.showHeader(); await this.mainMenu(); } async showLicenseAgreement() { if (this.hasAgreedToLicense()) return; const license = this.getLicense(); const lines = license.licenseText.split('\n'); const delay = 100; // ms per line let skipped = false; let skipResolver; const rl = readline_1.default.createInterface({ input: process.stdin, output: process.stdout }); // Listen for key to skip const skipPromise = new Promise((resolve) => { skipResolver = resolve; process.stdin.setRawMode(true); process.stdin.resume(); process.stdin.once('data', () => { skipped = true; process.stdin.setRawMode(false); resolve(); }); }); const animateText = async () => { const total = lines.length; for (let i = 0; i < total; i++) { if (skipped) break; const line = lines[i]; const faded = gradient.teen(line); console.log(faded); await new Promise(res => setTimeout(res, delay)); } skipped = true; process.stdin.setRawMode(false); skipResolver(); console.log(); }; console.clear(); console.log(chalk_1.default.bold(`๐Ÿ“œ License: ${license.name}\n`)); console.log(chalk_1.default.dim('(Press any key to skip license animation...)\n')); await Promise.race([animateText(), skipPromise]); rl.close(); if (skipped) { console.clear(); console.log(chalk_1.default.bold(`๐Ÿ“œ License: ${license.name}\n`)); console.log(gradient.morning(license.licenseText)); console.log(); process.stdin.setRawMode(false); process.stdin.pause(); while (process.stdin.read() !== null) { } readline_1.default.emitKeypressEvents(process.stdin); process.stdin.setRawMode(false); process.stdin.resume(); } const { agree, remember } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'agree', message: chalk_1.default.hex('#4ADE80')('Do you agree to the license terms?'), default: false }, { type: 'confirm', name: 'remember', message: 'Only show this once?', default: true, when: (answers) => answers.agree } ]); if (agree) { if (remember) { data_manager.set("license:agreed", true); } } else { console.log(chalk_1.default.redBright('\nโŒ You must agree to the license terms to use Origami.')); process.exit(1); } } getVersion() { try { const pkgPath = path_1.default.resolve(__dirname, '../../../../package.json'); const pkg = JSON.parse((0, fs_1.readFileSync)(pkgPath, 'utf-8')); return pkg.version || 'unknown'; } catch (_) { return 'unknown'; } } getAllLicense() { try { const lcnPath = path_1.default.join(__dirname, '../../../../licences.json'); const lcn = JSON.parse((0, fs_1.readFileSync)(lcnPath, 'utf-8')); return lcn; } catch (_) { return {}; } } getLicense() { try { const pkgPath = path_1.default.join(__dirname, '../../../../package.json'); const pkg = JSON.parse((0, fs_1.readFileSync)(pkgPath, 'utf-8')); const lcn = pkg.license || 'GPL-3.0-only'; const license = this.getAllLicense()[lcn]; return license || { name: 'MIT', licenseText: "" }; } catch (_) { return { name: 'MIT', licenseText: "" }; } } hasAgreedToLicense() { return data_manager.get("license:agreed") ? true : false; } async showHeader() { await (0, origami_1.checkForLatestVersion)(this.version); const logo = figlet_1.default.textSync('Origami', { font: 'Standard' }); console.log(gradient.retro(logo)); console.log(chalk_1.default.gray(` โœจ Lightweight Minecraft CLI Launcher โ€” Version ${this.version}`)); console.log(); } async authenticatorMenu() { while (true) { const { choice } = await inquirer_1.default.prompt([ { type: 'list', name: 'choice', message: chalk_1.default.hex('#60a5fa')('๐Ÿ” Authenticator Menu'), choices: [ { name: '๐Ÿ‘ค Choose Account', value: 'choose' }, { name: 'โž• Login', value: 'login' }, { name: 'โŒ Remove Account', value: 'remove' }, new inquirer_1.default.Separator(), { name: '๐ŸŒ Add a Custom Yggdrasil Server', value: 'create_provider' }, { name: '๐ŸŒ Delete a Custom Yggdrasil Server', value: 'delete_provider' }, new inquirer_1.default.Separator(), { name: '๐Ÿ”™ Back to Main Menu', value: 'back' } ], loop: false } ]); console.clear(); const all_providers = await (0, account_1.getAuthProviders)(); switch (choice) { case 'choose': await this.handler.choose_account(); break; case 'create_provider': await (0, create_1.createProvider)(); break; case 'delete_provider': await (0, create_1.deleteProvider)(); break; case 'login': const grouped = {}; for (const [prov, providerCtor] of all_providers.entries()) { const metadata = new providerCtor('', '').metadata; if (!grouped[metadata.base]) { grouped[metadata.base] = []; } grouped[metadata.base].push({ name: metadata.name, value: prov }); } const sortedBases = Object.keys(grouped).sort(); const choices = []; for (const base of sortedBases) { choices.push(new prompts_1.Separator(chalk_1.default.bold.cyan(`๐Ÿ”‘ ${base}`))); const providers = grouped[base].sort((a, b) => a.name.localeCompare(b.name)); choices.push(...providers); } const { provider } = await inquirer_1.default.prompt({ type: 'list', name: 'provider', message: 'Auth Provider:', choices, }); const credentials = provider === "MSA" || provider === 'microsoft' ? { email: "", password: "" } : await inquirer_1.default.prompt([ { type: 'input', name: 'email', message: 'Email or Username:', }, { type: 'password', name: 'password', message: 'Password:', mask: '*' }, ]); const result = await this.handler.login(credentials, provider); if (result) { console.log(chalk_1.default.green(`โœ… Logged in as ${result.name}`)); } else { console.log(chalk_1.default.redBright('โŒ Login failed.')); } await new Promise(res => setTimeout(res, 2000)); await this.showHeader(); break; case 'remove': await this.handler.remove_account(); break; case 'back': return; } console.clear(); } } async mainMenu() { while (true) { const { choice } = await inquirer_1.default.prompt([ { type: 'list', name: 'choice', message: chalk_1.default.hex('#c084fc')('๐ŸŒธ What do you want to do?'), choices: [ { name: '๐ŸŽฎ Launch Minecraft', value: 'launch' }, new inquirer_1.default.Separator(), { name: '๐Ÿ” Authenticator', value: 'authenticator' }, { name: '๐Ÿ›  Configure Settings', value: 'configure_settings' }, new inquirer_1.default.Separator(), { name: '๐Ÿ“‚ All Profiles', value: 'choose_profile' }, { name: 'โฌ‡๏ธ Install Minecraft Version', value: 'install_version' }, { name: '๐Ÿ—‘๏ธ Delete Profile/Instance', value: 'delete_profile' }, new inquirer_1.default.Separator(), { name: '๐Ÿงฉ Install Mods / Resources / Shaders', value: 'install_content' }, { name: '๐Ÿงฐ Manage Installations', value: 'manage_installations' }, new inquirer_1.default.Separator(), { name: 'โ˜• Install Java', value: 'install_java' }, { name: '๐Ÿ“Œ Select Java', value: 'select_java' }, { name: '๐Ÿ—‘๏ธ Delete Java', value: 'delete_java' }, new inquirer_1.default.Separator(), { name: '๐Ÿงน Reset Minecraft', value: 'reset_minecraft' }, { name: '๐Ÿงน Reset Origami', value: 'reset_origami' }, new inquirer_1.default.Separator(), { name: '๐Ÿšช Exit', value: 'exit' } ], loop: false, } ]); switch (choice) { case 'launch': await this.launch(); console.log('\n\n\n'); await this.showHeader(); break; case 'choose_profile': await this.handler.choose_profile(); console.log('\n\n\n'); await this.showHeader(); break; case 'delete_profile': await this.handler.delete_profile(); console.log('\n\n\n'); await this.showHeader(); break; case 'authenticator': await this.authenticatorMenu(); console.log('\n\n\n'); await this.showHeader(); break; case 'configure_settings': await this.handler.configure_settings(); console.log('\n\n\n'); await this.showHeader(); break; case 'install_version': await this.handler.install_version(); console.log('\n\n\n'); await this.showHeader(); break; case 'install_content': const installer = new install_1.ModInstaller(handler_1.logger); const profile = this.handler.profiles.getSelectedProfile(); if (profile) await installer.install_modrinth_content(profile); console.log('\n\n\n'); await this.showHeader(); break; case 'manage_installations': const _profile = this.handler.profiles.getSelectedProfile(); if (_profile) await this.manageInstallationsMenu(_profile); break; case 'install_java': await java_1.default.download(); console.log('\n\n\n'); break; case 'select_java': await java_1.default.select(true); console.log('\n\n\n'); break; case 'delete_java': await java_1.default.delete(); console.log('\n\n\n'); break; case 'reset_minecraft': await this.resetMinecraft(); console.log('\n\n\n'); await this.showHeader(); break; case 'reset_origami': await this.resetOrigami(); console.log('\n\n\n'); await this.showHeader(); break; case 'exit': this.exit(); return; } } } async resetMinecraft() { const mcDir = (0, common_1.minecraft_dir)(); const { confirm } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'confirm', message: chalk_1.default.redBright(`โš ๏ธ This will delete everything in: ${mcDir}\nAre you sure?`), default: false, } ]); if (!confirm) return; try { (0, fs_extra_1.removeSync)(mcDir); console.log(chalk_1.default.green('๐Ÿงน Minecraft directory reset successfully.')); } catch (err) { console.log(chalk_1.default.red('โŒ Failed to reset Minecraft directory.')); console.error(err); } await new Promise(res => setTimeout(res, 2000)); } async resetOrigami() { const cache = (0, common_1.localpath)(true); const origami = (0, common_1.minecraft_dir)(true); const data = (0, common_1.localpath)(); const { confirm } = await inquirer_1.default.prompt([ { type: 'confirm', name: 'confirm', message: chalk_1.default.redBright(`โš ๏ธ This will delete everything in: ${data} and corresponding Origami settings, accounts and profiles\nAre you sure?`), default: false, } ]); if (!confirm) return; try { (0, fs_extra_1.removeSync)(data); (0, fs_extra_1.removeSync)(cache); (0, fs_extra_1.removeSync)(origami); console.log(chalk_1.default.green('๐Ÿงน Origami reset successfully.')); } catch (err) { console.log(chalk_1.default.red('โŒ Failed to reset Origami')); console.error(err); } await new Promise(res => setTimeout(res, 2000)); } async launch() { const code = await this.handler.run_minecraft(); if (code === 200) { console.log(chalk_1.default.green('โœ… Minecraft exited successfully!')); } else { console.log(chalk_1.default.red('โŒ Failed to launch Minecraft.')); } } exit() { console.log(chalk_1.default.gray('\n๐Ÿ‘‹ Thanks for using Origami! Happy crafting!')); process.exit(0); } async manageInstallationsMenu(profile) { const manager = new manager_1.default(profile); while (true) { const list = manager.getList(); const choices = []; const addGroup = (title, items, type) => { if (items.length > 0) { choices.push(new inquirer_1.default.Separator(`๐Ÿ“ ${title}`)); for (const item of items) { const isDisabled = type === 'mod' && manager.isModDisabled(item); choices.push({ name: `${item}${isDisabled ? chalk_1.default.gray(' (disabled)') : ''}`, value: { name: item, type } }); } } }; addGroup('Mods', list.mods, 'mod'); addGroup('Shaders', list.shaders, 'shader'); addGroup('Resource Packs', list.resourcepacks, 'resourcepack'); choices.push(new inquirer_1.default.Separator()); choices.push({ name: '๐Ÿ”™ Back', value: '__back' }); const { selected } = await inquirer_1.default.prompt({ type: 'list', name: 'selected', message: 'Select an installed item to manage:', choices, pageSize: 20 }); if (selected === '__back') break; await this.manageInstalledItem(manager, selected.name, selected.type); } } async manageInstalledItem(manager, name, type) { const isDisabled = type === 'mod' ? manager.isModDisabled(name) : false; const actions = [ { name: '๐Ÿ—‘ Delete', value: 'delete' } ]; if (type === 'mod') { actions.push({ name: isDisabled ? 'โœ… Enable' : '๐Ÿšซ Disable', value: isDisabled ? 'enable' : 'disable' }); } actions.push({ name: '๐Ÿ”™ Back', value: 'back' }); const { action } = await inquirer_1.default.prompt({ type: 'list', name: 'action', message: `What do you want to do with "${name}"?`, choices: actions }); switch (action) { case 'delete': manager.deleteFromType(name, type); console.log(chalk_1.default.redBright(`๐Ÿ—‘ Deleted ${name} from ${type}s.`)); break; case 'disable': manager.disableMod(name); console.log(chalk_1.default.yellow(`๐Ÿšซ Disabled ${name}.`)); break; case 'enable': manager.enableMod(name); console.log(chalk_1.default.green(`โœ… Enabled ${name}.`)); break; case 'back': default: return; } await new Promise(res => setTimeout(res, 1500)); } } exports.Runtime = Runtime; // Run directly if executed standalone if (require.main === module) { const runtime = new Runtime(); runtime.start(); } //# sourceMappingURL=runtime.js.map