Mod dependency sorting with only exact version matching
parent
259e867575
commit
9c582d1257
|
|
@ -18,7 +18,7 @@ pub struct ModInfo {
|
||||||
pub version: (i64, i64, i64),
|
pub version: (i64, i64, i64),
|
||||||
pub website_url: String,
|
pub website_url: String,
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
pub dependencies: Vec<Option<DependencyString>>,
|
pub dependencies: Vec<DependencyString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModInfo {
|
impl ModInfo {
|
||||||
|
|
@ -36,7 +36,7 @@ impl ModInfo {
|
||||||
dependencies: yaml["dependencies"]
|
dependencies: yaml["dependencies"]
|
||||||
.as_vec()?
|
.as_vec()?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|y| y.as_str().map(|str| str.to_owned()))
|
.filter_map(|y| y.as_str().map(|str| str.to_owned()))
|
||||||
.collect(),
|
.collect(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -226,6 +226,6 @@ pub fn game_dir() -> PathBuf {
|
||||||
match var("GAME_DIR").ok() {
|
match var("GAME_DIR").ok() {
|
||||||
Some(game_dir) => game_dir.into(),
|
Some(game_dir) => game_dir.into(),
|
||||||
None => PathBuf::from(var("HOME").unwrap())
|
None => PathBuf::from(var("HOME").unwrap())
|
||||||
.join(".steam/steam/steamapps/common/Lethal Company"),
|
.join("steam/SteamLibrary/steamapps/common/Lethal Company"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
77
src/main.rs
77
src/main.rs
|
|
@ -32,6 +32,7 @@ fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mod_list = fetch_mod_list(&profile_fetcher, &profile_uuid).unwrap();
|
let mod_list = fetch_mod_list(&profile_fetcher, &profile_uuid).unwrap();
|
||||||
|
let mod_list = sort_by_dependencies(&mod_list);
|
||||||
fetch_mods(&mod_fetcher, &mod_list).unwrap();
|
fetch_mods(&mod_fetcher, &mod_list).unwrap();
|
||||||
|
|
||||||
println!("");
|
println!("");
|
||||||
|
|
@ -80,26 +81,70 @@ fn fetch_mod_list(
|
||||||
// Handle yaml
|
// Handle yaml
|
||||||
let mods = &YamlLoader::load_from_str(&mods_yaml)?[0];
|
let mods = &YamlLoader::load_from_str(&mods_yaml)?[0];
|
||||||
|
|
||||||
Ok(sort_mods(
|
Ok(mods
|
||||||
&mods
|
.as_vec()
|
||||||
.as_vec()
|
.ok_or(std::io::Error::new(
|
||||||
.ok_or(std::io::Error::new(
|
std::io::ErrorKind::Other,
|
||||||
std::io::ErrorKind::Other,
|
format!("YAML file is not a list: {:?}", mods_yaml_path),
|
||||||
format!("YAML file is not a list: {:?}", mods_yaml_path),
|
))?
|
||||||
))?
|
.iter()
|
||||||
.iter()
|
.filter(|yaml| yaml["enabled"] == Yaml::Boolean(true))
|
||||||
.filter(|yaml| yaml["enabled"] == Yaml::Boolean(true))
|
.map(|yaml| ModInfo::from_yaml(yaml).unwrap())
|
||||||
.map(|yaml| ModInfo::from_yaml(yaml).unwrap())
|
.collect())
|
||||||
.collect(),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sort mods by dependency order
|
/// Sort mods so that dependencies are installed before dependants
|
||||||
fn sort_mods(mods: &Vec<ModInfo>) -> Vec<ModInfo> {
|
fn sort_by_dependencies(mods: &Vec<ModInfo>) -> Vec<ModInfo> {
|
||||||
// TODO: Actual dependecy sorting
|
let mut resolved_mods: Vec<ModInfo> = Vec::with_capacity(mods.len());
|
||||||
let mut mods = mods.clone();
|
let mut mods = mods.clone();
|
||||||
|
// Sort mods initially by their dependency count, so we are more likely to hit them in order
|
||||||
mods.sort_unstable_by_key(|mod_info| mod_info.dependencies.len());
|
mods.sort_unstable_by_key(|mod_info| mod_info.dependencies.len());
|
||||||
mods
|
|
||||||
|
let mut unsatisfied_iterations: Vec<Vec<ModInfo>> = vec![];
|
||||||
|
|
||||||
|
while mods.len() > 0 {
|
||||||
|
// Find a mod with satisfied dependencies
|
||||||
|
let index = mods
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, mod_info)| {
|
||||||
|
mod_info.dependencies.iter().all(|dependency| {
|
||||||
|
resolved_mods
|
||||||
|
.iter()
|
||||||
|
.any(|resolved| *dependency == resolved.dependency_string())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|(index, _)| index);
|
||||||
|
if index.is_none() {
|
||||||
|
unsatisfied_iterations.push(mods.clone());
|
||||||
|
}
|
||||||
|
// Even if no mods were satisfied, just pick one.
|
||||||
|
resolved_mods.push(mods.remove(index.unwrap_or(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if unsatisfied_iterations.len() > 0 {
|
||||||
|
eprintln!(
|
||||||
|
"{} unsatisfied dependencies:\n{:?}\n",
|
||||||
|
unsatisfied_iterations[0].len(),
|
||||||
|
unsatisfied_iterations[0]
|
||||||
|
);
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"Unsatisfied iterations:\n{:?}\n",
|
||||||
|
unsatisfied_iterations
|
||||||
|
.iter()
|
||||||
|
.map(|list| {
|
||||||
|
let list = list
|
||||||
|
.iter()
|
||||||
|
.map(|mod_info| mod_info.name.clone())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
format!("({} unsatisfied) {:?}", list.len(), list)
|
||||||
|
})
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolved_mods
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Download and extract mods
|
/// Download and extract mods
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue