--- title: Internal Implementation description: Detailed implementation and technical specifications of DropOut core functions --- # Internal Implementation This page details the technical implementation details, data structures, and processing flows of the launcher's core modules. ## 1. Authentication System The authentication chain contains multiple asynchronous steps, and failure at any step will interrupt the entire process. DropOut uses the Microsoft Device Code Flow to achieve secure login without redirection. ### 1.1 Detailed Process 1. **Device Code Request**: - Call `https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode` - Get user verification code and verification URL. 2. **Token Exchange**: Poll `/oauth2/v2.0/token` to get the primary Access Token and Refresh Token. 3. **Xbox Live Authentication**: Get `Token` and `uhs` (User Hash). 4. **XSTS Authorization**: Redirect to `rp://api.minecraftservices.com/`. 5. **Minecraft Login**: Exchange for the final game Access Token using the `XBL3.0 x=;` format token. ### 1.2 Account Storage and Security Account data is persisted in `accounts.json`, containing account type and encrypted token information: ```json { "active_account_uuid": "...", "accounts": [ { "type": "Microsoft", "username": "...", "uuid": "...", "access_token": "...", "refresh_token": "...", "expires_at": 1234567890 }, { "type": "Offline", "username": "Player", "uuid": "..." } ] } ``` **Offline UUID**: Uses a username-based deterministic UUID v3 to ensure consistency of local saves and configurations. ```rust // core/auth.rs implementation details pub fn generate_offline_uuid(username: &str) -> String { let namespace = Uuid::NAMESPACE_OID; Uuid::new_v3(&namespace, username.as_bytes()).to_string() } ``` ### 1.3 Authentication Related APIs | Command / Event | Type | Description | | :--- | :--- | :--- | | `start_microsoft_login` | Invoke | Start device flow and return verification code | | `complete_microsoft_login` | Invoke | Poll and complete the full authentication chain | | `login_offline` | Invoke | Create and switch to offline account | | `auth-progress` | Event | Report authentication progress in real-time (e.g., "Xbox Live Auth...") | --- ## 2. Java Runtime Management ### 2.1 Catalogs and Metadata The Java Catalog caches available versions and platform-specific links from Adoptium. - **Storage**: `java_catalog.json` records SHA256 checksums and file sizes for each version. ```json // java_catalog.json structure example { "releases": [ { "major_version": 17, "image_type": "jdk", "version": "17.0.9+9", "download_url": "...", "checksum": "...", "file_size": 123456789 } ], "cached_at": 1700000000 } ``` - **Detection**: Executes `java -version` command on candidate paths and parses version strings and 64-Bit identifiers from `stderr` output. ```rust // core/java.rs detection logic fn check_java_installation(path: &PathBuf) -> Option { let mut cmd = Command::new(path); cmd.arg("-version"); // Parse "version" keyword information from stderr output } ``` ### 2.2 Automatic Installation Logic 1. **Download**: Supports resumable downloads; large files are downloaded in parallel segments. 2. **Extraction**: Handles archives for different operating systems (macOS handles .app structure inside .tar.gz, Windows handles .zip). 3. **Verification**: Mandatory hash verification after download ensures runtime environment integrity. ### 2.3 Java Management Related APIs | Command / Event | Type | Description | | :--- | :--- | :--- | | `detect_java` | Invoke | Scan system installed Java environments | | `download_adoptium_java` | Invoke | Start asynchronous download and automatic extraction/configuration | | `cancel_java_download` | Invoke | Cancel current download task via atomic flag | | `java-download-progress` | Event | Report file size, speed, percentage, and ETA | --- ## 3. Game Launch Logic & JVM Optimization ### 3.1 Memory Allocation Scheme - **Xmx & Xms**: It is recommended to set initial memory and maximum memory to be consistent. - **Strategy**: The launcher automatically suggests optimal allocation based on total system memory and Java architecture, and parameters generated by the launcher have the highest priority. ### 3.2 G1GC Optimization Strategy For 1.17+ versions and high-load mod environments, DropOut injects a concise G1GC parameter chain by default: ```bash -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC ``` --- ## 4. Mod Loader Mechanism ### 4.1 Version Merging (Inheritance) Mod loaders link to the vanilla Minecraft version JSON via the `inheritsFrom` field. ```json // Typical Fabric version config (partial) { "id": "fabric-loader-0.15.0-1.20.4", "inheritsFrom": "1.20.4", "mainClass": "net.fabricmc.loader.impl.launch.knot.KnotClient", "libraries": [ { "name": "net.fabricmc:fabric-loader:0.15.0", "url": "https://maven.fabricmc.net/" } ] } ``` The following merging is performed during the launch phase: 1. **Library Priority**: Loader's own libraries (e.g., Fabric Loader) rank before vanilla libraries. 2. **Main Class Override**: `mainClass` is always taken from the child definition (i.e., the mod loader's entry point, like Fabric's `KnotClient`). 3. **Argument Chain**: Merge `jvm` and `game` argument arrays, automatically filtering out inapplicable system rules. ```rust // core/version_merge.rs merge core implementation pub fn merge_versions(child: GameVersion, parent: GameVersion) -> GameVersion { let mut merged_libraries = child.libraries; merged_libraries.extend(parent.libraries); // Merge argument logic and return new GameVersion instance } ``` ### 4.2 Library Path Resolution (Maven) The launcher implements complete Maven path conversion logic: `group:artifact:version` → `group_path/artifact/version/artifact-version.jar` ```rust // core/maven.rs coordinate conversion path logic pub fn to_path(&self) -> String { let group_path = self.group.replace('.', "/"); format!("{}/{}/{}/{}-{}.{}", group_path, self.artifact, self.version, self.artifact, self.version, self.extension ) } ``` ### 4.3 Mod Installation Interface The launcher uses differentiated installation strategies based on different loader characteristics. #### Forge Installation Logic For Forge, DropOut downloads the official Installer and invokes the standard installer via a Java subprocess, ensuring this process is completely consistent with the official flow (including bytecode patch generation). ```rust // core/forge.rs invoke official installer (simplified example) Command::new(java_path) .args(&[ "-jar", installer_path.to_str().unwrap(), "--installClient", game_dir.to_str().unwrap() ]) .output()?; ``` | Command / Event | Type | Description | | :--- | :--- | :--- | | `install_fabric` | Invoke | Download Fabric libraries and generate inheritance JSON | | `install_forge` | Invoke | Run Forge Installer and perform bytecode patching | | `mod-loader-progress` | Event | Report installation stage (e.g., "processing", "complete") | --- ## 5. Communication & Monitoring System ### 5.1 Event Bus The backend sends asynchronous pulses to the upper layer via Tauri's `Window` instance. ```rust // Backend emit_log! macro simplifies log emission macro_rules! emit_log { ($window:expr, $msg:expr) => { let _ = $window.emit("launcher-log", $msg); println!("[Launcher] {}", $msg); }; } ``` - **`launcher-log`**: General console output stream for global operation trajectory recording. - **`game-stdout` / `game-stderr`**: Capture game subprocess standard output and errors, transmitting to frontend in real-time via independent threads. ```typescript // Frontend listen example (Svelte 5) import { listen } from "@tauri-apps/api/event"; const unlisten = await listen("launcher-log", (event) => { logStore.addLine(event.payload); }); ``` - **`version-installed`**: Notify UI to update version list status after asynchronous task completion. ### 5.2 Launch Log Desensitization To prevent sensitive information leakage to third-party log platforms, the launcher masks tokens before recording launch commands. ```rust // partial argument masking logic based on main.rs let masked_args: Vec = args.iter().enumerate().map(|(i, arg)| { if i > 0 && (args[i-1] == "--accessToken" || args[i-1] == "--uuid") { "***".to_string() } else { arg.clone() } }).collect(); ``` --- ## 6. Architecture & Development Standards ### 6.1 Core Architecture Patterns #### Backend Command Pattern (Tauri) All backend functions are encapsulated as asynchronous Commands and injected with global state via `State`. 1. **Define Command**: ```rust #[tauri::command] async fn start_game( window: Window, auth_state: State<'_, AccountState>, config_state: State<'_, ConfigState> ) -> Result { emit_log!(window, "Starting game launch..."); // Business logic... Ok("Success".into()) } ``` 2. **Register Command (main.rs)**: ```rust tauri::Builder::default() .invoke_handler(tauri::generate_handler![start_game, ...]) ``` 3. **Frontend Call**: ```typescript import { invoke } from "@tauri-apps/api/core"; // Argument names must correspond to Rust function parameters in snake_case/camelCase const result = await invoke("start_game", { versionId: "1.20.4" }); ``` #### Error Handling Pattern All Tauri commands uniformly return `Result`, where the Err type is fixed as String, allowing the frontend to display error messages directly. ```rust // Uniformly use map_err to convert errors to String .await .map_err(|e| e.to_string())?; // Frontend catch try { await invoke("...") } catch (e) { // e is the error string returned by Rust console.error(e); } ``` #### Frontend State Management (Svelte 5 Runes) The frontend fully adopts Svelte 5's `Runes` system (`$state`, `$effect`) replacing the old `writable` stores. ```typescript // ui/src/stores/auth.svelte.ts export class AuthState { // Use $state to define reactive data currentAccount = $state(null); isLoginModalOpen = $state(false); constructor() { // Initialization logic } } // Export singleton for global access export const authState = new AuthState(); ``` #### Frontend View Routing (Manual Routing) DropOut does not use conventional URL routing, but instead manages the currently active view component via global state. ```typescript // ui/src/stores/ui.svelte.ts export class UIState { activeView = $state("home"); // "home" | "versions" | "settings" setView(view: string) { this.activeView = view; } } ``` ```svelte {#if uiState.activeView === "home"} {:else if uiState.activeView === "settings"} {/if} ``` ### 6.2 Development Best Practices 1. **Silent Refresh**: Check `expires_at` before calling `start_game`, and call `refresh_full_auth` if expired. 2. **UA Spoofing**: Microsoft auth WAF blocks requests with empty UA, so simulation of real UA in `reqwest` client is mandatory. 3. **Log Desensitization**: Sensitive parameter values like `--accessToken` and `--uuid` must be masked in launch logs. ### 6.3 Future Roadmap - **Multi-device Account Sync**: Explore OS-level encrypted storage solution to replace existing plaintext `accounts.json`. - **Automatic Dependency Resolution**: Automatically parse and download prerequisite libraries from Modrinth/CurseForge when installing mods. - **Intelligent Conflict Detection**: Scan `mods/` folder before launch to identify potential class conflicts or injection point errors. - **Config Sharing**: Support one-click export/import of complete instance configuration packages (Modpacks).