use lighty_loaders::types::{VersionInfo, version_metadata::AssetsFile};
use lighty_core::time_it;
use crate::errors::InstallerResult;
use crate::installer::verifier::{is_missing_or_empty, needs_download};
use crate::installer::downloader::{download_small_with_concurrency_limit, DownloadTask};
#[cfg(feature = "events")]
use lighty_event::EventBus;
pub async fn collect_asset_tasks<'a>(
version: &impl VersionInfo,
assets: Option<&'a AssetsFile>,
) -> Vec<DownloadTask<'a>> {
let Some(assets) = assets else {
return Vec::new();
};
let assets_root = version.game_dirs().join("assets");
let objects_root = assets_root.join("objects");
let mut tasks = Vec::new();
for asset in assets.objects.values() {
let Some(url) = &asset.url else { continue };
let outdated = match &asset.path {
Some(custom) => {
let path = assets_root.join(custom);
needs_download(&path, Some(&asset.hash), &asset.hash)
.await
.then_some(path)
}
None => {
let path = objects_root.join(&asset.hash[0..2]).join(&asset.hash);
is_missing_or_empty(&path).await.then_some(path)
}
};
if let Some(path) = outdated {
tasks.push(DownloadTask {
url,
dest: path,
sha1: Some(&asset.hash),
size: asset.size,
});
}
}
tasks.sort_unstable_by(|left, right| left.dest.cmp(&right.dest));
tasks.dedup_by(|left, right| left.dest == right.dest);
tasks
}
pub async fn download_assets(
tasks: Vec<DownloadTask<'_>>,
#[cfg(feature = "events")] event_bus: Option<&EventBus>,
) -> InstallerResult<()> {
if tasks.is_empty() {
lighty_core::trace_info!("[Installer] All assets already cached and verified");
return Ok(());
}
lighty_core::trace_info!("[Installer] Downloading {} new assets...", tasks.len());
time_it!("Assets download", {
download_small_with_concurrency_limit(
tasks,
#[cfg(feature = "events")]
event_bus,
)
.await?
});
lighty_core::trace_info!("[Installer] Assets installed");
Ok(())
}