Skip to content

Commit

Permalink
Compiler improvements (#145)
Browse files Browse the repository at this point in the history
* Initial bug fixes

* fix compile error on non-mac

* Fix even more bugs

* Fix more

* fix more

* fix build

* fix build

* working basic

* removed zip

* working functions

* merge fixes

* fixed loadintg bar bug

* changed to one layer deep

* forge version numbers

* improvements + refactoring

* renamed things to fit plugin

* fixed bugs

* removed println

* overrides dont include mrpack

* merge

* fixes

* fixes

* fixed deletion

* merge errors

* force sync before export

* removed testing

* missed line

* removed console log

* mac error reverted

* incoreclty named helper

* added to new register method

* review changes

* minor changes

* moved create pack

* renamed function

---------

Co-authored-by: Jai A <[email protected]>
  • Loading branch information
thesuzerain and Geometrically authored Jun 28, 2023
1 parent 47970d9 commit f52e777
Show file tree
Hide file tree
Showing 38 changed files with 1,044 additions and 893 deletions.
28 changes: 19 additions & 9 deletions theseus/src/api/jre.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use std::path::PathBuf;

use crate::event::emit::{emit_loading, init_loading};
use crate::util::fetch::{fetch_advanced, fetch_json};
use crate::util::jre::extract_java_majorminor_version;
use crate::{
state::JavaGlobals,
util::jre::{self, extract_java_majorminor_version, JavaVersion},
util::jre::{self, JavaVersion},
LoadingBarType, State,
};

Expand All @@ -16,12 +17,15 @@ pub const JAVA_17_KEY: &str = "JAVA_17";
pub const JAVA_18PLUS_KEY: &str = "JAVA_18PLUS";

// Autodetect JavaSettings default
// Using the supplied JavaVersions, autodetects the default JavaSettings
// Make a guess for what the default Java global settings should be
pub async fn autodetect_java_globals() -> crate::Result<JavaGlobals> {
let mut java_8 = find_filtered_jres("1.8").await?;
let mut java_17 = find_filtered_jres("1.17").await?;
let mut java_18plus = find_filtered_jres("1.18").await?;

// Since the JRE paths are passed in as args, this handles the logic for selection. Currently this just pops the last one found
// TODO: When tauri compiler issue is fixed, this can be be improved (ie: getting JREs in-function)
pub async fn autodetect_java_globals(
mut java_8: Vec<JavaVersion>,
mut java_17: Vec<JavaVersion>,
mut java_18plus: Vec<JavaVersion>,
) -> crate::Result<JavaGlobals> {
// Simply select last one found for initial guess
let mut java_globals = JavaGlobals::new();
if let Some(jre) = java_8.pop() {
Expand All @@ -38,18 +42,24 @@ pub async fn autodetect_java_globals() -> crate::Result<JavaGlobals> {
}

// Searches for jres on the system given a java version (ex: 1.8, 1.17, 1.18)
// Allow higher allows for versions higher than the given version to be returned ('at least')
pub async fn find_filtered_jres(
version: &str,
jres: Vec<JavaVersion>,
allow_higher: bool,
) -> crate::Result<Vec<JavaVersion>> {
let version = extract_java_majorminor_version(version)?;
let jres = jre::get_all_jre().await?;

// 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
if allow_higher {
jre_version >= version
} else {
jre_version == version
}
} else {
false
}
Expand Down
266 changes: 35 additions & 231 deletions theseus/src/api/pack.rs → theseus/src/api/pack/install.rs
Original file line number Diff line number Diff line change
@@ -1,247 +1,53 @@
use crate::config::MODRINTH_API_URL;
use crate::data::ModLoader;
use crate::event::emit::{
emit_loading, init_loading, init_or_edit_loading,
loading_try_for_each_concurrent,
};
use crate::event::{LoadingBarId, LoadingBarType};
use crate::state::{
LinkedData, ModrinthProject, ModrinthVersion, ProfileInstallStage, SideType,
};
use crate::util::fetch::{
fetch, fetch_advanced, fetch_json, fetch_mirrors, write, write_cached_icon,
emit_loading, init_or_edit_loading, loading_try_for_each_concurrent,
};
use crate::event::LoadingBarType;
use crate::pack::install_from::{EnvType, PackFile, PackFileHash};
use crate::state::{LinkedData, ProfileInstallStage, SideType};
use crate::util::fetch::{fetch_mirrors, write};
use crate::State;
use async_zip::tokio::read::seek::ZipFileReader;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

use std::io::Cursor;
use std::path::{Component, PathBuf};
use tokio::fs;

#[derive(Serialize, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PackFormat {
pub game: String,
pub format_version: i32,
pub version_id: String,
pub name: String,
pub summary: Option<String>,
pub files: Vec<PackFile>,
pub dependencies: HashMap<PackDependency, String>,
}

#[derive(Serialize, Deserialize, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PackFile {
pub path: String,
pub hashes: HashMap<PackFileHash, String>,
pub env: Option<HashMap<EnvType, SideType>>,
pub downloads: Vec<String>,
pub file_size: u32,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "camelCase", from = "String")]
pub enum PackFileHash {
Sha1,
Sha512,
Unknown(String),
}

impl From<String> for PackFileHash {
fn from(s: String) -> Self {
return match s.as_str() {
"sha1" => PackFileHash::Sha1,
"sha512" => PackFileHash::Sha512,
_ => PackFileHash::Unknown(s),
};
}
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "camelCase")]
pub enum EnvType {
Client,
Server,
}

