Skip to content

Commit 4e23937

Browse files
committed
Mod Compatibility Fixes
1 parent ac4ca6f commit 4e23937

24 files changed

+324
-331
lines changed

Diff for: src/headless/main.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static void print_rgo(ProvinceInstance const& province) {
5656
}
5757
}
5858

59-
static bool run_headless(const fs::path root, std::vector<std::string> mods, bool run_tests) {
59+
static bool run_headless(fs::path const& root, std::vector<std::string>& mods, bool run_tests) {
6060
bool ret = true;
6161
Dataloader::path_vector_t roots = { root };
6262
Dataloader::path_vector_t replace_paths = {};
@@ -227,7 +227,7 @@ int main(int argc, char const* argv[]) {
227227

228228
std::cout << "!!! HEADLESS SIMULATION START !!!" << std::endl;
229229

230-
const bool ret = run_headless(root, std::move(mods), run_tests);
230+
const bool ret = run_headless(root, mods, run_tests);
231231

232232
std::cout << "!!! HEADLESS SIMULATION END !!!" << std::endl;
233233

Diff for: src/openvic-simulation/GameManager.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ GameManager::GameManager(
66
InstanceManager::gamestate_updated_func_t new_gamestate_updated_callback
77
) : gamestate_updated_callback {
88
new_gamestate_updated_callback ? std::move(new_gamestate_updated_callback) : []() {}
9-
}, clock_state_changed_callback {
10-
new_clock_state_changed_callback ? std::move(new_clock_state_changed_callback) : []() {}
119
}, definitions_loaded { false }, mod_descriptors_loaded { false } {}
1210

1311
bool GameManager::load_mod_descriptors(std::vector<std::string> descriptors) {

Diff for: src/openvic-simulation/country/CountryDefinition.cpp

+16-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include <string_view>
44

5+
#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
6+
57
#include "openvic-simulation/dataloader/Dataloader.hpp"
68
#include "openvic-simulation/dataloader/NodeTools.hpp"
79
#include "openvic-simulation/DefinitionManager.hpp"
@@ -11,7 +13,7 @@
1113
#include "openvic-simulation/pop/Culture.hpp"
1214
#include "openvic-simulation/types/Colour.hpp"
1315
#include "openvic-simulation/types/IdentifierRegistry.hpp"
14-
#include <openvic-dataloader/v2script/AbstractSyntaxTree.hpp>
16+
#include "openvic-simulation/utility/Logger.hpp"
1517

1618
using namespace OpenVic;
1719
using namespace OpenVic::NodeTools;
@@ -129,13 +131,19 @@ bool CountryDefinitionManager::load_countries(
129131
}
130132

131133
bool CountryDefinitionManager::load_country_colours(ast::NodeCPtr root) {
132-
return country_definitions.expect_item_dictionary([](CountryDefinition& country, ast::NodeCPtr colour_node) -> bool {
133-
return expect_dictionary_keys(
134-
"color1", ONE_EXACTLY, expect_colour(assign_variable_callback(country.primary_unit_colour)),
135-
"color2", ONE_EXACTLY, expect_colour(assign_variable_callback(country.secondary_unit_colour)),
136-
"color3", ONE_EXACTLY, expect_colour(assign_variable_callback(country.tertiary_unit_colour))
137-
)(colour_node);
138-
})(root);
134+
return country_definitions.expect_item_dictionary_and_default(
135+
[](std::string_view key, ast::NodeCPtr value) -> bool {
136+
Logger::warning("country_colors.txt references country tag ", key, " which is not defined!");
137+
return true;
138+
},
139+
[](CountryDefinition& country, ast::NodeCPtr colour_node) -> bool {
140+
return expect_dictionary_keys(
141+
"color1", ONE_EXACTLY, expect_colour(assign_variable_callback(country.primary_unit_colour)),
142+
"color2", ONE_EXACTLY, expect_colour(assign_variable_callback(country.secondary_unit_colour)),
143+
"color3", ONE_EXACTLY, expect_colour(assign_variable_callback(country.tertiary_unit_colour))
144+
)(colour_node);
145+
}
146+
)(root);
139147
}
140148

141149
node_callback_t CountryDefinitionManager::load_country_party(

Diff for: src/openvic-simulation/dataloader/Dataloader.cpp

+18-40
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,6 @@ bool Dataloader::set_roots(path_vector_t const& new_roots, path_vector_t const&
7070
fs::path Dataloader::lookup_file(std::string_view path, bool print_error) const {
7171
const fs::path filepath { ensure_forward_slash_path(path) };
7272

73-
#if defined(FILESYSTEM_CASE_INSENSITIVE)
74-
/* Case-insensitive filesystem */
75-
for (fs::path const& root : roots) {
76-
const fs::path composed = root / filepath;
77-
if (fs::is_regular_file(composed)) {
78-
if (root == roots.back()) {
79-
bool ignore = false;
80-
for (auto const& replace_path : replace_paths) {
81-
if (filepath.string().starts_with(replace_path.string())) {
82-
ignore = true;
83-
break;
84-
}
85-
}
86-
if (!ignore) {
87-
return composed;
88-
}
89-
} else {
90-
return composed;
91-
}
92-
}
93-
}
94-
#else
95-
/* Case-sensitive filesystem */
9673
const std::string_view filename = StringUtils::get_filename(path);
9774
for (fs::path const& root : roots) {
9875
const fs::path composed = root / filepath;
@@ -135,7 +112,6 @@ fs::path Dataloader::lookup_file(std::string_view path, bool print_error) const
135112
}
136113
}
137114
}
138-
#endif
139115

140116
if (print_error) {
141117
Logger::error("Lookup for \"", path, "\" failed!");
@@ -154,6 +130,17 @@ fs::path Dataloader::lookup_image_file(std::string_view path) const {
154130
return lookup_file(path);
155131
}
156132

133+
bool Dataloader::should_ignore_path(fs::path const& path, path_vector_t const& replace_paths) const {
134+
bool ignore = false;
135+
for (auto const& replace_path : replace_paths) {
136+
if (path.string().starts_with(replace_path.string())) {
137+
ignore = true;
138+
break;
139+
}
140+
}
141+
return ignore;
142+
}
143+
157144
template<typename _DirIterator, UniqueFileKey _UniqueKey>
158145
Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(
159146
std::string_view path, fs::path const& extension, _UniqueKey const& unique_key
@@ -168,17 +155,8 @@ Dataloader::path_vector_t Dataloader::_lookup_files_in_dir(
168155
for (fs::path const& root : roots) {
169156
const size_t root_len = root.string().size();
170157
std::error_code ec;
171-
if (root == roots.back()) {
172-
bool ignore = false;
173-
for (auto const& replace_path : replace_paths) {
174-
if (dirpath.string().starts_with(replace_path.string())) {
175-
ignore = true;
176-
break;
177-
}
178-
}
179-
if (ignore) {
180-
continue;
181-
}
158+
if (root == roots.back() && should_ignore_path(dirpath, replace_paths)) {
159+
continue;
182160
}
183161
for (fs::directory_entry const& entry : _DirIterator { root / dirpath, ec }) {
184162
if (entry.is_regular_file()) {
@@ -824,6 +802,11 @@ bool Dataloader::_load_map_dir(DefinitionManager& definition_manager) const {
824802
ret = false;
825803
}
826804

805+
if (!map_definition.set_water_province_list(water_province_identifiers)) {
806+
Logger::error("Failed to set water provinces!");
807+
ret = false;
808+
}
809+
827810
{
828811
std::vector<colour_t> colours;
829812
if (!MapDefinition::load_region_colours(parse_defines(lookup_file(region_colours)).get_file_node(), colours)) {
@@ -841,11 +824,6 @@ bool Dataloader::_load_map_dir(DefinitionManager& definition_manager) const {
841824
}
842825
}
843826

844-
if (!map_definition.set_water_province_list(water_province_identifiers)) {
845-
Logger::error("Failed to set water provinces!");
846-
ret = false;
847-
}
848-
849827
if (!map_definition.get_terrain_type_manager().load_terrain_types(
850828
definition_manager.get_modifier_manager(),
851829
parse_defines(lookup_file(append_string_views(map_directory, terrain_definition))).get_file_node()

Diff for: src/openvic-simulation/dataloader/Dataloader.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ namespace OpenVic {
4242
bool _load_decisions(DefinitionManager& definition_manager);
4343
bool _load_history(DefinitionManager& definition_manager, bool unused_history_file_warnings) const;
4444

45+
bool should_ignore_path(fs::path const& path, path_vector_t const& replace_paths) const;
46+
4547
/* _DirIterator is fs::directory_iterator or fs::recursive_directory_iterator. _UniqueKey is the type of a callable
4648
* which converts a string_view filepath with root removed into a string_view unique key. Any path whose key is empty
4749
* or matches an earlier found path's key is discarded, ensuring each looked up path's key is non-empty and unique. */

Diff for: src/openvic-simulation/dataloader/ModManager.cpp

+25-26
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,44 @@
55

66
#include "openvic-simulation/dataloader/NodeTools.hpp"
77
#include "openvic-simulation/types/HasIdentifier.hpp"
8-
#include "types/IdentifierRegistry.hpp"
8+
#include "openvic-simulation/types/IdentifierRegistry.hpp"
99

1010
using namespace OpenVic;
1111
using namespace OpenVic::NodeTools;
1212

1313
Mod::Mod(std::string_view new_identifier, std::string_view new_path, std::optional<std::string_view> new_user_dir, std::vector<std::string> new_replace_paths, std::vector<std::string> new_dependencies)
14-
: HasIdentifier { new_identifier }, dataloader_root_path { new_path }, user_dir { new_user_dir }, replace_paths { new_replace_paths }, dependencies { new_dependencies } {}
14+
: HasIdentifier { new_identifier }, dataloader_root_path { new_path }, user_dir { new_user_dir }, replace_paths { new_replace_paths }, dependencies { new_dependencies } {}
1515

1616
ModManager::ModManager() {}
1717

1818
bool ModManager::load_mod_file(ast::NodeCPtr root) {
19-
std::string_view identifier;
20-
std::string_view path;
21-
std::optional<std::string_view> user_dir;
22-
std::vector<std::string> replace_paths;
23-
std::vector<std::string> dependencies;
24-
25-
bool ret = NodeTools::expect_dictionary_keys(
26-
"name", ONE_EXACTLY, expect_string(assign_variable_callback(identifier)),
27-
"path", ONE_EXACTLY, expect_string(assign_variable_callback(path)),
28-
"user_dir", ZERO_OR_ONE, expect_string(assign_variable_callback_opt(user_dir)),
29-
"replace_path", ZERO_OR_MORE, expect_string(vector_callback_string(replace_paths)),
30-
"dependencies", ZERO_OR_ONE, expect_list_reserve_length(dependencies, expect_string(vector_callback_string(dependencies)))
31-
)(root);
32-
33-
std::vector<std::string_view> previous_mods = mods.get_item_identifiers();
34-
for (std::string_view dependency : dependencies) {
19+
std::string_view identifier;
20+
std::string_view path;
21+
std::optional<std::string_view> user_dir;
22+
std::vector<std::string> replace_paths;
23+
std::vector<std::string> dependencies;
24+
25+
bool ret = NodeTools::expect_dictionary_keys(
26+
"name", ONE_EXACTLY, expect_string(assign_variable_callback(identifier)),
27+
"path", ONE_EXACTLY, expect_string(assign_variable_callback(path)),
28+
"user_dir", ZERO_OR_ONE, expect_string(assign_variable_callback_opt(user_dir)),
29+
"replace_path", ZERO_OR_MORE, expect_string(vector_callback_string(replace_paths)),
30+
"dependencies", ZERO_OR_ONE, expect_list_reserve_length(dependencies, expect_string(vector_callback_string(dependencies)))
31+
)(root);
32+
33+
std::vector<std::string_view> previous_mods = mods.get_item_identifiers();
34+
for (std::string_view dependency : dependencies) {
3535
if (std::find(previous_mods.begin(), previous_mods.end(), dependency) == previous_mods.end()) {
36-
ret = false;
36+
ret = false;
3737
Logger::error("Mod ", identifier, " has unmet dependency ", dependency);
3838
}
3939
}
4040

41-
if (ret) {
42-
ret &= mods.add_item(
43-
{ identifier, path, user_dir, std::move(replace_paths), std::move(dependencies) },
44-
duplicate_fail_callback
45-
);
46-
}
41+
if (ret) {
42+
ret &= mods.add_item(
43+
{ identifier, path, user_dir, std::move(replace_paths), std::move(dependencies) }
44+
);
45+
}
4746

48-
return ret;
47+
return ret;
4948
}

Diff for: src/openvic-simulation/dataloader/ModManager.hpp

+20-20
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,33 @@
55

66
#include "openvic-simulation/types/HasIdentifier.hpp"
77
#include "openvic-simulation/types/IdentifierRegistry.hpp"
8-
#include "dataloader/NodeTools.hpp"
8+
#include "openvic-simulation/dataloader/NodeTools.hpp"
99

1010
namespace OpenVic {
1111

12-
struct Mod : HasIdentifier {
13-
friend struct ModManager;
12+
struct Mod : HasIdentifier {
13+
friend struct ModManager;
1414

15-
private:
16-
const std::string PROPERTY(dataloader_root_path);
17-
const std::optional<std::string> PROPERTY(user_dir);
18-
const std::vector<std::string> PROPERTY(replace_paths);
19-
const std::vector<std::string> PROPERTY(dependencies);
15+
private:
16+
const std::string PROPERTY(dataloader_root_path);
17+
const std::optional<std::string> PROPERTY(user_dir);
18+
const std::vector<std::string> PROPERTY(replace_paths);
19+
const std::vector<std::string> PROPERTY(dependencies);
2020

21-
Mod(std::string_view new_identifier, std::string_view new_path, std::optional<std::string_view> new_user_dir, std::vector<std::string> new_replace_paths, std::vector<std::string> new_dependencies);
21+
Mod(std::string_view new_identifier, std::string_view new_path, std::optional<std::string_view> new_user_dir, std::vector<std::string> new_replace_paths, std::vector<std::string> new_dependencies);
2222

23-
public:
24-
Mod(Mod&&) = default;
25-
};
23+
public:
24+
Mod(Mod&&) = default;
25+
};
2626

27-
struct ModManager {
28-
29-
private:
30-
IdentifierRegistry<Mod> IDENTIFIER_REGISTRY(mod);
27+
struct ModManager {
28+
29+
private:
30+
IdentifierRegistry<Mod> IDENTIFIER_REGISTRY(mod);
3131

32-
public:
33-
ModManager();
32+
public:
33+
ModManager();
3434

35-
bool load_mod_file(ast::NodeCPtr root);
36-
};
35+
bool load_mod_file(ast::NodeCPtr root);
36+
};
3737
} // namespace OpenVic

Diff for: src/openvic-simulation/dataloader/NodeTools.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ namespace OpenVic {
9898
constexpr bool key_value_success_callback(std::string_view, ast::NodeCPtr) {
9999
return true;
100100
}
101+
inline bool key_value_warn_callback(std::string_view key, ast::NodeCPtr) {
102+
Logger::warning("Invalid dictionary key: ", key);
103+
return true;
104+
}
101105
inline bool key_value_invalid_callback(std::string_view key, ast::NodeCPtr) {
102106
Logger::error("Invalid dictionary key: ", key);
103107
return false;

Diff for: src/openvic-simulation/economy/production/ProductionType.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,7 @@ bool ProductionTypeManager::load_production_types_file(
220220

221221
std::string_view template_id = "";
222222
bool found_template = false;
223-
const bool ret =
224-
expect_key(template_symbol, expect_identifier(assign_variable_callback(template_id)), &found_template)(value);
223+
const bool ret = expect_key(template_symbol, expect_identifier(assign_variable_callback(template_id)), &found_template)(value);
225224
if (found_template) {
226225
if (ret) {
227226
templates.emplace(template_id);
@@ -230,6 +229,12 @@ bool ProductionTypeManager::load_production_types_file(
230229
Logger::error("Failed get template identifier for ", key);
231230
return false;
232231
}
232+
} else {
233+
// this registers templates too, works in some mods (PDM/DoD) that have templates that are unused but aren't factories themselves
234+
if (key.ends_with(template_symbol.view())) {
235+
templates.emplace(key);
236+
template_target_map.emplace(key, key);
237+
}
233238
}
234239
return true;
235240
}

Diff for: src/openvic-simulation/history/CountryHistory.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "openvic-simulation/country/CountryDefinition.hpp"
44
#include "openvic-simulation/DefinitionManager.hpp"
5+
#include "openvic-simulation/dataloader/NodeTools.hpp"
56

67
using namespace OpenVic;
78
using namespace OpenVic::NodeTools;
@@ -135,7 +136,15 @@ bool CountryHistoryMap::_load_history_entry(
135136
),
136137
"civilized", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.civilised)),
137138
"prestige", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.prestige)),
138-
"ruling_party", ZERO_OR_ONE, country.expect_party_identifier(assign_variable_callback_pointer_opt(entry.ruling_party)),
139+
"ruling_party", ZERO_OR_ONE, [this, &entry](ast::NodeCPtr value) -> bool {
140+
country.expect_party_identifier(assign_variable_callback_pointer_opt(entry.ruling_party), true)(value);
141+
if (!entry.ruling_party.has_value()) {
142+
std::string_view def {};
143+
expect_identifier(assign_variable_callback(def))(value);
144+
Logger::warning("In ", country.get_identifier(), " history: ruling_party ", def, " does NOT exist!");
145+
}
146+
return true;
147+
},
139148
"last_election", ZERO_OR_ONE, expect_date(assign_variable_callback(entry.last_election)),
140149
"upper_house", ZERO_OR_ONE, politics_manager.get_ideology_manager().expect_ideology_dictionary(
141150
[&entry](Ideology const& ideology, ast::NodeCPtr value) -> bool {
@@ -163,7 +172,7 @@ bool CountryHistoryMap::_load_history_entry(
163172
"consciousness", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.consciousness)),
164173
"nonstate_consciousness", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.nonstate_consciousness)),
165174
"is_releasable_vassal", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.releasable_vassal)),
166-
"decision", ZERO_OR_MORE, decision_manager.expect_decision_identifier(set_callback_pointer(entry.decisions)),
175+
"decision", ZERO_OR_MORE, decision_manager.expect_decision_identifier(set_callback_pointer(entry.decisions), true), // if a mod lists an invalid decision here (as some hpm-derived mods that remove hpm decisions do) vic2 just ignores it.
167176
"govt_flag", ZERO_OR_MORE, [&entry, &politics_manager](ast::NodeCPtr value) -> bool {
168177
GovernmentTypeManager const& government_type_manager = politics_manager.get_government_type_manager();
169178
GovernmentType const* government_type = nullptr;

Diff for: src/openvic-simulation/history/HistoryMap.hpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ namespace OpenVic {
6767
const Date sub_date { Date::from_string(key, &result) };
6868
if (result.ec == std::errc{}) {
6969
if (sub_date < date) {
70-
Logger::error("History entry ", sub_date, " defined before parent entry date ", date);
71-
return false;
70+
Logger::warning("History entry ", sub_date, " defined before parent entry date ", date);
7271
}
7372
if (sub_date == date) {
7473
Logger::warning("History entry ", sub_date, " defined with same date as parent entry");

0 commit comments

Comments
 (0)