diff options
Diffstat (limited to '')
| -rw-r--r-- | src/main.rs | 105 |
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 @@ | |||
| 1 | mod constants; | 1 | //! Main module for the DML Launcher. |
| 2 | mod 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 | ||
| 4 | mod config; | 34 | mod config; |
| 35 | mod constants; | ||
| 36 | mod errors; | ||
| 5 | mod minecraft; | 37 | mod minecraft; |
| 6 | mod platform; | 38 | mod platform; |
| 7 | mod util; | 39 | mod util; |
| 8 | 40 | ||
| 9 | use clap::Parser; | 41 | use clap::Parser; |
| 10 | use config::Config; | ||
| 11 | use dotenvy::dotenv; | 42 | use dotenvy::dotenv; |
| 12 | use errors::McError; | 43 | use errors::McError; |
| 13 | use log::{debug, info}; | 44 | use log::LevelFilter::Warn; |
| 45 | use reqwest::Client; | ||
| 46 | use platform::paths::ensure_directories; | ||
| 14 | 47 | ||
| 15 | use crate::minecraft::{ | 48 | use 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 | }; |
| 55 | use crate::config::RuntimeConfig; | ||
| 56 | use 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)] |
| 22 | struct Cli { | 65 | struct 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] |
| 34 | async fn main() -> Result<(), McError> { | 101 | async 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 | ||
