aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/openvic-simulation/dataloader/Dataloader.cpp9
-rw-r--r--src/openvic-simulation/research/Technology.cpp113
-rw-r--r--src/openvic-simulation/research/Technology.hpp21
3 files changed, 106 insertions, 37 deletions
diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp
index b7ccba3..9df9725 100644
--- a/src/openvic-simulation/dataloader/Dataloader.cpp
+++ b/src/openvic-simulation/dataloader/Dataloader.cpp
@@ -426,15 +426,15 @@ bool Dataloader::_load_technologies(GameManager& game_manager) {
const v2script::Parser technology_file_parser = parse_defines(lookup_file(technology_file));
- if (!technology_manager.load_technology_file_areas(technology_file_parser.get_file_node())) {
- Logger::error("Failed to load technology areas and folders!");
+ if (!technology_manager.load_technology_file_folders_and_areas(technology_file_parser.get_file_node())) {
+ Logger::error("Failed to load technology folders and areas!");
ret = false;
}
ModifierManager& modifier_manager = game_manager.get_modifier_manager();
if (!technology_manager.generate_modifiers(modifier_manager)) {
- Logger::error("Failed to generate technollogy-based modifiers!");
+ Logger::error("Failed to generate technology-based modifiers!");
ret = false;
}
@@ -460,6 +460,9 @@ bool Dataloader::_load_technologies(GameManager& game_manager) {
}
technology_manager.lock_technologies();
+
+ ret &= technology_manager.generate_technology_lists();
+
return ret;
}
diff --git a/src/openvic-simulation/research/Technology.cpp b/src/openvic-simulation/research/Technology.cpp
index 1d209ba..00b736c 100644
--- a/src/openvic-simulation/research/Technology.cpp
+++ b/src/openvic-simulation/research/Technology.cpp
@@ -76,41 +76,71 @@ bool TechnologyManager::add_technology_school(std::string_view identifier, Modif
return technology_schools.add_item({ identifier, std::move(values) });
}
-bool TechnologyManager::load_technology_file_areas(ast::NodeCPtr root) {
- return expect_dictionary_reserve_length(technology_folders, [this](std::string_view root_key, ast::NodeCPtr root_value) -> bool {
- if (root_key == "folders") {
- return expect_dictionary([this](std::string_view folder_key, ast::NodeCPtr folder_value) -> bool {
- bool ret = add_technology_folder(folder_key);
- TechnologyFolder const* current_folder = get_technology_folder_by_identifier(folder_key);
- if (current_folder == nullptr)
- return false;
- ret &= expect_list(expect_identifier([this, current_folder](std::string_view area) -> bool {
- return add_technology_area(area, current_folder);
- }))(folder_value);
- return ret;
- })(root_value);
+bool TechnologyManager::load_technology_file_folders_and_areas(ast::NodeCPtr root) {
+ return expect_dictionary_keys(
+ "folders", ONE_EXACTLY, [this](ast::NodeCPtr root_value) -> bool {
+ const bool ret = expect_dictionary_reserve_length(
+ technology_folders,
+ [this](std::string_view folder_key, ast::NodeCPtr folder_value) -> bool {
+ bool ret = add_technology_folder(folder_key);
+
+ TechnologyFolder const* current_folder = get_technology_folder_by_identifier(folder_key);
+ if (current_folder == nullptr) {
+ Logger::error("Failed to add and retrieve technology folder: \"", folder_key, "\"");
+ return false;
+ }
+
+ ret &= expect_list_reserve_length(
+ technology_areas,
+ expect_identifier(
+ std::bind(&TechnologyManager::add_technology_area, this, std::placeholders::_1, current_folder)
+ )
+ )(folder_value);
+
+ return ret;
+ }
+ )(root_value);
+
lock_technology_folders();
lock_technology_areas();
- } else {
- return root_key == "schools"; /* Ignore schools, error otherwise */
- }
- })(root);
+
+ return ret;
+ },
+ /* Never fail because of "schools", even if it's missing or there are duplicate entries,
+ * those issues will be caught by load_technology_file_schools. */
+ "schools", ZERO_OR_MORE, success_callback
+ )(root);
}
-bool TechnologyManager::load_technology_file_schools(ModifierManager const& modifier_manager, ast::NodeCPtr root) {
- return expect_dictionary([this, &modifier_manager](std::string_view root_key, ast::NodeCPtr root_value) -> bool {
- if (root_key == "schools") {
- return expect_dictionary_reserve_length(technology_schools, [this, &modifier_manager](std::string_view school_key, ast::NodeCPtr school_value) -> bool {
- ModifierValue modifiers;
- bool ret = modifier_manager.expect_modifier_value(move_variable_callback(modifiers))(school_value);
- ret &= add_technology_school(school_key, std::move(modifiers));
- return ret;
- })(root_value);
+bool TechnologyManager::load_technology_file_schools(
+ ModifierManager const& modifier_manager, ast::NodeCPtr root
+) {
+ if (!technology_folders.is_locked() || !technology_areas.is_locked()) {
+ Logger::error("Cannot load technology schools until technology folders and areas are locked!");
+ return false;
+ }
+ return expect_dictionary_keys(
+ /* Never fail because of "folders", even if it's missing or there are duplicate entries,
+ * those issues will have been caught by load_technology_file_folders_and_areas. */
+ "folders", ZERO_OR_MORE, success_callback,
+ "schools", ONE_EXACTLY, [this, &modifier_manager](ast::NodeCPtr root_value) -> bool {
+ const bool ret = expect_dictionary_reserve_length(
+ technology_schools,
+ [this, &modifier_manager](std::string_view school_key, ast::NodeCPtr school_value) -> bool {
+ ModifierValue modifiers;
+ bool ret = modifier_manager.expect_modifier_value(move_variable_callback(modifiers))(school_value);
+
+ ret &= add_technology_school(school_key, std::move(modifiers));
+
+ return ret;
+ }
+ )(root_value);
+
lock_technology_schools();
- } else {
- return root_key == "folders"; /* Ignore folders, error otherwise */
+
+ return ret;
}
- })(root);
+ )(root);
}
bool TechnologyManager::load_technologies_file(
@@ -118,7 +148,8 @@ bool TechnologyManager::load_technologies_file(
ast::NodeCPtr root
) {
return expect_dictionary_reserve_length(technologies, [this, &modifier_manager, &unit_manager, &building_type_manager](
- std::string_view tech_key, ast::NodeCPtr tech_value) -> bool {
+ std::string_view tech_key, ast::NodeCPtr tech_value
+ ) -> bool {
ModifierValue modifiers;
TechnologyArea const* area = nullptr;
Date::year_t year = 0;
@@ -129,7 +160,8 @@ bool TechnologyManager::load_technologies_file(
Technology::building_set_t activated_buildings;
ConditionalWeight ai_chance { scope_t::COUNTRY, scope_t::COUNTRY, scope_t::NO_SCOPE };
- bool ret = modifier_manager.expect_modifier_value_and_keys(move_variable_callback(modifiers),
+ bool ret = modifier_manager.expect_modifier_value_and_keys(
+ move_variable_callback(modifiers),
"area", ONE_EXACTLY, expect_technology_area_identifier(assign_variable_callback_pointer(area)),
"year", ONE_EXACTLY, expect_uint(assign_variable_callback(year)),
"cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(cost)),
@@ -164,8 +196,27 @@ bool TechnologyManager::generate_modifiers(ModifierManager& modifier_manager) co
bool TechnologyManager::parse_scripts(GameManager const& game_manager) {
bool ret = true;
+
for (Technology& technology : technologies.get_items()) {
ret &= technology.parse_scripts(game_manager);
}
+
return ret;
}
+
+bool TechnologyManager::generate_technology_lists() {
+ if (!technology_folders.is_locked() || !technology_areas.is_locked() || !technologies.is_locked()) {
+ Logger::error("Cannot generate technology lists until technology folders, areas, and technologies are locked!");
+ return false;
+ }
+
+ for (TechnologyArea const& area : technology_areas.get_items()) {
+ const_cast<TechnologyFolder&>(area.folder).technology_areas.push_back(&area);
+ }
+
+ for (Technology const& tech : technologies.get_items()) {
+ const_cast<TechnologyArea&>(tech.area).technologies.push_back(&tech);
+ }
+
+ return true;
+}
diff --git a/src/openvic-simulation/research/Technology.hpp b/src/openvic-simulation/research/Technology.hpp
index a4287a5..aa47301 100644
--- a/src/openvic-simulation/research/Technology.hpp
+++ b/src/openvic-simulation/research/Technology.hpp
@@ -10,21 +10,28 @@
#include "openvic-simulation/types/OrderedContainers.hpp"
namespace OpenVic {
+ struct TechnologyArea;
+
struct TechnologyFolder : HasIdentifier {
friend struct TechnologyManager;
private:
+ std::vector<TechnologyArea const*> PROPERTY(technology_areas);
+
TechnologyFolder(std::string_view new_identifier);
public:
TechnologyFolder(TechnologyFolder&&) = default;
};
+ struct Technology;
+
struct TechnologyArea : HasIdentifier {
friend struct TechnologyManager;
private:
TechnologyFolder const& PROPERTY(folder);
+ std::vector<Technology const*> PROPERTY(technologies);
TechnologyArea(std::string_view new_identifier, TechnologyFolder const& new_folder);
@@ -86,14 +93,22 @@ namespace OpenVic {
bool add_technology_school(std::string_view identifier, ModifierValue&& values);
- bool load_technology_file_areas(ast::NodeCPtr root); // common/technology.txt
- bool load_technology_file_schools(ModifierManager const& modifier_manager, ast::NodeCPtr root); // also common/technology.txt
+ /* Both of these functions load data from "common/technology.txt", they are separated because the schools depend
+ * on modifiers generated from the folder definitions and so loading must be staggered. */
+ bool load_technology_file_folders_and_areas(ast::NodeCPtr root);
+ bool load_technology_file_schools(ModifierManager const& modifier_manager, ast::NodeCPtr root);
+
+ /* Loaded from "technologies/.txt" files named after technology folders. */
bool load_technologies_file(
ModifierManager const& modifier_manager, UnitManager const& unit_manager,
BuildingTypeManager const& building_type_manager, ast::NodeCPtr root
- ); // technologies/*.txt
+ );
+
bool generate_modifiers(ModifierManager& modifier_manager) const;
+ /* Populates the lists of technology areas for each technology folder and technologies for each technology area. */
+ bool generate_technology_lists();
+
bool parse_scripts(GameManager const& game_manager);
};
} \ No newline at end of file