use crate::error::InstallationResult;
use crate::minecraft::InstallOptions;
use crate::minecraft::InstallationUpdate;
use crate::utils::{download, download_progress_channel, Download, DownloadProgress};
use futures::join;
use tokio::sync::mpsc::{Receiver, Sender};
#[instrument(
name = "install_client",
level = "trace",
skip_all,
fields(
version = &options.version_data.id,
minecraft_path = %options.minecraft_path.display(),
parallel_downloads = options.parallel_downloads,
download_retries = options.download_retries,
verify_downloads = options.verify_downloads,
)
)]
pub async fn install_client(
options: &InstallOptions,
update_sender: Sender<InstallationUpdate>,
) -> InstallationResult<()> {
let downloads = match &options.version_data.downloads {
Some(downloads) => downloads,
None => {
debug!("The version data does not contain download information. Skipping download.");
return Ok(());
}
};
trace!("Building download for client");
let mut minecraft_path = options.minecraft_path.clone();
minecraft_path.push("bin");
minecraft_path.push(format!("minecraft-{}-client.jar", &options.version_data.id));
let sha1 = hex::decode(&downloads.client.sha1)?;
let downloads = vec![Download {
url: downloads.client.url.clone(),
file: minecraft_path,
sha1: Some(sha1),
}];
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 send_result = sender
.send(InstallationUpdate::Client(
ClientInstallationUpdate::Downloading(p),
))
.await;
if send_result.is_err() {
debug!("Failed to translate DownloadProgress to InstallationUpdate");
break;
}
}
}
#[derive(Clone, Debug)]
pub enum ClientInstallationUpdate {
Downloading(DownloadProgress),
}