cobble-core 1.2.0

Library for managing, installing and launching Minecraft instances and more.
Documentation
use crate::minecraft::fabric::FabricVersionData;
use crate::minecraft::models::VersionData;
use crate::minecraft::{
    build_classpath, build_game_args, build_jvm_args, build_logging_arg, combine_launch_parts,
    ArgumentReplacements, LaunchOptions,
};
use crate::utils::Platform;
use std::path::Path;
use std::process::Command;

/// Builds the launch command for Minecraft.
/// The game needs to be installed to launch.
#[cfg_attr(doc_cfg, doc(cfg(feature = "fabric")))]
#[allow(clippy::too_many_arguments)]
#[instrument(
    name = "build_launch_command",
    level = "trace",
    skip_all,
    fields(
        game_version = version_data.id,
        fabric_version = fabric_version_data.id,
        launch_options,
        minecraft_path,
        libraries_path,
        assets_path,
        natives_path,
        log_configs_path,
    )
)]
pub fn build_fabric_launch_command(
    version_data: &VersionData,
    fabric_version_data: &FabricVersionData,
    launch_options: &LaunchOptions,
    minecraft_path: impl AsRef<Path>,
    libraries_path: impl AsRef<Path>,
    assets_path: impl AsRef<Path>,
    natives_path: impl AsRef<Path>,
    log_configs_path: impl AsRef<Path>,
) -> Command {
    // Classpath
    trace!("Build classpath");
    let mut classpath = build_classpath(version_data, &minecraft_path, &libraries_path);
    extend_classpath(&mut classpath, fabric_version_data, &libraries_path);

    // Argument replacements
    trace!("Create argument replacements");
    let argument_replacements = ArgumentReplacements::build(
        launch_options,
        version_data,
        classpath,
        minecraft_path.as_ref().to_string_lossy().to_string(),
        assets_path.as_ref().to_string_lossy().to_string(),
        natives_path.as_ref().to_string_lossy().to_string(),
    );

    // Arguments
    trace!("Build JVM arguments");
    let mut jvm_args = build_jvm_args(version_data, &argument_replacements, launch_options);
    extend_jvm_args(&mut jvm_args, fabric_version_data, &argument_replacements);
    trace!("Build game arguments");
    let mut game_args = build_game_args(version_data, &argument_replacements, launch_options);
    extend_game_args(&mut game_args, fabric_version_data, &argument_replacements);

    // Logging config
    trace!("Build log argument");
    let log_arg = build_logging_arg(version_data, &log_configs_path);

    trace!("Build command");
    combine_launch_parts(
        launch_options.java_executable.clone(),
        minecraft_path,
        jvm_args,
        game_args,
        log_arg,
        fabric_version_data.main_class.clone(),
        launch_options.environment_variables.clone(),
    )
}

fn extend_classpath(
    classpath: &mut String,
    fabric_version_data: &FabricVersionData,
    libraries_path: impl AsRef<Path>,
) {
    let classes = fabric_version_data
        .libraries
        .iter()
        .map(|l| l.jar_path(&libraries_path))
        .map(|p| p.to_string_lossy().to_string())
        .collect::<Vec<_>>();

    let classes = classes.join(&Platform::current().classpath_seperator().to_string());
    classpath.push(Platform::current().classpath_seperator());
    classpath.push_str(&classes);
}

fn extend_jvm_args(
    jvm_args: &mut Vec<String>,
    fabric_version_data: &FabricVersionData,
    argument_replacements: &ArgumentReplacements,
) {
    if let Some(args) = &fabric_version_data.arguments {
        for argument in args.jvm_arguments() {
            jvm_args.push(argument_replacements.replace(argument.clone()));
        }
    }
}

fn extend_game_args(
    game_args: &mut Vec<String>,
    fabric_version_data: &FabricVersionData,
    argument_replacements: &ArgumentReplacements,
) {
    if let Some(args) = &fabric_version_data.arguments {
        for argument in args.game_arguments() {
            game_args.push(argument_replacements.replace(argument.clone()));
        }
    }
}