cobble_core/minecraft/install/
client.rs1use crate::error::InstallationResult;
2use crate::minecraft::InstallOptions;
3use crate::minecraft::InstallationUpdate;
4use crate::utils::{download, download_progress_channel, Download, DownloadProgress};
5use futures::join;
6use tokio::sync::mpsc::{Receiver, Sender};
7
8#[instrument(
12 name = "install_client",
13 level = "trace",
14 skip_all,
15 fields(
16 version = &options.version_data.id,
17 minecraft_path = %options.minecraft_path.display(),
18 parallel_downloads = options.parallel_downloads,
19 download_retries = options.download_retries,
20 verify_downloads = options.verify_downloads,
21 )
22)]
23pub async fn install_client(
24 options: &InstallOptions,
25 update_sender: Sender<InstallationUpdate>,
26) -> InstallationResult<()> {
27 let downloads = match &options.version_data.downloads {
28 Some(downloads) => downloads,
29 None => {
30 debug!("The version data does not contain download information. Skipping download.");
31 return Ok(());
32 }
33 };
34
35 trace!("Building download for client");
36 let mut minecraft_path = options.minecraft_path.clone();
37 minecraft_path.push("bin");
38 minecraft_path.push(format!("minecraft-{}-client.jar", &options.version_data.id));
39
40 let sha1 = hex::decode(&downloads.client.sha1)?;
41 let downloads = vec![Download {
42 url: downloads.client.url.clone(),
43 file: minecraft_path,
44 sha1: Some(sha1),
45 }];
46
47 trace!("Preparing futures for downloading and channel translation");
48 let (tx, rx) = download_progress_channel(500);
49 let download_future = download(
50 downloads,
51 Some(tx),
52 options.parallel_downloads,
53 options.download_retries,
54 options.verify_downloads,
55 );
56 let map_future = map_progress(update_sender.clone(), rx);
57
58 trace!("Starting downloads");
59 join!(download_future, map_future).0?;
60
61 Ok(())
62}
63
64async fn map_progress(
65 sender: Sender<InstallationUpdate>,
66 mut receiver: Receiver<DownloadProgress>,
67) {
68 while let Some(p) = receiver.recv().await {
69 let send_result = sender
70 .send(InstallationUpdate::Client(
71 ClientInstallationUpdate::Downloading(p),
72 ))
73 .await;
74
75 if send_result.is_err() {
76 debug!("Failed to translate DownloadProgress to InstallationUpdate");
77 break;
78 }
79 }
80}
81
82#[derive(Clone, Debug)]
84pub enum ClientInstallationUpdate {
85 Downloading(DownloadProgress),
87}