mc-launcher-core 0.1.1

Rust building blocks for installing and launching Minecraft profiles.
Documentation
# mc-launcher-core

`mc-launcher-core` is a Rust library for building Minecraft launchers. It
handles the install and launch-preparation work that sits behind a launcher UI:
resolving version metadata, installing client files, preparing loader profiles,
extracting natives, and building a structured Java launch command.

The crate is designed as a launcher SDK. It does not provide a GUI and it does
not spawn Minecraft automatically unless your application chooses to use the
returned command with `std::process::Command`.

## Features

- Install vanilla Minecraft profiles.
- Install Fabric, Quilt, Forge, and NeoForge profiles.
- Download client jars, libraries, asset indexes, asset objects, and natives.
- Merge inherited version metadata before launch.
- Build cross-platform Java launch commands without shell string quoting.
- Use offline accounts or Microsoft account helper APIs.
- Report install progress through a simple callback trait.
- Apply macOS Apple Silicon compatibility patches for older LWJGL metadata.
- Keep compatibility wrappers for older `mc-launcher-core` callers.

## Installation

```bash
cargo add mc-launcher-core
```

Or add it manually:

```toml
[dependencies]
mc-launcher-core = "0.1.1"
```

## Quick Start

Install Fabric and launch with an offline account:

```rust
use std::process::Command;

use mc_launcher_core::prelude::*;

fn main() -> mc_launcher_core::Result<()> {
    let minecraft_dir = std::env::current_dir()?.join(".minecraft");
    let launcher = Launcher::new(minecraft_dir);

    let install = launcher.install(InstallRequest {
        minecraft_version: "1.20.1".to_string(),
        loader: Some(LoaderSpec::Fabric {
            version: LoaderVersion::LatestStable,
        }),
        java: JavaInstallPolicy::Auto,
    })?;

    let version = launcher.load_version(&install.version_id)?;
    let command = launcher.build_launch_command_from_version(
        &version,
        LaunchOptions {
            account: Account::offline("Steve"),
            ..Default::default()
        },
    )?;

    let mut child = Command::new(&command.executable)
        .args(&command.args)
        .current_dir(&command.working_dir)
        .spawn()?;
    child.wait()?;
    Ok(())
}
```

## Main API

Use `mc_launcher_core::prelude::*` for the common facade:

- `Launcher` owns a Minecraft directory and coordinates install/load/launch work.
- `InstallRequest` describes the Minecraft version and optional loader.
- `LoaderSpec` and `LoaderVersion` select Fabric, Quilt, Forge, or NeoForge.
- `LaunchOptions` controls account, Java path, game directory, resolution, server,
  and compatibility behavior.
- `LaunchCommand` contains `executable`, `args`, `working_dir`, and `env`.
- `ProgressReporter` receives install/download progress events.
- `LauncherError` and `Result` are the crate-wide error types.

## Installing Versions

Vanilla:

```rust
use mc_launcher_core::prelude::*;

fn main() -> mc_launcher_core::Result<()> {
    let launcher = Launcher::new(".minecraft");
    let install = launcher.install(InstallRequest::vanilla("1.20.1"))?;
    println!("installed profile: {}", install.version_id);
    Ok(())
}
```

Fabric, Quilt, Forge, and NeoForge use the same request shape:

```rust
use mc_launcher_core::prelude::*;

fn main() -> mc_launcher_core::Result<()> {
    let launcher = Launcher::new(".minecraft");
    let install = launcher.install(InstallRequest {
        minecraft_version: "1.20.1".to_string(),
        loader: Some(LoaderSpec::Quilt {
            version: LoaderVersion::Latest,
        }),
        java: JavaInstallPolicy::Auto,
    })?;
    println!("installed profile: {}", install.version_id);
    Ok(())
}
```

Use `LoaderVersion::Exact("...".to_string())` when a launcher UI lets users pick
a specific loader version.

## Progress Reporting

`Launcher::install_with_progress` accepts any closure that takes a
`ProgressEvent`:

