aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
authorFilip Wandzio <contact@philw.dev>2026-02-25 16:10:23 +0100
committerFilip Wandzio <contact@philw.dev>2026-02-25 16:10:23 +0100
commitf7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a (patch)
treec96432be342b02bc0409e5b78b6b5d54afcc7cd6 /src/main.rs
parent2e10b0713f5369f489d2ababd70108cc359c5d2d (diff)
downloaddml-f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a.tar.gz
dml-f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a.zip
Feat: Refactor core download logic with concurrency and async features
Implement basic unit testing Implement automatic java executable switching based on game version Split loader module into smaller modules Implement basic documentation
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs105
1 files changed, 86 insertions, 19 deletions
diff --git a/src/main.rs b/src/main.rs
index e229a3e..4b32c51 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,47 +1,116 @@
1mod constants; 1//! Main module for the DML Launcher.
2mod errors; 2//!
3//! This module contains the entry point and orchestrates the full lifecycle
4//! of the launcher. It coordinates configuration loading, environment setup,
5//! version management, asset downloading, native extraction, and client launch.
6//!
7//! # Workflow
8//!
9//! 1. Load environment variables from .env.
10//! 2. Initialize logging with the warning level.
11//! 3. Parse command-line arguments using clap.
12//! 4. Load the persistent configuration file.
13//! 5. Apply command-line overrides to configuration values.
14//! 6. Ensure all necessary directories exist.
15//! 7. Load the version manifest for the selected Minecraft version.
16//! 8. Download required assets including libraries and client binaries.
17//! 9. Extract native libraries for the current platform.
18//! 10. Launch the Minecraft client with the configured JVM arguments and
19//! session information.
20//!
21//! # Error Handling
22//!
23//! All operations that can fail propagate errors through the
24//! McError type. This centralizes error management and
25//! simplifies the use of the ? operator throughout the launcher.
26//!
27//! # Asynchronous Operations
28//!
29//! HTTP requests and asset downloads are performed asynchronously using
30//! tokio to maximize efficiency and reduce blocking. Local file
31//! operations and the client launch remain synchronous to maintain
32//! consistency and avoid race conditions.
3 33
4mod config; 34mod config;
35mod constants;
36mod errors;
5mod minecraft; 37mod minecraft;
6mod platform; 38mod platform;
7mod util; 39mod util;
8 40
9use clap::Parser; 41use clap::Parser;
10use config::Config;
11use dotenvy::dotenv; 42use dotenvy::dotenv;
12use errors::McError; 43use errors::McError;
13use log::{debug, info}; 44use log::LevelFilter::Warn;
45use reqwest::Client;
46use platform::paths::ensure_directories;
14 47
15use crate::minecraft::{ 48use crate::{
16 downloads::download_all, extraction::extract_natives, launcher::launch, 49 config::ConfigLoader,
17 manifests, 50 minecraft::{
51 downloads::download_all_files, extraction::extract_natives, launcher::launch,
52 manifests::load_version,
53 },
18}; 54};
55use crate::config::RuntimeConfig;
56use crate::minecraft::manifests::Version;
19 57
58/// Command-line interface definition.
59///
60/// Provides user-configurable options for the launcher, including
61/// specifying a Minecraft version, a username, and additional
62/// JVM arguments. Utilizes clap for argument parsing and validation.
20#[derive(Parser, Debug)] 63#[derive(Parser, Debug)]
21#[command(author, about, disable_version_flag = true)] 64#[command(author, about, disable_version_flag = true)]
22struct Cli { 65struct Cli {
66 /// Optional Minecraft version to launch.
23 #[arg(long)] 67 #[arg(long)]
24 version: Option<String>, 68 version: Option<String>,
25 69
70 /// Optional username for the Minecraft session.
26 #[arg(long)] 71 #[arg(long)]
27 username: Option<String>, 72 username: Option<String>,
28 73
74 /// Optional JVM arguments to pass to the Minecraft process.
75 ///
76 /// Supports multiple values and allows arguments that begin with hyphens.
29 #[arg(long, num_args(0..), allow_hyphen_values = true)] 77 #[arg(long, num_args(0..), allow_hyphen_values = true)]
30 jvm_args: Vec<String>, 78 jvm_args: Vec<String>,
31} 79}
32 80
81/// Launcher entry point.
82///
83/// This asynchronous function orchestrates the entire launch process,
84/// handling configuration, directory setup, asset management, native
85/// extraction, and client execution. Returns a Result<(), McError>
86/// to capture and propagate all errors encountered during execution.
87///
88/// # Steps
89///
90/// 1. Load environment variables from .env.
91/// 2. Initialize logging with a warning level filter.
92/// 3. Parse CLI arguments and merge them into the configuration.
93/// 4. Ensure required directories exist for game data and assets.
94/// 5. Load the manifest for the specified Minecraft version.
95/// 6. Build an HTTP client with HTTP/2 support for asset downloads.
96/// 7. Download all required assets including libraries and client binaries.
97/// 8. Extract platform-specific native libraries.
98/// 9. Launch the Minecraft client using the configured JVM arguments and
99/// session.
33#[tokio::main] 100#[tokio::main]
34async fn main() -> Result<(), McError> { 101async fn main() -> Result<(), McError> {
35 dotenv().ok(); 102 dotenv().ok();
36 env_logger::init();
37 103
38 let cli = Cli::parse(); 104 env_logger::Builder::new()
39 let mut config = Config::load()?; 105 .filter_level(Warn)
106 .init();
40 107
108 let cli: Cli = Cli::parse();
109 let mut config: RuntimeConfig = ConfigLoader::load(None)?;
110
41 if let Some(v) = cli.version { 111 if let Some(v) = cli.version {
42 config.version = v; 112 config.version = v;
43 } 113 }
44
45 if let Some(u) = cli.username { 114 if let Some(u) = cli.username {
46 config.username = u; 115 config.username = u;
47 } 116 }
@@ -49,16 +118,14 @@ async fn main() -> Result<(), McError> {
49 config.jvm_args = cli.jvm_args; 118 config.jvm_args = cli.jvm_args;
50 } 119 }
51 120
52 info!("Final config after CLI overrides: {:?}", config); 121 ensure_directories(&config)?;
53
54 platform::paths::ensure_dirs(&config)?;
55 info!("Using Minecraft version {}", config.version);
56 122
57 let version = manifests::load_version(&config).await?; 123 let version: Version = load_version(&config).await?;
58 info!("Loaded version manifest for: {}", version.id); 124 let client: Client = Client::builder()
59 debug!("Main class: {}", version.main_class); 125 .http2_prior_knowledge()
126 .build()?;
60 127
61 download_all(&config, &version).await?; 128 download_all_files(&client, &config, &version).await?;
62 extract_natives(&config, &version)?; 129 extract_natives(&config, &version)?;
63 launch(&config, &version)?; 130 launch(&config, &version)?;
64 131