diff --git a/src/openvic-simulation/InstanceManager.cpp b/src/openvic-simulation/InstanceManager.cpp index 64cb30f90..0f08ee854 100644 --- a/src/openvic-simulation/InstanceManager.cpp +++ b/src/openvic-simulation/InstanceManager.cpp @@ -3,6 +3,7 @@ #include "openvic-simulation/DefinitionManager.hpp" #include "openvic-simulation/console/ConsoleInstance.hpp" #include "openvic-simulation/misc/GameAction.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/types/TypedSpan.hpp" #include "openvic-simulation/utility/Logger.hpp" #include "openvic-simulation/utility/ThreadDeps.hpp" @@ -67,8 +68,12 @@ InstanceManager::InstanceManager( }, new_definition_manager.get_pop_manager().get_pop_types(), new_definition_manager.get_politics_manager().get_issue_manager().get_reform_groups(), - new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types(), - new_definition_manager.get_military_manager().get_unit_type_manager().get_ship_types(), + get_values( + new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types() + ), + get_values( + new_definition_manager.get_military_manager().get_unit_type_manager().get_ship_types() + ), new_definition_manager.get_pop_manager().get_stratas(), new_definition_manager.get_research_manager().get_technology_manager().get_technologies(), new_definition_manager.get_military_manager().get_unit_type_manager() @@ -115,7 +120,9 @@ InstanceManager::InstanceManager( good_instance_manager, new_definition_manager.get_define_manager().get_pops_defines(), new_definition_manager.get_pop_manager().get_pop_types(), - new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types(), + get_values( + new_definition_manager.get_military_manager().get_unit_type_manager().get_regiment_types() + ), thread_pool }, unit_instance_manager { @@ -244,7 +251,7 @@ bool InstanceManager::setup() { definition_manager.get_define_manager().get_pops_defines(), definition_manager.get_economy_manager().get_production_type_manager(), definition_manager.get_modifier_manager().get_static_modifier_cache(), - country_index_t(definition_manager.get_country_definition_manager().get_country_definition_count()), + country_index_t(definition_manager.get_country_definition_manager().get_country_definitions().size()), good_index_t(definition_manager.get_economy_manager().get_good_definition_manager().get_good_definition_count()), strata_index_t(definition_manager.get_pop_manager().get_strata_count()) }, diff --git a/src/openvic-simulation/console/ConsoleInstance.cpp b/src/openvic-simulation/console/ConsoleInstance.cpp index ff035f9ab..8cb7bca25 100644 --- a/src/openvic-simulation/console/ConsoleInstance.cpp +++ b/src/openvic-simulation/console/ConsoleInstance.cpp @@ -16,13 +16,13 @@ #include "openvic-simulation/DefinitionManager.hpp" #include "openvic-simulation/InstanceManager.hpp" #include "openvic-simulation/map/ProvinceInstance.hpp" -#include "openvic-simulation/military/UnitType.hpp" #include "openvic-simulation/military/Wargoal.hpp" #include "openvic-simulation/misc/Event.hpp" #include "openvic-simulation/research/Invention.hpp" #include "openvic-simulation/research/Technology.hpp" #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/Date.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace std::string_view_literals; @@ -223,12 +223,16 @@ CountryInstance* ConsoleInstance::validate_country_tag(std::string_view value_st return nullptr; } - CountryInstance* country = instance_manager.get_country_instance_manager().get_country_instance_by_identifier(value_string); + CountryDefinition const* const country_definition_ptr = find( + instance_manager.definition_manager.get_country_definition_manager().get_country_definitions(), + value_string + ); - if (country == nullptr) { + if (country_definition_ptr == nullptr) { write_error("Unknown country"); + return nullptr; } - return country; + return &instance_manager.get_country_instance_manager().get_country_instance_by_index(country_definition_ptr->index); } Event const* ConsoleInstance::validate_event_id(std::string_view value_string) { @@ -249,26 +253,6 @@ Event const* ConsoleInstance::validate_event_id(std::string_view value_string) { return event; } -UnitType const* ConsoleInstance::validate_unit(std::string_view value_string) { - if (value_string.empty()) { - write_error("Please specify unit type"); - return nullptr; - } - - UnitType const* unit_type = // - instance_manager - .definition_manager // - .get_military_manager() - .get_unit_type_manager() - .get_unit_type_by_identifier(value_string); - - if (unit_type == nullptr) { - write_error("Unknown unit type"); - } - - return unit_type; -} - std::string_view ConsoleInstance::validate_filename(std::string_view value_string) { // TODO: validate filename return value_string; diff --git a/src/openvic-simulation/console/ConsoleInstance.hpp b/src/openvic-simulation/console/ConsoleInstance.hpp index 3eeb5f18f..4efd1256a 100644 --- a/src/openvic-simulation/console/ConsoleInstance.hpp +++ b/src/openvic-simulation/console/ConsoleInstance.hpp @@ -89,7 +89,6 @@ namespace OpenVic { ProvinceInstance* validate_province_number(std::string_view value_string); CountryInstance* validate_country_tag(std::string_view value_string); Event const* validate_event_id(std::string_view value_string); - UnitType const* validate_unit(std::string_view value_string); std::string_view validate_filename(std::string_view value_string); std::string_view validate_shader_effect(std::string_view value_string); std::string_view validate_texture_name(std::string_view value_string); diff --git a/src/openvic-simulation/core/template/RangeConcepts.hpp b/src/openvic-simulation/core/template/RangeConcepts.hpp new file mode 100644 index 000000000..1e839f223 --- /dev/null +++ b/src/openvic-simulation/core/template/RangeConcepts.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +namespace OpenVic { + template + concept RangeOfType = std::ranges::input_range + && std::convertible_to, ValueType>; +} \ No newline at end of file diff --git a/src/openvic-simulation/country/CountryDefinition.cpp b/src/openvic-simulation/country/CountryDefinition.cpp index 6814f1ee7..29584dbf0 100644 --- a/src/openvic-simulation/country/CountryDefinition.cpp +++ b/src/openvic-simulation/country/CountryDefinition.cpp @@ -4,7 +4,6 @@ #include "openvic-simulation/population/Culture.hpp" #include "openvic-simulation/types/Colour.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" using namespace OpenVic; @@ -13,10 +12,10 @@ CountryDefinition::CountryDefinition( colour_t new_colour, index_t new_index, GraphicalCultureType const& new_graphical_culture, - IdentifierRegistry&& new_parties, - unit_names_map_t&& new_unit_names, + std::remove_const_t&& new_parties, + decltype(ship_names)&& new_ship_names, bool new_is_dynamic_tag, - government_colour_map_t&& new_alternative_colours, + decltype(alternative_colours)&& new_alternative_colours, colour_t new_primary_unit_colour, colour_t new_secondary_unit_colour, colour_t new_tertiary_unit_colour @@ -24,7 +23,7 @@ CountryDefinition::CountryDefinition( HasIndex { new_index }, graphical_culture { new_graphical_culture }, parties { std::move(new_parties) }, - unit_names { std::move(new_unit_names) }, + ship_names { std::move(new_ship_names) }, is_dynamic_tag { new_is_dynamic_tag }, alternative_colours { std::move(new_alternative_colours) }, primary_unit_colour { new_primary_unit_colour }, diff --git a/src/openvic-simulation/country/CountryDefinition.hpp b/src/openvic-simulation/country/CountryDefinition.hpp index 244de5de6..0020d0c16 100644 --- a/src/openvic-simulation/country/CountryDefinition.hpp +++ b/src/openvic-simulation/country/CountryDefinition.hpp @@ -1,34 +1,37 @@ #pragma once +#include #include +#include +#include "openvic-simulation/core/memory/String.hpp" #include "openvic-simulation/core/Typedefs.hpp" #include "openvic-simulation/country/CountryParty.hpp" +#include "openvic-simulation/types/Colour.hpp" +#include "openvic-simulation/types/FixedVector.hpp" #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" +#include "openvic-simulation/types/registries/OwningRegistry.hpp" #include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { struct CountryDefinitionManager; struct GraphicalCultureType; struct GovernmentType; - struct UnitType; /* Generic information about a TAG */ struct CountryDefinition : HasIdentifierAndColour, HasIndex { friend struct CountryDefinitionManager; - - using unit_names_map_t = ordered_map>; - using government_colour_map_t = ordered_map; private: - /* Not const to allow elements to be moved, otherwise a copy is forced - * which causes a compile error as the copy constructor has been deleted. */ - IdentifierRegistry IDENTIFIER_REGISTRY_CUSTOM_PLURAL(party, parties); - unit_names_map_t PROPERTY(unit_names); - government_colour_map_t PROPERTY(alternative_colours); + memory::FixedVector< // for each ship type + memory::FixedVector< // collection of names + memory::string + >, + ship_type_index_t + > PROPERTY(ship_names); + ordered_map PROPERTY(alternative_colours); colour_t PROPERTY(primary_unit_colour); colour_t PROPERTY(secondary_unit_colour); colour_t PROPERTY(tertiary_unit_colour); @@ -37,6 +40,7 @@ namespace OpenVic { public: const bool is_dynamic_tag; + const OwningRegistry parties; GraphicalCultureType const& graphical_culture; OV_ALWAYS_INLINE bool is_rebel_country() const { @@ -45,11 +49,13 @@ namespace OpenVic { CountryDefinition( std::string_view new_identifier, colour_t new_colour, index_t new_index, - GraphicalCultureType const& new_graphical_culture, IdentifierRegistry&& new_parties, - unit_names_map_t&& new_unit_names, bool new_is_dynamic_tag, government_colour_map_t&& new_alternative_colours, + GraphicalCultureType const& new_graphical_culture, + std::remove_const_t&& new_parties, + decltype(ship_names)&& new_ship_names, + bool new_is_dynamic_tag, + decltype(alternative_colours)&& new_alternative_colours, colour_t new_primary_unit_colour, colour_t new_secondary_unit_colour, colour_t new_tertiary_unit_colour ); - CountryDefinition(CountryDefinition&&) = default; // TODO - get_colour including alternative colours }; diff --git a/src/openvic-simulation/country/CountryDefinitionManager.cpp b/src/openvic-simulation/country/CountryDefinitionManager.cpp index 4ef4a4c8d..978d1588d 100644 --- a/src/openvic-simulation/country/CountryDefinitionManager.cpp +++ b/src/openvic-simulation/country/CountryDefinitionManager.cpp @@ -1,9 +1,10 @@ #include "CountryDefinitionManager.hpp" #include +#include - - +#include "CountryDefinition.hpp" +#include "core/memory/String.hpp" #include "openvic-simulation/dataloader/Dataloader.hpp" #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/DefinitionManager.hpp" @@ -11,9 +12,12 @@ #include "openvic-simulation/politics/Ideology.hpp" #include "openvic-simulation/politics/PartyPolicy.hpp" #include "openvic-simulation/population/Culture.hpp" +#include "openvic-simulation/types/ConstructorTags.hpp" #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/FixedVector.hpp" #include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Modify.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Logger.hpp" @@ -22,8 +26,10 @@ using namespace OpenVic::NodeTools; bool CountryDefinitionManager::add_country( std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture, - IdentifierRegistry&& parties, CountryDefinition::unit_names_map_t&& unit_names, bool dynamic_tag, - CountryDefinition::government_colour_map_t&& alternative_colours + std::remove_const_t&& parties, + decltype(CountryDefinition::ship_names)&& ship_names, + bool is_dynamic_tag, + decltype(CountryDefinition::alternative_colours)&& alternative_colours ) { if (identifier.empty()) { spdlog::error_s("Invalid country identifier - empty!"); @@ -42,23 +48,29 @@ bool CountryDefinitionManager::add_country( static constexpr colour_t default_colour = colour_t::fill_as(colour_t::max_value); - return country_definitions.emplace_item( - identifier, // - identifier, colour, CountryDefinition::index_t { get_country_definition_count() }, *graphical_culture, - std::move(parties), std::move(unit_names), dynamic_tag, std::move(alternative_colours), + return emplace_item( + country_definitions, + identifier, + identifier, colour, country_definitions.size(), *graphical_culture, + std::move(parties), std::move(ship_names), is_dynamic_tag, std::move(alternative_colours), /* Default to country colour for the chest and grey for the others. Update later if necessary. */ colour, default_colour, default_colour ); } bool CountryDefinitionManager::load_countries( - DefinitionManager const& definition_manager, Dataloader const& dataloader, ovdl::v2script::ast::Node const* root + DefinitionManager const& definition_manager, + Dataloader const& dataloader, + ovdl::v2script::ast::Node const* root ) { static constexpr std::string_view common_dir = "common/"; bool is_dynamic = false; - const bool ret = expect_dictionary_reserve_length( - country_definitions, + const bool ret = expect_dictionary_and_length( + [this](const std::size_t country_count) -> std::size_t { + country_definitions.clear_and_reserve(country_index_t(country_count)); + return country_count; + }, [this, &definition_manager, &is_dynamic, &dataloader](std::string_view key, ovdl::v2script::ast::Node const* value) -> bool { if (key == "dynamic_tags") { return expect_bool([&is_dynamic](bool val) -> bool { @@ -93,29 +105,44 @@ bool CountryDefinitionManager::load_countries( return false; } )(root); - lock_country_definitions(); + lock_registry(country_definitions); return ret; } bool CountryDefinitionManager::load_country_colours(ovdl::v2script::ast::Node const* root) { - return country_definitions.expect_item_dictionary_and_default( - [](std::string_view key, ovdl::v2script::ast::Node const* value) -> bool { - spdlog::warn_s("country_colors.txt references country tag {} which is not defined!", key); - return true; - }, - [](CountryDefinition& country, ovdl::v2script::ast::Node const* colour_node) -> bool { - return expect_dictionary_keys( - "color1", ONE_EXACTLY, expect_colour(assign_variable_callback(country.primary_unit_colour)), - "color2", ONE_EXACTLY, expect_colour(assign_variable_callback(country.secondary_unit_colour)), - "color3", ONE_EXACTLY, expect_colour(assign_variable_callback(country.tertiary_unit_colour)) - )(colour_node); - } + return NodeTools::expect_list_and_length( + NodeTools::default_length_callback, + NodeTools::expect_assign( + [this](std::string_view identifier, ovdl::v2script::ast::Node const* node) -> bool { + const auto it = find(country_definitions, identifier); + if (it == country_definitions.end()) { + spdlog::warn_s("country_colors.txt references country tag {} which is not defined!", identifier); + return true; + } + + CountryDefinition& country = *it; + return expect_dictionary_keys( + "color1", ONE_EXACTLY, expect_colour(assign_variable_callback(country.primary_unit_colour)), + "color2", ONE_EXACTLY, expect_colour(assign_variable_callback(country.secondary_unit_colour)), + "color3", ONE_EXACTLY, expect_colour(assign_variable_callback(country.tertiary_unit_colour)) + )(node); + } + ) )(root); } -NodeTools::node_callback_t CountryDefinitionManager::load_country_party( - PoliticsManager const& politics_manager, IdentifierRegistry& country_parties -) const { +struct CountryPartyDto { // data transfer object + std::string_view identifier; + Date start_date; + Date end_date; + Ideology const* ideology; + memory::FixedVector policies; +}; + +static NodeTools::node_callback_t load_country_party( + PoliticsManager const& politics_manager, + memory::vector& country_parties +) { return [&politics_manager, &country_parties](ovdl::v2script::ast::Node const* value) -> bool { std::string_view party_name; Date start_date, end_date; @@ -170,24 +197,35 @@ NodeTools::node_callback_t CountryDefinitionManager::load_country_party( spdlog::warn_s("Country party {} has no ideology, defaulting to nullptr / no ideology", party_name); } - ret &= country_parties.emplace_item( - party_name, - duplicate_warning_callback, - party_name, start_date, end_date, ideology, std::move(policies) - ); + if (ret) { + country_parties.emplace_back( + party_name, + start_date, + end_date, + ideology, + std::move(policies) + ); + } return ret; }; } bool CountryDefinitionManager::load_country_data_file( - DefinitionManager const& definition_manager, std::string_view name, bool is_dynamic, ovdl::v2script::ast::Node const* root + DefinitionManager const& definition_manager, + std::string_view name, + bool is_dynamic_tag, + ovdl::v2script::ast::Node const* root ) { colour_t colour; GraphicalCultureType const* graphical_culture; - IdentifierRegistry parties { "country parties" }; - CountryDefinition::unit_names_map_t unit_names; - CountryDefinition::government_colour_map_t alternative_colours; + auto const& ship_types = definition_manager.get_military_manager().get_unit_type_manager().get_ship_types(); + decltype(CountryDefinition::ship_names) ship_names { + ship_types.size(), + [](const ship_type_index_t) { return create_empty; } + }; + decltype(CountryDefinition::alternative_colours) alternative_colours; + memory::vector party_dtos; bool ret = expect_dictionary_keys_and_default( [&definition_manager, &alternative_colours](std::string_view key, ovdl::v2script::ast::Node const* value) -> bool { return definition_manager.get_politics_manager().get_government_type_manager().expect_government_type_str( @@ -201,18 +239,36 @@ bool CountryDefinitionManager::load_country_data_file( definition_manager.get_pop_manager().get_culture_manager().expect_graphical_culture_type_identifier( assign_variable_callback_pointer(graphical_culture) ), - "party", ZERO_OR_MORE, load_country_party(definition_manager.get_politics_manager(), parties), - "unit_names", ZERO_OR_ONE, - definition_manager.get_military_manager().get_unit_type_manager().expect_unit_type_dictionary_reserve_length( - unit_names, - [&unit_names](UnitType const& unit, ovdl::v2script::ast::Node const* value) -> bool { - return name_list_callback(map_callback(unit_names, &unit))(value); + "party", ZERO_OR_MORE, load_country_party(definition_manager.get_politics_manager(), party_dtos), + "unit_names", ZERO_OR_ONE, expect_item_dictionary( + ship_types, + [&ship_names](const ship_type_index_t ship_type_index, ovdl::v2script::ast::Node const* value) -> bool { + return name_list_callback( + [&ship_names, ship_type_index](memory::FixedVector&& names) -> bool { + ship_names[ship_type_index] = std::move(names); + return true; + } + )(value); } ) )(root); + OwningRegistry parties { create_empty, party_dtos.size() }; + + for (CountryPartyDto& dto : party_dtos) { + ret &= emplace_item( + parties, + dto.identifier, + duplicate_warning_callback, + dto.identifier, dto.start_date, dto.end_date, dto.ideology, std::move(dto.policies) + ); + } + lock_registry(parties); + ret &= add_country( - name, colour, graphical_culture, std::move(parties), std::move(unit_names), is_dynamic, std::move(alternative_colours) + name, colour, graphical_culture, + std::move(parties), std::move(ship_names), + is_dynamic_tag, std::move(alternative_colours) ); return ret; } \ No newline at end of file diff --git a/src/openvic-simulation/country/CountryDefinitionManager.hpp b/src/openvic-simulation/country/CountryDefinitionManager.hpp index 53740f4e8..0803dca62 100644 --- a/src/openvic-simulation/country/CountryDefinitionManager.hpp +++ b/src/openvic-simulation/country/CountryDefinitionManager.hpp @@ -3,9 +3,11 @@ #include #include "openvic-simulation/country/CountryDefinition.hpp" -#include "openvic-simulation/country/CountryParty.hpp" -#include "openvic-simulation/dataloader/NodeCallbacks.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/dataloader/Node_forwarded.hpp" +#include "openvic-simulation/types/ConstructorTags.hpp" +#include "openvic-simulation/types/registries/OwningRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/utility/Getters.hpp" namespace OpenVic { class Dataloader; @@ -14,24 +16,30 @@ namespace OpenVic { struct CountryDefinitionManager { private: - IdentifierRegistry IDENTIFIER_REGISTRY(country_definition); - - NodeTools::node_callback_t load_country_party( - PoliticsManager const& politics_manager, IdentifierRegistry& country_parties - ) const; + OwningRegistry PROPERTY(country_definitions); public: + constexpr CountryDefinitionManager() : country_definitions(create_empty) {} + bool add_country( std::string_view identifier, colour_t colour, GraphicalCultureType const* graphical_culture, - IdentifierRegistry&& parties, CountryDefinition::unit_names_map_t&& unit_names, bool dynamic_tag, - CountryDefinition::government_colour_map_t&& alternative_colours + std::remove_const_t&& parties, + decltype(CountryDefinition::ship_names)&& ship_names, + bool is_dynamic_tag, + decltype(CountryDefinition::alternative_colours)&& alternative_colours ); bool load_country_colours(ovdl::v2script::ast::Node const* root); - bool load_countries(DefinitionManager const& definition_manager, Dataloader const& dataloader, ovdl::v2script::ast::Node const* root); + bool load_countries( + DefinitionManager const& definition_manager, + Dataloader const& dataloader, + ovdl::v2script::ast::Node const* root + ); bool load_country_data_file( - DefinitionManager const& definition_manager, std::string_view name, bool is_dynamic, ovdl::v2script::ast::Node const* root + DefinitionManager const& definition_manager, + std::string_view name, bool is_dynamic_tag, + ovdl::v2script::ast::Node const* root ); }; } diff --git a/src/openvic-simulation/country/CountryInstance.cpp b/src/openvic-simulation/country/CountryInstance.cpp index 9f8b9ca0e..7add8e06f 100644 --- a/src/openvic-simulation/country/CountryInstance.cpp +++ b/src/openvic-simulation/country/CountryInstance.cpp @@ -43,7 +43,6 @@ #include "openvic-simulation/politics/RuleSet.hpp" #include "openvic-simulation/population/Culture.hpp" #include "openvic-simulation/population/Pop.hpp" -#include "openvic-simulation/population/PopsAggregateDeps.hpp" #include "openvic-simulation/population/PopSize.hpp" #include "openvic-simulation/population/PopSum.hpp" #include "openvic-simulation/population/PopType.hpp" @@ -300,13 +299,13 @@ CountryInstance::CountryInstance( for (RegimentType const& regiment_type : country_instance_deps.regiment_types) { if (regiment_type.starts_unlocked) { - unlock_unit_type(regiment_type); + unlock_unit_type(regiment_type.index); } } for (ShipType const& ship_type : country_instance_deps.ship_types) { if (ship_type.starts_unlocked) { - unlock_unit_type(ship_type); + unlock_unit_type(ship_type.index); } } } @@ -852,7 +851,7 @@ bool CountryInstance::modify_unit_type_unlock(const regiment_type_index_t regime //recalculate entirely allowed_regiment_cultures = regiment_allowed_cultures_t::NO_CULTURES; for (RegimentType const& regiment_type : regiment_types) { - if (!is_unit_type_unlocked(regiment_type)) { + if (!is_unit_type_unlocked(regiment_type.index)) { continue; } @@ -879,42 +878,12 @@ bool CountryInstance::modify_unit_type_unlock(const ship_type_index_t ship_type_ return true; } -bool CountryInstance::modify_unit_type_unlock(UnitType const& unit_type, technology_unlock_level_t unlock_level_change) { - using enum unit_branch_t; - - switch (unit_type.branch) { - case LAND: - return modify_unit_type_unlock(static_cast const&>(unit_type).index, unlock_level_change); - case NAVAL: - return modify_unit_type_unlock(static_cast const&>(unit_type).index, unlock_level_change); - default: - spdlog::error_s( - "Attempted to change unlock level for unit type \"{}\" with invalid branch {} for country {}", - unit_type, static_cast(unit_type.branch), *this - ); - return false; - } +bool CountryInstance::unlock_unit_type(const regiment_type_index_t regiment_type_index) { + return modify_unit_type_unlock(regiment_type_index, technology_unlock_level_t { 1 }); } -bool CountryInstance::unlock_unit_type(UnitType const& unit_type) { - return modify_unit_type_unlock(unit_type, technology_unlock_level_t { 1 }); -} - -bool CountryInstance::is_unit_type_unlocked(UnitType const& unit_type) const { - using enum unit_branch_t; - - switch (unit_type.branch) { - case LAND: - return is_unit_type_unlocked(static_cast const&>(unit_type).index); - case NAVAL: - return is_unit_type_unlocked(static_cast const&>(unit_type).index); - default: - spdlog::error_s( - "Attempted to check if unit type \"{}\" with invalid branch {} is unlocked for country {}", - unit_type, static_cast(unit_type.branch), *this - ); - return false; - } +bool CountryInstance::unlock_unit_type(const ship_type_index_t ship_type_index) { + return modify_unit_type_unlock(ship_type_index, technology_unlock_level_t { 1 }); } bool CountryInstance::modify_building_type_unlock( @@ -1093,8 +1062,11 @@ bool CountryInstance::modify_technology_unlock( if (technology.get_unit_variant().has_value()) { ret &= modify_unit_variant_unlock(*technology.get_unit_variant(), unlock_level_change); } - for (UnitType const* unit : technology.activated_units) { - ret &= modify_unit_type_unlock(*unit, unlock_level_change); + for (RegimentType const* unit : technology.activated_regiment_types) { + ret &= modify_unit_type_unlock(unit->index, unlock_level_change); + } + for (ShipType const* unit : technology.activated_ship_types) { + ret &= modify_unit_type_unlock(unit->index, unlock_level_change); } for (BuildingType const* building : technology.activated_buildings) { ret &= modify_building_type_unlock(*building, unlock_level_change); @@ -1147,8 +1119,11 @@ bool CountryInstance::modify_invention_unlock( // TODO - handle invention.is_news() - for (UnitType const* unit : invention.activated_units) { - ret &= modify_unit_type_unlock(*unit, unlock_level_change); + for (RegimentType const* unit : invention.activated_regiment_types) { + ret &= modify_unit_type_unlock(unit->index, unlock_level_change); + } + for (ShipType const* unit : invention.activated_ship_types) { + ret &= modify_unit_type_unlock(unit->index, unlock_level_change); } for (BuildingType const* building : invention.activated_buildings) { ret &= modify_building_type_unlock(*building, unlock_level_change); @@ -1232,10 +1207,10 @@ void CountryInstance::start_research(Technology const& technology, const Date to } void CountryInstance::apply_foreign_investments( - fixed_point_map_t const& investments, CountryInstanceManager const& country_instance_manager + fixed_point_map_t const& investments, CountryInstanceManager const& country_instance_manager ) { - for (auto const& [country, money_invested] : investments) { - foreign_investments[country_instance_manager.get_country_instance_by_definition(*country)] = money_invested; + for (auto const& [country_index, money_invested] : investments) { + foreign_investments[country_instance_manager.get_country_instance_by_index(country_index)] = money_invested; } } @@ -1661,7 +1636,13 @@ void CountryInstance::_update_military() { supply_consumption * fp::mul_div( sum_of_regiment_type_stats, fixed_point_t::parse_raw(regular_army_size), - fixed_point_t::parse_raw(7 * (1 + unit_type_manager.get_regiment_type_count())) + fixed_point_t::parse_raw( + 7 * ( + 1 + type_safe::get( + unit_type_manager.get_regiment_types().size() + ) + ) + ) ) ); @@ -1989,9 +1970,7 @@ void CountryInstance::update_gamestate_after_map(const Date today) { _update_politics(); _update_diplomacy(); - using const_it_t = typename CountryDefinition::government_colour_map_t::const_iterator; - const const_it_t it = country_definition.get_alternative_colours().find(government_type.get_untracked()); - + const auto it = country_definition.get_alternative_colours().find(government_type.get_untracked()); if (it != country_definition.get_alternative_colours().end()) { colour = it.value(); } else { diff --git a/src/openvic-simulation/country/CountryInstance.hpp b/src/openvic-simulation/country/CountryInstance.hpp index 7d44c2ca9..52a0efef9 100644 --- a/src/openvic-simulation/country/CountryInstance.hpp +++ b/src/openvic-simulation/country/CountryInstance.hpp @@ -558,12 +558,11 @@ namespace OpenVic { [[nodiscard]] constexpr bool is_unit_type_unlocked(const ship_type_index_t ship_type_index) const { return is_unlocked(ship_type_unlock_levels[ship_type_index]); } - [[nodiscard]] bool is_unit_type_unlocked(UnitType const& unit_type) const; - bool modify_unit_type_unlock(UnitType const&, technology_unlock_level_t unlock_level_change); bool modify_unit_type_unlock(const regiment_type_index_t regiment_type_index, technology_unlock_level_t unlock_level_change); bool modify_unit_type_unlock(const ship_type_index_t ship_type_index, technology_unlock_level_t unlock_level_change); - bool unlock_unit_type(UnitType const& unit_type); + bool unlock_unit_type(const regiment_type_index_t regiment_type_index); + bool unlock_unit_type(const ship_type_index_t ship_type_index); bool modify_building_type_unlock( BuildingType const& building_type, technology_unlock_level_t unlock_level_change @@ -616,7 +615,7 @@ namespace OpenVic { // Sets the investment of each country in the map (rather than adding to them), leaving the rest unchanged. void apply_foreign_investments( - fixed_point_map_t const& investments, + fixed_point_map_t const& investments, CountryInstanceManager const& country_instance_manager ); diff --git a/src/openvic-simulation/country/CountryInstanceDeps.hpp b/src/openvic-simulation/country/CountryInstanceDeps.hpp index 487943801..9a3431b11 100644 --- a/src/openvic-simulation/country/CountryInstanceDeps.hpp +++ b/src/openvic-simulation/country/CountryInstanceDeps.hpp @@ -1,9 +1,10 @@ #pragma once -#include "openvic-simulation/core/memory/Vector.hpp" #include "openvic-simulation/core/portable/ForwardableSpan.hpp" #include "openvic-simulation/population/PopsAggregateDeps.hpp" #include "openvic-simulation/types/Date.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/TypedSpan.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" namespace OpenVic { @@ -48,8 +49,8 @@ namespace OpenVic { PopsAggregateDeps pops_aggregate_deps; forwardable_span pop_types; forwardable_span reform_groups; - memory::vector const& regiment_types; //can't use forwardable_span due to macos - memory::vector const& ship_types; + TypedSpan regiment_types; + TypedSpan ship_types; forwardable_span stratas; forwardable_span technologies; UnitTypeManager const& unit_type_manager; diff --git a/src/openvic-simulation/country/CountryInstanceManager.cpp b/src/openvic-simulation/country/CountryInstanceManager.cpp index 09aba90de..cd2e53a3e 100644 --- a/src/openvic-simulation/country/CountryInstanceManager.cpp +++ b/src/openvic-simulation/country/CountryInstanceManager.cpp @@ -11,6 +11,7 @@ #include "openvic-simulation/history/CountryHistory.hpp" #include "openvic-simulation/military/UnitInstanceGroup.hpp" #include "openvic-simulation/population/Pop.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/utility/ThreadPool.hpp" using namespace OpenVic; @@ -22,7 +23,7 @@ CountryInstanceManager::CountryInstanceManager( GoodInstanceManager const& new_good_instance_manager, PopsDefines const& new_pop_defines, forwardable_span pop_type_keys, - memory::vector const& regiment_types, + TypedSpan regiment_types, ThreadPool& new_thread_pool ) : thread_pool { new_thread_pool }, country_definition_manager { new_country_definition_manager }, @@ -34,21 +35,21 @@ CountryInstanceManager::CountryInstanceManager( regiment_types }, country_instances { - country_index_t(new_country_definition_manager.get_country_definition_count()), + new_country_definition_manager.get_country_definitions().size(), [ this, &new_country_definition_manager, &country_instance_deps ](const country_index_t country_index)->auto{ return std::make_tuple( - std::ref(*new_country_definition_manager.get_country_definition_by_index(country_index)), + std::ref(new_country_definition_manager.get_country_definitions()[country_index]), std::ref(shared_country_values), std::ref(country_instance_deps) ); } } { - assert(new_country_definition_manager.country_definitions_are_locked()); + assert(new_country_definition_manager.get_country_definitions().is_locked()); great_powers.reserve(new_country_defines.get_great_power_rank()); secondary_powers.reserve(new_country_defines.get_max_secondary_power_count()); } @@ -178,14 +179,21 @@ void CountryInstanceManager::update_rankings(const Date today) { } } +CountryDefinition const* find_country_definition_by_identifier( + CountryDefinitionManager const& country_definition_manager, + std::string_view identifier +) { + return find(country_definition_manager.get_country_definitions(), identifier); +} + CountryInstance* CountryInstanceManager::get_country_instance_by_identifier(std::string_view identifier) { - CountryDefinition const* country_definition = country_definition_manager.get_country_definition_by_identifier(identifier); + CountryDefinition const* country_definition = find_country_definition_by_identifier(country_definition_manager, identifier); return country_definition == nullptr ? nullptr - : &get_country_instance_by_definition(*country_definition); + : &(country_instances[country_definition->index]); } CountryInstance const* CountryInstanceManager::get_country_instance_by_identifier(std::string_view identifier) const { - CountryDefinition const* country_definition = country_definition_manager.get_country_definition_by_identifier(identifier); + CountryDefinition const* country_definition = find_country_definition_by_identifier(country_definition_manager, identifier); return country_definition == nullptr ? nullptr : &(country_instances[country_definition->index]); diff --git a/src/openvic-simulation/country/CountryInstanceManager.hpp b/src/openvic-simulation/country/CountryInstanceManager.hpp index c0230b7b4..5252b4ad0 100644 --- a/src/openvic-simulation/country/CountryInstanceManager.hpp +++ b/src/openvic-simulation/country/CountryInstanceManager.hpp @@ -9,6 +9,7 @@ #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/FixedVector.hpp" #include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/TypedSpan.hpp" #include "openvic-simulation/utility/Getters.hpp" namespace OpenVic { @@ -49,7 +50,7 @@ namespace OpenVic { GoodInstanceManager const& new_good_instance_manager, PopsDefines const& new_pop_defines, forwardable_span pop_type_keys, - memory::vector const& regiment_types, + TypedSpan regiment_types, ThreadPool& new_thread_pool ); diff --git a/src/openvic-simulation/country/SharedCountryValues.cpp b/src/openvic-simulation/country/SharedCountryValues.cpp index d7d5ca224..bbdf59f29 100644 --- a/src/openvic-simulation/country/SharedCountryValues.cpp +++ b/src/openvic-simulation/country/SharedCountryValues.cpp @@ -14,7 +14,7 @@ SharedCountryValues::SharedCountryValues( PopsDefines const& new_pop_defines, GoodInstanceManager const& new_good_instance_manager, decltype(shared_pop_type_values)::keys_span_type pop_type_keys, - memory::vector const& new_regiment_types + TypedSpan new_regiment_types ) : pop_defines { new_pop_defines }, good_instance_manager { new_good_instance_manager }, shared_pop_type_values { pop_type_keys }, diff --git a/src/openvic-simulation/country/SharedCountryValues.hpp b/src/openvic-simulation/country/SharedCountryValues.hpp index 71c366fd3..a04272d71 100644 --- a/src/openvic-simulation/country/SharedCountryValues.hpp +++ b/src/openvic-simulation/country/SharedCountryValues.hpp @@ -3,6 +3,8 @@ #include "openvic-simulation/population/PopNeedsMacro.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/TypedSpan.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" #include "openvic-simulation/utility/reactive/MutableState.hpp" @@ -45,7 +47,7 @@ namespace OpenVic { void update_costs(); public: - memory::vector const& regiment_types; + TypedSpan regiment_types; SharedPopTypeValues& get_shared_pop_type_values(PopType const& pop_type); @@ -53,7 +55,7 @@ namespace OpenVic { PopsDefines const& new_pop_defines, GoodInstanceManager const& new_good_instance_manager, decltype(shared_pop_type_values)::keys_span_type pop_type_keys, - memory::vector const& new_regiment_types + TypedSpan new_regiment_types ); SharedCountryValues(SharedCountryValues&&) = delete; SharedCountryValues(SharedCountryValues const&) = delete; diff --git a/src/openvic-simulation/dataloader/Dataloader.cpp b/src/openvic-simulation/dataloader/Dataloader.cpp index 2888096cd..3d7b466e6 100644 --- a/src/openvic-simulation/dataloader/Dataloader.cpp +++ b/src/openvic-simulation/dataloader/Dataloader.cpp @@ -21,6 +21,7 @@ #include "openvic-simulation/interface/UI.hpp" #include "openvic-simulation/misc/GameRulesManager.hpp" #include "openvic-simulation/misc/SoundEffect.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/utility/Logger.hpp" using namespace OpenVic; @@ -606,7 +607,8 @@ bool Dataloader::_load_history(DefinitionManager& definition_manager, bool unuse const std::string_view country_id = extract_basic_identifier_prefix(filename); CountryDefinitionManager const& country_definition_manager = definition_manager.get_country_definition_manager(); - CountryDefinition const* country = country_definition_manager.get_country_definition_by_identifier( + CountryDefinition const* country = find( + country_definition_manager.get_country_definitions(), country_id ); if (country == nullptr) { diff --git a/src/openvic-simulation/dataloader/IdentifierPolicy.hpp b/src/openvic-simulation/dataloader/IdentifierPolicy.hpp new file mode 100644 index 000000000..175df03b0 --- /dev/null +++ b/src/openvic-simulation/dataloader/IdentifierPolicy.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace OpenVic { + enum struct IdentifierPolicy : uint8_t { + Either, + Identifier, // ENG + String // "ENG" + }; +} \ No newline at end of file diff --git a/src/openvic-simulation/dataloader/NodeTools.cpp b/src/openvic-simulation/dataloader/NodeTools.cpp index faa57e164..134f18954 100644 --- a/src/openvic-simulation/dataloader/NodeTools.cpp +++ b/src/openvic-simulation/dataloader/NodeTools.cpp @@ -19,6 +19,7 @@ #include "openvic-simulation/core/ui/TextFormat.hpp" #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/fixed_point/String.hpp" +#include "openvic-simulation/types/FixedVector.hpp" #include "openvic-simulation/types/Vector.hpp" #include "openvic-simulation/utility/Getters.hpp" @@ -521,6 +522,24 @@ NodeTools::node_callback_t NodeTools::expect_dictionary(key_value_callback_t cal return expect_dictionary_and_length(default_length_callback, callback); } +NodeTools::node_callback_t NodeTools::name_list_callback(NodeTools::callback_t&&> callback) { + return [callback](ovdl::v2script::ast::Node const* node) mutable -> bool { + memory::FixedVector fixed_size_vector { create_empty }; + bool ret = expect_list_and_length( + [&fixed_size_vector](const std::size_t size) -> std::size_t { + fixed_size_vector = std::move(decltype(fixed_size_vector) { create_empty, size }); + return fixed_size_vector.capacity(); + }, + expect_identifier_or_string([&fixed_size_vector](std::string_view val) -> bool { + fixed_size_vector.emplace_back(std::move(val)); + return true; + }) + )(node); + ret &= callback(std::move(fixed_size_vector)); + return ret; + }; +} + NodeTools::node_callback_t NodeTools::name_list_callback(NodeTools::callback_t&&> callback) { return [callback](ovdl::v2script::ast::Node const* node) mutable -> bool { memory::vector list; diff --git a/src/openvic-simulation/dataloader/NodeTools.hpp b/src/openvic-simulation/dataloader/NodeTools.hpp index 8018e0ded..f9db275b0 100644 --- a/src/openvic-simulation/dataloader/NodeTools.hpp +++ b/src/openvic-simulation/dataloader/NodeTools.hpp @@ -27,6 +27,7 @@ #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/Date.hpp" #include "openvic-simulation/types/IndexedFlatMap.hpp" +#include "openvic-simulation/types/FixedVector.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/Vector.hpp" #include "openvic-simulation/utility/TslHelper.hpp" @@ -537,6 +538,7 @@ using namespace std::string_view_literals; return expect_dictionary_keys_and_length(reserve_length_callback(reservable), FWD(args)...); } + NodeTools::node_callback_t name_list_callback(NodeTools::callback_t&&> callback); NodeTools::node_callback_t name_list_callback(NodeTools::callback_t&&> callback); template diff --git a/src/openvic-simulation/history/CountryHistory.cpp b/src/openvic-simulation/history/CountryHistory.cpp index 89da34bed..569892542 100644 --- a/src/openvic-simulation/history/CountryHistory.cpp +++ b/src/openvic-simulation/history/CountryHistory.cpp @@ -5,6 +5,7 @@ #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/politics/Government.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/core/FormatValidate.hpp" using namespace OpenVic; @@ -158,7 +159,12 @@ bool CountryHistoryMap::_load_history_entry( "civilized", ZERO_OR_ONE, expect_bool(assign_variable_callback(entry.civilised)), "prestige", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.prestige)), "ruling_party", ZERO_OR_ONE, [this, &entry](ovdl::v2script::ast::Node const* value) -> bool { - country.expect_party_identifier(assign_variable_callback_pointer_opt(entry.ruling_party), true)(value); + expect_item( + country.parties, + assign_variable_callback_pointer_opt(entry.ruling_party), + true + )(value); + if (!entry.ruling_party.has_value()) { std::string_view def {}; bool is_valid = true; @@ -166,7 +172,7 @@ bool CountryHistoryMap::_load_history_entry( expect_identifier(assign_variable_callback(def))(value); // if the party specified is invalid, replace with the first valid party - for (const auto& party : country.get_parties()) { + for (const auto& party : country.parties) { if (party.start_date <= entry.date && entry.date < party.end_date) { entry.ruling_party.emplace(&party); break; @@ -176,7 +182,7 @@ bool CountryHistoryMap::_load_history_entry( // if there's somehow no valid party, we use the first defined party even though it isn't valid for the entry if (!entry.ruling_party.has_value()) { is_valid = false; - entry.ruling_party.emplace(&country.get_front_party()); + entry.ruling_party.emplace(&country.parties.front()); } spdlog::log_s( @@ -217,8 +223,10 @@ bool CountryHistoryMap::_load_history_entry( "schools", ZERO_OR_ONE, technology_manager.expect_technology_school_identifier( assign_variable_callback_pointer_opt(entry.tech_school) ), - "foreign_investment", ZERO_OR_ONE, - country_definition_manager.expect_country_definition_decimal_map(move_variable_callback(entry.foreign_investment)), + "foreign_investment", ZERO_OR_ONE, expect_item_decimal_map( + country_definition_manager.get_country_definitions(), + move_variable_callback(entry.foreign_investment) + ), "literacy", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.literacy)), "non_state_culture_literacy", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(entry.nonstate_culture_literacy)), diff --git a/src/openvic-simulation/history/CountryHistory.hpp b/src/openvic-simulation/history/CountryHistory.hpp index 898142c55..38a517184 100644 --- a/src/openvic-simulation/history/CountryHistory.hpp +++ b/src/openvic-simulation/history/CountryHistory.hpp @@ -8,6 +8,7 @@ #include "openvic-simulation/types/IndexedFlatMap.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/research/TechnologyUnlockLevel.hpp" namespace OpenVic { @@ -47,7 +48,7 @@ namespace OpenVic { std::optional PROPERTY(tech_school); ordered_map PROPERTY(technologies); ordered_map PROPERTY(inventions); - fixed_point_map_t PROPERTY(foreign_investment); + fixed_point_map_t PROPERTY(foreign_investment); std::optional PROPERTY(consciousness); std::optional PROPERTY(nonstate_consciousness); std::optional PROPERTY(literacy); diff --git a/src/openvic-simulation/history/DiplomaticHistory.cpp b/src/openvic-simulation/history/DiplomaticHistory.cpp index 1d7ced5a2..52a9c86ac 100644 --- a/src/openvic-simulation/history/DiplomaticHistory.cpp +++ b/src/openvic-simulation/history/DiplomaticHistory.cpp @@ -3,6 +3,7 @@ #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/DefinitionManager.hpp" #include "openvic-simulation/history/DiplomaticHistory.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -59,10 +60,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(first) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(second) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -81,10 +84,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(overlord) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(subject) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -103,10 +108,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(overlord) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(subject) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -125,10 +132,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(overlord) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(subject) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -147,10 +156,12 @@ bool DiplomaticHistoryManager::load_diplomacy_history_file( std::optional end {}; bool ret = expect_dictionary_keys( - "first", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "first", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(receiver) ), - "second", ONE_EXACTLY, country_definition_manager.expect_country_definition_identifier_or_string( + "second", ONE_EXACTLY, expect_item( + country_definition_manager.get_country_definitions(), assign_variable_callback_pointer(sender) ), "start_date", ONE_EXACTLY, expect_date_identifier_or_string(assign_variable_callback(start)), @@ -196,7 +207,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de ret &= expect_dictionary_keys( "add_attacker", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { for (WarHistory::war_participant_t const& attacker : attackers) { CountryDefinition const& attacker_country = attacker.country; @@ -214,7 +226,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de } ), "add_defender", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { for (WarHistory::war_participant_t const& defender : defenders) { CountryDefinition const& defender_country = defender.country; @@ -232,7 +245,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de } ), "rem_attacker", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { WarHistory::war_participant_t* participant_to_remove = nullptr; @@ -256,7 +270,8 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de } ), "rem_defender", ZERO_OR_MORE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), [¤t_date, &name](CountryDefinition const& country) -> bool { WarHistory::war_participant_t* participant_to_remove = nullptr; @@ -283,23 +298,26 @@ bool DiplomaticHistoryManager::load_war_history_file(DefinitionManager const& de CountryDefinition const* actor = nullptr; CountryDefinition const* receiver = nullptr; WargoalType const* type = nullptr; - std::optional third_party {}; + std::optional third_party {}; std::optional target {}; bool ret = expect_dictionary_keys( "actor", ONE_EXACTLY, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), assign_variable_callback_pointer(actor) ), "receiver", ONE_EXACTLY, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( + expect_item( + definition_manager.get_country_definition_manager().get_country_definitions(), assign_variable_callback_pointer(receiver) ), "casus_belli", ONE_EXACTLY, definition_manager.get_military_manager().get_wargoal_type_manager() .expect_wargoal_type_identifier(assign_variable_callback_pointer(type)), "country", ZERO_OR_ONE, - definition_manager.get_country_definition_manager().expect_country_definition_identifier( - assign_variable_callback_pointer_opt(third_party) + expect_index( + definition_manager.get_country_definition_manager().get_country_definitions(), + assign_variable_callback_opt(third_party) ), "state_province_id", ZERO_OR_ONE, definition_manager.get_map_definition().expect_province_definition_identifier( diff --git a/src/openvic-simulation/history/ProvinceHistory.cpp b/src/openvic-simulation/history/ProvinceHistory.cpp index 694ef29e2..0092ddb0c 100644 --- a/src/openvic-simulation/history/ProvinceHistory.cpp +++ b/src/openvic-simulation/history/ProvinceHistory.cpp @@ -8,6 +8,7 @@ #include "openvic-simulation/economy/BuildingLevel.hpp" #include "openvic-simulation/economy/GoodDefinition.hpp" #include "openvic-simulation/map/ProvinceDefinition.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Logger.hpp" @@ -51,18 +52,18 @@ bool ProvinceHistoryMap::_load_history_entry( }; const auto set_core_instruction = [&entry](bool add) { - return [&entry, add](CountryDefinition const& country) -> bool { - const auto it = entry.cores.find(&country); + return [&entry, add](const country_index_t country_index) -> bool { + const auto it = entry.cores.find(country_index); if (it == entry.cores.end()) { // No current core instruction - entry.cores.emplace(&country, add); + entry.cores.emplace(country_index, add); return true; } else if (it->second == add) { // Desired core instruction already exists spdlog::warn_s( "Duplicate attempt to {} core of country {} {} province history of {}", add ? "add" : "remove", - country, + country_index, add ? "to" : "from", entry.province ); @@ -73,7 +74,7 @@ bool ProvinceHistoryMap::_load_history_entry( spdlog::warn_s( "Attempted to {} core of country {} {} province history of {} after previously {} it", add ? "add" : "remove", - country, + country_index, add ? "to" : "from", entry.province, add ? "removing" : "adding" @@ -132,16 +133,20 @@ bool ProvinceHistoryMap::_load_history_entry( return _load_history_sub_entry_callback(definition_manager, entry.date, value, key_map, key, value); }, - "owner", ZERO_OR_ONE, country_definition_manager.expect_country_definition_identifier( - assign_variable_callback_pointer_opt(entry.owner, true) + "owner", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(entry.owner, true) ), - "controller", ZERO_OR_ONE, country_definition_manager.expect_country_definition_identifier( - assign_variable_callback_pointer_opt(entry.controller, true) + "controller", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(entry.controller, true) ), - "add_core", ZERO_OR_MORE, country_definition_manager.expect_country_definition_identifier( + "add_core", ZERO_OR_MORE, expect_index( + country_definition_manager.get_country_definitions(), set_core_instruction(true) ), - "remove_core", ZERO_OR_MORE, country_definition_manager.expect_country_definition_identifier( + "remove_core", ZERO_OR_MORE, expect_index( + country_definition_manager.get_country_definitions(), set_core_instruction(false) ), "colonial", ZERO_OR_ONE, diff --git a/src/openvic-simulation/history/ProvinceHistory.hpp b/src/openvic-simulation/history/ProvinceHistory.hpp index fcab3d584..43363f785 100644 --- a/src/openvic-simulation/history/ProvinceHistory.hpp +++ b/src/openvic-simulation/history/ProvinceHistory.hpp @@ -35,11 +35,11 @@ namespace OpenVic { Date new_date ); private: - std::optional PROPERTY(owner); - std::optional PROPERTY(controller); + std::optional PROPERTY(owner); + std::optional PROPERTY(controller); std::optional PROPERTY(colonial); std::optional PROPERTY(slave); - ordered_map PROPERTY(cores); + ordered_map PROPERTY(cores); std::optional PROPERTY(rgo_production_type_nullable); std::optional PROPERTY(life_rating); std::optional PROPERTY(terrain_type); diff --git a/src/openvic-simulation/history/diplomacy/WarHistory.hpp b/src/openvic-simulation/history/diplomacy/WarHistory.hpp index 2a13ce3b3..80590ec53 100644 --- a/src/openvic-simulation/history/diplomacy/WarHistory.hpp +++ b/src/openvic-simulation/history/diplomacy/WarHistory.hpp @@ -6,6 +6,7 @@ #include "openvic-simulation/core/memory/Vector.hpp" #include "openvic-simulation/history/Period.hpp" #include "openvic-simulation/types/Date.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/utility/Getters.hpp" namespace OpenVic { @@ -24,7 +25,7 @@ namespace OpenVic { WargoalType const& wargoal; // TODO - could these just be nullptr when unset rather than using optionals? - const std::optional third_party; + const std::optional third_party; const std::optional target; constexpr added_wargoal_t( @@ -32,7 +33,7 @@ namespace OpenVic { CountryDefinition const& new_actor, CountryDefinition const& new_receiver, WargoalType const& new_wargoal, - std::optional new_third_party, + std::optional new_third_party, std::optional new_target ) : date_added { new_date_added }, actor { new_actor }, diff --git a/src/openvic-simulation/map/ProvinceInstance.cpp b/src/openvic-simulation/map/ProvinceInstance.cpp index 6d0e0cdaf..ad689793a 100644 --- a/src/openvic-simulation/map/ProvinceInstance.cpp +++ b/src/openvic-simulation/map/ProvinceInstance.cpp @@ -476,19 +476,19 @@ bool ProvinceInstance::apply_history_to_province(ProvinceHistoryEntry const& ent } }; - if (entry.get_owner()) { - ret &= set_owner(&country_manager.get_country_instance_by_definition(**entry.get_owner())); + if (const auto owner = entry.get_owner(); owner.has_value()) { + ret &= set_owner(&country_manager.get_country_instance_by_index(owner.value())); } - if (entry.get_controller()) { - ret &= set_controller(&country_manager.get_country_instance_by_definition(**entry.get_controller())); + if (const auto controller = entry.get_controller(); controller.has_value()) { + ret &= set_controller(&country_manager.get_country_instance_by_index(controller.value())); } set_optional(colony_status, entry.get_colonial()); set_optional(slave, entry.get_slave()); - for (auto const& [country, add] : entry.get_cores()) { + for (auto const& [country_index, add] : entry.get_cores()) { if (add) { - ret &= add_core(country_manager.get_country_instance_by_definition(*country), true); + ret &= add_core(country_manager.get_country_instance_by_index(country_index), true); } else { - ret &= remove_core(country_manager.get_country_instance_by_definition(*country), true); + ret &= remove_core(country_manager.get_country_instance_by_index(country_index), true); } } diff --git a/src/openvic-simulation/military/DeploymentManager.cpp b/src/openvic-simulation/military/DeploymentManager.cpp index a3d92aaa6..142cbb053 100644 --- a/src/openvic-simulation/military/DeploymentManager.cpp +++ b/src/openvic-simulation/military/DeploymentManager.cpp @@ -6,6 +6,7 @@ #include "openvic-simulation/military/MilitaryManager.hpp" #include "openvic-simulation/military/Leader.hpp" #include "openvic-simulation/military/LeaderTrait.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -161,8 +162,10 @@ bool DeploymentManager::load_oob_file( const bool ret = expect_dictionary_keys( "name", ONE_EXACTLY, expect_string(assign_variable_callback(regiment_name)), - "type", ONE_EXACTLY, military_manager.get_unit_type_manager() - .expect_regiment_type_identifier(assign_variable_callback_pointer(regiment_type)), + "type", ONE_EXACTLY, expect_item( + military_manager.get_unit_type_manager().get_regiment_types(), + assign_variable_callback_pointer(regiment_type) + ), "home", ZERO_OR_ONE, map_definition .expect_province_definition_identifier(assign_variable_callback_pointer(regiment_home)) )(node); @@ -214,8 +217,10 @@ bool DeploymentManager::load_oob_file( const bool ret = expect_dictionary_keys( "name", ONE_EXACTLY, expect_string(assign_variable_callback(ship_name)), - "type", ONE_EXACTLY, military_manager.get_unit_type_manager() - .expect_ship_type_identifier(assign_variable_callback_pointer(ship_type)) + "type", ONE_EXACTLY, expect_item( + military_manager.get_unit_type_manager().get_ship_types(), + assign_variable_callback_pointer(ship_type) + ) )(node); if (ship_type == nullptr) { diff --git a/src/openvic-simulation/military/UnitTypeManager.cpp b/src/openvic-simulation/military/UnitTypeManager.cpp index 7d5319774..a7f73e07f 100644 --- a/src/openvic-simulation/military/UnitTypeManager.cpp +++ b/src/openvic-simulation/military/UnitTypeManager.cpp @@ -9,8 +9,11 @@ #include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/modifier/ModifierEffectCache.hpp" #include "openvic-simulation/types/FixedVector.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Modify.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" #include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" +#include "types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -19,15 +22,13 @@ using enum unit_branch_t; using enum UnitType::unit_category_t; void UnitTypeManager::reserve_all_unit_types(size_t size) { - reserve_more_unit_types(size); - reserve_more_regiment_types(size); - reserve_more_ship_types(size); + regiment_types.clear_and_reserve(regiment_type_index_t(size)); + ship_types.clear_and_reserve(ship_type_index_t(size)); } void UnitTypeManager::lock_all_unit_types() { - unit_types.lock(); - regiment_types.lock(); - ship_types.lock(); + lock_registry(regiment_types); + lock_registry(ship_types); } static bool _check_shared_parameters(std::string_view identifier, UnitType::unit_type_args_t const& unit_args) { @@ -63,21 +64,17 @@ bool UnitTypeManager::add_regiment_type( // TODO check that sprite_override, sprite_mount, and sprite_mount_attach_node exist - if (ship_types.has_identifier(identifier)) { + if (has_identifier(ship_types, identifier)) { spdlog::error_s("Land unit {} already exists as a naval unit!", identifier); return false; } - bool ret = regiment_types.emplace_item( + return emplace_item( + regiment_types, identifier, - RegimentType::index_t { get_regiment_type_count() }, identifier, + regiment_types.size(), identifier, unit_args, std::move(regiment_type_args) ); - if (ret) { - // Cannot use get_back_regiment_type() as we need non-const but don't want to generate all non-const functions. - ret &= unit_types.emplace_via_copy(®iment_types.back()); - } - return ret; } bool UnitTypeManager::add_ship_type( @@ -96,21 +93,17 @@ bool UnitTypeManager::add_ship_type( spdlog::warn_s("Supply consumption score for {} is not positive!", identifier); } - if (regiment_types.has_identifier(identifier)) { + if (has_identifier(regiment_types, identifier)) { spdlog::error_s("Naval unit {} already exists as a land unit!", identifier); return false; } - bool ret = ship_types.emplace_item( + return emplace_item( + ship_types, identifier, - ShipType::index_t { get_ship_type_count() }, identifier, + ship_types.size(), identifier, unit_args, ship_type_args ); - if (ret) { - // Cannot use get_back_ship_type() as we need non-const but don't want to generate all non-const functions. - ret &= unit_types.emplace_via_copy(&ship_types.back()); - } - return ret; } bool UnitTypeManager::load_unit_type_file( @@ -325,7 +318,7 @@ bool UnitTypeManager::generate_modifiers(ModifierManager& modifier_manager) cons regiment_type_effects = std::move( decltype(ModifierEffectCache::regiment_type_effects) { generate_values, - regiment_type_index_t(get_regiment_type_count()) + regiment_types.size() } ); @@ -341,7 +334,7 @@ bool UnitTypeManager::generate_modifiers(ModifierManager& modifier_manager) cons ship_type_effects = std::move( decltype(ModifierEffectCache::ship_type_effects) { generate_values, - ship_type_index_t(get_ship_type_count()) + ship_types.size() } ); diff --git a/src/openvic-simulation/military/UnitTypeManager.hpp b/src/openvic-simulation/military/UnitTypeManager.hpp index c6bd41e9c..472a80d49 100644 --- a/src/openvic-simulation/military/UnitTypeManager.hpp +++ b/src/openvic-simulation/military/UnitTypeManager.hpp @@ -4,7 +4,9 @@ #include "openvic-simulation/core/template/FunctionalConcepts.hpp" #include "openvic-simulation/military/UnitType.hpp" -#include "openvic-simulation/types/IdentifierRegistry.hpp" +#include "openvic-simulation/types/ConstructorTags.hpp" +#include "openvic-simulation/types/registries/OwningRegistry.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" #include "openvic-simulation/types/UnitBranchType.hpp" namespace ovdl::v2script { @@ -18,11 +20,14 @@ namespace OpenVic { struct UnitTypeManager { private: - IdentifierPointerRegistry IDENTIFIER_REGISTRY(unit_type); - IdentifierRegistry IDENTIFIER_REGISTRY(regiment_type); - IdentifierRegistry IDENTIFIER_REGISTRY(ship_type); + OwningRegistry PROPERTY(regiment_types); + OwningRegistry PROPERTY(ship_types); public: + constexpr UnitTypeManager() : + regiment_types(create_empty), + ship_types(create_empty) {} + void reserve_all_unit_types(size_t size); void lock_all_unit_types(); diff --git a/src/openvic-simulation/misc/GameAction.cpp b/src/openvic-simulation/misc/GameAction.cpp index dc7727b45..fd28f1a5c 100644 --- a/src/openvic-simulation/misc/GameAction.cpp +++ b/src/openvic-simulation/misc/GameAction.cpp @@ -293,16 +293,17 @@ bool GameActionManager::VariantVisitor::operator() (set_mobilise_argument_t cons bool GameActionManager::VariantVisitor::operator() (start_land_unit_recruitment_argument_t const& argument) const { const auto [regiment_type_index, province_index, pop_id_in_province] = argument; - - RegimentType const* const regiment_type = instance_manager.definition_manager + auto const& regiment_types = instance_manager.definition_manager .get_military_manager() .get_unit_type_manager() - .get_regiment_type_by_index(regiment_type_index); - if (OV_unlikely(regiment_type == nullptr)) { + .get_regiment_types(); + if (OV_unlikely(regiment_type_index < regiment_type_index_t{} || regiment_type_index >= regiment_types.size())) { spdlog::error_s("GAME_ACTION_START_LAND_UNIT_RECRUITMENT called with invalid regiment type index: {}", regiment_type_index); return false; } + RegimentType const& regiment_type = regiment_types[regiment_type_index]; + ProvinceInstance* province = instance_manager .get_map_instance() .get_province_instance_by_index(province_index); diff --git a/src/openvic-simulation/population/Culture.cpp b/src/openvic-simulation/population/Culture.cpp index f113789b1..506f098cb 100644 --- a/src/openvic-simulation/population/Culture.cpp +++ b/src/openvic-simulation/population/Culture.cpp @@ -10,13 +10,13 @@ GraphicalCultureType::GraphicalCultureType(std::string_view new_identifier) : Ha CultureGroup::CultureGroup( std::string_view new_identifier, std::string_view new_leader, GraphicalCultureType const& new_unit_graphical_culture_type, - bool new_is_overseas, CountryDefinition const* new_union_country + bool new_is_overseas, std::optional new_union_country ) : HasIdentifier { new_identifier }, leader { new_leader }, unit_graphical_culture_type { new_unit_graphical_culture_type }, is_overseas { new_is_overseas }, union_country { new_union_country } {} Culture::Culture( std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group, memory::vector&& new_first_names, - memory::vector&& new_last_names, fixed_point_t new_radicalism, CountryDefinition const* new_primary_country + memory::vector&& new_last_names, fixed_point_t new_radicalism, std::optional new_primary_country ) : HasIdentifierAndColour { new_identifier, new_colour, false }, group { new_group }, first_names { std::move(new_first_names) }, last_names { std::move(new_last_names) }, radicalism { new_radicalism }, primary_country { new_primary_country } {} diff --git a/src/openvic-simulation/population/Culture.hpp b/src/openvic-simulation/population/Culture.hpp index 7f2071da0..2cf0d7762 100644 --- a/src/openvic-simulation/population/Culture.hpp +++ b/src/openvic-simulation/population/Culture.hpp @@ -1,14 +1,15 @@ #pragma once +#include + #include "openvic-simulation/core/memory/String.hpp" #include "openvic-simulation/core/memory/Vector.hpp" #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/types/fixed_point/FixedPoint.hpp" #include "openvic-simulation/types/HasIdentifier.hpp" +#include "openvic-simulation/types/TypedIndices.hpp" namespace OpenVic { - struct CountryDefinition; - struct GraphicalCultureType : HasIdentifier { friend struct CultureManager; @@ -26,18 +27,14 @@ namespace OpenVic { public: GraphicalCultureType const& unit_graphical_culture_type; const bool is_overseas; - CountryDefinition const* const union_country; + const std::optional union_country; CultureGroup( std::string_view new_identifier, std::string_view new_leader, GraphicalCultureType const& new_unit_graphical_culture_type, bool new_is_overseas, - CountryDefinition const* new_union_country + std::optional new_union_country ); CultureGroup(CultureGroup&&) = default; - - constexpr bool has_union_country() const { - return union_country != nullptr; - } }; struct Culture : HasIdentifierAndColour { @@ -48,16 +45,16 @@ namespace OpenVic { public: CultureGroup const& group; const fixed_point_t radicalism; - CountryDefinition const* const primary_country; + const std::optional primary_country; Culture( std::string_view new_identifier, colour_t new_colour, CultureGroup const& new_group, memory::vector&& new_first_names, - memory::vector&& new_last_names, fixed_point_t new_radicalism, CountryDefinition const* new_primary_country + memory::vector&& new_last_names, fixed_point_t new_radicalism, std::optional new_primary_country ); Culture(Culture&&) = default; constexpr bool has_union_country() const { - return group.has_union_country(); + return group.union_country.has_value(); } }; } diff --git a/src/openvic-simulation/population/CultureManager.cpp b/src/openvic-simulation/population/CultureManager.cpp index 6e2882096..f0e189afa 100644 --- a/src/openvic-simulation/population/CultureManager.cpp +++ b/src/openvic-simulation/population/CultureManager.cpp @@ -8,6 +8,7 @@ #include "openvic-simulation/types/Colour.hpp" #include "openvic-simulation/core/string/Utility.hpp" #include "openvic-simulation/core/Typedefs.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -27,7 +28,7 @@ bool CultureManager::add_graphical_culture_type(std::string_view identifier) { bool CultureManager::add_culture_group( std::string_view identifier, std::string_view leader, GraphicalCultureType const* graphical_culture_type, bool is_overseas, - CountryDefinition const* union_country + std::optional union_country ) { if (!graphical_culture_types.is_locked()) { spdlog::error_s("Cannot register culture groups until graphical culture types are locked!"); @@ -68,7 +69,7 @@ bool CultureManager::add_culture_group( bool CultureManager::add_culture( std::string_view identifier, colour_t colour, CultureGroup const& group, memory::vector&& first_names, - memory::vector&& last_names, fixed_point_t radicalism, CountryDefinition const* primary_country + memory::vector&& last_names, fixed_point_t radicalism, std::optional primary_country ) { if (!culture_groups.is_locked()) { spdlog::error_s("Cannot register cultures until culture groups are locked!"); @@ -90,7 +91,7 @@ bool CultureManager::add_culture( bool CultureManager::load_graphical_culture_type_file(ovdl::v2script::ast::Node const* root) { const bool ret = expect_list_reserve_length( graphical_culture_types, - expect_identifier(std::bind_front(&CultureManager::add_graphical_culture_type, this)) + NodeTools::expect_identifier(std::bind_front(&CultureManager::add_graphical_culture_type, this)) )(root); lock_graphical_culture_types(); @@ -113,15 +114,17 @@ bool CultureManager::_load_culture_group( std::string_view leader {}; GraphicalCultureType const* unit_graphical_culture_type = default_graphical_culture_type; bool is_overseas = true; - CountryDefinition const* union_country = nullptr; + std::optional union_country; bool ret = expect_dictionary_keys_and_default( increment_callback(total_expected_cultures), "leader", ZERO_OR_ONE, expect_identifier(assign_variable_callback(leader)), // acts like ONE_EXACTLY, but vic2 doesn't complain and loads anyway if not present, for now I just commuted the error to a warning in the add function and fudged a default leader from the first defined culture group if it exists - brickpi "unit", ZERO_OR_ONE, expect_graphical_culture_type_identifier(assign_variable_callback_pointer(unit_graphical_culture_type)), - "union", ZERO_OR_ONE, - country_definition_manager.expect_country_definition_identifier(assign_variable_callback_pointer(union_country)), + "union", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(union_country) + ), "is_overseas", ZERO_OR_ONE, expect_bool(assign_variable_callback(is_overseas)) )(culture_group_node); ret &= add_culture_group(culture_group_key, leader, unit_graphical_culture_type, is_overseas, union_country); @@ -135,15 +138,18 @@ bool CultureManager::_load_culture( colour_t colour = colour_t::null(); memory::vector first_names {}, last_names {}; fixed_point_t radicalism = 0; - CountryDefinition const* primary_country = nullptr; + std::optional primary_country; bool ret = expect_dictionary_keys( "color", ONE_EXACTLY, expect_colour(assign_variable_callback(colour)), "first_names", ONE_EXACTLY, name_list_callback(move_variable_callback(first_names)), "last_names", ONE_EXACTLY, name_list_callback(move_variable_callback(last_names)), "radicalism", ZERO_OR_ONE, expect_fixed_point(assign_variable_callback(radicalism)), - "primary", ZERO_OR_ONE, - country_definition_manager.expect_country_definition_identifier(assign_variable_callback_pointer(primary_country)) + "primary", ZERO_OR_ONE, expect_index( + country_definition_manager.get_country_definitions(), + assign_variable_callback_opt(primary_country), + false + ) )(culture_node); ret &= add_culture( culture_key, colour, culture_group, std::move(first_names), std::move(last_names), radicalism, primary_country diff --git a/src/openvic-simulation/population/CultureManager.hpp b/src/openvic-simulation/population/CultureManager.hpp index d34066836..5bf47ad4f 100644 --- a/src/openvic-simulation/population/CultureManager.hpp +++ b/src/openvic-simulation/population/CultureManager.hpp @@ -40,12 +40,12 @@ namespace OpenVic { bool add_culture_group( std::string_view identifier, std::string_view leader, GraphicalCultureType const* graphical_culture_type, - bool is_overseas, CountryDefinition const* union_country + bool is_overseas, std::optional union_country ); bool add_culture( std::string_view identifier, colour_t colour, CultureGroup const& group, memory::vector&& first_names, - memory::vector&& last_names, fixed_point_t radicalism, CountryDefinition const* primary_country + memory::vector&& last_names, fixed_point_t radicalism, std::optional primary_country ); bool load_graphical_culture_type_file(ovdl::v2script::ast::Node const* root); diff --git a/src/openvic-simulation/population/Pop.cpp b/src/openvic-simulation/population/Pop.cpp index 9fb8be96a..219fd3897 100644 --- a/src/openvic-simulation/population/Pop.cpp +++ b/src/openvic-simulation/population/Pop.cpp @@ -199,7 +199,7 @@ void Pop::update_location_based_attributes() { } CountryDefinition const& country_definition = owner->country_definition; - auto view = country_definition.get_parties() | std::views::transform( + auto view = country_definition.parties | std::views::transform( [](CountryParty const& key) { return std::make_pair(&key, fixed_point_t::_0); } diff --git a/src/openvic-simulation/population/PopManager.cpp b/src/openvic-simulation/population/PopManager.cpp index 4fee536d0..d9d70ae59 100644 --- a/src/openvic-simulation/population/PopManager.cpp +++ b/src/openvic-simulation/population/PopManager.cpp @@ -14,6 +14,7 @@ #include "openvic-simulation/politics/RebelManager.hpp" #include "openvic-simulation/population/Pop.hpp" #include "openvic-simulation/population/PopSize.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp" #include "openvic-simulation/utility/Logger.hpp" using namespace OpenVic; @@ -167,7 +168,7 @@ bool PopManager::add_pop_type( life_needs_income_types, everyday_needs_income_types, luxury_needs_income_types, - PopType::rebel_units_t{}, + fixed_point_map_t{}, max_size, merge_max_size, state_capital_only, @@ -399,9 +400,12 @@ bool PopManager::load_delayed_parse_pop_type_data( pop_type->promote_to = std::move(decltype(PopType::promote_to){get_pop_types()}); - if (rebel_units != nullptr && !unit_type_manager.expect_unit_type_decimal_map( - move_variable_callback(pop_type->rebel_units) - )(rebel_units)) { + if (rebel_units != nullptr + && !expect_item_decimal_map( + unit_type_manager.get_regiment_types(), + move_variable_callback(pop_type->rebel_units) + )(rebel_units) + ) { spdlog::error_s("Errors parsing rebel unit distribution for pop type {}!", ovfmt::validate(pop_type)); ret = false; } diff --git a/src/openvic-simulation/population/PopType.cpp b/src/openvic-simulation/population/PopType.cpp index 12a463db0..718155a6f 100644 --- a/src/openvic-simulation/population/PopType.cpp +++ b/src/openvic-simulation/population/PopType.cpp @@ -2,7 +2,6 @@ #include -#include "openvic-simulation/country/CountryDefinition.hpp" #include "openvic-simulation/map/ProvinceInstance.hpp" #include "openvic-simulation/utility/TslHelper.hpp" @@ -23,7 +22,7 @@ PopType::PopType( income_type_t new_life_needs_income_types, income_type_t new_everyday_needs_income_types, income_type_t new_luxury_needs_income_types, - rebel_units_t&& new_rebel_units, + fixed_point_map_t&& new_rebel_units, pop_size_t new_max_size, pop_size_t new_merge_max_size, bool new_state_capital_only, diff --git a/src/openvic-simulation/population/PopType.hpp b/src/openvic-simulation/population/PopType.hpp index 2bef12ef1..54554f63f 100644 --- a/src/openvic-simulation/population/PopType.hpp +++ b/src/openvic-simulation/population/PopType.hpp @@ -46,7 +46,6 @@ namespace OpenVic { MILITARY = 1 << 2 }; - using rebel_units_t = fixed_point_map_t; using poptype_weight_map_t = IndexedFlatMap; using ideology_weight_map_t = IndexedFlatMap; using issue_weight_map_t = ordered_map; @@ -58,7 +57,7 @@ namespace OpenVic { income_type_t PROPERTY(life_needs_income_types); income_type_t PROPERTY(everyday_needs_income_types); income_type_t PROPERTY(luxury_needs_income_types); - rebel_units_t PROPERTY(rebel_units); + fixed_point_map_t PROPERTY(rebel_units); PopType const* PROPERTY(equivalent); ConditionalWeightFactorMul PROPERTY(country_migration_target); /* Scope - country, THIS - pop */ @@ -103,7 +102,7 @@ namespace OpenVic { income_type_t new_life_needs_income_types, income_type_t new_everyday_needs_income_types, income_type_t new_luxury_needs_income_types, - rebel_units_t&& new_rebel_units, + fixed_point_map_t&& new_rebel_units, pop_size_t new_max_size, pop_size_t new_merge_max_size, bool new_state_capital_only, diff --git a/src/openvic-simulation/population/PopsAggregate.cpp b/src/openvic-simulation/population/PopsAggregate.cpp index 05eeb25a1..020b1d5b1 100644 --- a/src/openvic-simulation/population/PopsAggregate.cpp +++ b/src/openvic-simulation/population/PopsAggregate.cpp @@ -253,7 +253,7 @@ void PopsAggregate::update_parties_for_votes(CountryDefinition const* country_de return; } - auto view = country_definition->get_parties() | std::views::transform( + auto view = country_definition->parties | std::views::transform( [](CountryParty const& key) { return std::make_pair(&key, fixed_point_t::_0); } diff --git a/src/openvic-simulation/research/Invention.cpp b/src/openvic-simulation/research/Invention.cpp index f7535cfaa..4827bfd06 100644 --- a/src/openvic-simulation/research/Invention.cpp +++ b/src/openvic-simulation/research/Invention.cpp @@ -7,7 +7,8 @@ Invention::Invention( std::string_view new_identifier, ModifierValue&& new_values, bool new_is_news, - unit_set_t&& new_activated_units, + std::remove_const_t&& new_activated_regiment_types, + std::remove_const_t&& new_activated_ship_types, building_set_t&& new_activated_buildings, crime_set_t&& new_enabled_crimes, bool new_unlocks_gas_attack, @@ -18,7 +19,8 @@ Invention::Invention( ) : HasIndex { new_index }, Modifier { new_identifier, std::move(new_values), modifier_type_t::INVENTION }, is_news { new_is_news }, - activated_units { std::move(new_activated_units) }, + activated_regiment_types { std::move(new_activated_regiment_types) }, + activated_ship_types { std::move(new_activated_ship_types) }, activated_buildings { std::move(new_activated_buildings) }, enabled_crimes { std::move(new_enabled_crimes) }, unlocks_gas_attack { new_unlocks_gas_attack }, diff --git a/src/openvic-simulation/research/Invention.hpp b/src/openvic-simulation/research/Invention.hpp index 9bdfa8aef..60c07b58a 100644 --- a/src/openvic-simulation/research/Invention.hpp +++ b/src/openvic-simulation/research/Invention.hpp @@ -1,10 +1,13 @@ #pragma once +#include + #include "openvic-simulation/modifier/Modifier.hpp" #include "openvic-simulation/scripts/ConditionalWeight.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/OrderedContainers.hpp" #include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/UnitBranchType.hpp" namespace OpenVic { struct BuildingType; @@ -17,7 +20,6 @@ namespace OpenVic { friend struct InventionManager; //TODO implement limit and chance - using unit_set_t = ordered_set; using building_set_t = ordered_set; using crime_set_t = ordered_set; @@ -31,7 +33,8 @@ namespace OpenVic { public: const bool is_news; - const unit_set_t activated_units; + const ordered_set activated_regiment_types; + const ordered_set activated_ship_types; const building_set_t activated_buildings; const crime_set_t enabled_crimes; const bool unlocks_gas_attack; @@ -42,7 +45,8 @@ namespace OpenVic { std::string_view new_identifier, ModifierValue&& new_values, bool new_is_news, - unit_set_t&& new_activated_units, + std::remove_const_t&& new_activated_regiment_types, + std::remove_const_t&& new_activated_ship_types, building_set_t&& new_activated_buildings, crime_set_t&& new_enabled_crimes, bool new_unlocks_gas_attack, diff --git a/src/openvic-simulation/research/InventionManager.cpp b/src/openvic-simulation/research/InventionManager.cpp index 755aaf19e..b51a4cf93 100644 --- a/src/openvic-simulation/research/InventionManager.cpp +++ b/src/openvic-simulation/research/InventionManager.cpp @@ -1,17 +1,22 @@ #include "InventionManager.hpp" +#include + #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/economy/BuildingTypeManager.hpp" #include "openvic-simulation/map/CrimeManager.hpp" #include "openvic-simulation/military/UnitTypeManager.hpp" #include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/research/TechnologyManager.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; bool InventionManager::add_invention( - std::string_view identifier, ModifierValue&& values, bool news, Invention::unit_set_t&& activated_units, + std::string_view identifier, ModifierValue&& values, bool news, + std::remove_const_t&& activated_regiment_types, + std::remove_const_t&& activated_ship_types, Invention::building_set_t&& activated_buildings, Invention::crime_set_t&& enabled_crimes, bool unlock_gas_attack, bool unlock_gas_defence, ConditionScript&& limit, ConditionalWeightBase&& chance, memory::vector&& raw_associated_tech_identifiers @@ -23,7 +28,8 @@ bool InventionManager::add_invention( return inventions.emplace_item( identifier, Invention::index_t { get_invention_count() }, identifier, std::move(values), news, - std::move(activated_units), std::move(activated_buildings), std::move(enabled_crimes), unlock_gas_attack, + std::move(activated_regiment_types), std::move(activated_ship_types), + std::move(activated_buildings), std::move(enabled_crimes), unlock_gas_attack, unlock_gas_defence, std::move(limit), std::move(chance), std::move(raw_associated_tech_identifiers) ); @@ -40,7 +46,14 @@ bool InventionManager::load_inventions_file( ModifierValue loose_modifiers; ModifierValue modifiers; - Invention::unit_set_t activated_units; + auto const& regiment_types = unit_type_manager.get_regiment_types(); + std::remove_const_t activated_regiment_types; + assert_is_locked(regiment_types); + + auto const& ship_types = unit_type_manager.get_ship_types(); + std::remove_const_t activated_ship_types; + assert_is_locked(ship_types); + Invention::building_set_t activated_buildings; Invention::crime_set_t enabled_crimes; @@ -80,8 +93,20 @@ bool InventionManager::load_inventions_file( modifier_manager.expect_technology_modifier(modifiers), "gas_attack", ZERO_OR_ONE, expect_bool(assign_variable_callback(unlock_gas_attack)), "gas_defence", ZERO_OR_ONE, expect_bool(assign_variable_callback(unlock_gas_defence)), - "activate_unit", ZERO_OR_MORE, - unit_type_manager.expect_unit_type_identifier(set_callback_pointer(activated_units)), + "activate_unit", ZERO_OR_MORE, NodeTools::expect_identifier( + [ + &activated_regiment_types, &activated_ship_types, + ®iment_types, &ship_types + ](std::string_view identifier) -> bool { + if (const auto regiment_it = find(regiment_types, identifier); regiment_it != regiment_types.end()) { + return (activated_regiment_types.emplace(regiment_it)).second; + } + if (const auto ship_it = find(ship_types, identifier); ship_it != ship_types.end()) { + return (activated_ship_types.emplace(ship_it)).second; + } + return false; + } + ), "activate_building", ZERO_OR_MORE, building_type_manager.expect_building_type_identifier( set_callback_pointer(activated_buildings) ), @@ -94,7 +119,9 @@ bool InventionManager::load_inventions_file( modifiers += loose_modifiers; ret &= add_invention( - identifier, std::move(modifiers), news, std::move(activated_units), std::move(activated_buildings), + identifier, std::move(modifiers), news, + std::move(activated_regiment_types), std::move(activated_ship_types), + std::move(activated_buildings), std::move(enabled_crimes), unlock_gas_attack, unlock_gas_defence, std::move(limit), std::move(chance), std::move(found_tech_ids) ); diff --git a/src/openvic-simulation/research/InventionManager.hpp b/src/openvic-simulation/research/InventionManager.hpp index db2eb3e46..664bd1d42 100644 --- a/src/openvic-simulation/research/InventionManager.hpp +++ b/src/openvic-simulation/research/InventionManager.hpp @@ -16,7 +16,9 @@ namespace OpenVic { public: bool add_invention( - std::string_view identifier, ModifierValue&& values, bool news, Invention::unit_set_t&& activated_units, + std::string_view identifier, ModifierValue&& values, bool news, + std::remove_const_t&& activated_regiment_types, + std::remove_const_t&& activated_ship_types, Invention::building_set_t&& activated_buildings, Invention::crime_set_t&& enabled_crimes, bool unlock_gas_attack, bool unlock_gas_defence, ConditionScript&& limit, ConditionalWeightBase&& chance, memory::vector&& raw_associated_tech_identifiers diff --git a/src/openvic-simulation/research/Technology.cpp b/src/openvic-simulation/research/Technology.cpp index 898d64a7e..74cebfa8d 100644 --- a/src/openvic-simulation/research/Technology.cpp +++ b/src/openvic-simulation/research/Technology.cpp @@ -17,7 +17,8 @@ Technology::Technology( area_index_t new_index_in_area, bool new_unciv_military, std::optional&& new_unit_variant, - unit_set_t&& new_activated_units, + std::remove_const_t&& new_activated_regiment_types, + std::remove_const_t&& new_activated_ship_types, building_set_t&& new_activated_buildings, ModifierValue&& new_values, ConditionalWeightFactorMul&& new_ai_chance @@ -29,7 +30,8 @@ Technology::Technology( index_in_area { new_index_in_area }, unciv_military { new_unciv_military }, unit_variant { std::move(new_unit_variant) }, - activated_units { std::move(new_activated_units) }, + activated_regiment_types { std::move(new_activated_regiment_types) }, + activated_ship_types { std::move(new_activated_ship_types) }, activated_buildings { std::move(new_activated_buildings) }, ai_chance { std::move(new_ai_chance) } {} diff --git a/src/openvic-simulation/research/Technology.hpp b/src/openvic-simulation/research/Technology.hpp index c0a7be304..64a2153d6 100644 --- a/src/openvic-simulation/research/Technology.hpp +++ b/src/openvic-simulation/research/Technology.hpp @@ -10,6 +10,7 @@ #include "openvic-simulation/types/HasIdentifier.hpp" #include "openvic-simulation/types/HasIndex.hpp" #include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/UnitBranchType.hpp" #include "openvic-simulation/types/UnitVariant.hpp" namespace OpenVic { @@ -48,7 +49,6 @@ namespace OpenVic { friend struct TechnologyManager; using area_index_t = uint8_t; - using unit_set_t = ordered_set; using building_set_t = ordered_set; private: @@ -64,7 +64,8 @@ namespace OpenVic { const fixed_point_t cost; const area_index_t index_in_area; const bool unciv_military; - const unit_set_t activated_units; + const ordered_set activated_regiment_types; + const ordered_set activated_ship_types; const building_set_t activated_buildings; Technology( @@ -76,7 +77,8 @@ namespace OpenVic { area_index_t new_index_in_area, bool new_unciv_military, std::optional&& new_unit_variant, - unit_set_t&& new_activated_units, + std::remove_const_t&& new_activated_regiment_types, + std::remove_const_t&& new_activated_ship_types, building_set_t&& new_activated_buildings, ModifierValue&& new_values, ConditionalWeightFactorMul&& new_ai_chance diff --git a/src/openvic-simulation/research/TechnologyManager.cpp b/src/openvic-simulation/research/TechnologyManager.cpp index a0faca333..13318b348 100644 --- a/src/openvic-simulation/research/TechnologyManager.cpp +++ b/src/openvic-simulation/research/TechnologyManager.cpp @@ -6,6 +6,7 @@ #include "openvic-simulation/modifier/ModifierManager.hpp" #include "openvic-simulation/types/FixedVector.hpp" #include "openvic-simulation/types/TypedIndices.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -36,7 +37,9 @@ bool TechnologyManager::add_technology_area(std::string_view identifier, Technol bool TechnologyManager::add_technology( std::string_view identifier, TechnologyArea* area, Date::year_t year, fixed_point_t cost, bool unciv_military, - std::optional&& unit_variant, Technology::unit_set_t&& activated_units, + std::optional&& unit_variant, + std::remove_const_t&& activated_regiment_types, + std::remove_const_t&& activated_ship_types, Technology::building_set_t&& activated_buildings, ModifierValue&& values, ConditionalWeightFactorMul&& ai_chance ) { if (identifier.empty()) { @@ -71,7 +74,8 @@ bool TechnologyManager::add_technology( static_cast(index_in_area), unciv_military, std::move(unit_variant), - std::move(activated_units), + std::move(activated_regiment_types), + std::move(activated_ship_types), std::move(activated_buildings), std::move(values), std::move(ai_chance) @@ -179,7 +183,15 @@ bool TechnologyManager::load_technologies_file( fixed_point_t cost = 0; bool unciv_military = false; std::optional unit_variant; - Technology::unit_set_t activated_units; + + auto const& regiment_types = unit_type_manager.get_regiment_types(); + std::remove_const_t activated_regiment_types; + assert_is_locked(regiment_types); + + auto const& ship_types = unit_type_manager.get_ship_types(); + std::remove_const_t activated_ship_types; + assert_is_locked(ship_types); + Technology::building_set_t activated_buildings; ConditionalWeightFactorMul ai_chance { COUNTRY, COUNTRY, NO_SCOPE }; @@ -190,8 +202,20 @@ bool TechnologyManager::load_technologies_file( "cost", ONE_EXACTLY, expect_fixed_point(assign_variable_callback(cost)), "unciv_military", ZERO_OR_ONE, expect_bool(assign_variable_callback(unciv_military)), "unit", ZERO_OR_ONE, expect_uint(assign_variable_callback_opt(unit_variant)), - "activate_unit", ZERO_OR_MORE, - unit_type_manager.expect_unit_type_identifier(set_callback_pointer(activated_units)), + "activate_unit", ZERO_OR_MORE,NodeTools::expect_identifier( + [ + &activated_regiment_types, &activated_ship_types, + ®iment_types, &ship_types + ](std::string_view identifier) -> bool { + if (const auto regiment_it = find(regiment_types, identifier); regiment_it != regiment_types.end()) { + return (activated_regiment_types.emplace(regiment_it)).second; + } + if (const auto ship_it = find(ship_types, identifier); ship_it != ship_types.end()) { + return (activated_ship_types.emplace(ship_it)).second; + } + return false; + } + ), "activate_building", ZERO_OR_MORE, building_type_manager.expect_building_type_identifier( set_callback_pointer(activated_buildings) ), @@ -199,7 +223,8 @@ bool TechnologyManager::load_technologies_file( )(tech_value); ret &= add_technology( - tech_key, area, year, cost, unciv_military, std::move(unit_variant), std::move(activated_units), + tech_key, area, year, cost, unciv_military, std::move(unit_variant), + std::move(activated_regiment_types), std::move(activated_ship_types), std::move(activated_buildings), std::move(modifiers), std::move(ai_chance) ); return ret; diff --git a/src/openvic-simulation/research/TechnologyManager.hpp b/src/openvic-simulation/research/TechnologyManager.hpp index 618664cdf..16922b2a1 100644 --- a/src/openvic-simulation/research/TechnologyManager.hpp +++ b/src/openvic-simulation/research/TechnologyManager.hpp @@ -31,7 +31,9 @@ namespace OpenVic { bool add_technology( std::string_view identifier, TechnologyArea* area, Date::year_t year, fixed_point_t cost, bool unciv_military, - std::optional&& unit_variant, Technology::unit_set_t&& activated_units, + std::optional&& unit_variant, + std::remove_const_t&& activated_regiment_types, + std::remove_const_t&& activated_ship_types, Technology::building_set_t&& activated_buildings, ModifierValue&& values, ConditionalWeightFactorMul&& ai_chance ); diff --git a/src/openvic-simulation/scripts/ConditionManager.cpp b/src/openvic-simulation/scripts/ConditionManager.cpp index de61819df..1424d8434 100644 --- a/src/openvic-simulation/scripts/ConditionManager.cpp +++ b/src/openvic-simulation/scripts/ConditionManager.cpp @@ -2,8 +2,10 @@ #include +#include "openvic-simulation/core/template/RangeConcepts.hpp" #include "openvic-simulation/dataloader/NodeTools.hpp" #include "openvic-simulation/DefinitionManager.hpp" +#include "openvic-simulation/types/registries/OwningRegistry_Search.hpp" using namespace OpenVic; using namespace OpenVic::NodeTools; @@ -324,14 +326,14 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana ret &= add_condition("strata", IDENTIFIER, POP, NO_SCOPE, NO_IDENTIFIER, POP_STRATA); ret &= add_condition("type", IDENTIFIER, POP, NO_SCOPE, NO_IDENTIFIER, POP_TYPE); - const auto import_identifiers = [this, &ret]( - memory::vector const& identifiers, + const auto import_identifiers = [this, &ret]( + R const& identifiers, value_type_t value_type, scope_type_t scope, scope_type_t scope_change = NO_SCOPE, identifier_type_t key_identifier_type = NO_IDENTIFIER, identifier_type_t value_identifier_type = NO_IDENTIFIER - ) -> void { + ) -> void requires RangeOfType { for (std::string_view const& identifier : identifiers) { ret &= add_condition( identifier, value_type, scope, scope_change, @@ -342,7 +344,9 @@ bool ConditionManager::setup_conditions(DefinitionManager const& definition_mana /* Scopes from other registries */ import_identifiers( - definition_manager.get_country_definition_manager().get_country_definition_identifiers(), + get_identifiers( + definition_manager.get_country_definition_manager().get_country_definitions() + ), GROUP, COUNTRY, COUNTRY, @@ -452,7 +456,7 @@ NodeTools::callback_t ConditionManager::expect_parse_identifie return [this, &definition_manager, identifier_type, callback](std::string_view identifier) mutable -> bool { HasIdentifier const* identified = nullptr; - #define EXPECT_CALL(type, name, manager, ...) \ + #define EXPECT_CALL_IDENTIFIERGRESITRY(type, name, manager, ...) \ if (share_identifier_type(identifier_type, type)) { \ identified = manager.get_##name##_by_identifier(identifier); \ if (identified != nullptr) { \ @@ -465,6 +469,19 @@ NodeTools::callback_t ConditionManager::expect_parse_identifie } \ }) \ } + #define EXPECT_CALL_OWNINGRESITRY(type, registry, ...) \ + if (share_identifier_type(identifier_type, type)) { \ + const auto it = find(registry, identifier); \ + if (it != registry.end()) { \ + return callback(&*it); \ + } __VA_OPT__(else { \ + /* TODO: the set is just a placeholder for actual logic */ \ + static const case_insensitive_string_set_t chances { __VA_ARGS__ }; \ + if (chances.contains(identifier)) { \ + return true; \ + } \ + }) \ + } //TODO: placeholder for not implemented stuff #define EXPECT_CALL_PLACEHOLDER(type) \ @@ -474,38 +491,41 @@ NodeTools::callback_t ConditionManager::expect_parse_identifie EXPECT_CALL_PLACEHOLDER(GLOBAL_FLAG); EXPECT_CALL_PLACEHOLDER(COUNTRY_FLAG); EXPECT_CALL_PLACEHOLDER(PROVINCE_FLAG); - EXPECT_CALL( - COUNTRY_TAG, country_definition, definition_manager.get_country_definition_manager(), "THIS", "FROM", "OWNER" + EXPECT_CALL_OWNINGRESITRY( + COUNTRY_TAG, definition_manager.get_country_definition_manager().get_country_definitions(), + "THIS", "FROM", "OWNER" ); - EXPECT_CALL(PROVINCE_ID, province_definition, definition_manager.get_map_definition(), "THIS", "FROM"); - EXPECT_CALL(REGION, region, definition_manager.get_map_definition()); - EXPECT_CALL(IDEOLOGY, ideology, definition_manager.get_politics_manager().get_ideology_manager()); - EXPECT_CALL(REFORM_GROUP, reform_group, definition_manager.get_politics_manager().get_issue_manager()); - EXPECT_CALL(REFORM, reform, definition_manager.get_politics_manager().get_issue_manager()); - EXPECT_CALL(PARTY_POLICY, party_policy, definition_manager.get_politics_manager().get_issue_manager()); - EXPECT_CALL(POP_TYPE, pop_type, definition_manager.get_pop_manager()); - EXPECT_CALL(POP_STRATA, strata, definition_manager.get_pop_manager()); - EXPECT_CALL(TECHNOLOGY, technology, definition_manager.get_research_manager().get_technology_manager()); - EXPECT_CALL(INVENTION, invention, definition_manager.get_research_manager().get_invention_manager()); - EXPECT_CALL(TECH_SCHOOL, technology_school, definition_manager.get_research_manager().get_technology_manager()); - EXPECT_CALL(CULTURE, culture, definition_manager.get_pop_manager().get_culture_manager(), "THIS", "FROM"); - EXPECT_CALL(CULTURE_GROUP, culture_group, definition_manager.get_pop_manager().get_culture_manager()); - EXPECT_CALL(RELIGION, religion, definition_manager.get_pop_manager().get_religion_manager(), "THIS", "FROM"); - EXPECT_CALL(TRADE_GOOD, good_definition, definition_manager.get_economy_manager().get_good_definition_manager()); - EXPECT_CALL(BUILDING, building_type, definition_manager.get_economy_manager().get_building_type_manager(), "FACTORY"); - EXPECT_CALL(CASUS_BELLI, wargoal_type, definition_manager.get_military_manager().get_wargoal_type_manager()); - EXPECT_CALL(GOVERNMENT_TYPE, government_type, definition_manager.get_politics_manager().get_government_type_manager()); - EXPECT_CALL(COUNTRY_EVENT_MODIFIER | PROVINCE_EVENT_MODIFIER, event_modifier, definition_manager.get_modifier_manager()); - EXPECT_CALL(COUNTRY_EVENT_MODIFIER, triggered_modifier, definition_manager.get_modifier_manager()); - EXPECT_CALL(NATIONAL_VALUE, national_value, definition_manager.get_politics_manager().get_national_value_manager()); - EXPECT_CALL( - CULTURE_UNION, country_definition, definition_manager.get_country_definition_manager(), "THIS", "FROM", "THIS_UNION" + EXPECT_CALL_IDENTIFIERGRESITRY(PROVINCE_ID, province_definition, definition_manager.get_map_definition(), "THIS", "FROM"); + EXPECT_CALL_IDENTIFIERGRESITRY(REGION, region, definition_manager.get_map_definition()); + EXPECT_CALL_IDENTIFIERGRESITRY(IDEOLOGY, ideology, definition_manager.get_politics_manager().get_ideology_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(REFORM_GROUP, reform_group, definition_manager.get_politics_manager().get_issue_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(REFORM, reform, definition_manager.get_politics_manager().get_issue_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(PARTY_POLICY, party_policy, definition_manager.get_politics_manager().get_issue_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(POP_TYPE, pop_type, definition_manager.get_pop_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(POP_STRATA, strata, definition_manager.get_pop_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(TECHNOLOGY, technology, definition_manager.get_research_manager().get_technology_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(INVENTION, invention, definition_manager.get_research_manager().get_invention_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(TECH_SCHOOL, technology_school, definition_manager.get_research_manager().get_technology_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(CULTURE, culture, definition_manager.get_pop_manager().get_culture_manager(), "THIS", "FROM"); + EXPECT_CALL_IDENTIFIERGRESITRY(CULTURE_GROUP, culture_group, definition_manager.get_pop_manager().get_culture_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(RELIGION, religion, definition_manager.get_pop_manager().get_religion_manager(), "THIS", "FROM"); + EXPECT_CALL_IDENTIFIERGRESITRY(TRADE_GOOD, good_definition, definition_manager.get_economy_manager().get_good_definition_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(BUILDING, building_type, definition_manager.get_economy_manager().get_building_type_manager(), "FACTORY"); + EXPECT_CALL_IDENTIFIERGRESITRY(CASUS_BELLI, wargoal_type, definition_manager.get_military_manager().get_wargoal_type_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(GOVERNMENT_TYPE, government_type, definition_manager.get_politics_manager().get_government_type_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(COUNTRY_EVENT_MODIFIER | PROVINCE_EVENT_MODIFIER, event_modifier, definition_manager.get_modifier_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(COUNTRY_EVENT_MODIFIER, triggered_modifier, definition_manager.get_modifier_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(NATIONAL_VALUE, national_value, definition_manager.get_politics_manager().get_national_value_manager()); + EXPECT_CALL_OWNINGRESITRY( + CULTURE_UNION, definition_manager.get_country_definition_manager().get_country_definitions(), + "THIS", "FROM", "THIS_UNION" ); - EXPECT_CALL(CONTINENT, continent, definition_manager.get_map_definition()); - EXPECT_CALL(CRIME, crime_modifier, definition_manager.get_crime_manager()); - EXPECT_CALL(TERRAIN, terrain_type, definition_manager.get_map_definition().get_terrain_type_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(CONTINENT, continent, definition_manager.get_map_definition()); + EXPECT_CALL_IDENTIFIERGRESITRY(CRIME, crime_modifier, definition_manager.get_crime_manager()); + EXPECT_CALL_IDENTIFIERGRESITRY(TERRAIN, terrain_type, definition_manager.get_map_definition().get_terrain_type_manager()); - #undef EXPECT_CALL + #undef EXPECT_CALL_IDENTIFIERGRESITRY + #undef EXPECT_CALL_OWNINGRESITRY #undef EXPECT_CALL_PLACEHOLDER return false; diff --git a/src/openvic-simulation/types/registries/OwningRegistry.hpp b/src/openvic-simulation/types/registries/OwningRegistry.hpp new file mode 100644 index 000000000..bdb5caa5b --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry.hpp @@ -0,0 +1,120 @@ +#pragma once + +#include +#include + +#include + +#include "openvic-simulation/core/Assert.hpp" +#include "openvic-simulation/types/ConstructorTags.hpp" +#include "openvic-simulation/types/FixedVector.hpp" + +namespace OpenVic { + struct owning_registry_internal_tag {}; + + template< + typename ValueType, + typename SizeType, + typename Allocator = foonathan::memory::default_allocator + > + struct OwningRegistry { + private: + bool _is_locked { false }; + memory::FixedVector _values; + + constexpr void swap(OwningRegistry& other) noexcept { + std::swap(_is_locked, other._is_locked); + std::swap(_values, other._values); + } + + public: + constexpr OwningRegistry(OwningRegistry&& other) noexcept : _values(create_empty) { + swap(other); + } + + template + requires (sizeof...(Args) != 1 || (!std::is_same_v, OwningRegistry> && ...)) + constexpr OwningRegistry(Args&&... args) : _values(std::forward(args)...) {} + + [[nodiscard]] constexpr bool is_locked() const { return _is_locked; } + [[nodiscard]] constexpr bool& is_locked_internal(owning_registry_internal_tag) { return _is_locked; } + [[nodiscard]] constexpr decltype(_values)& values_internal(owning_registry_internal_tag) { return _values; } + constexpr void clear_and_reserve(const SizeType new_cap) noexcept { + assert(!_is_locked); + _is_locked = false; + _values = std::move( + decltype(_values) { + create_empty, + new_cap + } + ); + } + + // Member types based on std::vector + using value_type = typename decltype(_values)::value_type; + using size_type = SizeType; + using difference_type = typename decltype(_values)::difference_type; + using reference = typename decltype(_values)::reference; + using const_reference = typename decltype(_values)::const_reference; + using iterator = typename decltype(_values)::iterator; + using const_iterator = typename decltype(_values)::const_iterator; + using reverse_iterator = typename decltype(_values)::reverse_iterator; + using const_reverse_iterator = typename decltype(_values)::const_reverse_iterator; + + // Element access based on std::vector + [[nodiscard]] constexpr reference operator[](const size_type pos) { + OV_HARDEN_ASSERT_ACCESS(pos, "operator[]"); + return _values[pos]; + } + [[nodiscard]] constexpr const_reference operator[](const size_type pos) const { + OV_HARDEN_ASSERT_ACCESS(pos, "operator[]"); + return _values[pos]; + } + + [[nodiscard]] constexpr reference front() { + OV_HARDEN_ASSERT_NONEMPTY("front"); + return _values[0]; + } + [[nodiscard]] constexpr const_reference front() const { + OV_HARDEN_ASSERT_NONEMPTY("front"); + return _values[0]; + } + + [[nodiscard]] constexpr reference back() { + OV_HARDEN_ASSERT_NONEMPTY("back"); + return _values[_values.size()-1]; + } + [[nodiscard]] constexpr const_reference back() const { + OV_HARDEN_ASSERT_NONEMPTY("back"); + return _values[_values.size()-1]; + } + + [[nodiscard]] constexpr value_type* data() noexcept { return _values.data(); } + [[nodiscard]] constexpr value_type const* data() const noexcept { return _values.data(); } + + // Iterators based on std::vector + [[nodiscard]] constexpr iterator begin() noexcept { return _values.begin(); } + [[nodiscard]] constexpr const_iterator begin() const noexcept { return _values.begin(); } + [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return _values.cbegin(); } + + [[nodiscard]] constexpr iterator end() noexcept { return _values.end(); } + [[nodiscard]] constexpr const_iterator end() const noexcept { return _values.end(); } + [[nodiscard]] constexpr const_iterator cend() const noexcept { return _values.cend(); } + + [[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return _values.rbegin(); } + [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return _values.rbegin(); } + [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return _values.crbegin(); } + + [[nodiscard]] constexpr reverse_iterator rend() noexcept { return _values.rend(); } + [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return _values.rend(); } + [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return _values.crend(); } + + // Capacity based on std::vector + [[nodiscard]] constexpr bool empty() const noexcept { return _values.empty(); } + [[nodiscard]] constexpr size_type size() const noexcept { return _values.size(); } + [[nodiscard]] constexpr size_type max_size() const noexcept { return _values.max_size(); } + [[nodiscard]] constexpr size_type capacity() const noexcept { return _values.capacity(); } + + // Modifiers omitted on purpose + }; +} \ No newline at end of file diff --git a/src/openvic-simulation/types/registries/OwningRegistry_Modify.hpp b/src/openvic-simulation/types/registries/OwningRegistry_Modify.hpp new file mode 100644 index 000000000..5eb59470f --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry_Modify.hpp @@ -0,0 +1,141 @@ +#pragma once + +#include + +#include "OwningRegistry.hpp" +#include "OwningRegistry_Search.hpp" + +#include "openvic-simulation/core/template/FunctionalConcepts.hpp" +#include "openvic-simulation/core/Typedefs.hpp" +#include "openvic-simulation/utility/Logger.hpp" + +namespace OpenVic { + inline bool duplicate_fail_cb(std::string_view registry_name, std::string_view duplicate_identifier) { + spdlog::error_s( + "Failure adding item to the {} registry - an item with the identifier \"{}\" already exists!", + registry_name, duplicate_identifier + ); + return false; + } + inline bool duplicate_warning_cb(std::string_view registry_name, std::string_view duplicate_identifier) { + spdlog::warn_s( + "Warning adding item to the {} registry - an item with the identifier \"{}\" already exists!", + registry_name, duplicate_identifier + ); + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline void lock_registry( + OwningRegistry& registry, + const bool should_log = false + ) { + if (registry.is_locked()) { + spdlog::error_s("Failed to lock {} registry - already locked!", OpenVic::type_name()); + } else { + registry.is_locked_internal(owning_registry_internal_tag{}) = true; + if (should_log) { + SPDLOG_INFO("Locked {} registry after registering {} items", OpenVic::type_name(), registry.size()); + } + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr bool validate_emplacement( + OwningRegistry& registry, + const std::string_view identifier, + Callback auto duplicate_callback + ) { + assert(!registry.is_locked()); + if (registry.is_locked()) { + spdlog::error_s("Cannot emplace_item to the {} registry - locked!", OpenVic::type_name()); + return false; + } + + assert(registry.size() < registry.capacity()); + if (registry.size() >= registry.capacity()) { + spdlog::error_s("Cannot emplace_item to the {} registry - no capacity!", OpenVic::type_name()); + return false; + } + + if (has_identifier(registry, identifier)) { + return duplicate_callback(OpenVic::type_name(), identifier); + } + + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator, + typename... Args + > + inline constexpr bool emplace_item( + OwningRegistry& registry, + const std::string_view identifier, + Callback auto duplicate_callback, + Args&&... args + ) { + if (!validate_emplacement(registry, identifier, duplicate_callback)) { + return false; + } + + registry.values_internal(owning_registry_internal_tag{}).emplace_back(std::forward(args)...); + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator, + typename... Args + > + inline constexpr bool emplace_item( + OwningRegistry& registry, + std::string_view identifier, + Args&&... args + ) { + return emplace_item(registry, identifier, duplicate_fail_cb, std::forward(args)...); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr bool emplace_via_move( + OwningRegistry& registry, + std::string_view identifier, + Callback auto duplicate_callback, + ValueType&& item + ) { + if (!validate_emplacement(registry, identifier, duplicate_callback)) { + return false; + } + + registry.values_internal(owning_registry_internal_tag{}).emplace_back(std::move(item)); + return true; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr bool emplace_via_move( + OwningRegistry& registry, + std::string_view identifier, + ValueType&& item + ) { + return emplace_via_move(registry, identifier, duplicate_fail_cb, std::move(item)); + } +} \ No newline at end of file diff --git a/src/openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp b/src/openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp new file mode 100644 index 000000000..abcdc76a3 --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry_NodeTools.hpp @@ -0,0 +1,252 @@ +#pragma once + +#include + +#include "OwningRegistry.hpp" +#include "OwningRegistry_Search.hpp" + +#include "openvic-simulation/core/template/FunctionalConcepts.hpp" +#include "openvic-simulation/core/Typedefs.hpp" +#include "openvic-simulation/dataloader/IdentifierPolicy.hpp" +#include "openvic-simulation/dataloader/NodeTools.hpp" +#include "openvic-simulation/types/fixed_point/FixedPoint.hpp" +#include "openvic-simulation/types/fixed_point/FixedPointMap.hpp" +#include "openvic-simulation/utility/Logger.hpp" + +namespace OpenVic { + inline constexpr NodeTools::KeyValueCallback auto key_value_invalid_callback(std::string_view name) { + return [name](std::string_view key, ovdl::v2script::ast::Node const*) -> bool { + spdlog::error_s("Invalid {}: {}", name, key); + return false; + }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr Callback auto expect_index_by_identifier( + OwningRegistry const& registry, + Callback auto callback, + bool allow_empty = false, + bool warn = false + ) { + assert_is_locked(registry); + return [®istry, callback, allow_empty, warn](std::string_view identifier) -> bool { + if (identifier.empty()) { + if (allow_empty) { + return true; + } else { + spdlog::log_s( + warn ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: empty!", OpenVic::type_name() + ); + return warn; + } + } + const auto it = find(registry, identifier); + if (it != registry.end()) { + return callback(SizeType(std::distance(registry.begin(), it))); + } + spdlog::log_s( + warn ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: {}", OpenVic::type_name(), identifier + ); + return warn; + }; + } + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline NodeTools::node_callback_t expect_index( + OwningRegistry const& registry, + Callback auto callback, + bool allow_empty = false, + bool warn = false + ) { + return NodeTools::expect_identifier(expect_index_by_identifier(registry, callback)); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr Callback auto expect_mutable_item_by_identifier( + OwningRegistry& registry, + Callback auto callback, + bool allow_empty = false, + bool warn = false + ) { + assert_is_locked(registry); + return [®istry, callback, allow_empty, warn](std::string_view identifier) -> bool { + if (identifier.empty()) { + if (allow_empty) { + return true; + } else { + spdlog::log_s( + warn ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: empty!", OpenVic::type_name() + ); + return warn; + } + } + const auto it = find(registry, identifier); + if (it != registry.end()) { + return callback(*it); + } + spdlog::log_s( + warn ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: {}", OpenVic::type_name(), identifier + ); + return warn; + }; + } + template< + IdentifierPolicy Policy = IdentifierPolicy::Either, + typename ValueType, + typename SizeType, + typename Allocator + > + inline NodeTools::node_callback_t expect_mutable_item( + OwningRegistry& registry, + Callback auto callback, + bool allow_empty = false, + bool warn = false + ) { + if constexpr (Policy == IdentifierPolicy::Either) { + return NodeTools::expect_identifier_or_string(expect_mutable_item_by_identifier(registry, callback)); + } + else if constexpr (Policy == IdentifierPolicy::Identifier) { + return NodeTools::expect_identifier(expect_mutable_item_by_identifier(registry, callback)); + } + else if constexpr (Policy == IdentifierPolicy::String) { + return NodeTools::expect_string(expect_mutable_item_by_identifier(registry, callback)); + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr Callback auto expect_item_by_identifier( + OwningRegistry const& registry, + Callback auto callback, + bool allow_empty = false, + bool warn = false + ) { + assert_is_locked(registry); + return [®istry, callback, allow_empty, warn](std::string_view identifier) -> bool { + if (identifier.empty()) { + if (allow_empty) { + return true; + } else { + spdlog::log_s( + warn ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: empty!", OpenVic::type_name() + ); + return warn; + } + } + const auto it = find(registry, identifier); + if (it != registry.end()) { + return callback(*it); + } + spdlog::log_s( + warn ? spdlog::level::warn : spdlog::level::err, + "Invalid {} identifier: {}", OpenVic::type_name(), identifier + ); + return warn; + }; + } + template< + IdentifierPolicy Policy = IdentifierPolicy::Either, + typename ValueType, + typename SizeType, + typename Allocator + > + inline NodeTools::node_callback_t expect_item( + OwningRegistry const& registry, + Callback auto callback, + bool allow_empty = false, + bool warn = false + ) { + if constexpr (Policy == IdentifierPolicy::Either) { + return NodeTools::expect_identifier_or_string(expect_item_by_identifier(registry, callback)); + } + else if constexpr (Policy == IdentifierPolicy::Identifier) { + return NodeTools::expect_identifier(expect_item_by_identifier(registry, callback)); + } + else if constexpr (Policy == IdentifierPolicy::String) { + return NodeTools::expect_string(expect_item_by_identifier(registry, callback)); + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > + constexpr NodeTools::NodeCallback auto expect_item_dictionary( + OwningRegistry const& registry, + Callback auto callback + ) { + assert_is_locked(registry); + return NodeTools::expect_list_and_length( + NodeTools::default_length_callback, + NodeTools::expect_assign( + [®istry, callback]( + std::string_view identifier, + ovdl::v2script::ast::Node const* value + ) -> bool { + const auto it = find(registry, identifier); + if (it != registry.end()) { + return callback( + SizeType(std::distance(registry.begin(), it)), + value + ); + } else { + return key_value_invalid_callback(OpenVic::type_name())(identifier, value); + } + } + ) + ); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator, + FunctorConvertible FixedPointFunctor = std::identity + > + inline constexpr NodeTools::NodeCallback auto expect_item_decimal_map( + OwningRegistry const& registry, + Callback&&> auto callback, + FixedPointFunctor fixed_point_functor = {} + ) { + assert_is_locked(registry); + return [®istry, callback, fixed_point_functor](ovdl::v2script::ast::Node const* node) -> bool { + fixed_point_map_t map; + + bool ret = expect_item_dictionary( + registry, + [&map, fixed_point_functor](const SizeType index, ovdl::v2script::ast::Node const* value) -> bool { + return NodeTools::expect_fixed_point( + [&map, fixed_point_functor, index](fixed_point_t val) -> bool { + map.emplace(index, fixed_point_functor(val)); + return true; + } + )(value); + } + )(node); + + ret &= callback(std::move(map)); + + return ret; + }; + } +} \ No newline at end of file diff --git a/src/openvic-simulation/types/registries/OwningRegistry_Search.hpp b/src/openvic-simulation/types/registries/OwningRegistry_Search.hpp new file mode 100644 index 000000000..9900ba22a --- /dev/null +++ b/src/openvic-simulation/types/registries/OwningRegistry_Search.hpp @@ -0,0 +1,126 @@ +#pragma once + +#include +#include +#include +#include + +#include "OwningRegistry.hpp" + +#include "openvic-simulation/core/template/Concepts.hpp" +#include "openvic-simulation/types/TypedSpan.hpp" +#include "openvic-simulation/utility/Logger.hpp" + +namespace OpenVic { + template< + typename ValueType, + typename SizeType, + typename Allocator + > + inline constexpr void assert_is_locked( + OwningRegistry const& registry + ) { + assert(registry.is_locked()); + if (!registry.is_locked()) { + spdlog::error_s("registry {} is used but not yet locked!", OpenVic::type_name()); + } + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires is_strongly_typed + [[nodiscard]] inline constexpr TypedSpan get_values(OwningRegistry& registry) { + assert_is_locked(registry); + return { registry }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires is_strongly_typed + [[nodiscard]] inline constexpr TypedSpan get_values(OwningRegistry const& registry) { + assert_is_locked(registry); + return { registry }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires (!is_strongly_typed) + [[nodiscard]] inline constexpr std::span get_values(OwningRegistry& registry) { + assert_is_locked(registry); + return { registry.data(), registry.size() }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires (!is_strongly_typed) + [[nodiscard]] inline constexpr std::span get_values(OwningRegistry const& registry) { + assert_is_locked(registry); + return { registry.data(), registry.size() }; + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr auto get_identifiers( + OwningRegistry const& registry + ) { + assert_is_locked(registry); + return registry | std::views::transform([](auto const& x) -> std::string_view { + return x.get_identifier(); + }); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr bool has_identifier( + OwningRegistry const& registry, + std::string_view identifier + ) { + return std::ranges::any_of(registry.begin(), registry.end(), [&](ValueType const& value) { + return value.get_identifier() == identifier; + }); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr OwningRegistry::iterator find( + OwningRegistry& registry, + std::string_view identifier + ) { + assert_is_locked(registry); + return std::find_if(registry.begin(), registry.end(), [&](ValueType const& value) { + return value.get_identifier() == identifier; + }); + } + + template< + typename ValueType, + typename SizeType, + typename Allocator + > requires has_get_identifier + [[nodiscard]] inline constexpr OwningRegistry::const_iterator find( + OwningRegistry const& registry, + std::string_view identifier + ) { + assert_is_locked(registry); + return std::find_if(registry.begin(), registry.end(), [&](ValueType const& value) { + return value.get_identifier() == identifier; + }); + } +} \ No newline at end of file