* basic push

* actual push

* JRE detection, and autosetting

* removed a println, retrying CI/CD

* new game version compare; preset java 7 and 8 using our jre

* 1.8 mislabeled

* working JRE changes

* fixed bugs with JRE setup

* fixed bugs with JRE setup

* manual merge

* prettier

* fixes + jre 17

* clippy, prettier

* typo

* forgot to hook up a function

* pr fix + comment fix

* added loader_version

* take 2
This commit is contained in:
Wyatt Verchere
2023-04-07 13:31:06 -07:00
committed by GitHub
parent 4b41ffbd8a
commit 34005dd2e2
21 changed files with 542 additions and 83 deletions

137
theseus/src/api/jre.rs Normal file
View File

@@ -0,0 +1,137 @@
//! Authentication flow interface
use crate::{
launcher::download,
prelude::Profile,
state::JavaGlobals,
util::jre::{self, extract_java_majorminor_version, JavaVersion},
State,
};
pub const JAVA_8_KEY: &str = "JAVA_8";
pub const JAVA_17_KEY: &str = "JAVA_17";
pub const JAVA_18PLUS_KEY: &str = "JAVA_18PLUS";
// Autodetect JavaSettings default
// Make a guess for what the default Java global settings should be
pub fn autodetect_java_globals() -> crate::Result<JavaGlobals> {
let mut java_8 = find_java8_jres()?;
let mut java_17 = find_java17_jres()?;
let mut java_18plus = find_java18plus_jres()?;
// Simply select last one found for initial guess
let mut java_globals = JavaGlobals::new();
if let Some(jre) = java_8.pop() {
java_globals.insert(JAVA_8_KEY.to_string(), jre);
}
if let Some(jre) = java_17.pop() {
java_globals.insert(JAVA_17_KEY.to_string(), jre);
}
if let Some(jre) = java_18plus.pop() {
java_globals.insert(JAVA_18PLUS_KEY.to_string(), jre);
}
Ok(java_globals)
}
// Gets the optimal JRE key for the given profile, using Daedalus
// Generally this would be used for profile_create, to get the optimal JRE key
// this can be overwritten by the user a profile-by-profile basis
pub async fn get_optimal_jre_key(profile: &Profile) -> crate::Result<String> {
let state = State::get().await?;
// Fetch version info from stored profile game_version
let version = state
.metadata
.minecraft
.versions
.iter()
.find(|it| it.id == profile.metadata.game_version.as_ref())
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"Invalid or unknown Minecraft version: {}",
profile.metadata.game_version
))
})?;
// Get detailed manifest info from Daedalus
let version_info =
download::download_version_info(&state, version, profile.metadata.loader_version.as_ref()).await?;
let optimal_key = match version_info
.java_version
.as_ref()
.map(|it| it.major_version)
.unwrap_or(0)
{
0..=16 => JAVA_8_KEY.to_string(),
17 => JAVA_17_KEY.to_string(),
_ => JAVA_18PLUS_KEY.to_string(),
};
Ok(optimal_key)
}
// Searches for jres on the system that are 1.18 or higher
pub fn find_java18plus_jres() -> crate::Result<Vec<JavaVersion>> {
let version = extract_java_majorminor_version("1.18")?;
let jres = jre::get_all_jre()?;
// Filter out JREs that are not 1.17 or higher
Ok(jres
.into_iter()
.filter(|jre| {
let jre_version = extract_java_majorminor_version(&jre.version);
if let Ok(jre_version) = jre_version {
jre_version >= version
} else {
false
}
})
.collect())
}
// Searches for jres on the system that are 1.8 exactly
pub fn find_java8_jres() -> crate::Result<Vec<JavaVersion>> {
let version = extract_java_majorminor_version("1.8")?;
let jres = jre::get_all_jre()?;
// Filter out JREs that are not 1.8
Ok(jres
.into_iter()
.filter(|jre| {
let jre_version = extract_java_majorminor_version(&jre.version);
if let Ok(jre_version) = jre_version {
jre_version == version
} else {
false
}
})
.collect())
}
// Searches for jres on the system that are 1.17 exactly
pub fn find_java17_jres() -> crate::Result<Vec<JavaVersion>> {
let version = extract_java_majorminor_version("1.17")?;
let jres = jre::get_all_jre()?;
// Filter out JREs that are not 1.8
Ok(jres
.into_iter()
.filter(|jre| {
let jre_version = extract_java_majorminor_version(&jre.version);
if let Ok(jre_version) = jre_version {
jre_version == version
} else {
false
}
})
.collect())
}
// Get all JREs that exist on the system
pub fn get_all_jre() -> crate::Result<Vec<JavaVersion>> {
Ok(jre::get_all_jre()?)
}
pub async fn validate_globals() -> crate::Result<bool> {
let state = State::get().await?;
let settings = state.settings.read().await;
Ok(settings.java_globals.is_all_valid())
}

View File

@@ -1,5 +1,6 @@
//! API for interacting with Theseus
pub mod auth;
pub mod jre;
pub mod pack;
pub mod process;
pub mod profile;
@@ -18,8 +19,11 @@ pub mod prelude {
pub use crate::{
auth::{self, Credentials},
data::*,
pack, process,
jre, pack, process,
profile::{self, Profile},
profile_create, settings, State,
profile_create, settings,
state::JavaGlobals,
util::jre::JavaVersion,
State,
};
}

View File

@@ -1,10 +1,9 @@
//! Theseus profile management interface
use crate::state::MinecraftChild;
use crate::{launcher::download, state::MinecraftChild};
pub use crate::{
state::{JavaSettings, Profile},
State,
};
use daedalus as d;
use std::{
future::Future,
path::{Path, PathBuf},
@@ -120,8 +119,8 @@ pub async fn run(
profile.metadata.game_version
))
})?;
let version_info = d::minecraft::fetch_version_info(version).await?;
let version_info =
download::download_version_info(&state, version, profile.metadata.loader_version.as_ref()).await?;
let pre_launch_hooks =
&profile.hooks.as_ref().unwrap_or(&settings.hooks).pre_launch;
for hook in pre_launch_hooks.iter() {
@@ -145,29 +144,42 @@ pub async fn run(
}
}
let java_install = match profile.java {
let java_version = match profile.java {
// Load profile-specific Java implementation choice
// (This defaults to Daedalus-decided key on init, but can be changed by the user)
Some(JavaSettings {
install: Some(ref install),
jre_key: Some(ref jre_key),
..
}) => install,
_ => if version_info
.java_version
.as_ref()
.filter(|it| it.major_version >= 16)
.is_some()
{
settings.java_17_path.as_ref()
} else {
settings.java_8_path.as_ref()
}) => settings.java_globals.get(jre_key),
// Fall back to Daedalus-decided key if no profile-specific key is set
_ => {
match version_info
.java_version
.as_ref()
.map(|it| it.major_version)
.unwrap_or(0)
{
0..=16 => settings
.java_globals
.get(&crate::jre::JAVA_8_KEY.to_string()),
17 => settings
.java_globals
.get(&crate::jre::JAVA_17_KEY.to_string()),
_ => settings
.java_globals
.get(&crate::jre::JAVA_18PLUS_KEY.to_string()),
}
}
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"No Java installed for version {}",
version_info.java_version.map_or(8, |it| it.major_version),
))
})?,
};
let java_version = java_version.as_ref().ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"No Java stored for version {}",
version_info.java_version.map_or(8, |it| it.major_version),
))
})?;
// Get the path to the Java executable from the chosen Java implementation key
let java_install: &Path = &PathBuf::from(&java_version.path);
if !java_install.exists() {
return Err(crate::ErrorKind::LauncherError(format!(
"Could not find Java install: {}",
@@ -175,7 +187,6 @@ pub async fn run(
))
.as_error());
}
let java_args = profile
.java
.as_ref()

View File

@@ -1,5 +1,5 @@
//! Theseus profile management interface
use crate::prelude::ModLoader;
use crate::{jre, prelude::ModLoader};
pub use crate::{
state::{JavaSettings, Profile},
State,
@@ -145,6 +145,20 @@ pub async fn profile_create(
}
profile.metadata.linked_project_id = linked_project_id;
// Attempts to find optimal JRE for the profile from the JavaGlobals
// Finds optimal key, and see if key has been set in JavaGlobals
let settings = state.settings.read().await;
let optimal_version_key = jre::get_optimal_jre_key(&profile).await?;
if settings.java_globals.get(&optimal_version_key).is_some() {
profile.set_java_settings(Some(JavaSettings {
jre_key: Some(optimal_version_key),
extra_arguments: None,
}))?;
} else {
println!("Could not detect optimal JRE: {optimal_version_key}, falling back to system default.");
}
{
let mut profiles = state.profiles.write().await;
profiles.insert(profile)?;