summaryrefslogtreecommitdiffstats
path: root/src/launcher/runner.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/launcher/runner.rs')
-rw-r--r--src/launcher/runner.rs222
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()))
- }
-}