- // Step 1: remove mods in sorted_mods from unmet dependencies
- // of new_mods. new mods without unmet dependencies are
- // temporarily stored in satisfied_mods
- std::vector<ModSpec> satisfied_mods;
- for(std::vector<ModSpec>::iterator it = m_sorted_mods.begin();
- it != m_sorted_mods.end(); ++it)
- {
- ModSpec mod = *it;
- for(std::vector<ModSpec>::iterator it_new = new_mods.begin();
- it_new != new_mods.end(); ++it_new)
- {
- ModSpec& mod_new = *it_new;
- //infostream << "erasing dependency " << mod.name << " from " << mod_new.name << std::endl;
- mod_new.unsatisfied_depends.erase(mod.name);
+ // Maintain a map of all existing m_unsatisfied_mods.
+ // Keys are mod names and values are indices into m_unsatisfied_mods.
+ std::map<std::string, u32> existing_mods;
+ for(u32 i = 0; i < m_unsatisfied_mods.size(); ++i){
+ existing_mods[m_unsatisfied_mods[i].name] = i;
+ }
+
+ // Add new mods
+ for(int want_from_modpack = 1; want_from_modpack >= 0; --want_from_modpack){
+ // First iteration:
+ // Add all the mods that come from modpacks
+ // Second iteration:
+ // Add all the mods that didn't come from modpacks
+
+ std::set<std::string> seen_this_iteration;
+
+ for(std::vector<ModSpec>::const_iterator it = new_mods.begin();
+ it != new_mods.end(); ++it){
+ const ModSpec &mod = *it;
+ if(mod.part_of_modpack != (bool)want_from_modpack)
+ continue;
+ if(existing_mods.count(mod.name) == 0){
+ // GOOD CASE: completely new mod.
+ m_unsatisfied_mods.push_back(mod);
+ existing_mods[mod.name] = m_unsatisfied_mods.size() - 1;
+ }
+ else if(seen_this_iteration.count(mod.name) == 0){
+ // BAD CASE: name conflict in different levels.
+ u32 oldindex = existing_mods[mod.name];
+ const ModSpec &oldmod = m_unsatisfied_mods[oldindex];
+ warningstream<<"Mod name conflict detected: \""
+ <<mod.name<<"\""<<std::endl
+ <<"Will not load: "<<oldmod.path<<std::endl
+ <<"Overridden by: "<<mod.path<<std::endl;
+ m_unsatisfied_mods[oldindex] = mod;
+
+ // If there was a "VERY BAD CASE" name conflict
+ // in an earlier level, ignore it.
+ m_name_conflicts.erase(mod.name);
+ }
+ else{
+ // VERY BAD CASE: name conflict in the same level.
+ u32 oldindex = existing_mods[mod.name];
+ const ModSpec &oldmod = m_unsatisfied_mods[oldindex];
+ warningstream<<"Mod name conflict detected: \""
+ <<mod.name<<"\""<<std::endl
+ <<"Will not load: "<<oldmod.path<<std::endl
+ <<"Will not load: "<<mod.path<<std::endl;
+ m_unsatisfied_mods[oldindex] = mod;
+ m_name_conflicts.insert(mod.name);
+ }
+ seen_this_iteration.insert(mod.name);