Initial bug fixes (#127)

* Initial bug fixes

* fix compile error on non-mac

* Fix even more bugs

* Fix more

* fix more

* fix build

* fix build

* address review comments
This commit is contained in:
Geometrically
2023-06-02 07:09:46 -07:00
committed by GitHub
parent 9ea548cfe3
commit ee61951698
57 changed files with 3823 additions and 2813 deletions

View File

@@ -79,6 +79,7 @@ enum PackDependency {
#[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>,
@@ -91,7 +92,10 @@ pub async fn install_pack_from_version_id(
None,
None,
icon_url.clone(),
None,
Some(LinkedData {
project_id: Some(project_id),
version_id: Some(version_id.clone()),
}),
Some(true),
)
.await?;
@@ -240,261 +244,277 @@ async fn install_pack(
) -> crate::Result<PathBuf> {
let state = &State::get().await?;
let reader: Cursor<&bytes::Bytes> = Cursor::new(&file);
let result = async {
let reader: Cursor<&bytes::Bytes> = Cursor::new(&file);
// Create zip reader around file
let mut zip_reader = ZipFileReader::new(reader).await.map_err(|_| {
crate::Error::from(crate::ErrorKind::InputError(
"Failed to read input modpack zip".to_string(),
))
})?;
// Create zip reader around file
let mut zip_reader =
ZipFileReader::new(reader).await.map_err(|_| {
crate::Error::from(crate::ErrorKind::InputError(
"Failed to read input modpack zip".to_string(),
))
})?;
// Extract index of modrinth.index.json
let zip_index_option = zip_reader
.file()
.entries()
.iter()
.position(|f| f.entry().filename() == "modrinth.index.json");
if let Some(zip_index) = zip_index_option {
let mut manifest = String::new();
let entry = zip_reader
// Extract index of modrinth.index.json
let zip_index_option = zip_reader
.file()
.entries()
.get(zip_index)
.unwrap()
.entry()
.clone();
let mut reader = zip_reader.entry(zip_index).await?;
reader.read_to_string_checked(&mut manifest, &entry).await?;
.iter()
.position(|f| f.entry().filename() == "modrinth.index.json");
if let Some(zip_index) = zip_index_option {
let mut manifest = String::new();
let entry = zip_reader
.file()
.entries()
.get(zip_index)
.unwrap()
.entry()
.clone();
let mut reader = zip_reader.entry(zip_index).await?;
reader.read_to_string_checked(&mut manifest, &entry).await?;
let pack: PackFormat = serde_json::from_str(&manifest)?;
let pack: PackFormat = serde_json::from_str(&manifest)?;
if &*pack.game != "minecraft" {
return Err(crate::ErrorKind::InputError(
"Pack does not support Minecraft".to_string(),
)
.into());
}
let mut game_version = None;
let mut mod_loader = None;
let mut loader_version = None;
for (key, value) in &pack.dependencies {
match key {
PackDependency::Forge => {
mod_loader = Some(ModLoader::Forge);
loader_version = Some(value);
}
PackDependency::FabricLoader => {
mod_loader = Some(ModLoader::Fabric);
loader_version = Some(value);
}
PackDependency::QuiltLoader => {
mod_loader = Some(ModLoader::Quilt);
loader_version = Some(value);
}
PackDependency::Minecraft => game_version = Some(value),
if &*pack.game != "minecraft" {
return Err(crate::ErrorKind::InputError(
"Pack does not support Minecraft".to_string(),
)
.into());
}
}
let game_version = if let Some(game_version) = game_version {
game_version
} else {
return Err(crate::ErrorKind::InputError(
"Pack did not specify Minecraft version".to_string(),
)
.into());
};
let loader_version =
crate::profile_create::get_loader_version_from_loader(
game_version.clone(),
mod_loader.unwrap_or(ModLoader::Vanilla),
loader_version.cloned(),
)
.await?;
crate::api::profile::edit(&profile, |prof| {
prof.metadata.name =
override_title.clone().unwrap_or_else(|| pack.name.clone());
prof.install_stage = ProfileInstallStage::PackInstalling;
prof.metadata.linked_data = Some(LinkedData {
project_id: project_id.clone(),
version_id: version_id.clone(),
});
prof.metadata.icon = icon.clone();
prof.metadata.game_version = game_version.clone();
prof.metadata.loader_version = loader_version.clone();
prof.metadata.loader = mod_loader.unwrap_or(ModLoader::Vanilla);
async { Ok(()) }
})
.await?;
State::sync().await?;
let profile = profile.clone();
let result = async {
let loading_bar = init_or_edit_loading(
existing_loading_bar,
LoadingBarType::PackDownload {
profile_path: profile.clone(),
pack_name: pack.name.clone(),
icon,
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),
70.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.fetch_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(())
let mut game_version = None;
let mut mod_loader = None;
let mut loader_version = None;
for (key, value) in &pack.dependencies {
match key {
PackDependency::Forge => {
mod_loader = Some(ModLoader::Forge);
loader_version = Some(value);
}
},
)
.await?;
PackDependency::FabricLoader => {
mod_loader = Some(ModLoader::Fabric);
loader_version = Some(value);
}
PackDependency::QuiltLoader => {
mod_loader = Some(ModLoader::Quilt);
loader_version = Some(value);
}
PackDependency::Minecraft => game_version = Some(value),
}
}
emit_loading(&loading_bar, 0.0, Some("Extracting overrides"))
let game_version = if let Some(game_version) = game_version {
game_version
} else {
return Err(crate::ErrorKind::InputError(
"Pack did not specify Minecraft version".to_string(),
)
.into());
};
let loader_version =
crate::profile_create::get_loader_version_from_loader(
game_version.clone(),
mod_loader.unwrap_or(ModLoader::Vanilla),
loader_version.cloned(),
)
.await?;
crate::api::profile::edit(&profile, |prof| {
prof.metadata.name =
override_title.clone().unwrap_or_else(|| pack.name.clone());
prof.install_stage = ProfileInstallStage::PackInstalling;
prof.metadata.linked_data = Some(LinkedData {
project_id: project_id.clone(),
version_id: version_id.clone(),
});
prof.metadata.icon = icon.clone();
prof.metadata.game_version = game_version.clone();
prof.metadata.loader_version = loader_version.clone();
prof.metadata.loader = mod_loader.unwrap_or(ModLoader::Vanilla);
async { Ok(()) }
})
.await?;
State::sync().await?;
let profile = profile.clone();
let result = async {
let loading_bar = init_or_edit_loading(
existing_loading_bar,
LoadingBarType::PackDownload {
profile_path: profile.clone(),
pack_name: pack.name.clone(),
icon,
pack_id: project_id,
pack_version: version_id,
},
100.0,
"Downloading modpack",
)
.await?;
let mut total_len = 0;
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),
70.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(());
}
}
for index in 0..zip_reader.file().entries().len() {
let file =
zip_reader.file().entries().get(index).unwrap().entry();
let file = fetch_mirrors(
&project
.downloads
.iter()
.map(|x| &**x)
.collect::<Vec<&str>>(),
project
.hashes
.get(&PackFileHash::Sha1)
.map(|x| &**x),
&state.fetch_semaphore,
)
.await?;
if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
total_len += 1;
}
}
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?;
for index in 0..zip_reader.file().entries().len() {
let file = zip_reader
.file()
.entries()
.get(index)
.unwrap()
.entry()
.clone();
emit_loading(&loading_bar, 0.0, Some("Extracting overrides"))
.await?;
let file_path = PathBuf::from(file.filename());
if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
// Reads the file into the 'content' variable
let mut content = Vec::new();
let mut reader = zip_reader.entry(index).await?;
reader.read_to_end_checked(&mut content, &file).await?;
let mut total_len = 0;
let mut new_path = PathBuf::new();
let components = file_path.components().skip(1);
for index in 0..zip_reader.file().entries().len() {
let file =
zip_reader.file().entries().get(index).unwrap().entry();
for component in components {
new_path.push(component);
if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
total_len += 1;
}
}
if new_path.file_name().is_some() {
write(
&profile.join(new_path),
&content,
&state.io_semaphore,
for index in 0..zip_reader.file().entries().len() {
let file = zip_reader
.file()
.entries()
.get(index)
.unwrap()
.entry()
.clone();
let file_path = PathBuf::from(file.filename());
if (file.filename().starts_with("overrides")
|| file.filename().starts_with("client_overrides"))
&& !file.filename().ends_with('/')
{
// Reads the file into the 'content' variable
let mut content = Vec::new();
let mut reader = zip_reader.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?;
}
emit_loading(
&loading_bar,
30.0 / total_len as f64,
Some(&format!(
"Extracting override {}/{}",
index, total_len
)),
)
.await?;
}
}
emit_loading(
&loading_bar,
30.0 / total_len as f64,
Some(&format!(
"Extracting override {}/{}",
index, total_len
)),
if let Some(profile_val) =
crate::api::profile::get(&profile, None).await?
{
crate::launcher::install_minecraft(
&profile_val,
Some(loading_bar),
)
.await?;
}
}
if let Some(profile_val) =
crate::api::profile::get(&profile, None).await?
{
crate::launcher::install_minecraft(
&profile_val,
Some(loading_bar),
)
.await?;
Ok::<PathBuf, crate::Error>(profile.clone())
}
.await;
Ok::<PathBuf, crate::Error>(profile.clone())
match result {
Ok(profile) => Ok(profile),
Err(err) => {
let _ = crate::api::profile::remove(&profile).await;
Err(err)
}
}
} else {
Err(crate::Error::from(crate::ErrorKind::InputError(
"No pack manifest found in mrpack".to_string(),
)))
}
.await;
}
.await;
match result {
Ok(profile) => Ok(profile),
Err(err) => {
let _ = crate::api::profile::remove(&profile).await;
match result {
Ok(profile) => Ok(profile),
Err(err) => {
let _ = crate::api::profile::remove(&profile).await;
Err(err)
}
Err(err)
}
} else {
let _ = crate::api::profile::remove(&profile).await;
Err(crate::Error::from(crate::ErrorKind::InputError(
"No pack manifest found in mrpack".to_string(),
)))
}
}