```rust
use mc_launcher_core::prelude::*;

fn main() -> mc_launcher_core::Result<()> {
    let launcher = Launcher::new(".minecraft");
    let mut progress = |event: ProgressEvent| {
        println!("{event:?}");
    };

    launcher.install_with_progress(InstallRequest::vanilla("1.20.1"), &mut progress)?;
    Ok(())
}
```

## Launch Options

`LaunchOptions::default()` is suitable for a basic offline launch. Override only
what your launcher exposes:

```rust
use std::path::PathBuf;

use mc_launcher_core::prelude::*;

let options = LaunchOptions {
    account: Account::offline("Steve"),
    java_executable: Some(PathBuf::from("/path/to/java")),
    game_directory: Some(PathBuf::from(".minecraft/instances/survival")),
    custom_resolution: Some((1280, 720)),
    server: Some(("example.org".to_string(), Some(25565))),
    ..Default::default()
};
```

By default, the game directory is isolated per installed profile at
`<minecraft_dir>/versions/<version_id>`. Set `game_directory` if your launcher
has separate instance folders.

## Java Runtime

The new facade does not bundle a Java runtime. Select a runtime in your
application and pass it through `LaunchOptions::java_executable`. If omitted,
the generated command uses `java` from `PATH`.

Forge and NeoForge installer execution currently invokes `java` while
installing. Future runtime management can use the existing `JavaInstallPolicy`
request field.

## Compatibility

On macOS Apple Silicon, older Minecraft metadata may reference LWJGL libraries
that do not work on arm64. By default, command construction and download
planning use `CompatibilityPolicy::Auto` and apply known patches.

The compatibility layer can:

- replace legacy LWJGL 2 metadata with arm64-capable libraries;
- replace older LWJGL 3 metadata with macOS arm64 native classifiers;
- recommend a matching arm64 Java runtime;
- report when legacy LWJGL 2 should be hosted from a real macOS app bundle.

Disable automatic patching only if your launcher manages this itself:

```rust
use mc_launcher_core::prelude::*;

let options = LaunchOptions {
    compatibility: CompatibilityPolicy::Disabled,
    ..Default::default()
};
```

## Microsoft Login

Offline launch is available through `Account::offline`. Microsoft login helpers
live in `mc_launcher_core::auth::microsoft_account` and expose the individual
OAuth, Xbox Live, XSTS, and Minecraft services steps.

For new apps, start with `get_secure_login_data` so the login URL uses PKCE.
After the browser redirects back to your app, parse the auth code and call
`complete_login`.

## Lower-Level Modules

The facade is intentionally small, but the crate also exposes lower-level
modules for custom launchers:

- `core::version` contains the normalized version JSON model.
- `install::vanilla`, `install::libraries`, and `install::assets` build download
  plans without immediately running them.
- `net::download` executes structured download plans with checksum validation.
- `io::paths` and `io::archive` provide path-safe filesystem helpers.
- `loader::{fabric, quilt, forge, neoforge}` expose loader metadata helpers.

Generate local rustdoc for the full API:

```bash
cargo doc --no-deps --open
```

## Examples

The repository includes runnable examples:

```bash
cargo run --example simple_offline_launch
cargo run --example simple_launch
cargo run --example launch_matrix
```

The examples download real Minecraft metadata and files, so they require
network access and enough disk space for the selected versions.

## Status

- Crate library: done
- Vanilla install: done
- Offline launch: done
- Microsoft account login helpers: done
- Forge, Fabric, Quilt, and NeoForge loader metadata: done
- mrpack modpack install: planned
- Rustdoc and README documentation: done

## Notes

- Version `0.1.1` focuses on complete vanilla/Fabric/Quilt client installation,
  Forge/NeoForge installer support, and version-isolated launches.
- This project aims to provide a user-friendly launcher SDK written in Rust.
- The project was inspired in part by the Python `minecraft-launcher-lib`
  ecosystem.