Skip to content

Commit 61ee374

Browse files
authored
Merge pull request #551 from OpenVicProject/move/mod-dep-list
Move Mod dependency generator to Mod class
2 parents 4b41a21 + 0938d04 commit 61ee374

File tree

4 files changed

+60
-44
lines changed

4 files changed

+60
-44
lines changed

src/openvic-simulation/GameManager.cpp

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "GameManager.hpp"
22

3-
#include <cstddef>
43
#include <string_view>
54

65
#include "openvic-simulation/dataloader/Dataloader.hpp"
@@ -38,35 +37,6 @@ bool GameManager::load_mod_descriptors() {
3837
return true;
3938
}
4039

41-
bool GameManager::_get_mod_dependencies(Mod const* mod, memory::vector<Mod const*>& dep_list) {
42-
static constexpr size_t MAX_RECURSE = 16;
43-
size_t current_recurse = 0;
44-
45-
static auto dep_cycle = [this, &current_recurse](auto self, Mod const* mod, memory::vector<Mod const*>& dep_list) -> bool {
46-
bool ret = true;
47-
for (std::string_view dep_identifier : mod->get_dependencies()) {
48-
if (!mod_manager.has_mod_identifier(dep_identifier)) {
49-
Logger::error("Mod \"", mod->get_identifier(), "\" has unmet dependency \"", dep_identifier, "\" and cannot be loaded!");
50-
return false;
51-
}
52-
Mod const* dep = mod_manager.get_mod_by_identifier(dep_identifier);
53-
/* The poor man's cycle checking (cycles should be very rare and hard to accomplish with vic2 modding, this is a failsafe) */
54-
if (current_recurse == MAX_RECURSE) {
55-
Logger::error("Mod \"", mod->get_identifier(), "\" has cyclical or broken dependency chain and cannot be loaded!");
56-
return false;
57-
} else {
58-
current_recurse++;
59-
ret &= self(self, dep, dep_list); /* recursively search for mod dependencies */
60-
}
61-
if (std::find(dep_list.begin(), dep_list.end(), dep) == dep_list.end()) {
62-
dep_list.emplace_back(dep);
63-
}
64-
}
65-
return ret;
66-
};
67-
return dep_cycle(dep_cycle, mod, dep_list);
68-
}
69-
7040
bool GameManager::load_mods(
7141
Dataloader::path_vector_t& roots,
7242
Dataloader::path_vector_t& replace_paths,
@@ -78,7 +48,7 @@ bool GameManager::load_mods(
7848

7949
bool ret = true;
8050

81-
memory::vector<Mod const*> load_list;
51+
vector_ordered_set<Mod const*> load_list;
8252

8353
/* Check loaded mod descriptors for requested mods, using either full name or user directory name
8454
* (Historical Project Mod 0.4.6 or HPM both valid, for example), and load them plus their dependencies.
@@ -99,21 +69,24 @@ bool GameManager::load_mods(
9969
}
10070

10171
Mod const* mod_ptr = &*it;
102-
memory::vector<Mod const*> dependencies;
103-
if(!_get_mod_dependencies(mod_ptr, dependencies)) {
104-
ret = false;
72+
vector_ordered_set<Mod const*> dependencies = mod_ptr->generate_dependency_list(&ret);
73+
if(!ret) {
10574
continue;
10675
}
10776

10877
/* Add mod plus dependencies to load_list in proper order. */
109-
load_list.reserve(1 + dependencies.size());
110-
for (Mod const* dep : dependencies) {
111-
if (ret && std::find(load_list.begin(), load_list.end(), dep) == load_list.end()) {
112-
load_list.emplace_back(dep);
78+
if (load_list.empty()) {
79+
load_list = std::move(dependencies);
80+
} else {
81+
for (Mod const* dep : dependencies) {
82+
if (!load_list.contains(dep)) {
83+
load_list.emplace(dep);
84+
}
11385
}
11486
}
115-
if (ret && std::find(load_list.begin(), load_list.end(), mod_ptr) == load_list.end()) {
116-
load_list.emplace_back(mod_ptr);
87+
88+
if (!load_list.contains(mod_ptr)) {
89+
load_list.emplace(mod_ptr);
11790
}
11891
}
11992

@@ -129,7 +102,7 @@ bool GameManager::load_mods(
129102

130103
/* Load only vanilla and push an error if mod loading failed. */
131104
if (ret) {
132-
mod_manager.set_loaded_mods(std::move(load_list));
105+
mod_manager.set_loaded_mods(std::move(load_list.release()));
133106
} else {
134107
mod_manager.set_loaded_mods({});
135108
replace_paths.clear();

src/openvic-simulation/GameManager.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ namespace OpenVic {
2424
bool PROPERTY_CUSTOM_PREFIX(definitions_loaded, are);
2525
bool PROPERTY_CUSTOM_PREFIX(mod_descriptors_loaded, are);
2626

27-
bool _get_mod_dependencies(Mod const* mod, memory::vector<Mod const*>& load_list);
28-
2927
public:
3028
GameManager(
3129
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback

src/openvic-simulation/dataloader/ModManager.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,63 @@
55
#include "openvic-simulation/dataloader/NodeTools.hpp"
66
#include "openvic-simulation/types/HasIdentifier.hpp"
77
#include "openvic-simulation/types/IdentifierRegistry.hpp"
8+
#include "openvic-simulation/types/OrderedContainers.hpp"
89
#include "openvic-simulation/utility/ErrorMacros.hpp"
910

1011
using namespace OpenVic;
1112
using namespace OpenVic::NodeTools;
1213

1314
Mod::Mod(
15+
ModManager const& manager,
1416
std::string_view new_identifier,
1517
std::string_view new_path,
1618
std::optional<std::string_view> new_user_dir,
1719
memory::vector<memory::string> new_replace_paths,
1820
memory::vector<memory::string> new_dependencies
1921
)
2022
: HasIdentifier { new_identifier },
23+
mod_manager { manager },
2124
dataloader_root_path { new_path },
2225
user_dir { new_user_dir },
2326
replace_paths { new_replace_paths },
2427
dependencies { new_dependencies } {}
2528

29+
vector_ordered_set<Mod const*> Mod::generate_dependency_list(bool* success) const {
30+
static constexpr size_t MAX_RECURSE = 16;
31+
size_t current_recurse = 0;
32+
33+
vector_ordered_set<Mod const*> result;
34+
35+
auto dep_cycle = [this, &current_recurse](auto self, Mod const* mod, vector_ordered_set<Mod const*>& dep_list) -> bool {
36+
bool ret = true;
37+
for (std::string_view dep_identifier : mod->get_dependencies()) {
38+
if (!mod_manager.has_mod_identifier(dep_identifier)) {
39+
Logger::error("Mod \"", mod->get_identifier(), "\" has unmet dependency \"", dep_identifier, "\" and cannot be loaded!");
40+
return false;
41+
}
42+
Mod const* dep = mod_manager.get_mod_by_identifier(dep_identifier);
43+
/* The poor man's cycle checking (cycles should be very rare and hard to accomplish with vic2 modding, this is a failsafe) */
44+
if (current_recurse == MAX_RECURSE) {
45+
Logger::error("Mod \"", mod->get_identifier(), "\" has cyclical or broken dependency chain and cannot be loaded!");
46+
return false;
47+
} else {
48+
current_recurse++;
49+
ret &= self(self, dep, dep_list); /* recursively search for mod dependencies */
50+
}
51+
if (!dep_list.contains(dep)) {
52+
dep_list.emplace(dep);
53+
}
54+
}
55+
return ret;
56+
};
57+
58+
bool loaded_deps = dep_cycle(dep_cycle, this, result);
59+
if (success) {
60+
*success = loaded_deps;
61+
}
62+
return result;
63+
}
64+
2665
ModManager::ModManager() {}
2766

2867
bool ModManager::load_mod_file(ast::NodeCPtr root) {
@@ -49,7 +88,7 @@ bool ModManager::load_mod_file(ast::NodeCPtr root) {
4988
Logger::info("Loaded mod descriptor for \"", identifier, "\"");
5089
mods.emplace_item(
5190
identifier,
52-
identifier, path, user_dir, std::move(replace_paths), std::move(dependencies)
91+
*this, identifier, path, user_dir, std::move(replace_paths), std::move(dependencies)
5392
);
5493
return true;
5594
}

src/openvic-simulation/dataloader/ModManager.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,28 @@
88
#include "openvic-simulation/dataloader/NodeTools.hpp"
99

1010
namespace OpenVic {
11+
struct ModManager;
12+
1113
struct Mod : HasIdentifier {
1214
private:
15+
ModManager const& PROPERTY(mod_manager);
1316
const memory::string PROPERTY(dataloader_root_path);
1417
const std::optional<memory::string> PROPERTY(user_dir);
1518
const memory::vector<memory::string> PROPERTY(replace_paths);
1619
const memory::vector<memory::string> PROPERTY(dependencies);
1720

1821
public:
1922
Mod(
23+
ModManager const& manager,
2024
std::string_view new_identifier,
2125
std::string_view new_path,
2226
std::optional<std::string_view> new_user_dir,
2327
memory::vector<memory::string> new_replace_paths,
2428
memory::vector<memory::string> new_dependencies
2529
);
2630
Mod(Mod&&) = default;
31+
32+
vector_ordered_set<Mod const*> generate_dependency_list(bool* success = nullptr) const;
2733
};
2834

2935
struct ModManager {

0 commit comments

Comments
 (0)