#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum PackDependency {
Forge,
FabricLoader,
QuiltLoader,
Minecraft,
}
use super::install_from::{
generate_pack_from_file, generate_pack_from_version_id,
CreatePackDescription, CreatePackLocation, PackDependency, PackFormat,
};

#[tracing::instrument]
#[theseus_macros::debug_pin]
pub async fn install_pack_from_version_id(
project_id: String,
version_id: String,
title: String,
icon_url: Option<String>,
pub async fn install_pack(
location: CreatePackLocation,
profile: PathBuf,
) -> crate::Result<PathBuf> {
let state = State::get().await?;
let profile = crate::api::profile_create::profile_create(
title.clone(),
"1.19.4".to_string(),
ModLoader::Vanilla,
None,
None,
icon_url.clone(),
Some(LinkedData {
project_id: Some(project_id),
version_id: Some(version_id.clone()),
}),
Some(true),
)
.await?;

let loading_bar = init_loading(
LoadingBarType::PackFileDownload {
profile_path: profile.clone(),
pack_name: title,
icon: icon_url,
pack_version: version_id.clone(),
},
100.0,
"Downloading pack file",
)
.await?;

emit_loading(&loading_bar, 0.0, Some("Fetching version")).await?;
let version: ModrinthVersion = fetch_json(
Method::GET,
&format!("{}version/{}", MODRINTH_API_URL, version_id),
None,
None,
&state.fetch_semaphore,
)
.await?;
emit_loading(&loading_bar, 10.0, None).await?;

let (url, hash) =
if let Some(file) = version.files.iter().find(|x| x.primary) {
Some((file.url.clone(), file.hashes.get("sha1")))
} else {
version
.files
.first()
.map(|file| (file.url.clone(), file.hashes.get("sha1")))
}
.ok_or_else(|| {
crate::ErrorKind::InputError(
"Specified version has no files".to_string(),
// Get file from description
let description: CreatePackDescription = match location {
CreatePackLocation::FromVersionId {
project_id,
version_id,
title,
icon_url,
} => {
generate_pack_from_version_id(
project_id, version_id, title, icon_url, profile,
)
})?;

let file = fetch_advanced(
Method::GET,
&url,
hash.map(|x| &**x),
None,
None,
Some((&loading_bar, 70.0)),
&state.fetch_semaphore,
)
.await?;
emit_loading(&loading_bar, 0.0, Some("Fetching project metadata")).await?;

let project: ModrinthProject = fetch_json(
Method::GET,
&format!("{}project/{}", MODRINTH_API_URL, version.project_id),
None,
None,
&state.fetch_semaphore,
)
.await?;

emit_loading(&loading_bar, 10.0, Some("Retrieving icon")).await?;
let icon = if let Some(icon_url) = project.icon_url {
let state = State::get().await?;
let icon_bytes = fetch(&icon_url, None, &state.fetch_semaphore).await?;

let filename = icon_url.rsplit('/').next();

if let Some(filename) = filename {
Some(
write_cached_icon(
filename,
&state.directories.caches_dir(),
icon_bytes,
&state.io_semaphore,
)
.await?,
)
} else {
None
.await?
}
CreatePackLocation::FromFile { path } => {
generate_pack_from_file(path, profile).await?
}
} else {
None
};
emit_loading(&loading_bar, 10.0, None).await?;

install_pack(
file,
icon,
Some(project.title),
Some(version.project_id),
Some(version.id),
Some(loading_bar),
profile,
)
.await
}

#[tracing::instrument]
#[theseus_macros::debug_pin]
pub async fn install_pack_from_file(path: PathBuf) -> crate::Result<PathBuf> {
let file = fs::read(&path).await?;

let file_name = path
.file_name()
.unwrap_or_default()
.to_string_lossy()
.to_string();

let profile = crate::api::profile_create::profile_create(
file_name,
"1.19.4".to_string(),
ModLoader::Vanilla,
None,
None,
None,
None,
Some(true),
)
.await?;

install_pack(
bytes::Bytes::from(file),
None,
None,
None,
None,
None,
profile,
)
.await
}
let file = description.file;
let icon = description.icon;
let override_title = description.override_title;
let project_id = description.project_id;
let version_id = description.version_id;
let existing_loading_bar = description.existing_loading_bar;
let profile = description.profile;

#[tracing::instrument(skip(file))]
#[theseus_macros::debug_pin]
async fn install_pack(
file: bytes::Bytes,
icon: Option<PathBuf>,
override_title: Option<String>,
project_id: Option<String>,
version_id: Option<String>,
existing_loading_bar: Option<LoadingBarId>,
profile: PathBuf,
) -> crate::Result<PathBuf> {
let state = &State::get().await?;

let result = async {
Expand Down Expand Up @@ -299,9 +105,7 @@ async fn install_pack(
mod_loader = Some(ModLoader::Quilt);
loader_version = Some(value);
}
PackDependency::Minecraft => {
game_version = Some(value.clone())
}
PackDependency::Minecraft => game_version = Some(value),
}
}

Expand Down
Loading

0 comments on commit f52e777

Please sign in to comment.