use std::path::PathBuf;
use lighty_core::time_it;
use lighty_loaders::types::{version_metadata::Mods, VersionInfo};
use crate::errors::InstallerResult;
use crate::installer::downloader::download_with_concurrency_limit;
use crate::installer::verifier::needs_download;
#[cfg(feature = "events")]
use lighty_event::EventBus;
pub(super) async fn collect<V: VersionInfo>(
version: &V,
mods: &[Mods],
subdir: &str,
legacy_fallback: bool,
) -> (Vec<(String, PathBuf)>, u64) {
if mods.is_empty() {
return (Vec::new(), 0);
}
let runtime = version.runtime_dir();
let parent = runtime.join(subdir);
lighty_core::mkdir!(&parent);
let prefix = format!("{}/", subdir);
let mut tasks = Vec::new();
let mut bytes = 0u64;
for entry in mods {
let Some(url) = &entry.url else { continue };
let Some(path_str) = &entry.path else { continue };
let target = if let Some(rest) = path_str.strip_prefix(&prefix) {
parent.join(rest)
} else if legacy_fallback && !path_str.contains('/') && !path_str.contains('\\') {
lighty_core::trace_warn!(
"[Installer] Legacy unqualified path '{}' — falling back to {}/",
path_str,
subdir
);
parent.join(path_str)
} else {
continue;
};
if let Some(dir) = target.parent() {
lighty_core::mkdir!(dir);
}
if needs_download(&target, entry.sha1.as_ref(), &entry.name).await {
bytes += entry.size.unwrap_or(0);
tasks.push((url.clone(), target));
}
}
(tasks, bytes)
}
pub(super) async fn download(
tasks: Vec<(String, PathBuf)>,
label: &str,
#[cfg(feature = "events")] event_bus: Option<&EventBus>,
) -> InstallerResult<()> {
if tasks.is_empty() {
return Ok(());
}
lighty_core::trace_info!("[Installer] Downloading {} {}...", tasks.len(), label);
let label_owned = format!("{} download", label);
time_it!(label_owned.as_str(), {
download_with_concurrency_limit(
tasks,
#[cfg(feature = "events")]
event_bus,
)
.await?
});
lighty_core::trace_info!("[Installer] {} installed", label);
Ok(())
}