Bump Theseus Version (#818)

* push to test on windows

* Fix windows sup

* Fix macos

* Fix back

* new resolver for windows testing

* Custom macos handling for some versions

* Fix 1.13+ broken

* fix arg parsing mac

* small winblows fix

* remove debug info; set meta url

* run lint + fix clippy

* Remove useless commnet
This commit is contained in:
Geometrically 2023-10-21 13:08:47 -07:00 committed by GitHub
parent 7fb8850071
commit afaec4b1bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 189 additions and 97 deletions

6
Cargo.lock generated
View File

@ -4685,7 +4685,7 @@ dependencies = [
[[package]] [[package]]
name = "theseus" name = "theseus"
version = "0.5.4" version = "0.6.0"
dependencies = [ dependencies = [
"async-recursion", "async-recursion",
"async-tungstenite", "async-tungstenite",
@ -4733,7 +4733,7 @@ dependencies = [
[[package]] [[package]]
name = "theseus_cli" name = "theseus_cli"
version = "0.5.4" version = "0.6.0"
dependencies = [ dependencies = [
"argh", "argh",
"color-eyre", "color-eyre",
@ -4760,7 +4760,7 @@ dependencies = [
[[package]] [[package]]
name = "theseus_gui" name = "theseus_gui"
version = "0.5.4" version = "0.6.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"cocoa", "cocoa",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "theseus" name = "theseus"
version = "0.5.4" version = "0.6.0"
authors = ["Jai A <jaiagr+gpg@pm.me>"] authors = ["Jai A <jaiagr+gpg@pm.me>"]
edition = "2018" edition = "2018"

View File

@ -68,10 +68,14 @@ pub async fn refresh(user: uuid::Uuid) -> crate::Result<Credentials> {
} }
// Update player info from bearer token // Update player info from bearer token
let player_info = hydra::stages::player_info::fetch_info(&credentials.access_token).await.map_err(|_err| { let player_info =
crate::ErrorKind::HydraError("No Minecraft account for your profile. Make sure you own the game and have set a username through the official Minecraft launcher." hydra::stages::player_info::fetch_info(&credentials.access_token)
.to_string()) .await
})?; .map_err(|_err| {
crate::ErrorKind::HydraError(
"No Minecraft account for your profile. Please try again or contact support in our Discord for help!".to_string(),
)
})?;
credentials.username = player_info.name; credentials.username = player_info.name;
users.insert(&credentials).await?; users.insert(&credentials).await?;

View File

@ -13,7 +13,7 @@ impl Default for PlayerInfo {
fn default() -> Self { fn default() -> Self {
Self { Self {
id: "606e2ff0ed7748429d6ce1d3321c7838".to_string(), id: "606e2ff0ed7748429d6ce1d3321c7838".to_string(),
name: String::from("???"), name: String::from("Unknown"),
} }
} }
} }

View File

@ -127,7 +127,7 @@ pub async fn auto_install_java(java_version: u32) -> crate::Result<PathBuf> {
// removes the old installation of java // removes the old installation of java
if let Some(file) = archive.file_names().next() { if let Some(file) = archive.file_names().next() {
if let Some(dir) = file.split("/").next() { if let Some(dir) = file.split('/').next() {
let path = path.join(dir); let path = path.join(dir);
if path.exists() { if path.exists() {

View File

@ -245,8 +245,12 @@ async fn import_atlauncher_unmanaged(
if let Some(profile_val) = if let Some(profile_val) =
crate::api::profile::get(&profile_path, None).await? crate::api::profile::get(&profile_path, None).await?
{ {
crate::launcher::install_minecraft(&profile_val, Some(loading_bar)) crate::launcher::install_minecraft(
.await?; &profile_val,
Some(loading_bar),
false,
)
.await?;
{ {
let state = State::get().await?; let state = State::get().await?;
let mut file_watcher = state.file_watcher.write().await; let mut file_watcher = state.file_watcher.write().await;

View File

@ -199,8 +199,12 @@ pub async fn import_curseforge(
if let Some(profile_val) = if let Some(profile_val) =
crate::api::profile::get(&profile_path, None).await? crate::api::profile::get(&profile_path, None).await?
{ {
crate::launcher::install_minecraft(&profile_val, Some(loading_bar)) crate::launcher::install_minecraft(
.await?; &profile_val,
Some(loading_bar),
false,
)
.await?;
{ {
let state = State::get().await?; let state = State::get().await?;

View File

@ -112,8 +112,12 @@ pub async fn import_gdlauncher(
if let Some(profile_val) = if let Some(profile_val) =
crate::api::profile::get(&profile_path, None).await? crate::api::profile::get(&profile_path, None).await?
{ {
crate::launcher::install_minecraft(&profile_val, Some(loading_bar)) crate::launcher::install_minecraft(
.await?; &profile_val,
Some(loading_bar),
false,
)
.await?;
{ {
let state = State::get().await?; let state = State::get().await?;
let mut file_watcher = state.file_watcher.write().await; let mut file_watcher = state.file_watcher.write().await;

View File

@ -323,8 +323,12 @@ async fn import_mmc_unmanaged(
if let Some(profile_val) = if let Some(profile_val) =
crate::api::profile::get(&profile_path, None).await? crate::api::profile::get(&profile_path, None).await?
{ {
crate::launcher::install_minecraft(&profile_val, Some(loading_bar)) crate::launcher::install_minecraft(
.await?; &profile_val,
Some(loading_bar),
false,
)
.await?;
{ {
let state = State::get().await?; let state = State::get().await?;
let mut file_watcher = state.file_watcher.write().await; let mut file_watcher = state.file_watcher.write().await;

View File

@ -283,8 +283,12 @@ pub async fn install_zipped_mrpack_files(
} }
if let Some(profile_val) = profile::get(&profile_path, None).await? { if let Some(profile_val) = profile::get(&profile_path, None).await? {
crate::launcher::install_minecraft(&profile_val, Some(loading_bar)) crate::launcher::install_minecraft(
.await?; &profile_val,
Some(loading_bar),
false,
)
.await?;
State::sync().await?; State::sync().await?;
} }

View File

@ -125,7 +125,7 @@ pub async fn profile_create(
} }
if !skip_install_profile.unwrap_or(false) { if !skip_install_profile.unwrap_or(false) {
crate::launcher::install_minecraft(&profile, None).await?; crate::launcher::install_minecraft(&profile, None, false).await?;
} }
State::sync().await?; State::sync().await?;
@ -196,7 +196,8 @@ pub async fn profile_create_from_duplicate(
ErrorKind::UnmanagedProfileError(profile_path_id.to_string()) ErrorKind::UnmanagedProfileError(profile_path_id.to_string())
})?; })?;
crate::launcher::install_minecraft(&duplicated_profile, Some(bar)).await?; crate::launcher::install_minecraft(&duplicated_profile, Some(bar), false)
.await?;
{ {
let state = State::get().await?; let state = State::get().await?;
let mut file_watcher = state.file_watcher.write().await; let mut file_watcher = state.file_watcher.write().await;

View File

@ -281,9 +281,9 @@ pub async fn list(
/// Installs/Repairs a profile /// Installs/Repairs a profile
#[tracing::instrument] #[tracing::instrument]
pub async fn install(path: &ProfilePathId) -> crate::Result<()> { pub async fn install(path: &ProfilePathId, force: bool) -> crate::Result<()> {
if let Some(profile) = get(path, None).await? { if let Some(profile) = get(path, None).await? {
crate::launcher::install_minecraft(&profile, None).await?; crate::launcher::install_minecraft(&profile, None, force).await?;
} else { } else {
return Err(crate::ErrorKind::UnmanagedProfileError(path.to_string()) return Err(crate::ErrorKind::UnmanagedProfileError(path.to_string())
.as_error()); .as_error());

View File

@ -1,6 +1,6 @@
//! Minecraft CLI argument logic //! Minecraft CLI argument logic
// TODO: Rafactor this section use super::auth::Credentials;
use super::{auth::Credentials, parse_rule}; use crate::launcher::parse_rules;
use crate::{ use crate::{
state::{MemorySettings, WindowSize}, state::{MemorySettings, WindowSize},
util::{io::IOError, platform::classpath_separator}, util::{io::IOError, platform::classpath_separator},
@ -23,12 +23,13 @@ pub fn get_class_paths(
libraries: &[Library], libraries: &[Library],
client_path: &Path, client_path: &Path,
java_arch: &str, java_arch: &str,
minecraft_updated: bool,
) -> crate::Result<String> { ) -> crate::Result<String> {
let mut cps = libraries let mut cps = libraries
.iter() .iter()
.filter_map(|library| { .filter_map(|library| {
if let Some(rules) = &library.rules { if let Some(rules) = &library.rules {
if !rules.iter().any(|x| parse_rule(x, java_arch)) { if !parse_rules(rules, java_arch, minecraft_updated) {
return None; return None;
} }
} }
@ -335,7 +336,7 @@ where
} }
} }
Argument::Ruled { rules, value } => { Argument::Ruled { rules, value } => {
if rules.iter().any(|x| parse_rule(x, java_arch)) { if parse_rules(rules, java_arch, true) {
match value { match value {
ArgumentValue::Single(arg) => { ArgumentValue::Single(arg) => {
parsed_arguments.push(parse_function( parsed_arguments.push(parse_function(

View File

@ -1,5 +1,6 @@
//! Downloader for Minecraft data //! Downloader for Minecraft data
use crate::launcher::parse_rules;
use crate::state::CredentialsStore; use crate::state::CredentialsStore;
use crate::{ use crate::{
event::{ event::{
@ -26,11 +27,13 @@ pub async fn download_minecraft(
version: &GameVersionInfo, version: &GameVersionInfo,
loading_bar: &LoadingBarId, loading_bar: &LoadingBarId,
java_arch: &str, java_arch: &str,
force: bool,
minecraft_updated: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
tracing::info!("Downloading Minecraft version {}", version.id); tracing::info!("Downloading Minecraft version {}", version.id);
// 5 // 5
let assets_index = let assets_index =
download_assets_index(st, version, Some(loading_bar)).await?; download_assets_index(st, version, Some(loading_bar), force).await?;
let amount = if version let amount = if version
.processors .processors
@ -45,9 +48,9 @@ pub async fn download_minecraft(
tokio::try_join! { tokio::try_join! {
// Total loading sums to 90/60 // Total loading sums to 90/60
download_client(st, version, Some(loading_bar)), // 10 download_client(st, version, Some(loading_bar), force), // 10
download_assets(st, version.assets == "legacy", &assets_index, Some(loading_bar), amount), // 40 download_assets(st, version.assets == "legacy", &assets_index, Some(loading_bar), amount, force), // 40
download_libraries(st, version.libraries.as_slice(), &version.id, Some(loading_bar), amount, java_arch) // 40 download_libraries(st, version.libraries.as_slice(), &version.id, Some(loading_bar), amount, java_arch, force, minecraft_updated) // 40
}?; }?;
tracing::info!("Done downloading Minecraft!"); tracing::info!("Done downloading Minecraft!");
@ -105,6 +108,7 @@ pub async fn download_client(
st: &State, st: &State,
version_info: &GameVersionInfo, version_info: &GameVersionInfo,
loading_bar: Option<&LoadingBarId>, loading_bar: Option<&LoadingBarId>,
force: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
let version = &version_info.id; let version = &version_info.id;
tracing::debug!("Locating client for version {version}"); tracing::debug!("Locating client for version {version}");
@ -123,7 +127,7 @@ pub async fn download_client(
.await .await
.join(format!("{version}.jar")); .join(format!("{version}.jar"));
if !path.exists() { if !path.exists() || force {
let bytes = fetch( let bytes = fetch(
&client_download.url, &client_download.url,
Some(&client_download.sha1), Some(&client_download.sha1),
@ -148,6 +152,7 @@ pub async fn download_assets_index(
st: &State, st: &State,
version: &GameVersionInfo, version: &GameVersionInfo,
loading_bar: Option<&LoadingBarId>, loading_bar: Option<&LoadingBarId>,
force: bool,
) -> crate::Result<AssetsIndex> { ) -> crate::Result<AssetsIndex> {
tracing::debug!("Loading assets index"); tracing::debug!("Loading assets index");
let path = st let path = st
@ -156,7 +161,7 @@ pub async fn download_assets_index(
.await .await
.join(format!("{}.json", &version.asset_index.id)); .join(format!("{}.json", &version.asset_index.id));
let res = if path.exists() { let res = if path.exists() && !force {
io::read(path) io::read(path)
.err_into::<crate::Error>() .err_into::<crate::Error>()
.await .await
@ -183,6 +188,7 @@ pub async fn download_assets(
index: &AssetsIndex, index: &AssetsIndex,
loading_bar: Option<&LoadingBarId>, loading_bar: Option<&LoadingBarId>,
loading_amount: f64, loading_amount: f64,
force: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
tracing::debug!("Loading assets"); tracing::debug!("Loading assets");
let num_futs = index.objects.len(); let num_futs = index.objects.len();
@ -206,7 +212,7 @@ pub async fn download_assets(
let fetch_cell = OnceCell::<bytes::Bytes>::new(); let fetch_cell = OnceCell::<bytes::Bytes>::new();
tokio::try_join! { tokio::try_join! {
async { async {
if !resource_path.exists() { if !resource_path.exists() || force {
let resource = fetch_cell let resource = fetch_cell
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore, &CredentialsStore(None))) .get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore, &CredentialsStore(None)))
.await?; .await?;
@ -216,13 +222,14 @@ pub async fn download_assets(
Ok::<_, crate::Error>(()) Ok::<_, crate::Error>(())
}, },
async { async {
if with_legacy { let resource_path = st.directories.legacy_assets_dir().await.join(
name.replace('/', &String::from(std::path::MAIN_SEPARATOR))
);
if with_legacy && !resource_path.exists() || force {
let resource = fetch_cell let resource = fetch_cell
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore, &CredentialsStore(None))) .get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore, &CredentialsStore(None)))
.await?; .await?;
let resource_path = st.directories.legacy_assets_dir().await.join(
name.replace('/', &String::from(std::path::MAIN_SEPARATOR))
);
write(&resource_path, resource, &st.io_semaphore).await?; write(&resource_path, resource, &st.io_semaphore).await?;
tracing::trace!("Fetched legacy asset with hash {hash}"); tracing::trace!("Fetched legacy asset with hash {hash}");
} }
@ -239,6 +246,7 @@ pub async fn download_assets(
#[tracing::instrument(skip(st, libraries))] #[tracing::instrument(skip(st, libraries))]
#[theseus_macros::debug_pin] #[theseus_macros::debug_pin]
#[allow(clippy::too_many_arguments)]
pub async fn download_libraries( pub async fn download_libraries(
st: &State, st: &State,
libraries: &[Library], libraries: &[Library],
@ -246,6 +254,8 @@ pub async fn download_libraries(
loading_bar: Option<&LoadingBarId>, loading_bar: Option<&LoadingBarId>,
loading_amount: f64, loading_amount: f64,
java_arch: &str, java_arch: &str,
force: bool,
minecraft_updated: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
tracing::debug!("Loading libraries"); tracing::debug!("Loading libraries");
@ -258,7 +268,7 @@ pub async fn download_libraries(
stream::iter(libraries.iter()) stream::iter(libraries.iter())
.map(Ok::<&Library, crate::Error>), None, loading_bar,loading_amount,num_files, None,|library| async move { .map(Ok::<&Library, crate::Error>), None, loading_bar,loading_amount,num_files, None,|library| async move {
if let Some(rules) = &library.rules { if let Some(rules) = &library.rules {
if !rules.iter().any(|x| super::parse_rule(x, java_arch)) { if !parse_rules(rules, java_arch, minecraft_updated) {
tracing::trace!("Skipped library {}", &library.name); tracing::trace!("Skipped library {}", &library.name);
return Ok(()); return Ok(());
} }
@ -270,7 +280,7 @@ pub async fn download_libraries(
let path = st.directories.libraries_dir().await.join(&artifact_path); let path = st.directories.libraries_dir().await.join(&artifact_path);
match library.downloads { match library.downloads {
_ if path.exists() => Ok(()), _ if path.exists() && !force => Ok(()),
Some(d::minecraft::LibraryDownloads { Some(d::minecraft::LibraryDownloads {
artifact: Some(ref artifact), artifact: Some(ref artifact),
.. ..

View File

@ -13,7 +13,7 @@ use crate::{
}; };
use chrono::Utc; use chrono::Utc;
use daedalus as d; use daedalus as d;
use daedalus::minecraft::VersionInfo; use daedalus::minecraft::{RuleAction, VersionInfo};
use st::Profile; use st::Profile;
use std::collections::HashMap; use std::collections::HashMap;
use std::{process::Stdio, sync::Arc}; use std::{process::Stdio, sync::Arc};
@ -25,14 +25,48 @@ mod args;
pub mod auth; pub mod auth;
pub mod download; pub mod download;
// All nones -> disallowed
// 1+ true -> allowed
// 1+ false -> disallowed
#[tracing::instrument] #[tracing::instrument]
pub fn parse_rule(rule: &d::minecraft::Rule, java_version: &str) -> bool { pub fn parse_rules(
rules: &[d::minecraft::Rule],
java_version: &str,
minecraft_updated: bool,
) -> bool {
let mut x = rules
.iter()
.map(|x| parse_rule(x, java_version, minecraft_updated))
.collect::<Vec<Option<bool>>>();
if rules
.iter()
.all(|x| matches!(x.action, RuleAction::Disallow))
{
x.push(Some(true))
}
!(x.iter().any(|x| x == &Some(false)) || x.iter().all(|x| x.is_none()))
}
// if anything is disallowed, it should NOT be included
// if anything is not disallowed, it shouldn't factor in final result
// if anything is not allowed, it shouldn't factor in final result
// if anything is allowed, it should be included
#[tracing::instrument]
pub fn parse_rule(
rule: &d::minecraft::Rule,
java_version: &str,
minecraft_updated: bool,
) -> Option<bool> {
use d::minecraft::{Rule, RuleAction}; use d::minecraft::{Rule, RuleAction};
let res = match rule { let res = match rule {
Rule { Rule {
os: Some(ref os), .. os: Some(ref os), ..
} => crate::util::platform::os_rule(os, java_version), } => {
crate::util::platform::os_rule(os, java_version, minecraft_updated)
}
Rule { Rule {
features: Some(ref features), features: Some(ref features),
.. ..
@ -44,12 +78,24 @@ pub fn parse_rule(rule: &d::minecraft::Rule, java_version: &str) -> bool {
|| !features.is_quick_play_realms.unwrap_or(true) || !features.is_quick_play_realms.unwrap_or(true)
|| !features.is_quick_play_singleplayer.unwrap_or(true) || !features.is_quick_play_singleplayer.unwrap_or(true)
} }
_ => false, _ => return Some(true),
}; };
match rule.action { match rule.action {
RuleAction::Allow => res, RuleAction::Allow => {
RuleAction::Disallow => !res, if res {
Some(true)
} else {
None
}
}
RuleAction::Disallow => {
if res {
Some(false)
} else {
None
}
}
} }
} }
@ -102,6 +148,7 @@ pub async fn get_java_version_from_profile(
pub async fn install_minecraft( pub async fn install_minecraft(
profile: &Profile, profile: &Profile,
existing_loading_bar: Option<LoadingBarId>, existing_loading_bar: Option<LoadingBarId>,
repairing: bool,
) -> crate::Result<()> { ) -> crate::Result<()> {
let sync_projects = existing_loading_bar.is_some(); let sync_projects = existing_loading_bar.is_some();
let loading_bar = init_or_edit_loading( let loading_bar = init_or_edit_loading(
@ -133,15 +180,23 @@ pub async fn install_minecraft(
&io::canonicalize(&profile.get_profile_full_path().await?)?; &io::canonicalize(&profile.get_profile_full_path().await?)?;
let metadata = state.metadata.read().await; let metadata = state.metadata.read().await;
let version = metadata let version_index = metadata
.minecraft .minecraft
.versions .versions
.iter() .iter()
.find(|it| it.id == profile.metadata.game_version) .position(|it| it.id == profile.metadata.game_version)
.ok_or(crate::ErrorKind::LauncherError(format!( .ok_or(crate::ErrorKind::LauncherError(format!(
"Invalid game version: {}", "Invalid game version: {}",
profile.metadata.game_version profile.metadata.game_version
)))?; )))?;
let version = &metadata.minecraft.versions[version_index];
let minecraft_updated = version_index
<= metadata
.minecraft
.versions
.iter()
.position(|x| x.id == "22w16a")
.unwrap_or(0);
let version_jar = profile let version_jar = profile
.metadata .metadata
@ -156,7 +211,7 @@ pub async fn install_minecraft(
&state, &state,
version, version,
profile.metadata.loader_version.as_ref(), profile.metadata.loader_version.as_ref(),
None, Some(repairing),
Some(&loading_bar), Some(&loading_bar),
) )
.await?; .await?;
@ -185,6 +240,8 @@ pub async fn install_minecraft(
&version_info, &version_info,
&loading_bar, &loading_bar,
&java_version.architecture, &java_version.architecture,
repairing,
minecraft_updated,
) )
.await?; .await?;
@ -325,7 +382,7 @@ pub async fn launch_minecraft(
} }
if profile.install_stage != ProfileInstallStage::Installed { if profile.install_stage != ProfileInstallStage::Installed {
install_minecraft(profile, None).await?; install_minecraft(profile, None, false).await?;
} }
let state = State::get().await?; let state = State::get().await?;
@ -334,15 +391,23 @@ pub async fn launch_minecraft(
let instance_path = profile.get_profile_full_path().await?; let instance_path = profile.get_profile_full_path().await?;
let instance_path = &io::canonicalize(instance_path)?; let instance_path = &io::canonicalize(instance_path)?;
let version = metadata let version_index = metadata
.minecraft .minecraft
.versions .versions
.iter() .iter()
.find(|it| it.id == profile.metadata.game_version) .position(|it| it.id == profile.metadata.game_version)
.ok_or(crate::ErrorKind::LauncherError(format!( .ok_or(crate::ErrorKind::LauncherError(format!(
"Invalid game version: {}", "Invalid game version: {}",
profile.metadata.game_version profile.metadata.game_version
)))?; )))?;
let version = &metadata.minecraft.versions[version_index];
let minecraft_updated = version_index
<= metadata
.minecraft
.versions
.iter()
.position(|x| x.id == "22w16a")
.unwrap_or(0);
let version_jar = profile let version_jar = profile
.metadata .metadata
@ -418,6 +483,7 @@ pub async fn launch_minecraft(
version_info.libraries.as_slice(), version_info.libraries.as_slice(),
&client_path, &client_path,
&java_version.architecture, &java_version.architecture,
minecraft_updated,
)?, )?,
&version_jar, &version_jar,
*memory, *memory,

View File

@ -322,29 +322,6 @@ pub async fn create_account(
get_creds_from_res(response, semaphore).await get_creds_from_res(response, semaphore).await
} }
pub async fn login_minecraft(
flow: &str,
semaphore: &FetchSemaphore,
) -> crate::Result<ModrinthCredentialsResult> {
let resp = fetch_advanced(
Method::POST,
&format!("{MODRINTH_API_URL}auth/login/minecraft"),
None,
Some(serde_json::json!({
"flow": flow,
})),
None,
None,
semaphore,
&CredentialsStore(None),
)
.await?;
let response = serde_json::from_slice::<HashMap<String, Value>>(&resp)?;
get_result_from_res("session", response, semaphore).await
}
pub async fn refresh_credentials( pub async fn refresh_credentials(
credentials_store: &mut CredentialsStore, credentials_store: &mut CredentialsStore,
semaphore: &FetchSemaphore, semaphore: &FetchSemaphore,

View File

@ -889,8 +889,6 @@ impl Profiles {
// Fetch online from Modrinth each latest version // Fetch online from Modrinth each latest version
future::try_join_all(modrinth_updatables.into_iter().map( future::try_join_all(modrinth_updatables.into_iter().map(
|(profile_path, linked_project)| { |(profile_path, linked_project)| {
let profile_path = profile_path;
let linked_project = linked_project;
let state = state.clone(); let state = state.clone();
async move { async move {
let creds = state.credentials.read().await; let creds = state.credentials.read().await;

View File

@ -43,7 +43,9 @@ pub async fn get_all_jre() -> Result<Vec<JavaVersion>, JREError> {
r"C:\Program Files (x86)\Eclipse Adoptium", r"C:\Program Files (x86)\Eclipse Adoptium",
]; ];
for java_path in java_paths { for java_path in java_paths {
let Ok(java_subpaths) = std::fs::read_dir(java_path) else {continue }; let Ok(java_subpaths) = std::fs::read_dir(java_path) else {
continue;
};
for java_subpath in java_subpaths.flatten() { for java_subpath in java_subpaths.flatten() {
let path = java_subpath.path(); let path = java_subpath.path();
jre_paths.insert(path.join("bin")); jre_paths.insert(path.join("bin"));
@ -97,7 +99,7 @@ pub fn get_paths_from_jre_winregkey(jre_key: RegKey) -> HashSet<PathBuf> {
for subkey_value in subkey_value_names { for subkey_value in subkey_value_names {
let path: Result<String, std::io::Error> = let path: Result<String, std::io::Error> =
subkey.get_value(subkey_value); subkey.get_value(subkey_value);
let Ok(path) = path else {continue}; let Ok(path) = path else { continue };
jre_paths.insert(PathBuf::from(path).join("bin")); jre_paths.insert(PathBuf::from(path).join("bin"));
} }
@ -264,7 +266,9 @@ pub async fn check_java_at_filepaths(
pub async fn check_java_at_filepath(path: &Path) -> Option<JavaVersion> { pub async fn check_java_at_filepath(path: &Path) -> Option<JavaVersion> {
// Attempt to canonicalize the potential java filepath // Attempt to canonicalize the potential java filepath
// If it fails, this path does not exist and None is returned (no Java here) // If it fails, this path does not exist and None is returned (no Java here)
let Ok(path) = io::canonicalize(path) else { return None }; let Ok(path) = io::canonicalize(path) else {
return None;
};
// Checks for existence of Java at this filepath // Checks for existence of Java at this filepath
// Adds JAVA_BIN to the end of the path if it is not already there // Adds JAVA_BIN to the end of the path if it is not already there

View File

@ -56,7 +56,12 @@ pub const ARCH_WIDTH: &str = "64";
pub const ARCH_WIDTH: &str = "32"; pub const ARCH_WIDTH: &str = "32";
// Platform rule handling // Platform rule handling
pub fn os_rule(rule: &OsRule, java_arch: &str) -> bool { pub fn os_rule(
rule: &OsRule,
java_arch: &str,
// Minecraft updated over 1.18.2 (supports MacOS Natively)
minecraft_updated: bool,
) -> bool {
let mut rule_match = true; let mut rule_match = true;
if let Some(ref arch) = rule.arch { if let Some(ref arch) = rule.arch {
@ -64,8 +69,14 @@ pub fn os_rule(rule: &OsRule, java_arch: &str) -> bool {
} }
if let Some(name) = &rule.name { if let Some(name) = &rule.name {
rule_match &= if minecraft_updated
&Os::native() == name || &Os::native_arch(java_arch) == name; && (name != &Os::LinuxArm64 || name != &Os::LinuxArm32)
{
rule_match &=
&Os::native() == name || &Os::native_arch(java_arch) == name;
} else {
rule_match &= &Os::native_arch(java_arch) == name;
}
} }
if let Some(version) = &rule.version { if let Some(version) = &rule.version {

View File

@ -1,6 +1,6 @@
[package] [package]
name = "theseus_cli" name = "theseus_cli"
version = "0.5.4" version = "0.6.0"
authors = ["Jai A <jaiagr+gpg@pm.me>"] authors = ["Jai A <jaiagr+gpg@pm.me>"]
edition = "2018" edition = "2018"

View File

@ -1,7 +1,7 @@
{ {
"name": "theseus_gui", "name": "theseus_gui",
"private": true, "private": true,
"version": "0.5.4", "version": "0.6.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "theseus_gui" name = "theseus_gui"
version = "0.5.4" version = "0.6.0"
description = "A Tauri App" description = "A Tauri App"
authors = ["you"] authors = ["you"]
license = "" license = ""

View File

@ -117,8 +117,8 @@ pub async fn profile_check_installed(
/// Installs/Repairs a profile /// Installs/Repairs a profile
/// invoke('plugin:profile|profile_install') /// invoke('plugin:profile|profile_install')
#[tauri::command] #[tauri::command]
pub async fn profile_install(path: ProfilePathId) -> Result<()> { pub async fn profile_install(path: ProfilePathId, force: bool) -> Result<()> {
profile::install(&path).await?; profile::install(&path, force).await?;
Ok(()) Ok(())
} }

View File

@ -8,7 +8,7 @@
}, },
"package": { "package": {
"productName": "Modrinth App", "productName": "Modrinth App",
"version": "0.5.4" "version": "0.6.0"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {

View File

@ -33,7 +33,7 @@ const themeStore = useTheming()
const initFiles = async () => { const initFiles = async () => {
const newFolders = new Map() const newFolders = new Map()
const sep = '/'; const sep = '/'
files.value = [] files.value = []
await get_pack_export_candidates(props.instance.path).then((filePaths) => await get_pack_export_candidates(props.instance.path).then((filePaths) =>
filePaths filePaths

View File

@ -72,8 +72,8 @@ export async function check_installed(path, projectId) {
} }
// Installs/Repairs a profile // Installs/Repairs a profile
export async function install(path) { export async function install(path, force) {
return await invoke('plugin:profile|profile_install', { path }) return await invoke('plugin:profile|profile_install', { path, force })
} }
// Updates all of a profile's projects // Updates all of a profile's projects

View File

@ -468,7 +468,7 @@
id="repair-profile" id="repair-profile"
color="highlight" color="highlight"
:disabled="installing || inProgress || repairing || offline" :disabled="installing || inProgress || repairing || offline"
@click="repairProfile" @click="repairProfile(true)"
> >
<HammerIcon /> Repair <HammerIcon /> Repair
</Button> </Button>
@ -755,9 +755,9 @@ async function duplicateProfile() {
}) })
} }
async function repairProfile() { async function repairProfile(force) {
repairing.value = true repairing.value = true
await install(props.instance.path).catch(handleError) await install(props.instance.path, force).catch(handleError)
repairing.value = false repairing.value = false
mixpanel_track('InstanceRepair', { mixpanel_track('InstanceRepair', {
@ -910,7 +910,7 @@ async function saveGvLoaderEdits() {
editProfile.metadata.loader_version = selectableLoaderVersions.value[loaderVersionIndex.value] editProfile.metadata.loader_version = selectableLoaderVersions.value[loaderVersionIndex.value]
} }
await edit(props.instance.path, editProfile).catch(handleError) await edit(props.instance.path, editProfile).catch(handleError)
await repairProfile() await repairProfile(false)
editing.value = false editing.value = false
changeVersionsModal.value.hide() changeVersionsModal.value.hide()