use std::path::Path;
use crate::error::InstallationResult;
use crate::minecraft::fabric::{FabricLibrary, FabricVersionData};
use crate::minecraft::{InstallOptions, InstallationUpdate, LibraryInstallationUpdate};
use crate::utils::{download, download_progress_channel, Download, DownloadProgress};
use futures::join;
use tokio::sync::mpsc::{Receiver, Sender};
#[cfg_attr(doc_cfg, doc(cfg(feature = "fabric")))]
#[instrument(
name = "install_fabric_libraries",
level = "trace",
skip_all,
fields(
minecraft_version = &options.version_data.id,
libraries_path = %options.libraries_path.display(),
parallel_downloads = options.parallel_downloads,
)
)]
pub async fn install_fabric_libraries(
fabric_version_data: &FabricVersionData,
options: &InstallOptions,
update_sender: Sender<InstallationUpdate>,
) -> InstallationResult<()> {
trace!("Building downloads for fabric libraries");
let downloads = fabric_version_data
.libraries
.iter()
.map(|l| build_download(l, &options.libraries_path))
.collect::<Vec<_>>();
trace!("Preparing futures for downloading and channel translation");
let (tx, rx) = download_progress_channel(500);
let download_future = download(
downloads,
Some(tx),
options.parallel_downloads,
options.download_retries,
options.verify_downloads,
);
let map_future = map_progress(update_sender.clone(), rx);
trace!("Starting downloads");
join!(download_future, map_future).0?;
Ok(())
}
async fn map_progress(
sender: Sender<InstallationUpdate>,
mut receiver: Receiver<DownloadProgress>,
) {
while let Some(p) = receiver.recv().await {
let path = p
.file
.file_name()
.map(|s| s.to_string_lossy().to_string())
.unwrap_or_default();
let send_result = sender
.send(InstallationUpdate::Library((
path,
LibraryInstallationUpdate::Downloading(p),
)))
.await;
if send_result.is_err() {
warn!("Failed to translate DownloadProgress to InstallationUpdate");
break;
}
}
}
fn build_download(library: &FabricLibrary, libraries_path: impl AsRef<Path>) -> Download {
Download {
url: library.download_url(),
file: library.jar_path(libraries_path),
sha1: None,
}
}