diff options
| author | 2025-02-01 23:06:37 -0600 | |
|---|---|---|
| committer | 2025-02-01 23:06:37 -0600 | |
| commit | c19a1077e85334a3e5ba885a60b03d76409a2b2e (patch) | |
| tree | 5e726e8180770ac9c2f6c415a0437d6d2c29c226 /src/launcher/runner.rs | |
| parent | random changes (diff) | |
restructure project
Diffstat (limited to 'src/launcher/runner.rs')
| -rw-r--r-- | src/launcher/runner.rs | 222 |
1 files changed, 0 insertions, 222 deletions
diff --git a/src/launcher/runner.rs b/src/launcher/runner.rs deleted file mode 100644 index afdfc7f..0000000 --- a/src/launcher/runner.rs +++ /dev/null @@ -1,222 +0,0 @@ -use std::borrow::Cow; -use std::ffi::{OsStr, OsString}; -use std::iter; -use std::path::{Path, PathBuf}; -use std::process::Command; -use log::{debug, warn}; -use tokio::{fs, io}; -use crate::util::AsJavaPath; -use crate::version::{CompleteVersion, FeatureMatcher, OperatingSystem}; -use super::rules::CompatCheck; -use super::strsub::{self, SubFunc}; -use super::{Launch, LaunchInfo}; - -#[derive(Clone, Copy)] -struct LaunchArgSub<'a, 'l, F: FeatureMatcher>(&'a LaunchInfo<'l, F>); - -// FIXME: this is not correct -#[cfg(windows)] -const PATH_SEP: &str = ";"; - -#[cfg(not(windows))] -const PATH_SEP: &str = ":"; - -impl<'rep, F: FeatureMatcher> SubFunc<'rep> for LaunchArgSub<'rep, '_, F> { - fn substitute(&self, key: &str) -> Option<Cow<'rep, str>> { - match key { - "assets_index_name" => self.0.asset_index_name.as_ref().map(|s| Cow::Borrowed(s.as_str())), - "assets_root" => Some(self.0.launcher.assets.get_home().as_java_path().to_string_lossy()), - "auth_access_token" => Some(Cow::Borrowed("-")), // TODO - "auth_player_name" => Some(Cow::Borrowed("Player")), // TODO - "auth_session" => Some(Cow::Borrowed("-")), // TODO - "auth_uuid" => Some(Cow::Borrowed("00000000-0000-0000-0000-000000000000")), // TODO - "auth_xuid" => Some(Cow::Borrowed("00000000-0000-0000-0000-000000000000")), // TODO - "classpath" => Some(Cow::Borrowed(self.0.classpath.as_str())), - "classpath_separator" => Some(Cow::Borrowed(PATH_SEP)), - "game_assets" => self.0.virtual_assets_path.as_ref() - .map(|s| s.as_path().as_java_path().to_string_lossy()), - "game_directory" => Some(self.0.instance_home.as_java_path().to_string_lossy()), - "language" => Some(Cow::Borrowed("en-us")), // ??? - "launcher_name" => Some(Cow::Borrowed("ozone (olauncher 3)")), // TODO - "launcher_version" => Some(Cow::Borrowed("yeah")), // TODO - "library_directory" => Some(self.0.launcher.libraries.home.as_java_path().to_string_lossy()), - "natives_directory" => Some(self.0.natives_path.as_java_path().to_string_lossy()), - "primary_jar" => self.0.client_jar.as_ref().map(|p| p.as_path().as_java_path().to_string_lossy()), - "quickPlayMultiplayer" => None, // TODO - "quickPlayPath" => None, // TODO - "quickPlayRealms" => None, // TODO - "quickPlaySingleplayer" => None, // TODO - "resolution_height" => None, // TODO - "resolution_width" => None, // TODO - "user_properties" => Some(Cow::Borrowed("{}")), // TODO - "user_property_map" => Some(Cow::Borrowed("[]")), // TODO - "user_type" => Some(Cow::Borrowed("legacy")), // TODO - "version_name" => Some(Cow::Borrowed(self.0.version_id.as_ref())), - "version_type" => self.0.version_type.as_ref().map(|s| Cow::Borrowed(s.to_str())), - _ => { - if let Some(asset_key) = key.strip_prefix("asset=") { - return self.0.asset_index.as_ref().and_then(|idx| idx.objects.get(asset_key)) - .map(|obj| Cow::Owned(self.0.launcher.assets.get_object_path(obj).as_java_path().to_string_lossy().into_owned())) - } - - None - } - } - } -} - -#[derive(Clone, Copy)] -pub enum ArgumentType { - Jvm, - Game -} - -pub fn build_arguments<F: FeatureMatcher>(launch: &LaunchInfo<'_, F>, version: &CompleteVersion, arg_type: ArgumentType) -> Vec<OsString> { - let sub = LaunchArgSub(launch); - let system_info = &launch.launcher.system_info; - - if let Some(arguments) = version.arguments.as_ref().and_then(|args| match arg_type { - ArgumentType::Jvm => args.jvm.as_ref(), - ArgumentType::Game => args.game.as_ref() - }) { - arguments.iter() - .filter(|wa| wa.rules_apply(system_info, launch.feature_matcher).is_ok()) - .flat_map(|wa| &wa.value) - .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned())).collect() - } else if let Some(arguments) = version.minecraft_arguments.as_ref() { - match arg_type { - ArgumentType::Jvm => { - [ - "-Djava.library.path=${natives_directory}", - "-Dminecraft.launcher.brand=${launcher_name}", - "-Dminecraft.launcher.version=${launcher_version}", - "-Dminecraft.client.jar=${primary_jar}", - "-cp", - "${classpath}" - ].into_iter() - .chain(iter::once("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump") - .take_while(|_| system_info.os == OperatingSystem::Windows)) - .chain(iter::once(["-Dos.name=Windows 10", "-Dos.version=10.0"]) - .take_while(|_| launch.feature_matcher.matches("__ozone_win10_hack")) - .flatten()) - .chain(iter::once(["-Xdock:icon=${asset=icons/minecraft.icns}", "-Xdock:name=Minecraft"]) - .take_while(|_| system_info.os == OperatingSystem::MacOS) - .flatten()) - .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned())) - .collect() - }, - ArgumentType::Game => { - arguments.split(' ') - .chain(iter::once("--demo") - .take_while(|_| launch.feature_matcher.matches("is_demo_user"))) - .chain(iter::once(["--width", "${resolution_width}", "--height", "${resolution_height}"]) - .take_while(|_| launch.feature_matcher.matches("has_custom_resolution")) - .flatten()) - .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned())) - .collect() - } - } - } else { - Vec::default() - } -} - -pub fn run_the_game(launch: &Launch) -> Result<(), Box<dyn std::error::Error>> { - if launch.runtime_legacy_launch { - Command::new(launch.runtime_path.as_path().as_java_path()) - .args(launch.jvm_args.iter() - .map(|o| o.as_os_str()) - .chain(iter::once(OsStr::new(launch.main_class.as_str()))) - .chain(launch.game_args.iter().map(|o| o.as_os_str()))) - .current_dir(launch.instance_path.as_path().as_java_path()).spawn()?.wait()?; - } else { - todo!("jni launch not supported :(") - } - - Ok(()) -} - -#[allow(dead_code)] -mod windows { - pub const JNI_SEARCH_PATH: Option<&str> = Some("server/jvm.dll"); - pub const JAVA_SEARCH_PATH: Option<&str> = Some("bin/java.exe"); - pub const JRE_PLATFORM_KNOWN: bool = true; -} - -#[allow(dead_code)] -mod linux { - pub const JNI_SEARCH_PATH: Option<&str> = Some("server/libjvm.so"); - pub const JAVA_SEARCH_PATH: Option<&str> = Some("bin/java"); - pub const JRE_PLATFORM_KNOWN: bool = true; -} - -#[allow(dead_code)] -mod macos { - pub const JNI_SEARCH_PATH: Option<&str> = Some("server/libjvm.dylib"); - pub const JAVA_SEARCH_PATH: Option<&str> = Some("bin/java"); - pub const JRE_PLATFORM_KNOWN: bool = true; -} - -#[allow(dead_code)] -mod unknown { - pub const JNI_SEARCH_PATH: Option<&str> = None; - pub const JAVA_SEARCH_PATH: Option<&str> = None; - pub const JRE_PLATFORM_KNOWN: bool = false; -} - -#[cfg(target_os = "windows")] -use self::windows::*; -#[cfg(target_os = "linux")] -use self::linux::*; -#[cfg(target_os = "macos")] -use self::macos::*; -#[cfg(not(any(target_os = "windows", target_os = "linux", target_os = "macos")))] -use self::unknown::*; - -fn search_java_sync(base: impl AsRef<Path>, legacy: bool) -> Result<Option<PathBuf>, io::Error> { - assert!(JRE_PLATFORM_KNOWN); - let search_path = Path::new(match legacy { - true => JAVA_SEARCH_PATH, - _ => JNI_SEARCH_PATH - }.unwrap()); - - let walker = walkdir::WalkDir::new(base.as_ref()).into_iter() - .filter_map(|e| e.ok()) - .filter(|e| e.file_type().is_dir()); - - for entry in walker { - let check_path = [base.as_ref(), entry.path(), Path::new(search_path)].into_iter().collect::<PathBuf>(); - match std::fs::metadata(check_path.as_path()) { - Err(e) if e.kind() == io::ErrorKind::NotFound => (), - Err(e) => return Err(e), - Ok(meta) if meta.is_file() => return Ok(Some(check_path)), - _ => () - } - } - - Ok(None) // not found (sadface) -} - -//noinspection RsConstantConditionIf -pub async fn find_java(base: impl AsRef<Path>, legacy: bool) -> Result<Option<PathBuf>, io::Error> { - let meta = fs::metadata(&base).await?; - if meta.is_dir() { // do search - if !JRE_PLATFORM_KNOWN { - warn!("Unknown platform! Cannot search for java executable in {}. Please specify the executable file manually.", base.as_ref().display()); - return Ok(None); - } - - let (tx, rx) = tokio::sync::oneshot::channel(); - let base = base.as_ref().to_path_buf(); // idc - - tokio::task::spawn_blocking(move || { - let res = search_java_sync(base, legacy); - let _ = tx.send(res); // I really don't care if the reader hung up - }).await.expect("jre search panicked"); - - rx.await.expect("jre search didn't send us a result") - } else { // we are pointed directly at a file. assume it's what we want - debug!("JRE path {} is a file ({}). Assuming it's what we want.", base.as_ref().display(), legacy); - Ok(Some(base.as_ref().to_path_buf())) - } -} |
