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.rs103
1 files changed, 97 insertions, 6 deletions
diff --git a/src/launcher/runner.rs b/src/launcher/runner.rs
index 41b3ed1..50a9ff8 100644
--- a/src/launcher/runner.rs
+++ b/src/launcher/runner.rs
@@ -1,7 +1,10 @@
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;
@@ -113,12 +116,100 @@ pub fn build_arguments<'l, F: FeatureMatcher>(launch: &LaunchInfo<'l, F>, versio
}
pub fn run_the_game(launch: &Launch) -> Result<(), Box<dyn std::error::Error>> {
- Command::new("java")
- .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()?;
+ 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)
+}
+
+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()))
+ }
+}