LiquidLauncher provides a powerful game launching system that handles version management, resource downloading, and process execution automatically.
Quick Start
Select Branch
Choose your preferred LiquidBounce branch (e.g., nextgen, legacy)
Select Build
Pick a specific build version or use the latest
Configure Options
Set memory allocation, Java distribution, and other launch parameters
Launch
Click play and the launcher handles the rest!
Selecting Branches and Builds
Requesting Available Branches
The launcher fetches available branches from the LiquidBounce API:
// From: src-tauri/src/app/gui/commands/client.rs:43
#[tauri::command]
pub(crate) async fn request_branches(client: Client) -> Result<Branches, String> {
let branches = (|| async { client.branches().await })
.retry(ExponentialBuilder::default())
.notify(|err, dur| {
warn!("Failed to request branches. Retrying in {:?}. Error: {}", dur, err);
})
.await
.map_err(|e| format!("unable to request branches: {:?}", e))?;
Ok(branches)
}
The launcher uses exponential backoff to retry failed requests, ensuring reliable branch fetching even with network issues.
Fetching Builds for a Branch
Once you’ve selected a branch, fetch available builds:
// From: src-tauri/src/app/gui/commands/client.rs:56
#[tauri::command]
pub(crate) async fn request_builds(
client: Client,
branch: &str,
release: bool
) -> Result<Vec<Build>, String> {
let builds = (|| async { client.builds_by_branch(branch, release).await })
.retry(ExponentialBuilder::default())
.notify(|err, dur| {
warn!("Failed to request builds. Retrying in {:?}. Error: {}", dur, err);
})
.await
.map_err(|e| format!("unable to request builds: {:?}", e))?;
Ok(builds)
}
The branch name (e.g., “nextgen”, “legacy”)
Whether to show only release builds (true) or include nightly builds (false)
Launch Parameters
The launcher uses a comprehensive StartParameter structure to configure game launching:
// From: src-tauri/src/minecraft/launcher/mod.rs:263
pub struct StartParameter {
pub java_distribution: DistributionSelection,
pub jvm_args: Vec<String>,
pub memory: u64,
pub custom_data_path: Option<String>,
pub auth_player_name: String,
pub auth_uuid: String,
pub auth_access_token: String,
pub auth_xuid: String,
pub clientid: String,
pub user_type: String,
pub keep_launcher_open: bool,
pub concurrent_downloads: u32,
pub client: Client,
pub client_account: Option<ClientAccount>,
pub skip_advertisement: bool,
}
Key Parameters
Java runtime to use. Options:
Automatic: Let the launcher choose (recommended)
Custom: Specify a custom Java path
Manual: Choose specific distribution (Temurin, GraalVM, Zulu)
Custom JVM arguments to pass to Java (e.g., -XX:+UseG1GC)
Memory allocation in megabytes
Custom directory for game data. If empty, uses default launcher directory
Whether to keep the launcher window open after game starts
Number of parallel downloads for assets and libraries
Running the Client
The main launch command orchestrates the entire launch process:
// From: src-tauri/src/app/gui/commands/client.rs:260
#[tauri::command]
pub(crate) async fn run_client(
client: Client,
build_id: u32,
options: Options,
mods: Vec<LoaderMod>,
window: Window,
app_state: tauri::State<'_, AppState>,
) -> Result<(), String> {
// Prevent multiple instances
if runner_instance.lock()?.is_some() {
return Err("client is already running".to_string());
}
// Fetch launch manifest
let launch_manifest = client.fetch_launch_manifest(build_id).await?;
// Extract account credentials
let (account_name, uuid, token, user_type) = match minecraft_account {
MinecraftAccount::MsaAccount { profile, mca, .. } => (
profile.name,
profile.id.to_string(),
mca.data.access_token,
"msa".to_string(),
),
MinecraftAccount::OfflineAccount { name, id, .. } => (
name,
id.to_string(),
"-".to_string(),
"legacy".to_string()
)
};
// Build launch parameters
let parameters = StartParameter {
java_distribution: options.start_options.java_distribution,
jvm_args: options.start_options.jvm_args.unwrap_or_else(|| vec![]),
memory: options.start_options.memory,
// ... other parameters
};
// Launch in separate thread
thread::spawn(move || {
prelauncher::launch(launch_manifest, parameters, mods, launcher_data).await
});
Ok(())
}
Launch Process
The launcher performs these steps automatically:
Validation
Checks that no client is already running and validates account selection
Manifest Download
Fetches the launch manifest for the selected buildlet launch_manifest = client.fetch_launch_manifest(build_id).await
Resource Setup
Downloads and prepares:
- Java Runtime Environment (if needed)
- Client JAR file
- Required libraries
- Game assets
- Native libraries
JVM Configuration
Builds JVM arguments including:
- Memory settings (
-Xmx, -Xms)
- LiquidBounce API configuration
- Custom JVM args
- Classpath
Game Launch
Executes Java with game arguments and monitors the process
Launch Events
The launcher emits events during the launch process:
Emitted during resource download and setupwindow.listen('progress-update', (event) => {
console.log('Progress:', event.payload);
});
Game console output (stdout/stderr)// From: src-tauri/src/app/gui/commands/client.rs:206
fn handle_stdout(window: &ShareableWindow, data: &[u8]) -> anyhow::Result<()> {
let data = String::from_utf8(data.to_vec())?;
window.lock()?.emit("process-output", data)?;
Ok(())
}
Emitted when an error occurs during launchshareable_window.lock().unwrap().emit("client-error", ())
Emitted when the game process terminatesshareable_window.lock().unwrap().emit("client-exited", ())
Java Distribution Selection
LiquidLauncher supports multiple Java distributions:
// From: src-tauri/src/minecraft/java/distribution.rs:23
pub enum JavaDistribution {
Temurin, // Eclipse Temurin (Adoptium)
GraalVM, // Oracle GraalVM
Zulu, // Azul Zulu
}
Distribution Comparison
| Distribution | Java 8 | Java 11 | Java 17 | Java 21+ |
|---|
| Temurin | ✅ | ✅ | ✅ | ✅ |
| GraalVM | ❌ | ❌ | ✅ | ✅ |
| Zulu | ✅ | ✅ | ✅ | ✅ |
Temurin is recommended for most users as it supports all Java versions and has excellent compatibility.
Automatic Distribution Download
The launcher automatically downloads the appropriate Java distribution:
// From: src-tauri/src/minecraft/java/distribution.rs:41
impl JavaDistribution {
pub async fn get_url(&self, jre_version: &u32) -> Result<String> {
let os_arch = ARCHITECTURE.get_simple_name()?;
let archive_type = OS.get_archive_type()?;
Ok(match self {
JavaDistribution::Temurin => {
format!(
"https://api.adoptium.net/v3/binary/latest/{}/ga/{}/{}/jre/hotspot/normal/eclipse?project=jdk",
jre_version, os_name, os_arch
)
}
JavaDistribution::GraalVM => {
format!(
"https://download.oracle.com/graalvm/{}/latest/graalvm-jdk-{}_{}-{}_bin.{}",
jre_version, jre_version, os_name, os_arch, archive_type
)
}
JavaDistribution::Zulu => {
fetch_zulu_download_url(*jre_version).await?
}
})
}
}
Terminating the Game
You can stop the running game programmatically:
// From: src-tauri/src/app/gui/commands/client.rs:405
#[tauri::command]
pub(crate) async fn terminate(app_state: tauri::State<'_, AppState>) -> Result<(), String> {
let mut lck = app_state.runner_instance.lock()?;
if let Some(inst) = lck.take() {
info!("Sending sigterm");
inst.terminator.send(()).unwrap();
}
Ok(())
}
Terminating the game will immediately stop the process. Make sure to save your progress before terminating.
Viewing Changelogs
You can fetch changelogs for specific builds:
// From: src-tauri/src/app/gui/commands/client.rs:80
#[tauri::command]
pub(crate) async fn fetch_changelog(client: Client, build_id: u32) -> Result<Changelog, String> {
(|| async { client.fetch_changelog(build_id).await })
.retry(ExponentialBuilder::default())
.await
.map_err(|e| format!("unable to fetch changelog: {:?}", e))
}
Troubleshooting
Client is already running error
Only one game instance can run at a time. If you see this error:
- Close the existing game window
- Wait for the process to fully terminate
- Try launching again
Failed to fetch launch manifest
This usually indicates:
- Network connectivity issues
- Invalid build ID
- Server downtime
The launcher will automatically retry with exponential backoff.
If the Java binary is missing:
- Delete the
runtimes folder in your data directory
- Restart the launcher
- The Java runtime will be re-downloaded
Increase memory allocation in Settings:
- Go to Settings
- Increase the Memory slider
- Recommended: 4GB minimum, 8GB for better performance
Next Steps
Mods Management
Learn how to install and manage mods
Settings
Configure advanced launch options