use std::process::Command; use log::{debug, info}; use crate::{config::Config, errors::McError, minecraft::manifests::Version, platform::paths}; /// Build the full classpath fn build_classpath(config: &Config, version: &Version) -> Result { let sep = if cfg!(windows) { ";" } else { ":" }; let mut entries = Vec::new(); for lib in &version.libraries { if let Some(artifact) = &lib.downloads.artifact { let path = paths::library_file(config, &artifact.path)?; entries.push(path.to_string_lossy().to_string()); } } let client_jar = paths::client_jar(config, &version.id)?; entries.push(client_jar.to_string_lossy().to_string()); Ok(entries.join(sep)) } /// Launch Minecraft pub fn launch(config: &Config, version: &Version) -> Result<(), McError> { let java = &config.java_path; let classpath = build_classpath(config, version)?; let natives_dir = paths::natives_dir(config, &version.id); if !natives_dir.exists() { return Err(McError::Runtime(format!( "Natives folder does not exist: {}", natives_dir.display() ))); } info!("Launching Minecraft {}", version.id); debug!("Classpath: {}", classpath); debug!("Natives: {}", natives_dir.display()); let status = Command::new(java) .arg(format!("-Xmx{}M", config.max_memory_mb)) .arg(format!("-Djava.library.path={}", natives_dir.display())) .arg("-cp") .arg(classpath) .arg(&version.main_class) .arg("--username") .arg(&config.username) .arg("--version") .arg(&version.id) .arg("--gameDir") .arg(paths::minecraft_root(config)) .arg("--assetsDir") .arg(paths::minecraft_root(config).join("assets")) .arg("--assetIndex") .arg(&version.id) .arg("--uuid") .arg(&config.uuid) .arg("--userProperties") .arg("{}") .arg("--accessToken") .arg("0") .arg("--userType") .arg("legacy") .args(&config.jvm_args) .status()?; if !status.success() { return Err(McError::Process("Minecraft exited with error".into())); } Ok(()) }