use cobble_core::minecraft::models::{AssetIndex, VersionData, VersionManifest};
use cobble_core::minecraft::{
install_assets, install_client, install_libraries, install_log_config, AssetInstallationUpdate,
ClientInstallationUpdate, InstallOptionsBuilder, InstallationUpdate, LibraryInstallationUpdate,
LogConfigInstallationUpdate,
};
use cobble_core::utils::DownloadProgress;
use futures::join;
use std::env::temp_dir;
use tokio::sync::mpsc::{Receiver, Sender};
use tracing_subscriber::FmtSubscriber;
#[tokio::main]
async fn main() {
FmtSubscriber::builder()
.with_env_filter("info,cobble_core=debug")
.init();
let version_manifest = VersionManifest::fetch().await.unwrap();
let version_summary = version_manifest
.versions
.get(&version_manifest.latest.release)
.unwrap();
let version_data = VersionData::fetch(&version_summary.url).await.unwrap();
let asset_index = version_data.asset_index.fetch_index().await.unwrap();
let (tx, rx) = InstallationUpdate::channel(500);
join!(install(version_data, asset_index, tx), process_updates(rx));
}
async fn install(
version_data: VersionData,
asset_index: AssetIndex,
tx: Sender<InstallationUpdate>,
) {
let mut libraries_path = temp_dir();
libraries_path.push("cobble-core/libraries");
let mut natives_path = temp_dir();
natives_path.push("cobble-core/natives");
let mut assets_path = temp_dir();
assets_path.push("cobble-core/assets");
let mut log_configs_path = temp_dir();
log_configs_path.push("cobble-core/assets/log_configs");
let mut minecraft_path = temp_dir();
minecraft_path.push("cobble-core/.minecraft");
let options = InstallOptionsBuilder::default()
.version_data(version_data)
.asset_index(asset_index)
.libraries_path(libraries_path)
.natives_path(natives_path)
.assets_path(assets_path)
.log_configs_path(log_configs_path)
.minecraft_path(minecraft_path)
.parallel_downloads(5)
.download_retries(1)
.verify_downloads(true)
.build()
.unwrap();
install_libraries(&options, tx.clone()).await.unwrap();
install_assets(&options, tx.clone()).await.unwrap();
install_log_config(&options, tx.clone()).await.unwrap();
install_client(&options, tx.clone()).await.unwrap();
}
async fn process_updates(mut rx: Receiver<InstallationUpdate>) {
while let Some(update) = rx.recv().await {
match update {
InstallationUpdate::Library((n, p)) => match p {
LibraryInstallationUpdate::Downloading(p) => print_progress(p),
LibraryInstallationUpdate::Extracting => {
println!("{} extracting...", n);
}
},
InstallationUpdate::Asset((n, p)) => match p {
AssetInstallationUpdate::Downloading(p) => print_progress(p),
AssetInstallationUpdate::Symlink => {
println!("{} symlink...", n);
}
},
InstallationUpdate::LogConfig(p) => match p {
LogConfigInstallationUpdate::Downloading(p) => print_progress(p),
},
InstallationUpdate::Client(p) => match p {
ClientInstallationUpdate::Downloading(p) => print_progress(p),
},
}
}
}
fn print_progress(p: DownloadProgress) {
let name = p.file.file_name().map(|s| s.to_string_lossy()).unwrap();
let percent = p.downloaded_bytes as f64 / p.total_bytes as f64;
tracing::info!(
"{} ({}/{}): {}% done",
name,
p.current_file + 1,
p.total_files,
(percent * 100.0) as u64
);
}