Skip to content

Commit 0938d04

Browse files
committed
Move Mod dependency generator to Mod class
Add mod_manager property to Mod class
1 parent de4c853 commit 0938d04

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"
@@ -27,35 +26,6 @@ bool GameManager::load_mod_descriptors() {
2726
return true;
2827
}
2928

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

6838
bool ret = true;
6939

70-
memory::vector<Mod const*> load_list;
40+
vector_ordered_set<Mod const*> load_list;
7141

7242
/* Check loaded mod descriptors for requested mods, using either full name or user directory name
7343
* (Historical Project Mod 0.4.6 or HPM both valid, for example), and load them plus their dependencies.
@@ -88,21 +58,24 @@ bool GameManager::load_mods(
8858
}
8959

9060
Mod const* mod_ptr = &*it;
91-
memory::vector<Mod const*> dependencies;
92-
if(!_get_mod_dependencies(mod_ptr, dependencies)) {
93-
ret = false;
61+
vector_ordered_set<Mod const*> dependencies = mod_ptr->generate_dependency_list(&ret);
62+
if(!ret) {
9463
continue;
9564
}
9665

9766
/* Add mod plus dependencies to load_list in proper order. */
98-
load_list.reserve(1 + dependencies.size());
99-
for (Mod const* dep : dependencies) {
100-
if (ret && std::find(load_list.begin(), load_list.end(), dep) == load_list.end()) {
101-
load_list.emplace_back(dep);
67+
if (load_list.empty()) {
68+
load_list = std::move(dependencies);
69+
} else {
70+
for (Mod const* dep : dependencies) {
71+
if (!load_list.contains(dep)) {
72+
load_list.emplace(dep);
73+
}
10274
}
10375
}
104-
if (ret && std::find(load_list.begin(), load_list.end(), mod_ptr) == load_list.end()) {
105-
load_list.emplace_back(mod_ptr);
76+
77+
if (!load_list.contains(mod_ptr)) {
78+
load_list.emplace(mod_ptr);
10679
}
10780
}
10881

@@ -118,7 +91,7 @@ bool GameManager::load_mods(
11891

11992
/* Load only vanilla and push an error if mod loading failed. */
12093
if (ret) {
121-
mod_manager.set_loaded_mods(std::move(load_list));
94+
mod_manager.set_loaded_mods(std::move(load_list.release()));
12295
} else {
12396
mod_manager.set_loaded_mods({});
12497
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)