From d3f3187209cb4085f27f95ce8ad2a77af25704fd Mon Sep 17 00:00:00 2001 From: Hop311 Date: Sun, 23 Apr 2023 19:49:01 +0100 Subject: C++ refactoring + simulation prototype --- extension/src/openvic2/Logger.hpp | 83 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 extension/src/openvic2/Logger.hpp (limited to 'extension/src/openvic2/Logger.hpp') diff --git a/extension/src/openvic2/Logger.hpp b/extension/src/openvic2/Logger.hpp new file mode 100644 index 0000000..749c67f --- /dev/null +++ b/extension/src/openvic2/Logger.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include +#ifdef __cpp_lib_source_location +#include +#endif + +namespace OpenVic2 { + + #ifndef __cpp_lib_source_location + #include + //Implementation of std::source_location for compilers that do not support it + //Note: uses non-standard extensions that are supported by Clang, GCC, and MSVC + //https://clang.llvm.org/docs/LanguageExtensions.html#source-location-builtins + //https://stackoverflow.com/a/67970107 + class source_location { + std::string _file; + int _line; + std::string _function; + + public: + source_location(std::string f, int l, std::string n) : _file(f), _line(l), _function(n) {} + static source_location current(std::string f = __builtin_FILE(), int l = __builtin_LINE(), std::string n = __builtin_FUNCTION()) { + return source_location(f, l, n); + } + + inline const char* file_name() const { return _file.c_str(); } + inline int line() const {return _line; } + inline const char* function_name() const { return _function.c_str(); } + }; + #endif + + class Logger { + using log_func_t = std::function; + + #ifdef __cpp_lib_source_location + using source_location = std::source_location; + #else + using source_location = OpenVic2::source_location; + #endif + + static log_func_t info_func, error_func; + + static const char* get_filename(const char* filepath); + + template + struct log { + log(log_func_t log_func, Ts&&... ts, const source_location& location) { + if (log_func) { + std::stringstream stream; + stream << std::endl << get_filename(location.file_name()) << "(" << location.line() << ") `" << location.function_name() << "`: "; + ((stream << std::forward(ts)), ...); + stream << std::endl; + log_func(stream.str()); + } + } + }; + public: + static void set_info_func(log_func_t log_func); + static void set_error_func(log_func_t log_func); + + template + struct info { + info(Ts&&... ts, const source_location& location = source_location::current()) { + log{ info_func, std::forward(ts)..., location }; + } + }; + + template + info(Ts&&...) -> info; + + template + struct error { + error(Ts&&... ts, const source_location& location = source_location::current()) { + log{ error_func, std::forward(ts)..., location }; + } + }; + + template + error(Ts&&...) -> error; + }; +} -- cgit v1.2.3-56-ga3b1 From 8fba1c8a02f8680e0d80279b8b6451fea4a40a62 Mon Sep 17 00:00:00 2001 From: Hop311 Date: Tue, 25 Apr 2023 00:03:15 +0100 Subject: Req comments + cleanup + c++ registry refactoring --- extension/src/GameSingleton.cpp | 4 +- extension/src/openvic2/Logger.cpp | 4 +- extension/src/openvic2/Logger.hpp | 6 +- extension/src/openvic2/Types.hpp | 62 +++++++++++ extension/src/openvic2/map/Building.cpp | 34 ++---- extension/src/openvic2/map/Building.hpp | 11 +- extension/src/openvic2/map/Map.cpp | 139 ++++++++---------------- extension/src/openvic2/map/Map.hpp | 12 +- extension/src/openvic2/map/Province.cpp | 15 +-- extension/src/openvic2/map/Province.hpp | 3 +- game/localisation/en_GB/menus.csv | 1 + game/src/GameSession/GameSpeedPanel.gd | 1 - game/src/GameSession/ProvinceOverviewPanel.gd | 10 ++ game/src/GameSession/ProvinceOverviewPanel.tscn | 7 +- 14 files changed, 165 insertions(+), 144 deletions(-) (limited to 'extension/src/openvic2/Logger.hpp') diff --git a/extension/src/GameSingleton.cpp b/extension/src/GameSingleton.cpp index 68eb252..f596cc2 100644 --- a/extension/src/GameSingleton.cpp +++ b/extension/src/GameSingleton.cpp @@ -79,6 +79,7 @@ GameSingleton::GameSingleton() : game_manager{ [this]() { emit_signal("state_upd }; for (mapmode_t const& mapmode : mapmodes) game_manager.map.add_mapmode(mapmode.first, mapmode.second); + game_manager.map.lock_mapmodes(); using building_type_t = std::tuple; const std::vector building_types = { @@ -86,6 +87,7 @@ GameSingleton::GameSingleton() : game_manager{ [this]() { emit_signal("state_upd }; for (building_type_t const& type : building_types) game_manager.building_manager.add_building_type(std::get<0>(type), std::get<1>(type), std::get<2>(type)); + game_manager.building_manager.lock_building_types(); } @@ -332,7 +334,7 @@ Dictionary GameSingleton::get_province_info_from_index(int32_t index) const { Dictionary building_dict; Building const& building = buildings[idx]; - building_dict[building_key] = building.get_type().get_identifier().c_str(); + building_dict[building_key] = building.get_identifier().c_str(); building_dict[level_key] = static_cast(building.get_level()); building_dict[expansion_state_key] = static_cast(building.get_expansion_state()); building_dict[start_date_key] = static_cast(building.get_start_date()).c_str(); diff --git a/extension/src/openvic2/Logger.cpp b/extension/src/openvic2/Logger.cpp index f211e7e..56d74ab 100644 --- a/extension/src/openvic2/Logger.cpp +++ b/extension/src/openvic2/Logger.cpp @@ -7,9 +7,9 @@ using namespace OpenVic2; Logger::log_func_t Logger::info_func = [](std::string&& str) { std::cout << str; }; Logger::log_func_t Logger::error_func = [](std::string&& str) { std::cerr << str; }; -const char* Logger::get_filename(const char* filepath) { +char const* Logger::get_filename(char const* filepath) { if (filepath == nullptr) return nullptr; - const char *last_slash = filepath; + char const* last_slash = filepath; while (*filepath != '\0') { if (*filepath == '\\' || *filepath == '/') last_slash = filepath + 1; filepath++; diff --git a/extension/src/openvic2/Logger.hpp b/extension/src/openvic2/Logger.hpp index 749c67f..624df29 100644 --- a/extension/src/openvic2/Logger.hpp +++ b/extension/src/openvic2/Logger.hpp @@ -25,9 +25,9 @@ namespace OpenVic2 { return source_location(f, l, n); } - inline const char* file_name() const { return _file.c_str(); } + inline char const* file_name() const { return _file.c_str(); } inline int line() const {return _line; } - inline const char* function_name() const { return _function.c_str(); } + inline char const* function_name() const { return _function.c_str(); } }; #endif @@ -42,7 +42,7 @@ namespace OpenVic2 { static log_func_t info_func, error_func; - static const char* get_filename(const char* filepath); + static char const* get_filename(char const* filepath); template struct log { diff --git a/extension/src/openvic2/Types.hpp b/extension/src/openvic2/Types.hpp index b20db10..226dd30 100644 --- a/extension/src/openvic2/Types.hpp +++ b/extension/src/openvic2/Types.hpp @@ -17,4 +17,66 @@ namespace OpenVic2 { public: std::string const& get_identifier() const; }; + + template::value>::type* = nullptr> + class IdentifierRegistry { + std::vector items; + bool locked = false; + public: + return_t add_item(T&& item) { + if (locked) { + Logger::error("Cannot add item to the ", name, " registry - locked!"); + return FAILURE; + } + if (item.get_identifier().empty()) { + Logger::error("Cannot add item to the ", name, " registry - empty identifier!"); + return FAILURE; + } + T const* old_item = get_item_by_identifier(item.get_identifier()); + if (old_item != nullptr) { + Logger::error("Cannot add item to the ", name, " registry - an item with the identifier \"", item.get_identifier(), "\" already exists!"); + return FAILURE; + } + items.push_back(item); + return SUCCESS; + } + void lock() { + if (locked) { + Logger::error("Failed to lock ", name, " registry - already locked!"); + } else { + locked = true; + Logger::info("Locked ", name, " registry after registering ", get_item_count(), " items"); + } + } + bool is_locked() const { + return locked; + } + size_t get_item_count() const { + return items.size(); + } + T* get_item_by_identifier(std::string const& identifier) { + if (!identifier.empty()) + for (T& item : items) + if (item.get_identifier() == identifier) return &item; + return nullptr; + } + T const* get_item_by_identifier(std::string const& identifier) const { + if (!identifier.empty()) + for (T const& item : items) + if (item.get_identifier() == identifier) return &item; + return nullptr; + } + T* get_item_by_index(size_t index) { + return index < items.size() ? &items[index] : nullptr; + } + T const* get_item_by_index(size_t index) const { + return index < items.size() ? &items[index] : nullptr; + } + std::vector& get_items() { + return items; + } + std::vector const& get_items() const { + return items; + } + }; } diff --git a/extension/src/openvic2/map/Building.cpp b/extension/src/openvic2/map/Building.cpp index f453a0f..3643b4e 100644 --- a/extension/src/openvic2/map/Building.cpp +++ b/extension/src/openvic2/map/Building.cpp @@ -6,7 +6,7 @@ using namespace OpenVic2; -Building::Building(BuildingType const& new_type) : type{ new_type } {} +Building::Building(BuildingType const& new_type) : HasIdentifier{ new_type.get_identifier() }, type{ new_type } {} bool Building::_can_expand() const { return level < type.get_max_level(); @@ -45,6 +45,9 @@ return_t Building::expand() { return FAILURE; } +/* REQUIREMENTS: + * MAP-71, MAP-74, MAP-77 + */ void Building::update_state(Date const& today) { switch (expansion_state) { case ExpansionState::Preparing: @@ -84,15 +87,9 @@ Timespan BuildingType::get_build_time() const { return build_time; } +const char BuildingManager::building_types_name[] = "building types"; + return_t BuildingManager::add_building_type(std::string const& identifier, Building::level_t max_level, Timespan build_time) { - if (building_types_locked) { - Logger::error("The building type list has already been locked!"); - return FAILURE; - } - if (identifier.empty()) { - Logger::error("Empty building type identifier!"); - return FAILURE; - } if (max_level < 0) { Logger::error("Invalid building type max level: ", max_level); return FAILURE; @@ -101,29 +98,18 @@ return_t BuildingManager::add_building_type(std::string const& identifier, Build Logger::error("Invalid building type build time: ", build_time); return FAILURE; } - BuildingType new_building_type{ identifier, max_level, build_time }; - BuildingType const* old_building_type = get_building_type_by_identifier(identifier); - if (old_building_type != nullptr) { - Logger::error("Duplicate building type identifiers: ", old_building_type->get_identifier(), " and ", identifier); - return FAILURE; - } - building_types.push_back(new_building_type); - return SUCCESS; + return building_types.add_item({ identifier, max_level, build_time }); } void BuildingManager::lock_building_types() { - building_types_locked = true; - Logger::info("Locked building types after registering ", building_types.size()); + building_types.lock(); } BuildingType const* BuildingManager::get_building_type_by_identifier(std::string const& identifier) const { - if (!identifier.empty()) - for (BuildingType const& building_type : building_types) - if (building_type.get_identifier() == identifier) return &building_type; - return nullptr; + return building_types.get_item_by_identifier(identifier); } void BuildingManager::generate_province_buildings(std::vector& buildings) const { - for (BuildingType const& type : building_types) + for (BuildingType const& type : building_types.get_items()) buildings.push_back(Building{ type }); } diff --git a/extension/src/openvic2/map/Building.hpp b/extension/src/openvic2/map/Building.hpp index 7a1a777..08ede3a 100644 --- a/extension/src/openvic2/map/Building.hpp +++ b/extension/src/openvic2/map/Building.hpp @@ -9,7 +9,12 @@ namespace OpenVic2 { struct BuildingManager; struct BuildingType; - struct Building { + /* REQUIREMENTS: + * MAP-11, MAP-72, MAP-73 + * MAP-12, MAP-75, MAP-76 + * MAP-13, MAP-78, MAP-79 + */ + struct Building : HasIdentifier { friend struct BuildingManager; using level_t = int8_t; @@ -52,8 +57,8 @@ namespace OpenVic2 { struct BuildingManager { private: - std::vector building_types; - bool building_types_locked = false; + static const char building_types_name[]; + IdentifierRegistry building_types; public: return_t add_building_type(std::string const& identifier, Building::level_t max_level, Timespan build_time); void lock_building_types(); diff --git a/extension/src/openvic2/map/Map.cpp b/extension/src/openvic2/map/Map.cpp index 1089d61..a440f67 100644 --- a/extension/src/openvic2/map/Map.cpp +++ b/extension/src/openvic2/map/Map.cpp @@ -16,45 +16,32 @@ Mapmode::index_t Mapmode::get_index() const { return index; } -Mapmode::colour_func_t Mapmode::get_colour_func() const { - return colour_func; +Province::colour_t Mapmode::get_colour(Map const& map, Province const& province) const { + return colour_func ? colour_func(map, province) : Province::NULL_COLOUR; } +const char Map::provinces_name[] = "provinces", Map::regions_name[] = "regions", Map::mapmodes_name[] = "mapmodes"; + return_t Map::add_province(std::string const& identifier, Province::colour_t colour) { - if (provinces_locked) { - Logger::error("The map's province list has already been locked!"); - return FAILURE; - } - if (provinces.size() >= Province::MAX_INDEX) { + if (provinces.get_item_count() >= Province::MAX_INDEX) { Logger::error("The map's province list is full - there can be at most ", Province::MAX_INDEX, " provinces"); return FAILURE; } - if (identifier.empty()) { - Logger::error("Empty province identifier for colour ", Province::colour_to_hex_string(colour)); - return FAILURE; - } if (colour == Province::NULL_COLOUR || colour > Province::MAX_COLOUR) { Logger::error("Invalid province colour: ", Province::colour_to_hex_string(colour)); return FAILURE; } - Province new_province{ static_cast(provinces.size() + 1), identifier, colour }; - Province const* old_province = get_province_by_identifier(identifier); - if (old_province != nullptr) { - Logger::error("Duplicate province identifiers: ", old_province->to_string(), " and ", new_province.to_string()); - return FAILURE; - } - old_province = get_province_by_colour(colour); + Province new_province{ static_cast(provinces.get_item_count() + 1), identifier, colour }; + Province const* old_province = get_province_by_colour(colour); if (old_province != nullptr) { Logger::error("Duplicate province colours: ", old_province->to_string(), " and ", new_province.to_string()); return FAILURE; } - provinces.push_back(new_province); - return SUCCESS; + return provinces.add_item(std::move(new_province)); } void Map::lock_provinces() { - provinces_locked = true; - Logger::info("Locked provinces after registering ", provinces.size()); + provinces.lock(); } return_t Map::set_water_province(std::string const& identifier) { @@ -82,18 +69,6 @@ void Map::lock_water_provinces() { } return_t Map::add_region(std::string const& identifier, std::vector const& province_identifiers) { - if (regions_locked) { - Logger::error("The map's region list has already been locked!"); - return FAILURE; - } - if (identifier.empty()) { - Logger::error("Empty region identifier!"); - return FAILURE; - } - if (provinces.empty()) { - Logger::error("Empty province list for region ", identifier); - return FAILURE; - } return_t ret = SUCCESS; Region new_region{ identifier }; for (std::string const& province_identifier : province_identifiers) { @@ -106,8 +81,8 @@ return_t Map::add_region(std::string const& identifier, std::vector size_t other_region_index = reinterpret_cast(province->get_region()); if (other_region_index != 0) { other_region_index--; - if (other_region_index < regions.size()) - Logger::error("Province ", province_identifier, " is already part of ", regions[other_region_index].get_identifier()); + if (other_region_index < regions.get_item_count()) + Logger::error("Province ", province_identifier, " is already part of ", regions.get_item_by_index(other_region_index)->get_identifier()); else Logger::error("Province ", province_identifier, " is already part of an unknown region with index ", other_region_index); ret = FAILURE; @@ -122,65 +97,53 @@ return_t Map::add_region(std::string const& identifier, std::vector Logger::error("No valid provinces in region's list"); return FAILURE; } - Region const* old_region = get_region_by_identifier(identifier); - if (old_region != nullptr) { - Logger::error("Duplicate region identifiers: ", old_region->get_identifier(), " and ", identifier); - return FAILURE; - } - regions.push_back(new_region); // Used to detect provinces listed in multiple regions, will // be corrected once regions is stable (i.e. lock_regions). - Region* tmp_region_index = reinterpret_cast(regions.size()); + Region* tmp_region_index = reinterpret_cast(regions.get_item_count()); for (Province* province : new_region.get_provinces()) province->region = tmp_region_index; + if (regions.add_item(std::move(new_region)) != SUCCESS) ret = FAILURE; return ret; } void Map::lock_regions() { - regions_locked = true; - for (Region& region : regions) + regions.lock(); + for (Region& region : regions.get_items()) for (Province* province : region.get_provinces()) province->region = ®ion; - Logger::info("Locked regions after registering ", regions.size()); } size_t Map::get_province_count() const { - return provinces.size(); + return provinces.get_item_count(); } Province* Map::get_province_by_index(Province::index_t index) { - return index != Province::NULL_INDEX && index <= provinces.size() ? &provinces[index - 1] : nullptr; + return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr; } Province const* Map::get_province_by_index(Province::index_t index) const { - return index != Province::NULL_INDEX && index <= provinces.size() ? &provinces[index - 1] : nullptr; + return index != Province::NULL_INDEX ? provinces.get_item_by_index(index - 1) : nullptr; } Province* Map::get_province_by_identifier(std::string const& identifier) { - if (!identifier.empty()) - for (Province& province : provinces) - if (province.get_identifier() == identifier) return &province; - return nullptr; + return provinces.get_item_by_identifier(identifier); } Province const* Map::get_province_by_identifier(std::string const& identifier) const { - if (!identifier.empty()) - for (Province const& province : provinces) - if (province.get_identifier() == identifier) return &province; - return nullptr; + return provinces.get_item_by_identifier(identifier); } Province* Map::get_province_by_colour(Province::colour_t colour) { if (colour != Province::NULL_COLOUR) - for (Province& province : provinces) + for (Province& province : provinces.get_items()) if (province.get_colour() == colour) return &province; return nullptr; } Province const* Map::get_province_by_colour(Province::colour_t colour) const { if (colour != Province::NULL_COLOUR) - for (Province const& province : provinces) + for (Province const& province : provinces.get_items()) if (province.get_colour() == colour) return &province; return nullptr; } @@ -191,17 +154,11 @@ Province::index_t Map::get_province_index_at(size_t x, size_t y) const { } Region* Map::get_region_by_identifier(std::string const& identifier) { - if (!identifier.empty()) - for (Region& region : regions) - if (region.get_identifier() == identifier) return ®ion; - return nullptr; + return regions.get_item_by_identifier(identifier); } Region const* Map::get_region_by_identifier(std::string const& identifier) const { - if (!identifier.empty()) - for (Region const& region : regions) - if (region.get_identifier() == identifier) return ®ion; - return nullptr; + return regions.get_item_by_identifier(identifier); } static Province::colour_t colour_at(uint8_t const* colour_data, int32_t idx) { @@ -213,7 +170,7 @@ return_t Map::generate_province_index_image(size_t new_width, size_t new_height, Logger::error("Province index image has already been generated!"); return FAILURE; } - if (!provinces_locked) { + if (!provinces.is_locked()) { Logger::error("Province index image cannot be generated until after provinces are locked!"); return FAILURE; } @@ -229,7 +186,7 @@ return_t Map::generate_province_index_image(size_t new_width, size_t new_height, height = new_height; province_index_image.resize(width * height); - std::vector province_checklist(provinces.size()); + std::vector province_checklist(provinces.get_item_count()); return_t ret = SUCCESS; std::unordered_set unrecognised_colours; @@ -269,7 +226,7 @@ return_t Map::generate_province_index_image(size_t new_width, size_t new_height, for (size_t idx = 0; idx < province_checklist.size(); ++idx) { if (!province_checklist[idx]) { - Logger::error("Province missing from shape image: ", provinces[idx].to_string()); + Logger::error("Province missing from shape image: ", provinces.get_item_by_index(idx)->to_string()); ret = FAILURE; } } @@ -289,37 +246,27 @@ std::vector const& Map::get_province_index_image() const { } return_t Map::add_mapmode(std::string const& identifier, Mapmode::colour_func_t colour_func) { - if (identifier.empty()) { - Logger::error("Empty mapmode identifier!"); - return FAILURE; - } if (colour_func == nullptr) { Logger::error("Mapmode colour function is null for identifier: ", identifier); return FAILURE; } - Mapmode new_mapmode{ mapmodes.size(), identifier, colour_func }; - Mapmode const* old_mapmode = get_mapmode_by_identifier(identifier); - if (old_mapmode != nullptr) { - Logger::error("Duplicate mapmode identifiers: ", old_mapmode->get_identifier(), " and ", identifier); - return FAILURE; - } - mapmodes.push_back(new_mapmode); - return SUCCESS; + return mapmodes.add_item({ mapmodes.get_item_count(), identifier, colour_func }); +} + +void Map::lock_mapmodes() { + mapmodes.lock(); } size_t Map::get_mapmode_count() const { - return mapmodes.size(); + return mapmodes.get_item_count(); } Mapmode const* Map::get_mapmode_by_index(size_t index) const { - return index < mapmodes.size() ? &mapmodes[index] : nullptr; + return mapmodes.get_item_by_index(index); } Mapmode const* Map::get_mapmode_by_identifier(std::string const& identifier) const { - if (!identifier.empty()) - for (Mapmode const& mapmode : mapmodes) - if (mapmode.get_identifier() == identifier) return &mapmode; - return nullptr; + return mapmodes.get_item_by_identifier(identifier); } return_t Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) const { @@ -327,14 +274,14 @@ return_t Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) Logger::error("Mapmode colour target pointer is null!"); return FAILURE; } - if (index >= mapmodes.size()) { + Mapmode const* mapmode = mapmodes.get_item_by_index(index); + if (mapmode == nullptr) { Logger::error("Invalid mapmode index: ", index); return FAILURE; } - Mapmode const& mapmode = mapmodes[index]; target += 4; // Skip past Province::NULL_INDEX - for (Province const& province : provinces) { - const Province::colour_t colour = mapmode.get_colour_func()(*this, province); + for (Province const& province : provinces.get_items()) { + const Province::colour_t colour = mapmode->get_colour(*this, province); *target++ = (colour >> 16) & 0xFF; *target++ = (colour >> 8) & 0xFF; *target++ = colour & 0xFF; @@ -344,16 +291,16 @@ return_t Map::generate_mapmode_colours(Mapmode::index_t index, uint8_t* target) } void Map::generate_province_buildings(BuildingManager const& manager) { - for (Province& province : provinces) - manager.generate_province_buildings(province.buildings); + for (Province& province : provinces.get_items()) + manager.generate_province_buildings(province.buildings.get_items()); } void Map::update_state(Date const& today) { - for (Province& province : provinces) + for (Province& province : provinces.get_items()) province.update_state(today); } void Map::tick(Date const& today) { - for (Province& province : provinces) + for (Province& province : provinces.get_items()) province.tick(today); } diff --git a/extension/src/openvic2/map/Map.hpp b/extension/src/openvic2/map/Map.hpp index b6e7ac2..ed63912 100644 --- a/extension/src/openvic2/map/Map.hpp +++ b/extension/src/openvic2/map/Map.hpp @@ -18,7 +18,7 @@ namespace OpenVic2 { Mapmode(index_t new_index, std::string const& new_identifier, colour_func_t new_colour_func); public: index_t get_index() const; - colour_func_t get_colour_func() const; + Province::colour_t get_colour(Map const& map, Province const& province) const; }; /* REQUIREMENTS: @@ -26,14 +26,15 @@ namespace OpenVic2 { */ struct Map { private: - std::vector provinces; - std::vector regions; - bool provinces_locked = false, water_provinces_locked = false, regions_locked = false; + static const char provinces_name[], regions_name[], mapmodes_name[]; + IdentifierRegistry provinces; + IdentifierRegistry regions; + IdentifierRegistry mapmodes; + bool water_provinces_locked = false; size_t water_province_count = 0; size_t width = 0, height = 0; std::vector province_index_image; - std::vector mapmodes; public: return_t add_province(std::string const& identifier, Province::colour_t colour); void lock_provinces(); @@ -60,6 +61,7 @@ namespace OpenVic2 { std::vector const& get_province_index_image() const; return_t add_mapmode(std::string const& identifier, Mapmode::colour_func_t colour_func); + void lock_mapmodes(); size_t get_mapmode_count() const; Mapmode const* get_mapmode_by_index(Mapmode::index_t index) const; Mapmode const* get_mapmode_by_identifier(std::string const& identifier) const; diff --git a/extension/src/openvic2/map/Province.cpp b/extension/src/openvic2/map/Province.cpp index c641b7e..08711af 100644 --- a/extension/src/openvic2/map/Province.cpp +++ b/extension/src/openvic2/map/Province.cpp @@ -6,6 +6,8 @@ using namespace OpenVic2; +const char Province::buildings_name[] = "buildings"; + Province::Province(index_t new_index, std::string const& new_identifier, colour_t new_colour) : HasIdentifier{ new_identifier }, index{ new_index }, colour{ new_colour } { assert(index != NULL_INDEX); @@ -39,14 +41,13 @@ Province::life_rating_t Province::get_life_rating() const { } std::vector const& Province::get_buildings() const { - return buildings; + return buildings.get_items(); } return_t Province::expand_building(std::string const& building_type_identifier) { - for (Building& building : buildings) - if (building.get_type().get_identifier() == building_type_identifier) - return building.expand(); - return FAILURE; + Building* building = buildings.get_item_by_identifier(building_type_identifier); + if (building == nullptr) return FAILURE; + return building->expand(); } std::string Province::to_string() const { @@ -56,12 +57,12 @@ std::string Province::to_string() const { } void Province::update_state(Date const& today) { - for (Building& building : buildings) + for (Building& building : buildings.get_items()) building.update_state(today); } void Province::tick(Date const& today) { - for (Building& building : buildings) + for (Building& building : buildings.get_items()) building.tick(today); } diff --git a/extension/src/openvic2/map/Province.hpp b/extension/src/openvic2/map/Province.hpp index 79c6861..0b7cd4c 100644 --- a/extension/src/openvic2/map/Province.hpp +++ b/extension/src/openvic2/map/Province.hpp @@ -24,7 +24,8 @@ namespace OpenVic2 { Region* region = nullptr; bool water = false; life_rating_t life_rating = 0; - std::vector buildings; + static const char buildings_name[]; + IdentifierRegistry buildings; Province(index_t new_index, std::string const& new_identifier, colour_t new_colour); public: diff --git a/game/localisation/en_GB/menus.csv b/game/localisation/en_GB/menus.csv index 0009acd..3c3fff1 100644 --- a/game/localisation/en_GB/menus.csv +++ b/game/localisation/en_GB/menus.csv @@ -69,6 +69,7 @@ DIALOG_SAVE_AND_QUIT,Save and Quit ,, Province Overview Panel province_MISSING,No Province region_MISSING,No Region +LIFE_RATING_TOOLTIP,Liferating: %d building_MISSING,No Building building_fort,Fort building_naval_base,Naval Base diff --git a/game/src/GameSession/GameSpeedPanel.gd b/game/src/GameSession/GameSpeedPanel.gd index 8b7af29..80708b1 100644 --- a/game/src/GameSession/GameSpeedPanel.gd +++ b/game/src/GameSession/GameSpeedPanel.gd @@ -7,7 +7,6 @@ extends PanelContainer @export var _decrease_speed_button : Button @export var _increase_speed_button : Button -# Called when the node enters the scene tree for the first time. func _ready(): GameSingleton.state_updated.connect(_update_buttons) _update_buttons() diff --git a/game/src/GameSession/ProvinceOverviewPanel.gd b/game/src/GameSession/ProvinceOverviewPanel.gd index cbab9d0..17da9d0 100644 --- a/game/src/GameSession/ProvinceOverviewPanel.gd +++ b/game/src/GameSession/ProvinceOverviewPanel.gd @@ -2,6 +2,7 @@ extends PanelContainer @export var _province_name_label : Label @export var _region_name_label : Label +@export var _life_rating_bar : ProgressBar @export var _buildings_container : Container const _missing_suffix : String = "_MISSING" @@ -23,6 +24,10 @@ func _expand_building(building_identifier : String) -> void: if GameSingleton.expand_building(_selected_index, building_identifier) != OK: push_error("Failed to expand ", building_identifier, " in province #", _selected_index); +# REQUIREMENTS: +# * UI-183, UI-185, UI-186, UI-765, UI-187, UI-188, UI-189 +# * UI-191, UI-193, UI-194, UI-766, UI-195, UI-196, UI-197 +# * UI-199, UI-201, UI-202, UI-767, UI-203, UI-204, UI-205 func _add_building(building : Dictionary) -> void: const _building_key : StringName = &"building" const _level_key : StringName = &"level" @@ -62,11 +67,16 @@ func update_info() -> void: const _life_rating_key : StringName = &"life_rating" const _buildings_key : StringName = &"buildings" + const _life_rating_tooltip : String = "LIFE_RATING_TOOLTIP" + _province_info = GameSingleton.get_province_info_from_index(_selected_index) if _province_info: _province_name_label.text = _province_info.get(_province_key, _province_key + _missing_suffix) _region_name_label.text = _province_info.get(_region_key, _region_key + _missing_suffix) + _life_rating_bar.value = _province_info.get(_life_rating_key, 0) + _life_rating_bar.tooltip_text = tr(_life_rating_tooltip) % _life_rating_bar.value + for child in _buildings_container.get_children(): _buildings_container.remove_child(child) child.queue_free() diff --git a/game/src/GameSession/ProvinceOverviewPanel.tscn b/game/src/GameSession/ProvinceOverviewPanel.tscn index 7b28cc1..48e7c25 100644 --- a/game/src/GameSession/ProvinceOverviewPanel.tscn +++ b/game/src/GameSession/ProvinceOverviewPanel.tscn @@ -2,7 +2,7 @@ [ext_resource type="Script" path="res://src/GameSession/ProvinceOverviewPanel.gd" id="1_3n8k5"] -[node name="ProvinceOverviewPanel" type="PanelContainer" node_paths=PackedStringArray("_province_name_label", "_region_name_label", "_buildings_container")] +[node name="ProvinceOverviewPanel" type="PanelContainer" node_paths=PackedStringArray("_province_name_label", "_region_name_label", "_life_rating_bar", "_buildings_container")] editor_description = "UI-56" anchors_preset = 2 anchor_top = 1.0 @@ -13,6 +13,7 @@ grow_vertical = 0 script = ExtResource("1_3n8k5") _province_name_label = NodePath("PanelList/TopBarList/NameList/ProvinceName") _region_name_label = NodePath("PanelList/TopBarList/NameList/RegionName") +_life_rating_bar = NodePath("PanelList/TopBarList/NameList/LifeRatingBar") _buildings_container = NodePath("PanelList/InteractList/BuildingsContainer") [node name="PanelList" type="VBoxContainer" parent="."] @@ -38,6 +39,10 @@ layout_mode = 2 text = "region_MISSING" vertical_alignment = 1 +[node name="LifeRatingBar" type="ProgressBar" parent="PanelList/TopBarList/NameList"] +editor_description = "UI-62" +layout_mode = 2 + [node name="CloseButton" type="Button" parent="PanelList/TopBarList"] custom_minimum_size = Vector2(30, 30) layout_mode = 2 -- cgit v1.2.3-56-ga3b1