1
0

Misc improvements and fixes (#109)

* now utilizing tracing better

* better tracing

* fix mac vs pc oppositional env var issue

* modified loading package

* added droppable loadingbarid that sends completion message

* loading bar

* regressed bug on mac

* fixed non-updated loading bar on playground

* Loading bar improvements

---------

Co-authored-by: Jai A <jaiagr+gpg@pm.me>
This commit is contained in:
Wyatt Verchere
2023-05-08 12:14:08 -07:00
committed by GitHub
parent c79d5c32a6
commit 65c1942037
33 changed files with 726 additions and 294 deletions

View File

@@ -1,12 +1,11 @@
//! Authentication flow based on Hydra
use crate::util::fetch::{fetch_advanced, fetch_json};
use crate::util::fetch::{fetch_advanced, fetch_json, FetchSemaphore};
use async_tungstenite as ws;
use chrono::{prelude::*, Duration};
use futures::prelude::*;
use lazy_static::lazy_static;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use tokio::sync::{RwLock, Semaphore};
use url::Url;
lazy_static! {
@@ -95,7 +94,7 @@ impl HydraAuthFlow<ws::tokio::ConnectStream> {
pub async fn extract_credentials(
&mut self,
semaphore: &RwLock<Semaphore>,
semaphore: &FetchSemaphore,
) -> crate::Result<Credentials> {
// Minecraft bearer token
let token_resp = self
@@ -130,7 +129,7 @@ impl HydraAuthFlow<ws::tokio::ConnectStream> {
pub async fn refresh_credentials(
credentials: &mut Credentials,
semaphore: &RwLock<Semaphore>,
semaphore: &FetchSemaphore,
) -> crate::Result<()> {
let resp = fetch_json::<TokenJSON>(
Method::POST,
@@ -152,7 +151,7 @@ pub async fn refresh_credentials(
// Helpers
async fn fetch_info(
token: &str,
semaphore: &RwLock<Semaphore>,
semaphore: &FetchSemaphore,
) -> crate::Result<ProfileInfoJSON> {
let result = fetch_advanced(
Method::GET,
@@ -160,6 +159,7 @@ async fn fetch_info(
None,
None,
Some(("Authorization", &format!("Bearer {token}"))),
None,
semaphore,
)
.await?;

View File

@@ -1,7 +1,10 @@
//! Downloader for Minecraft data
use crate::{
event::emit::{emit_loading, loading_try_for_each_concurrent},
event::{
emit::{emit_loading, loading_try_for_each_concurrent},
LoadingBarId,
},
state::State,
util::{fetch::*, platform::OsExt},
};
@@ -15,24 +18,26 @@ use daedalus::{
};
use futures::prelude::*;
use tokio::{fs, sync::OnceCell};
use uuid::Uuid;
#[tracing::instrument(skip_all)]
pub async fn download_minecraft(
st: &State,
version: &GameVersionInfo,
loading_bar: Uuid,
loading_bar: &LoadingBarId,
) -> crate::Result<()> {
log::info!("Downloading Minecraft version {}", version.id);
let assets_index = download_assets_index(st, version).await?;
tracing::info!("Downloading Minecraft version {}", version.id);
// 5
let assets_index =
download_assets_index(st, version, Some(loading_bar)).await?;
tokio::try_join! {
download_client(st, version, Some(&loading_bar)),
download_assets(st, version.assets == "legacy", &assets_index, Some(&loading_bar)),
download_libraries(st, version.libraries.as_slice(), &version.id, Some(&loading_bar))
// Total loading sums to 80
download_client(st, version, Some(loading_bar)), // 10
download_assets(st, version.assets == "legacy", &assets_index, Some(loading_bar)), // 35
download_libraries(st, version.libraries.as_slice(), &version.id, Some(loading_bar)) // 35
}?;
log::info!("Done downloading Minecraft!");
tracing::info!("Done downloading Minecraft!");
Ok(())
}
@@ -42,10 +47,11 @@ pub async fn download_version_info(
version: &GameVersion,
loader: Option<&LoaderVersion>,
force: Option<bool>,
loading_bar: Option<&LoadingBarId>,
) -> crate::Result<GameVersionInfo> {
let version_id = loader
.map_or(version.id.clone(), |it| format!("{}-{}", version.id, it.id));
log::debug!("Loading version info for Minecraft {version_id}");
tracing::debug!("Loading version info for Minecraft {version_id}");
let path = st
.directories
.version_dir(&version_id)
@@ -57,7 +63,7 @@ pub async fn download_version_info(
.await
.and_then(|ref it| Ok(serde_json::from_slice(it)?))
} else {
log::info!("Downloading version info for version {}", &version.id);
tracing::info!("Downloading version info for version {}", &version.id);
let mut info = d::minecraft::fetch_version_info(version).await?;
if let Some(loader) = loader {
@@ -70,7 +76,25 @@ pub async fn download_version_info(
Ok(info)
}?;
log::debug!("Loaded version info for Minecraft {version_id}");
if let Some(loading_bar) = loading_bar {
emit_loading(
loading_bar,
if res
.processors
.as_ref()
.map(|x| !x.is_empty())
.unwrap_or(false)
{
5.0
} else {
15.0
},
None,
)
.await?;
}
tracing::debug!("Loaded version info for Minecraft {version_id}");
Ok(res)
}
@@ -78,10 +102,10 @@ pub async fn download_version_info(
pub async fn download_client(
st: &State,
version_info: &GameVersionInfo,
loading_bar: Option<&Uuid>,
loading_bar: Option<&LoadingBarId>,
) -> crate::Result<()> {
let version = &version_info.id;
log::debug!("Locating client for version {version}");
tracing::debug!("Locating client for version {version}");
let client_download = version_info
.downloads
.get(&d::minecraft::DownloadType::Client)
@@ -100,17 +124,17 @@ pub async fn download_client(
let bytes = fetch(
&client_download.url,
Some(&client_download.sha1),
&st.io_semaphore,
&st.fetch_semaphore,
)
.await?;
write(&path, &bytes, &st.io_semaphore).await?;
log::info!("Fetched client version {version}");
tracing::trace!("Fetched client version {version}");
}
if let Some(loading_bar) = loading_bar {
emit_loading(loading_bar, 20.0, None).await?;
emit_loading(loading_bar, 10.0, None).await?;
}
log::debug!("Client loaded for version {version}!");
tracing::debug!("Client loaded for version {version}!");
Ok(())
}
@@ -118,8 +142,9 @@ pub async fn download_client(
pub async fn download_assets_index(
st: &State,
version: &GameVersionInfo,
loading_bar: Option<&LoadingBarId>,
) -> crate::Result<AssetsIndex> {
log::debug!("Loading assets index");
tracing::debug!("Loading assets index");
let path = st
.directories
.assets_index_dir()
@@ -133,11 +158,14 @@ pub async fn download_assets_index(
} else {
let index = d::minecraft::fetch_assets_index(version).await?;
write(&path, &serde_json::to_vec(&index)?, &st.io_semaphore).await?;
log::info!("Fetched assets index");
tracing::info!("Fetched assets index");
Ok(index)
}?;
log::debug!("Assets index successfully loaded!");
if let Some(loading_bar) = loading_bar {
emit_loading(loading_bar, 5.0, None).await?;
}
tracing::debug!("Assets index successfully loaded!");
Ok(res)
}
@@ -146,9 +174,9 @@ pub async fn download_assets(
st: &State,
with_legacy: bool,
index: &AssetsIndex,
loading_bar: Option<&Uuid>,
loading_bar: Option<&LoadingBarId>,
) -> crate::Result<()> {
log::debug!("Loading assets");
tracing::debug!("Loading assets");
let num_futs = index.objects.len();
let assets = stream::iter(index.objects.iter())
.map(Ok::<(&String, &Asset), crate::Error>);
@@ -156,7 +184,7 @@ pub async fn download_assets(
loading_try_for_each_concurrent(assets,
None,
loading_bar,
50.0,
35.0,
num_futs,
None,
|(name, asset)| async move {
@@ -172,33 +200,33 @@ pub async fn download_assets(
async {
if !resource_path.exists() {
let resource = fetch_cell
.get_or_try_init(|| fetch(&url, Some(hash), &st.io_semaphore))
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore))
.await?;
write(&resource_path, resource, &st.io_semaphore).await?;
log::info!("Fetched asset with hash {hash}");
tracing::trace!("Fetched asset with hash {hash}");
}
Ok::<_, crate::Error>(())
},
async {
if with_legacy {
let resource = fetch_cell
.get_or_try_init(|| fetch(&url, Some(hash), &st.io_semaphore))
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore))
.await?;
let resource_path = st.directories.legacy_assets_dir().join(
name.replace('/', &String::from(std::path::MAIN_SEPARATOR))
);
write(&resource_path, resource, &st.io_semaphore).await?;
log::info!("Fetched legacy asset with hash {hash}");
tracing::trace!("Fetched legacy asset with hash {hash}");
}
Ok::<_, crate::Error>(())
},
}?;
log::debug!("Loaded asset with hash {hash}");
tracing::trace!("Loaded asset with hash {hash}");
Ok(())
}).await?;
log::debug!("Done loading assets!");
tracing::debug!("Done loading assets!");
Ok(())
}
@@ -207,9 +235,9 @@ pub async fn download_libraries(
st: &State,
libraries: &[Library],
version: &str,
loading_bar: Option<&Uuid>,
loading_bar: Option<&LoadingBarId>,
) -> crate::Result<()> {
log::debug!("Loading libraries");
tracing::debug!("Loading libraries");
tokio::try_join! {
fs::create_dir_all(st.directories.libraries_dir()),
@@ -218,7 +246,7 @@ pub async fn download_libraries(
let num_files = libraries.len();
loading_try_for_each_concurrent(
stream::iter(libraries.iter())
.map(Ok::<&Library, crate::Error>), None, loading_bar,50.0,num_files, None,|library| async move {
.map(Ok::<&Library, crate::Error>), None, loading_bar,35.0,num_files, None,|library| async move {
if let Some(rules) = &library.rules {
if !rules.iter().all(super::parse_rule) {
return Ok(());
@@ -235,10 +263,10 @@ pub async fn download_libraries(
artifact: Some(ref artifact),
..
}) => {
let bytes = fetch(&artifact.url, Some(&artifact.sha1), &st.io_semaphore)
let bytes = fetch(&artifact.url, Some(&artifact.sha1), &st.fetch_semaphore)
.await?;
write(&path, &bytes, &st.io_semaphore).await?;
log::info!("Fetched library {}", &library.name);
tracing::trace!("Fetched library {}", &library.name);
Ok::<_, crate::Error>(())
}
None => {
@@ -250,9 +278,9 @@ pub async fn download_libraries(
&artifact_path
].concat();
let bytes = fetch(&url, None, &st.io_semaphore).await?;
let bytes = fetch(&url, None, &st.fetch_semaphore).await?;
write(&path, &bytes, &st.io_semaphore).await?;
log::info!("Fetched library {}", &library.name);
tracing::trace!("Fetched library {}", &library.name);
Ok::<_, crate::Error>(())
}
_ => Ok(())
@@ -277,15 +305,15 @@ pub async fn download_libraries(
);
if let Some(native) = classifiers.get(&parsed_key) {
let data = fetch(&native.url, Some(&native.sha1), &st.io_semaphore).await?;
let data = fetch(&native.url, Some(&native.sha1), &st.fetch_semaphore).await?;
let reader = std::io::Cursor::new(&data);
if let Ok(mut archive) = zip::ZipArchive::new(reader) {
match archive.extract(&st.directories.version_natives_dir(version)) {
Ok(_) => log::info!("Fetched native {}", &library.name),
Err(err) => log::error!("Failed extracting native {}. err: {}", &library.name, err)
Ok(_) => tracing::info!("Fetched native {}", &library.name),
Err(err) => tracing::error!("Failed extracting native {}. err: {}", &library.name, err)
}
} else {
log::error!("Failed extracting native {}", &library.name)
tracing::error!("Failed extracting native {}", &library.name)
}
}
}
@@ -294,11 +322,11 @@ pub async fn download_libraries(
}
}?;
log::debug!("Loaded library {}", library.name);
tracing::debug!("Loaded library {}", library.name);
Ok(())
}
).await?;
log::debug!("Done loading libraries!");
tracing::debug!("Done loading libraries!");
Ok(())
}

View File

@@ -1,6 +1,6 @@
//! Logic for launching Minecraft
use crate::event::emit::{emit_loading, init_or_edit_loading};
use crate::event::LoadingBarType;
use crate::event::{LoadingBarId, LoadingBarType};
use crate::{
process,
state::{self as st, MinecraftChild},
@@ -53,9 +53,10 @@ macro_rules! processor_rules {
}
}
#[tracing::instrument(skip(profile))]
pub async fn install_minecraft(
profile: &Profile,
existing_loading_bar: Option<Uuid>,
existing_loading_bar: Option<LoadingBarId>,
) -> crate::Result<()> {
let state = State::get().await?;
let instance_path = &canonicalize(&profile.path)?;
@@ -79,14 +80,6 @@ pub async fn install_minecraft(
format!("{}-{}", version.id.clone(), it.id.clone())
});
let mut version_info = download::download_version_info(
&state,
version,
profile.metadata.loader_version.as_ref(),
None,
)
.await?;
let loading_bar = init_or_edit_loading(
existing_loading_bar,
LoadingBarType::MinecraftDownload {
@@ -95,11 +88,22 @@ pub async fn install_minecraft(
profile_uuid: profile.uuid,
},
100.0,
"Downloading Minecraft...",
"Downloading Minecraft",
)
.await?;
download::download_minecraft(&state, &version_info, loading_bar).await?;
// Download version info
let mut version_info = download::download_version_info(
&state,
version,
profile.metadata.loader_version.as_ref(),
None,
Some(&loading_bar),
)
.await?;
// Download minecraft (5-90)
download::download_minecraft(&state, &version_info, &loading_bar).await?;
let client_path = state
.directories
@@ -131,10 +135,11 @@ pub async fn install_minecraft(
.await?;
let total_length = processors.len();
// Forge processors (90-100)
for (index, processor) in processors.iter().enumerate() {
emit_loading(
&loading_bar,
index as f64 / total_length as f64,
10.0 / total_length as f64,
Some(&format!(
"Running forge processor {}/{}",
index, total_length
@@ -223,7 +228,7 @@ pub async fn launch_minecraft(
install_minecraft(profile, None).await?;
}
let state = st::State::get().await?;
let state = State::get().await?;
let metadata = state.metadata.read().await;
let instance_path = &canonicalize(&profile.path)?;
@@ -250,6 +255,7 @@ pub async fn launch_minecraft(
version,
profile.metadata.loader_version.as_ref(),
None,
None,
)
.await?;
@@ -320,8 +326,12 @@ pub async fn launch_minecraft(
.stdout(Stdio::piped())
.stderr(Stdio::piped());
// Clear cargo-added env varaibles for debugging, and add settings env vars
clear_cargo_env_vals(&mut command).envs(env_args);
// CARGO-set DYLD_LIBRARY_PATH breaks Minecraft on macOS during testing on playground
#[cfg(target_os = "macos")]
if std::env::var("CARGO").is_ok() {
command.env_remove("DYLD_FALLBACK_LIBRARY_PATH");
}
command.envs(env_args);
// Get Modrinth logs directories
let datetime_string =
@@ -351,14 +361,3 @@ pub async fn launch_minecraft(
)
.await
}
fn clear_cargo_env_vals(command: &mut Command) -> &mut Command {
for (key, _) in std::env::vars() {
command.env_remove(key);
// if key.starts_with("CARGO") {
// command.env_remove(key);
// }
}
command
}