UNPKG

openrbx

Version:

CLI tool to launch Roblox Studio with place and universe IDs

151 lines (131 loc) 4.74 kB
import { Command } from "commander"; import packageJson from "../package.json"; import { platform } from "os"; import { exec } from "child_process"; import { promisify } from "util"; import open from "open"; // execAsync is a promisified version of the exec function from child_process, // allowing to use async/await syntax for running shell commands. const execAsync = promisify(exec); async function checkExistingProcesses( noLogs: boolean = false ): Promise<boolean> { try { const currentPlatform = platform(); let command: string; switch (currentPlatform) { case "win32": command = 'tasklist /fi "imagename eq RobloxStudioBeta.exe" /fo csv | find /c "RobloxStudioBeta.exe"'; break; case "darwin": command = 'pgrep -f "RobloxStudio" | wc -l'; break; case "linux": command = 'pgrep -f "roblox-studio" | wc -l'; break; default: if (!noLogs) { console.warn( `Process checking not supported on platform: ${currentPlatform}` ); } return false; } const { stdout } = await execAsync(command); const processCount = parseInt(stdout.trim()); if (process.env.DEBUG) { console.log(`🔍 Found ${processCount} Roblox Studio processes`); } return processCount > 0; } catch (error) { if (process.env.DEBUG) { console.warn("Warning: Could not check for existing processes:", error); } return false; } } function buildProtocolUrl(option: any): string { const baseUrl = "roblox-studio:1"; const allParams = { launchmode: option.mode, task: option.task, placeId: option.placeId, universeId: option.universeId, }; const paramString = Object.entries(allParams) .map(([key, value]) => `${key}:${value}`) .join("+"); return `${baseUrl}+${paramString}`; } async function main() { const program = new Command(); program .name("openrbx") .description("🚀 OpenRBX - Roblox Studio Launcher") .version(packageJson.version) .option("-p, --place-id <id>", "Place ID (required)") .option("-u, --universe-id <id>", "Universe ID (required)") .option("-m, --mode <mode>", "Launch mode", "edit") .option("-t, --task <task>", "Task to execute", "EditPlace") .option("--multiple-process", "Allow multiple Roblox Studio instances") .option("--no-logs", "Show only essential logs") .action(async (options) => { try { const protocolUrl = buildProtocolUrl(options); const logs = !options.logs; // Invert logs option because we want to hide logs when --no-logs is set if (!logs) { console.log("Launching Roblox Studio:"); console.log(` - 📍 Place ID: ${options.placeId}`); console.log(` - 🌌 Universe ID: ${options.universeId}`); console.log(` - ⚙️ Mode: ${options.mode}`); console.log(` - 📋 Task: ${options.task}`); console.log(` - 🔗 Protocol URL: ${protocolUrl}`); } // Check for existing processes unless multiple-process is enabled if (!options["multiple-process"]) { if (!logs) { console.log("🔍 Checking for existing Roblox Studio processes..."); } const hasExistingProcesses = await checkExistingProcesses(logs); if (hasExistingProcesses) { console.log("⚠️ Warning: Roblox Studio is already running"); if (!logs) { console.log( "💡 Use --multiple-process to allow multiple instances" ); } console.log("❌ Aborting launch to prevent conflicts"); process.exit(1); } else { if (!logs) { console.log("✅ No existing Roblox Studio processes found"); } } } else { if (!logs) { console.log( "🔄 Multiple process mode enabled - skipping process check" ); } } open(protocolUrl); console.log("✅ Roblox Studio launched successfully!"); } catch (error) { if (error instanceof Error) { if ( "code" in error && error.code === "ERR_PARSE_ARGS_UNKNOWN_OPTION" ) { console.error( "❌ Unknown option provided. Use --help to see available options." ); } else { console.error("❌ Error:", error); } } } }); program.parse(); } main();