You've already forked AstralRinth
forked from didirus/AstralRinth
Navbar wireup (#98)
* Navbar wireup * Fix height issue * Fix syncing * working branch * Added root directories to breadcrumbs * fix jre detect --------- Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
@@ -69,8 +69,8 @@ pub async fn get_optimal_jre_key(profile: &Profile) -> crate::Result<String> {
|
||||
.map(|it| it.major_version)
|
||||
.unwrap_or(0)
|
||||
{
|
||||
0..=16 => JAVA_8_KEY.to_string(),
|
||||
17 => JAVA_17_KEY.to_string(),
|
||||
0..=15 => JAVA_8_KEY.to_string(),
|
||||
16..=17 => JAVA_17_KEY.to_string(),
|
||||
_ => JAVA_18PLUS_KEY.to_string(),
|
||||
};
|
||||
Ok(optimal_key)
|
||||
|
||||
@@ -136,18 +136,26 @@ pub async fn install_pack_from_version_id(
|
||||
None
|
||||
};
|
||||
|
||||
install_pack(file, icon, Some(version.project_id), Some(version.id)).await
|
||||
install_pack(
|
||||
file,
|
||||
icon,
|
||||
Some(project.title),
|
||||
Some(version.project_id),
|
||||
Some(version.id),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn install_pack_from_file(path: PathBuf) -> crate::Result<PathBuf> {
|
||||
let file = fs::read(path).await?;
|
||||
|
||||
install_pack(bytes::Bytes::from(file), None, None, None).await
|
||||
install_pack(bytes::Bytes::from(file), None, None, None, None).await
|
||||
}
|
||||
|
||||
async fn install_pack(
|
||||
file: bytes::Bytes,
|
||||
icon: Option<PathBuf>,
|
||||
override_title: Option<String>,
|
||||
project_id: Option<String>,
|
||||
version_id: Option<String>,
|
||||
) -> crate::Result<PathBuf> {
|
||||
@@ -192,7 +200,7 @@ async fn install_pack(
|
||||
let mut game_version = None;
|
||||
let mut mod_loader = None;
|
||||
let mut loader_version = None;
|
||||
for (key, value) in pack.dependencies {
|
||||
for (key, value) in &pack.dependencies {
|
||||
match key {
|
||||
PackDependency::Forge => {
|
||||
mod_loader = Some(ModLoader::Forge);
|
||||
@@ -219,13 +227,11 @@ async fn install_pack(
|
||||
.into());
|
||||
};
|
||||
|
||||
let pack_name = pack.name.clone();
|
||||
|
||||
let profile = crate::api::profile_create::profile_create(
|
||||
pack.name,
|
||||
let profile_raw = crate::api::profile_create::profile_create(
|
||||
override_title.unwrap_or_else(|| pack.name.clone()),
|
||||
game_version.clone(),
|
||||
mod_loader.unwrap_or(ModLoader::Vanilla),
|
||||
loader_version,
|
||||
loader_version.cloned(),
|
||||
icon,
|
||||
Some(LinkedData {
|
||||
project_id: project_id.clone(),
|
||||
@@ -234,141 +240,167 @@ async fn install_pack(
|
||||
Some(true),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let loading_bar = init_loading(
|
||||
LoadingBarType::PackDownload {
|
||||
pack_name,
|
||||
pack_id: project_id,
|
||||
pack_version: version_id,
|
||||
},
|
||||
100.0,
|
||||
"Downloading modpack...",
|
||||
)
|
||||
.await?;
|
||||
|
||||
let num_files = pack.files.len();
|
||||
use futures::StreamExt;
|
||||
loading_try_for_each_concurrent(
|
||||
futures::stream::iter(pack.files.into_iter())
|
||||
.map(Ok::<PackFile, crate::Error>),
|
||||
None,
|
||||
Some(&loading_bar),
|
||||
80.0,
|
||||
num_files,
|
||||
None,
|
||||
|project| {
|
||||
let profile = profile.clone();
|
||||
async move {
|
||||
//TODO: Future update: prompt user for optional files in a modpack
|
||||
if let Some(env) = project.env {
|
||||
if env
|
||||
.get(&EnvType::Client)
|
||||
.map(|x| x == &SideType::Unsupported)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
let file = fetch_mirrors(
|
||||
&project
|
||||
.downloads
|
||||
.iter()
|
||||
.map(|x| &**x)
|
||||
.collect::<Vec<&str>>(),
|
||||
project.hashes.get(&PackFileHash::Sha1).map(|x| &**x),
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let path =
|
||||
std::path::Path::new(&project.path).components().next();
|
||||
if let Some(path) = path {
|
||||
match path {
|
||||
Component::CurDir | Component::Normal(_) => {
|
||||
let path = profile.join(project.path);
|
||||
write(&path, &file, &state.io_semaphore)
|
||||
.await?;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
let extract_overrides = |overrides: String| async {
|
||||
let reader = Cursor::new(&file);
|
||||
|
||||
let mut overrides_zip =
|
||||
ZipFileReader::new(reader).await.map_err(|_| {
|
||||
crate::Error::from(crate::ErrorKind::InputError(
|
||||
"Failed extract overrides Zip".to_string(),
|
||||
))
|
||||
})?;
|
||||
|
||||
let profile = profile.clone();
|
||||
async move {
|
||||
for index in 0..overrides_zip.file().entries().len() {
|
||||
let file = overrides_zip
|
||||
.file()
|
||||
.entries()
|
||||
.get(index)
|
||||
.unwrap()
|
||||
.entry()
|
||||
.clone();
|
||||
|
||||
let file_path = PathBuf::from(file.filename());
|
||||
if file.filename().starts_with(&overrides)
|
||||
&& !file.filename().ends_with('/')
|
||||
{
|
||||
// Reads the file into the 'content' variable
|
||||
let mut content = Vec::new();
|
||||
let mut reader = overrides_zip.entry(index).await?;
|
||||
reader.read_to_end_checked(&mut content, &file).await?;
|
||||
|
||||
let mut new_path = PathBuf::new();
|
||||
let components = file_path.components().skip(1);
|
||||
|
||||
for component in components {
|
||||
new_path.push(component);
|
||||
}
|
||||
|
||||
if new_path.file_name().is_some() {
|
||||
write(
|
||||
&profile.join(new_path),
|
||||
&content,
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<(), crate::Error>(())
|
||||
}
|
||||
.await
|
||||
};
|
||||
|
||||
emit_loading(&loading_bar, 0.05, Some("Extracting overrides")).await?;
|
||||
extract_overrides("overrides".to_string()).await?;
|
||||
extract_overrides("client_overrides".to_string()).await?;
|
||||
emit_loading(&loading_bar, 0.1, Some("Done extacting overrides"))
|
||||
let profile = profile_raw.clone();
|
||||
let result = async {
|
||||
let loading_bar = init_loading(
|
||||
LoadingBarType::PackDownload {
|
||||
pack_name: pack.name.clone(),
|
||||
pack_id: project_id,
|
||||
pack_version: version_id,
|
||||
},
|
||||
100.0,
|
||||
"Downloading modpack...",
|
||||
)
|
||||
.await?;
|
||||
|
||||
super::profile::sync(&profile).await?;
|
||||
let num_files = pack.files.len();
|
||||
use futures::StreamExt;
|
||||
loading_try_for_each_concurrent(
|
||||
futures::stream::iter(pack.files.into_iter())
|
||||
.map(Ok::<PackFile, crate::Error>),
|
||||
None,
|
||||
Some(&loading_bar),
|
||||
80.0,
|
||||
num_files,
|
||||
None,
|
||||
|project| {
|
||||
let profile = profile.clone();
|
||||
async move {
|
||||
//TODO: Future update: prompt user for optional files in a modpack
|
||||
if let Some(env) = project.env {
|
||||
if env
|
||||
.get(&EnvType::Client)
|
||||
.map(|x| x == &SideType::Unsupported)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(profile) = crate::api::profile::get(&profile).await? {
|
||||
crate::launcher::install_minecraft(&profile, Some(loading_bar))
|
||||
let file = fetch_mirrors(
|
||||
&project
|
||||
.downloads
|
||||
.iter()
|
||||
.map(|x| &**x)
|
||||
.collect::<Vec<&str>>(),
|
||||
project
|
||||
.hashes
|
||||
.get(&PackFileHash::Sha1)
|
||||
.map(|x| &**x),
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let path = std::path::Path::new(&project.path)
|
||||
.components()
|
||||
.next();
|
||||
if let Some(path) = path {
|
||||
match path {
|
||||
Component::CurDir | Component::Normal(_) => {
|
||||
let path = profile.join(project.path);
|
||||
write(&path, &file, &state.io_semaphore)
|
||||
.await?;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
let extract_overrides = |overrides: String| async {
|
||||
let reader = Cursor::new(&file);
|
||||
|
||||
let mut overrides_zip =
|
||||
ZipFileReader::new(reader).await.map_err(|_| {
|
||||
crate::Error::from(crate::ErrorKind::InputError(
|
||||
"Failed extract overrides Zip".to_string(),
|
||||
))
|
||||
})?;
|
||||
|
||||
let profile = profile.clone();
|
||||
async move {
|
||||
for index in 0..overrides_zip.file().entries().len() {
|
||||
let file = overrides_zip
|
||||
.file()
|
||||
.entries()
|
||||
.get(index)
|
||||
.unwrap()
|
||||
.entry()
|
||||
.clone();
|
||||
|
||||
let file_path = PathBuf::from(file.filename());
|
||||
if file.filename().starts_with(&overrides)
|
||||
&& !file.filename().ends_with('/')
|
||||
{
|
||||
// Reads the file into the 'content' variable
|
||||
let mut content = Vec::new();
|
||||
let mut reader = overrides_zip.entry(index).await?;
|
||||
reader
|
||||
.read_to_end_checked(&mut content, &file)
|
||||
.await?;
|
||||
|
||||
let mut new_path = PathBuf::new();
|
||||
let components = file_path.components().skip(1);
|
||||
|
||||
for component in components {
|
||||
new_path.push(component);
|
||||
}
|
||||
|
||||
if new_path.file_name().is_some() {
|
||||
write(
|
||||
&profile.join(new_path),
|
||||
&content,
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<(), crate::Error>(())
|
||||
}
|
||||
.await
|
||||
};
|
||||
|
||||
emit_loading(&loading_bar, 0.05, Some("Extracting overrides"))
|
||||
.await?;
|
||||
} else {
|
||||
extract_overrides("overrides".to_string()).await?;
|
||||
extract_overrides("client_overrides".to_string()).await?;
|
||||
emit_loading(&loading_bar, 0.1, Some("Done extacting overrides"))
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(profile)
|
||||
if let Some(profile) = crate::api::profile::get(&profile).await? {
|
||||
tokio::try_join!(
|
||||
super::profile::sync(&profile.path),
|
||||
crate::launcher::install_minecraft(
|
||||
&profile,
|
||||
Some(loading_bar)
|
||||
),
|
||||
)?;
|
||||
} else {
|
||||
emit_loading(
|
||||
&loading_bar,
|
||||
0.1,
|
||||
Some("Done extacting overrides"),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok::<PathBuf, crate::Error>(profile)
|
||||
}
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(profile) => Ok(profile),
|
||||
Err(err) => {
|
||||
let _ = crate::api::profile::remove(&profile_raw).await;
|
||||
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(crate::Error::from(crate::ErrorKind::InputError(
|
||||
"No pack manifest found in mrpack".to_string(),
|
||||
|
||||
@@ -136,6 +136,7 @@ pub fn get_jvm_arguments(
|
||||
parsed_arguments.push(arg);
|
||||
}
|
||||
}
|
||||
parsed_arguments.push("-Dorg.lwjgl.util.Debug=true".to_string());
|
||||
|
||||
Ok(parsed_arguments)
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ pub async fn download_libraries(
|
||||
library
|
||||
.natives
|
||||
.as_ref()?
|
||||
.get(&Os::native())?,
|
||||
.get(&Os::native_arch())?,
|
||||
library
|
||||
.downloads
|
||||
.as_ref()?
|
||||
|
||||
@@ -4,6 +4,7 @@ use crate::event::LoadingBarType;
|
||||
use crate::{
|
||||
process,
|
||||
state::{self as st, MinecraftChild},
|
||||
State,
|
||||
};
|
||||
use daedalus as d;
|
||||
use dunce::canonicalize;
|
||||
@@ -55,7 +56,7 @@ pub async fn install_minecraft(
|
||||
profile: &Profile,
|
||||
existing_loading_bar: Option<Uuid>,
|
||||
) -> crate::Result<()> {
|
||||
let state = st::State::get().await?;
|
||||
let state = State::get().await?;
|
||||
let instance_path = &canonicalize(&profile.path)?;
|
||||
let metadata = state.metadata.read().await;
|
||||
|
||||
@@ -98,7 +99,6 @@ pub async fn install_minecraft(
|
||||
.await?;
|
||||
|
||||
download::download_minecraft(&state, &version_info, loading_bar).await?;
|
||||
st::State::sync().await?;
|
||||
|
||||
let client_path = state
|
||||
.directories
|
||||
@@ -201,7 +201,7 @@ pub async fn install_minecraft(
|
||||
async { Ok(()) }
|
||||
})
|
||||
.await?;
|
||||
crate::api::profile::sync(&profile.path).await?;
|
||||
State::sync().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -327,7 +327,7 @@ pub async fn launch_minecraft(
|
||||
let mut state_children = state.children.write().await;
|
||||
state_children
|
||||
.insert_process(
|
||||
uuid::Uuid::new_v4(),
|
||||
Uuid::new_v4(),
|
||||
instance_path.to_path_buf(),
|
||||
command,
|
||||
post_exit_hook,
|
||||
@@ -337,9 +337,11 @@ pub async fn launch_minecraft(
|
||||
|
||||
fn clear_cargo_env_vals(command: &mut Command) -> &mut Command {
|
||||
for (key, _) in std::env::vars() {
|
||||
if key.starts_with("CARGO") {
|
||||
command.env_remove(key);
|
||||
}
|
||||
command.env_remove(key);
|
||||
|
||||
// if key.starts_with("CARGO") {
|
||||
// command.env_remove(key);
|
||||
// }
|
||||
}
|
||||
command
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Theseus metadata
|
||||
use crate::data::DirectoryInfo;
|
||||
use crate::util::fetch::{read_json, write};
|
||||
use crate::State;
|
||||
use daedalus::{
|
||||
minecraft::{fetch_version_manifest, VersionManifest as MinecraftManifest},
|
||||
modded::{
|
||||
@@ -96,7 +97,7 @@ impl Metadata {
|
||||
pub async fn update() {
|
||||
let res = async {
|
||||
let metadata_fetch = Metadata::fetch().await?;
|
||||
let state = crate::State::get().await?;
|
||||
let state = State::get().await?;
|
||||
|
||||
let metadata_path =
|
||||
state.directories.caches_meta_dir().join("metadata.json");
|
||||
|
||||
@@ -164,7 +164,8 @@ impl Profile {
|
||||
|
||||
let paths = self.get_profile_project_paths()?;
|
||||
let projects = crate::state::infer_data_from_files(
|
||||
&[(self.clone(), paths)],
|
||||
self.clone(),
|
||||
paths,
|
||||
state.directories.caches_dir(),
|
||||
&state.io_semaphore,
|
||||
)
|
||||
@@ -386,31 +387,28 @@ impl Profiles {
|
||||
}
|
||||
}
|
||||
|
||||
if !files.is_empty() {
|
||||
let inferred = super::projects::infer_data_from_files(
|
||||
&files,
|
||||
state.directories.caches_dir(),
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
let mut wipe_profiles = Vec::new();
|
||||
for (key, value) in inferred {
|
||||
if let Some((profile, _)) =
|
||||
files.iter().find(|(_, files)| files.contains(&key))
|
||||
future::try_join_all(files.into_iter().map(
|
||||
|(profile, files)| async {
|
||||
let profile_path = profile.path.clone();
|
||||
let inferred = super::projects::infer_data_from_files(
|
||||
profile,
|
||||
files,
|
||||
state.directories.caches_dir(),
|
||||
&state.io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut new_profiles = state.profiles.write().await;
|
||||
if let Some(profile) = new_profiles.0.get_mut(&profile_path)
|
||||
{
|
||||
let mut new_profiles = state.profiles.write().await;
|
||||
if let Some(profile) =
|
||||
new_profiles.0.get_mut(&profile.path)
|
||||
{
|
||||
if !wipe_profiles.contains(&profile.path) {
|
||||
profile.projects = HashMap::new();
|
||||
wipe_profiles.push(profile.path.clone());
|
||||
}
|
||||
profile.projects.insert(key, value);
|
||||
}
|
||||
profile.projects = inferred;
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(new_profiles);
|
||||
|
||||
Ok::<(), crate::Error>(())
|
||||
},
|
||||
))
|
||||
.await?;
|
||||
|
||||
Ok::<(), crate::Error>(())
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! Project management + inference
|
||||
|
||||
use crate::config::MODRINTH_API_URL;
|
||||
use crate::data::ModLoader;
|
||||
use crate::state::Profile;
|
||||
use crate::util::fetch::{fetch_json, write_cached_icon};
|
||||
use async_zip::tokio::read::fs::ZipFileReader;
|
||||
@@ -250,36 +249,51 @@ async fn read_icon_from_file(
|
||||
}
|
||||
|
||||
pub async fn infer_data_from_files(
|
||||
paths: &[(Profile, Vec<PathBuf>)],
|
||||
profile: Profile,
|
||||
paths: Vec<PathBuf>,
|
||||
cache_dir: PathBuf,
|
||||
io_semaphore: &RwLock<Semaphore>,
|
||||
) -> crate::Result<HashMap<PathBuf, Project>> {
|
||||
let mut file_path_hashes = HashMap::new();
|
||||
|
||||
// TODO: Make this concurrent and use progressive hashing to avoid loading each JAR in memory
|
||||
for set in paths {
|
||||
for path in &set.1 {
|
||||
let mut file = tokio::fs::File::open(path.clone()).await?;
|
||||
for path in paths {
|
||||
let mut file = tokio::fs::File::open(path.clone()).await?;
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
file.read_to_end(&mut buffer).await?;
|
||||
let mut buffer = Vec::new();
|
||||
file.read_to_end(&mut buffer).await?;
|
||||
|
||||
let hash = format!("{:x}", sha2::Sha512::digest(&buffer));
|
||||
file_path_hashes.insert(hash, path.clone());
|
||||
}
|
||||
let hash = format!("{:x}", sha2::Sha512::digest(&buffer));
|
||||
file_path_hashes.insert(hash, path.clone());
|
||||
}
|
||||
|
||||
let files: HashMap<String, ModrinthVersion> = fetch_json(
|
||||
Method::POST,
|
||||
&format!("{}version_files", MODRINTH_API_URL),
|
||||
None,
|
||||
Some(json!({
|
||||
"hashes": file_path_hashes.keys().collect::<Vec<_>>(),
|
||||
"algorithm": "sha512",
|
||||
})),
|
||||
io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
let files_url = format!("{}version_files", MODRINTH_API_URL);
|
||||
let updates_url = format!("{}version_files/update", MODRINTH_API_URL);
|
||||
let (files, update_versions) = tokio::try_join!(
|
||||
fetch_json::<HashMap<String, ModrinthVersion>>(
|
||||
Method::POST,
|
||||
&files_url,
|
||||
None,
|
||||
Some(json!({
|
||||
"hashes": file_path_hashes.keys().collect::<Vec<_>>(),
|
||||
"algorithm": "sha512",
|
||||
})),
|
||||
io_semaphore,
|
||||
),
|
||||
fetch_json::<HashMap<String, ModrinthVersion>>(
|
||||
Method::POST,
|
||||
&updates_url,
|
||||
None,
|
||||
Some(json!({
|
||||
"hashes": file_path_hashes.keys().collect::<Vec<_>>(),
|
||||
"algorithm": "sha512",
|
||||
"loaders": [profile.metadata.loader],
|
||||
"game_versions": [profile.metadata.game_version]
|
||||
})),
|
||||
io_semaphore,
|
||||
)
|
||||
)?;
|
||||
|
||||
let projects: Vec<ModrinthProject> = fetch_json(
|
||||
Method::GET,
|
||||
&format!(
|
||||
@@ -297,6 +311,7 @@ pub async fn infer_data_from_files(
|
||||
io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let teams: Vec<ModrinthTeamMember> = fetch_json::<
|
||||
Vec<Vec<ModrinthTeamMember>>,
|
||||
>(
|
||||
@@ -317,26 +332,6 @@ pub async fn infer_data_from_files(
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let mut update_versions: Vec<ModrinthVersion> = fetch_json(
|
||||
Method::GET,
|
||||
&format!(
|
||||
"{}versions?ids={}",
|
||||
MODRINTH_API_URL,
|
||||
serde_json::to_string(
|
||||
&projects
|
||||
.iter()
|
||||
.flat_map(|x| x.versions.clone())
|
||||
.collect::<Vec<String>>()
|
||||
)?
|
||||
),
|
||||
None,
|
||||
None,
|
||||
io_semaphore,
|
||||
)
|
||||
.await?;
|
||||
|
||||
update_versions.sort_by(|a, b| b.date_published.cmp(&a.date_published));
|
||||
|
||||
let mut return_projects = HashMap::new();
|
||||
let mut further_analyze_projects: Vec<(String, PathBuf)> = Vec::new();
|
||||
|
||||
@@ -345,8 +340,6 @@ pub async fn infer_data_from_files(
|
||||
if let Some(project) =
|
||||
projects.iter().find(|x| version.project_id == x.id)
|
||||
{
|
||||
let profile = paths.iter().find(|x| x.1.contains(&path));
|
||||
|
||||
let file_name = path
|
||||
.file_name()
|
||||
.unwrap_or_default()
|
||||
@@ -356,7 +349,6 @@ pub async fn infer_data_from_files(
|
||||
return_projects.insert(
|
||||
path,
|
||||
Project {
|
||||
sha512: hash,
|
||||
disabled: false,
|
||||
metadata: ProjectMetadata::Modrinth {
|
||||
project: Box::new(project.clone()),
|
||||
@@ -366,48 +358,25 @@ pub async fn infer_data_from_files(
|
||||
.filter(|x| x.team_id == project.team)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>(),
|
||||
update_version: if let Some((profile, _)) = &profile
|
||||
update_version: if let Some(val) =
|
||||
update_versions.get(&hash)
|
||||
{
|
||||
update_versions
|
||||
.iter()
|
||||
.find(|x| {
|
||||
x.project_id == project.id
|
||||
&& x.game_versions.contains(
|
||||
&profile.metadata.game_version,
|
||||
)
|
||||
&& if profile.metadata.loader
|
||||
== ModLoader::Vanilla
|
||||
{
|
||||
true
|
||||
} else {
|
||||
x.loaders.contains(
|
||||
&profile
|
||||
.metadata
|
||||
.loader
|
||||
.as_api_str()
|
||||
.to_string(),
|
||||
)
|
||||
}
|
||||
})
|
||||
.cloned()
|
||||
.map(Box::new)
|
||||
Some(Box::new(val.clone()))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
incompatible: if let Some((profile, _)) = &profile {
|
||||
!version.loaders.contains(
|
||||
&profile
|
||||
.metadata
|
||||
.loader
|
||||
.as_api_str()
|
||||
.to_string(),
|
||||
) || version
|
||||
.game_versions
|
||||
.contains(&profile.metadata.game_version)
|
||||
} else {
|
||||
false
|
||||
},
|
||||
|
||||
incompatible: !version.loaders.contains(
|
||||
&profile
|
||||
.metadata
|
||||
.loader
|
||||
.as_api_str()
|
||||
.to_string(),
|
||||
) || version
|
||||
.game_versions
|
||||
.contains(&profile.metadata.game_version),
|
||||
},
|
||||
sha512: hash,
|
||||
file_name,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -6,10 +6,63 @@ use regex::Regex;
|
||||
pub trait OsExt {
|
||||
/// Get the OS of the current system
|
||||
fn native() -> Self;
|
||||
|
||||
/// Gets the OS + Arch of the current system
|
||||
fn native_arch() -> Self;
|
||||
}
|
||||
|
||||
impl OsExt for Os {
|
||||
fn native_arch() -> Self {
|
||||
if std::env::consts::OS == "windows" {
|
||||
if std::env::consts::ARCH == "aarch64" {
|
||||
Os::WindowsArm64
|
||||
} else {
|
||||
Os::Windows
|
||||
}
|
||||
} else if std::env::consts::OS == "linux" {
|
||||
if std::env::consts::ARCH == "aarch64" {
|
||||
Os::LinuxArm64
|
||||
} else if std::env::consts::ARCH == "arm" {
|
||||
Os::LinuxArm32
|
||||
} else {
|
||||
Os::Linux
|
||||
}
|
||||
} else if std::env::consts::OS == "macos" {
|
||||
if std::env::consts::ARCH == "aarch64" {
|
||||
Os::OsxArm64
|
||||
} else {
|
||||
Os::Osx
|
||||
}
|
||||
} else {
|
||||
Os::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
fn native() -> Self {
|
||||
if std::env::consts::OS == "windows" {
|
||||
if std::env::consts::ARCH == "aarch64" {
|
||||
Os::WindowsArm64
|
||||
} else {
|
||||
Os::Windows
|
||||
}
|
||||
} else if std::env::consts::OS == "linux" {
|
||||
if std::env::consts::ARCH == "aarch64" {
|
||||
Os::LinuxArm64
|
||||
} else if std::env::consts::ARCH == "arm" {
|
||||
Os::LinuxArm32
|
||||
} else {
|
||||
Os::Linux
|
||||
}
|
||||
} else if std::env::consts::OS == "macos" {
|
||||
if std::env::consts::ARCH == "aarch64" {
|
||||
Os::OsxArm64
|
||||
} else {
|
||||
Os::Osx
|
||||
}
|
||||
} else {
|
||||
Os::Unknown
|
||||
};
|
||||
|
||||
match std::env::consts::OS {
|
||||
"windows" => Self::Windows,
|
||||
"macos" => Self::Osx,
|
||||
@@ -35,7 +88,7 @@ pub fn os_rule(rule: &OsRule) -> bool {
|
||||
}
|
||||
|
||||
if let Some(name) = &rule.name {
|
||||
rule_match &= &Os::native() == name;
|
||||
rule_match &= &Os::native() == name || &Os::native_arch() == name;
|
||||
}
|
||||
|
||||
if let Some(version) = &rule.version {
|
||||
@@ -49,8 +102,13 @@ pub fn os_rule(rule: &OsRule) -> bool {
|
||||
}
|
||||
|
||||
pub fn classpath_separator() -> &'static str {
|
||||
match Os::native() {
|
||||
Os::Osx | Os::Linux | Os::Unknown => ":",
|
||||
Os::Windows => ";",
|
||||
match Os::native_arch() {
|
||||
Os::Osx
|
||||
| Os::OsxArm64
|
||||
| Os::Linux
|
||||
| Os::LinuxArm32
|
||||
| Os::LinuxArm64
|
||||
| Os::Unknown => ":",
|
||||
Os::Windows | Os::WindowsArm64 => ";",
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user