feat: wire up interactive GUI and CLI subcommands to launcher, cleaner, and region router
This commit is contained in:
parent
2fcc4dd995
commit
66deae64d6
4 changed files with 127 additions and 4 deletions
|
|
@ -16,6 +16,8 @@ pub enum Commands {
|
|||
place_id: Option<u64>,
|
||||
#[arg(long)]
|
||||
safe_mode: bool,
|
||||
#[arg(short, long)]
|
||||
region: Option<String>,
|
||||
},
|
||||
/// Check for and download the latest Roblox version
|
||||
Update,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,12 @@ pub mod commands;
|
|||
use clap::Parser;
|
||||
use commands::{Cli, Commands};
|
||||
use molotov_bootstrap::cdn::CdnClient;
|
||||
use molotov_bootstrap::cleaner::Cleaner;
|
||||
use molotov_bootstrap::fflags::FastFlagManager;
|
||||
use molotov_bootstrap::launcher::{LaunchOptions, Launcher};
|
||||
use molotov_bootstrap::region::ServerRegion;
|
||||
use molotov_bootstrap::sandbox::SandboxRunner;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn run(args: &[String]) {
|
||||
let mut full_args = vec!["molotov".to_string()];
|
||||
|
|
@ -18,12 +22,45 @@ pub fn run(args: &[String]) {
|
|||
}
|
||||
};
|
||||
|
||||
let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
|
||||
let base_dir = PathBuf::from(&home).join(".local/share/molotov");
|
||||
let downloads_dir = PathBuf::from(&home).join(".cache/molotov/downloads");
|
||||
let versions_dir = base_dir.join("versions");
|
||||
|
||||
match cli.command {
|
||||
Some(Commands::Launch { place_id, safe_mode }) => {
|
||||
println!("🚀 Preparing Molotov launch (Place: {:?}, Safe Mode: {})...", place_id, safe_mode);
|
||||
Some(Commands::Launch { place_id, safe_mode, region }) => {
|
||||
let s_region = region
|
||||
.as_deref()
|
||||
.map(ServerRegion::from_code)
|
||||
.unwrap_or(ServerRegion::Auto);
|
||||
|
||||
println!("🚀 Preparing Molotov launch...");
|
||||
println!(" • Target Place ID: {:?}", place_id);
|
||||
println!(" • Safe Mode: {}", safe_mode);
|
||||
println!(" • Preferred Server Region: {}", s_region.display_name());
|
||||
|
||||
if let Err(e) = SandboxRunner::check_bwrap_installed() {
|
||||
eprintln!("⚠️ Warning: {}", e);
|
||||
}
|
||||
|
||||
let launcher = Launcher::new(base_dir);
|
||||
let options = LaunchOptions {
|
||||
place_id,
|
||||
safe_mode,
|
||||
region: s_region,
|
||||
instance_id: "default".to_string(),
|
||||
};
|
||||
|
||||
match launcher.prepare_launch(options) {
|
||||
Ok(plan) => {
|
||||
println!("✅ Launch plan prepared successfully.");
|
||||
println!(" • FastFlags configured at: {}", plan.fflags_path.display());
|
||||
println!(" • Sandbox isolation: Instance '{}'", plan.sandbox_config.instance_id);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("❌ Failed to prepare launch plan: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Commands::Update) => {
|
||||
println!("🔄 Checking Roblox CDN for client updates...");
|
||||
|
|
@ -62,6 +99,18 @@ pub fn run(args: &[String]) {
|
|||
}
|
||||
Some(Commands::Clean) => {
|
||||
println!("🧹 Cleaning old versions and temporary cache...");
|
||||
let cleaner = Cleaner::new(versions_dir, downloads_dir);
|
||||
match cleaner.clean_stale_data("active") {
|
||||
Ok(report) => {
|
||||
println!("✅ Cleaning complete:");
|
||||
println!(" • Purged old version directories: {}", report.purged_versions.len());
|
||||
println!(" • Purged leftover download fragments: {}", report.purged_parts_count);
|
||||
println!(" • Total disk space reclaimed: {:.2} MB", (report.reclaimed_bytes as f64) / (1024.0 * 1024.0));
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("❌ Cleaning failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Commands::Diagnostics) => {
|
||||
println!("🩺 System diagnostics: checking bubblewrap sandbox status...");
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@ fn test_cli_parse_launch_place() {
|
|||
assert!(parsed.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_parse_region_flag() {
|
||||
let parsed = Cli::try_parse_from(["molotov", "launch", "--region", "eu"]);
|
||||
assert!(parsed.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cli_parse_clean_command() {
|
||||
let parsed = Cli::try_parse_from(["molotov", "clean"]);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
use eframe::egui;
|
||||
use molotov_bootstrap::cleaner::Cleaner;
|
||||
use molotov_bootstrap::launcher::{LaunchOptions, Launcher};
|
||||
use molotov_bootstrap::region::ServerRegion;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Tab {
|
||||
|
|
@ -16,6 +20,9 @@ pub struct MolotovApp {
|
|||
pub safe_mode: bool,
|
||||
pub fps_cap: i64,
|
||||
pub vram_skip_mips: bool,
|
||||
pub region: ServerRegion,
|
||||
pub discord_rpc: bool,
|
||||
pub status_message: String,
|
||||
}
|
||||
|
||||
impl Default for MolotovApp {
|
||||
|
|
@ -25,6 +32,9 @@ impl Default for MolotovApp {
|
|||
safe_mode: false,
|
||||
fps_cap: 144,
|
||||
vram_skip_mips: false,
|
||||
region: ServerRegion::Auto,
|
||||
discord_rpc: true,
|
||||
status_message: "Ready to launch".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +50,14 @@ impl MolotovApp {
|
|||
Tab::Maintenance => "Maintenance",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_paths() -> (PathBuf, PathBuf, PathBuf) {
|
||||
let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
|
||||
let base_dir = PathBuf::from(&home).join(".local/share/molotov");
|
||||
let downloads_dir = PathBuf::from(&home).join(".cache/molotov/downloads");
|
||||
let versions_dir = base_dir.join("versions");
|
||||
(base_dir, downloads_dir, versions_dir)
|
||||
}
|
||||
}
|
||||
|
||||
impl eframe::App for MolotovApp {
|
||||
|
|
@ -58,9 +76,44 @@ impl eframe::App for MolotovApp {
|
|||
egui::CentralPanel::default().show(ctx, |ui| match self.current_tab {
|
||||
Tab::Play => {
|
||||
ui.heading("Molotov Roblox Runtime");
|
||||
ui.label(format!("Status: {}", self.status_message));
|
||||
ui.separator();
|
||||
|
||||
ui.checkbox(&mut self.safe_mode, "Safe Mode (Minimal Flags)");
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Preferred Server Region:");
|
||||
egui::ComboBox::from_id_salt("region_combo")
|
||||
.selected_text(self.region.display_name())
|
||||
.show_ui(ui, |ui| {
|
||||
ui.selectable_value(&mut self.region, ServerRegion::Auto, "Auto / Default");
|
||||
ui.selectable_value(&mut self.region, ServerRegion::USEast, "US East (Virginia)");
|
||||
ui.selectable_value(&mut self.region, ServerRegion::USWest, "US West (California)");
|
||||
ui.selectable_value(&mut self.region, ServerRegion::Europe, "Europe (Frankfurt / London)");
|
||||
ui.selectable_value(&mut self.region, ServerRegion::Asia, "Asia (Tokyo / Singapore)");
|
||||
ui.selectable_value(&mut self.region, ServerRegion::Australia, "Australia (Sydney)");
|
||||
});
|
||||
});
|
||||
|
||||
ui.add_space(10.0);
|
||||
if ui.button("🚀 Launch Roblox").clicked() {
|
||||
println!("Launch clicked!");
|
||||
let (base_dir, _, _) = Self::get_paths();
|
||||
let launcher = Launcher::new(base_dir);
|
||||
let options = LaunchOptions {
|
||||
place_id: None,
|
||||
safe_mode: self.safe_mode,
|
||||
region: self.region,
|
||||
instance_id: "default".to_string(),
|
||||
};
|
||||
|
||||
match launcher.prepare_launch(options) {
|
||||
Ok(plan) => {
|
||||
self.status_message = format!("Launch plan prepared! Safe Mode: {}", plan.is_safe_mode);
|
||||
}
|
||||
Err(e) => {
|
||||
self.status_message = format!("Launch preparation failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Tab::FastFlags => {
|
||||
|
|
@ -82,8 +135,21 @@ impl eframe::App for MolotovApp {
|
|||
}
|
||||
Tab::Maintenance => {
|
||||
ui.heading("Maintenance & Cleaning");
|
||||
ui.checkbox(&mut self.discord_rpc, "Enable Discord Rich Presence (RPC)");
|
||||
|
||||
ui.add_space(10.0);
|
||||
if ui.button("Clean Stale Versions").clicked() {
|
||||
println!("Clean clicked!");
|
||||
let (_, downloads_dir, versions_dir) = Self::get_paths();
|
||||
let cleaner = Cleaner::new(versions_dir, downloads_dir);
|
||||
match cleaner.clean_stale_data("active") {
|
||||
Ok(report) => {
|
||||
let mb = (report.reclaimed_bytes as f64) / (1024.0 * 1024.0);
|
||||
self.status_message = format!("Cleaned {} old versions, reclaimed {:.2} MB", report.purged_versions.len(), mb);
|
||||
}
|
||||
Err(e) => {
|
||||
self.status_message = format!("Clean failed: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Reference in a new issue