cobble_core/minecraft/fabric/
launch.rs

1use crate::minecraft::fabric::FabricVersionData;
2use crate::minecraft::models::VersionData;
3use crate::minecraft::{
4    build_classpath, build_game_args, build_jvm_args, build_logging_arg, combine_launch_parts,
5    ArgumentReplacements, LaunchOptions,
6};
7use crate::utils::Platform;
8use std::path::Path;
9use std::process::Command;
10
11/// Builds the launch command for Minecraft.
12/// The game needs to be installed to launch.
13#[cfg_attr(doc_cfg, doc(cfg(feature = "fabric")))]
14#[allow(clippy::too_many_arguments)]
15#[instrument(
16    name = "build_launch_command",
17    level = "trace",
18    skip_all,
19    fields(
20        game_version = version_data.id,
21        fabric_version = fabric_version_data.id,
22        launch_options,
23        minecraft_path,
24        libraries_path,
25        assets_path,
26        natives_path,
27        log_configs_path,
28    )
29)]
30pub fn build_fabric_launch_command(
31    version_data: &VersionData,
32    fabric_version_data: &FabricVersionData,
33    launch_options: &LaunchOptions,
34    minecraft_path: impl AsRef<Path>,
35    libraries_path: impl AsRef<Path>,
36    assets_path: impl AsRef<Path>,
37    natives_path: impl AsRef<Path>,
38    log_configs_path: impl AsRef<Path>,
39) -> Command {
40    // Classpath
41    trace!("Build classpath");
42    let mut classpath = build_classpath(version_data, &minecraft_path, &libraries_path);
43    extend_classpath(&mut classpath, fabric_version_data, &libraries_path);
44
45    // Argument replacements
46    trace!("Create argument replacements");
47    let argument_replacements = ArgumentReplacements::build(
48        launch_options,
49        version_data,
50        classpath,
51        minecraft_path.as_ref().to_string_lossy().to_string(),
52        assets_path.as_ref().to_string_lossy().to_string(),
53        natives_path.as_ref().to_string_lossy().to_string(),
54    );
55
56    // Arguments
57    trace!("Build JVM arguments");
58    let mut jvm_args = build_jvm_args(version_data, &argument_replacements, launch_options);
59    extend_jvm_args(&mut jvm_args, fabric_version_data, &argument_replacements);
60    trace!("Build game arguments");
61    let mut game_args = build_game_args(version_data, &argument_replacements, launch_options);
62    extend_game_args(&mut game_args, fabric_version_data, &argument_replacements);
63
64    // Logging config
65    trace!("Build log argument");
66    let log_arg = build_logging_arg(version_data, &log_configs_path);
67
68    trace!("Build command");
69    combine_launch_parts(
70        launch_options.java_executable.clone(),
71        minecraft_path,
72        jvm_args,
73        game_args,
74        log_arg,
75        fabric_version_data.main_class.clone(),
76        launch_options.environment_variables.clone(),
77    )
78}
79
80fn extend_classpath(
81    classpath: &mut String,
82    fabric_version_data: &FabricVersionData,
83    libraries_path: impl AsRef<Path>,
84) {
85    let classes = fabric_version_data
86        .libraries
87        .iter()
88        .map(|l| l.jar_path(&libraries_path))
89        .map(|p| p.to_string_lossy().to_string())
90        .collect::<Vec<_>>();
91
92    let classes = classes.join(&Platform::current().classpath_seperator().to_string());
93    classpath.push(Platform::current().classpath_seperator());
94    classpath.push_str(&classes);
95}
96
97fn extend_jvm_args(
98    jvm_args: &mut Vec<String>,
99    fabric_version_data: &FabricVersionData,
100    argument_replacements: &ArgumentReplacements,
101) {
102    if let Some(args) = &fabric_version_data.arguments {
103        for argument in args.jvm_arguments() {
104            jvm_args.push(argument_replacements.replace(argument.clone()));
105        }
106    }
107}
108
109fn extend_game_args(
110    game_args: &mut Vec<String>,
111    fabric_version_data: &FabricVersionData,
112    argument_replacements: &ArgumentReplacements,
113) {
114    if let Some(args) = &fabric_version_data.arguments {
115        for argument in args.game_arguments() {
116            game_args.push(argument_replacements.replace(argument.clone()));
117        }
118    }
119}