From 12a47833bbe72d50271bde15c7579c1e801863c2 Mon Sep 17 00:00:00 2001 From: hop311 Date: Thu, 28 Dec 2023 15:16:41 +0000 Subject: Clock refactor + misc small fixes --- .gitmodules | 2 +- src/headless/main.cpp | 2 +- src/openvic-simulation/GameManager.cpp | 46 +++++++------- src/openvic-simulation/GameManager.hpp | 19 +++--- .../economy/BuildingInstance.cpp | 2 +- .../economy/BuildingInstance.hpp | 2 +- src/openvic-simulation/interface/GFX.cpp | 4 +- src/openvic-simulation/map/Map.cpp | 9 ++- src/openvic-simulation/map/Map.hpp | 2 +- src/openvic-simulation/map/Province.cpp | 4 +- src/openvic-simulation/map/Province.hpp | 3 +- .../misc/GameAdvancementHook.cpp | 72 ---------------------- .../misc/GameAdvancementHook.hpp | 47 -------------- src/openvic-simulation/misc/SimulationClock.cpp | 69 +++++++++++++++++++++ src/openvic-simulation/misc/SimulationClock.hpp | 59 ++++++++++++++++++ src/openvic-simulation/types/Vector.hpp | 2 +- 16 files changed, 180 insertions(+), 164 deletions(-) delete mode 100644 src/openvic-simulation/misc/GameAdvancementHook.cpp delete mode 100644 src/openvic-simulation/misc/GameAdvancementHook.hpp create mode 100644 src/openvic-simulation/misc/SimulationClock.cpp create mode 100644 src/openvic-simulation/misc/SimulationClock.hpp diff --git a/.gitmodules b/.gitmodules index 301d555..2309e93 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = https://github.com/OpenVicProject/scripts [submodule "deps/lexy-vdf"] path = deps/lexy-vdf - url = https://github.com/OpenVicProject/lexy-vdf.git + url = https://github.com/OpenVicProject/lexy-vdf diff --git a/src/headless/main.cpp b/src/headless/main.cpp index 0400302..d4c316a 100644 --- a/src/headless/main.cpp +++ b/src/headless/main.cpp @@ -52,7 +52,7 @@ static bool run_headless(Dataloader::path_vector_t const& roots, bool run_tests) GameManager game_manager { []() { Logger::info("State updated"); - } }; + }, nullptr }; ret &= headless_load(game_manager, dataloader); diff --git a/src/openvic-simulation/GameManager.cpp b/src/openvic-simulation/GameManager.cpp index 0471263..3f66352 100644 --- a/src/openvic-simulation/GameManager.cpp +++ b/src/openvic-simulation/GameManager.cpp @@ -5,29 +5,31 @@ using namespace OpenVic; using namespace OpenVic::colour_literals; -GameManager::GameManager(state_updated_func_t state_updated_callback) - : clock { - [this]() { - tick(); - }, - [this]() { - update_state(); - } }, state_updated { state_updated_callback } {} - -void GameManager::set_needs_update() { - needs_update = true; +GameManager::GameManager( + gamestate_updated_func_t gamestate_updated_callback, SimulationClock::state_changed_function_t clock_state_changed_callback +) : simulation_clock { + std::bind(&GameManager::tick, this), std::bind(&GameManager::update_gamestate, this), clock_state_changed_callback + }, gamestate_updated { gamestate_updated_callback ? std::move(gamestate_updated_callback) : []() {} }, + session_start { 0 }, today {}, gamestate_needs_update { false }, currently_updating_gamestate { false } {} + +void GameManager::set_gamestate_needs_update() { + if (!currently_updating_gamestate) { + gamestate_needs_update = true; + } else { + Logger::error("Attempted to queue a gamestate update already updating the gamestate!"); + } } -void GameManager::update_state() { - if (!needs_update) { +void GameManager::update_gamestate() { + if (!gamestate_needs_update) { return; } + currently_updating_gamestate = true; Logger::info("Update: ", today); - map.update_state(today); - if (state_updated) { - state_updated(); - } - needs_update = false; + map.update_gamestate(today); + gamestate_updated(); + gamestate_needs_update = false; + currently_updating_gamestate = false; } /* REQUIREMENTS: @@ -37,16 +39,16 @@ void GameManager::tick() { today++; Logger::info("Tick: ", today); map.tick(today); - set_needs_update(); + set_gamestate_needs_update(); } bool GameManager::reset() { session_start = time(nullptr); - clock.reset(); + simulation_clock.reset(); today = {}; economy_manager.get_good_manager().reset_to_defaults(); bool ret = map.reset(economy_manager.get_building_type_manager()); - set_needs_update(); + set_gamestate_needs_update(); return ret; } @@ -69,7 +71,7 @@ bool GameManager::load_bookmark(Bookmark const* new_bookmark) { } bool GameManager::expand_selected_province_building(size_t building_index) { - set_needs_update(); + set_gamestate_needs_update(); Province* province = map.get_selected_province(); if (province == nullptr) { Logger::error("Cannot expand building index ", building_index, " - no province selected!"); diff --git a/src/openvic-simulation/GameManager.hpp b/src/openvic-simulation/GameManager.hpp index 864b5bf..33be9d3 100644 --- a/src/openvic-simulation/GameManager.hpp +++ b/src/openvic-simulation/GameManager.hpp @@ -9,8 +9,8 @@ #include "openvic-simulation/map/Map.hpp" #include "openvic-simulation/military/MilitaryManager.hpp" #include "openvic-simulation/misc/Define.hpp" -#include "openvic-simulation/misc/GameAdvancementHook.hpp" #include "openvic-simulation/misc/Modifier.hpp" +#include "openvic-simulation/misc/SimulationClock.hpp" #include "openvic-simulation/politics/PoliticsManager.hpp" #include "openvic-simulation/pop/Pop.hpp" #include "openvic-simulation/research/ResearchManager.hpp" @@ -19,7 +19,7 @@ namespace OpenVic { struct GameManager { - using state_updated_func_t = std::function; + using gamestate_updated_func_t = std::function; private: Map PROPERTY_REF(map); @@ -36,20 +36,23 @@ namespace OpenVic { EventManager PROPERTY_REF(event_manager); DecisionManager PROPERTY_REF(decision_manager); UIManager PROPERTY_REF(ui_manager); - GameAdvancementHook PROPERTY_REF(clock); + SimulationClock PROPERTY_REF(simulation_clock); time_t session_start; /* SS-54, as well as allowing time-tracking */ Bookmark const* PROPERTY(bookmark); Date PROPERTY(today); - state_updated_func_t state_updated; - bool needs_update; + gamestate_updated_func_t gamestate_updated; + bool gamestate_needs_update, currently_updating_gamestate; - void set_needs_update(); - void update_state(); + void set_gamestate_needs_update(); + void update_gamestate(); void tick(); public: - GameManager(state_updated_func_t state_updated_callback); + GameManager( + gamestate_updated_func_t gamestate_updated_callback, + SimulationClock::state_changed_function_t clock_state_changed_callback + ); bool reset(); bool load_bookmark(Bookmark const* new_bookmark); diff --git a/src/openvic-simulation/economy/BuildingInstance.cpp b/src/openvic-simulation/economy/BuildingInstance.cpp index 047b759..f72c713 100644 --- a/src/openvic-simulation/economy/BuildingInstance.cpp +++ b/src/openvic-simulation/economy/BuildingInstance.cpp @@ -22,7 +22,7 @@ bool BuildingInstance::expand() { /* REQUIREMENTS: * MAP-71, MAP-74, MAP-77 */ -void BuildingInstance::update_state(Date today) { +void BuildingInstance::update_gamestate(Date today) { switch (expansion_state) { case ExpansionState::Preparing: start_date = today; diff --git a/src/openvic-simulation/economy/BuildingInstance.hpp b/src/openvic-simulation/economy/BuildingInstance.hpp index 00e2dd6..e027a69 100644 --- a/src/openvic-simulation/economy/BuildingInstance.hpp +++ b/src/openvic-simulation/economy/BuildingInstance.hpp @@ -25,7 +25,7 @@ namespace OpenVic { BuildingInstance(BuildingInstance&&) = default; bool expand(); - void update_state(Date today); + void update_gamestate(Date today); void tick(Date today); }; } diff --git a/src/openvic-simulation/interface/GFX.cpp b/src/openvic-simulation/interface/GFX.cpp index 3624655..d7b9042 100644 --- a/src/openvic-simulation/interface/GFX.cpp +++ b/src/openvic-simulation/interface/GFX.cpp @@ -61,8 +61,8 @@ ProgressBar::ProgressBar() : back_colour {}, progress_colour {} {} bool ProgressBar::_fill_key_map(key_map_t& key_map) { bool ret = Sprite::_fill_key_map(key_map); ret &= add_key_map_entries(key_map, - "color", ONE_EXACTLY, expect_colour(assign_variable_callback(back_colour)), - "colortwo", ONE_EXACTLY, expect_colour(assign_variable_callback(progress_colour)), + "color", ONE_EXACTLY, expect_colour(assign_variable_callback(progress_colour)), + "colortwo", ONE_EXACTLY, expect_colour(assign_variable_callback(back_colour)), "textureFile1", ZERO_OR_ONE, expect_string(assign_variable_callback_string(progress_texture_file)), "textureFile2", ZERO_OR_ONE, expect_string(assign_variable_callback_string(back_texture_file)), "size", ONE_EXACTLY, expect_ivec2(assign_variable_callback(size)), diff --git a/src/openvic-simulation/map/Map.cpp b/src/openvic-simulation/map/Map.cpp index 67e91cd..39d4870 100644 --- a/src/openvic-simulation/map/Map.cpp +++ b/src/openvic-simulation/map/Map.cpp @@ -286,9 +286,9 @@ bool Map::apply_history_to_provinces(ProvinceHistoryManager const& history_manag return ret; } -void Map::update_state(Date today) { +void Map::update_gamestate(Date today) { for (Province& province : provinces.get_items()) { - province.update_state(today); + province.update_gamestate(today); } update_highest_province_population(); update_total_map_population(); @@ -684,11 +684,14 @@ bool Map::load_climate_file(ModifierManager const& modifier_manager, ast::NodeCP return true; } ))(node); - cur_climate->lock(); } return ret; })(root); + for (Climate& climate : climates.get_items()) { + climate.lock(); + } + lock_climates(); return ret; diff --git a/src/openvic-simulation/map/Map.hpp b/src/openvic-simulation/map/Map.hpp index 2575324..0025cf4 100644 --- a/src/openvic-simulation/map/Map.hpp +++ b/src/openvic-simulation/map/Map.hpp @@ -124,7 +124,7 @@ namespace OpenVic { void update_highest_province_population(); void update_total_map_population(); - void update_state(Date today); + void update_gamestate(Date today); void tick(Date today); bool load_province_definitions(std::vector const& lines); diff --git a/src/openvic-simulation/map/Province.cpp b/src/openvic-simulation/map/Province.cpp index 2d301e8..1285b0d 100644 --- a/src/openvic-simulation/map/Province.cpp +++ b/src/openvic-simulation/map/Province.cpp @@ -112,9 +112,9 @@ void Province::update_pops() { } } -void Province::update_state(Date today) { +void Province::update_gamestate(Date today) { for (BuildingInstance& building : buildings.get_items()) { - building.update_state(today); + building.update_gamestate(today); } update_pops(); } diff --git a/src/openvic-simulation/map/Province.hpp b/src/openvic-simulation/map/Province.hpp index 431b4c2..7a42666 100644 --- a/src/openvic-simulation/map/Province.hpp +++ b/src/openvic-simulation/map/Province.hpp @@ -20,7 +20,6 @@ namespace OpenVic { using Climate = ProvinceSetModifier; using Continent = ProvinceSetModifier; - /* REQUIREMENTS: * MAP-5, MAP-7, MAP-8, MAP-43, MAP-47 * POP-22 @@ -143,7 +142,7 @@ namespace OpenVic { size_t get_pop_count() const; void update_pops(); - void update_state(Date today); + void update_gamestate(Date today); void tick(Date today); private: diff --git a/src/openvic-simulation/misc/GameAdvancementHook.cpp b/src/openvic-simulation/misc/GameAdvancementHook.cpp deleted file mode 100644 index f4c0adc..0000000 --- a/src/openvic-simulation/misc/GameAdvancementHook.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "GameAdvancementHook.hpp" - -using namespace OpenVic; - -const std::vector GameAdvancementHook::GAME_SPEEDS = { - std::chrono::milliseconds { 3000 }, std::chrono::milliseconds { 2000 }, std::chrono::milliseconds { 1000 }, - std::chrono::milliseconds { 100 }, std::chrono::milliseconds { 1 } -}; - -GameAdvancementHook::GameAdvancementHook( - AdvancementFunction tick_function, RefreshFunction update_function, bool start_paused, speed_t starting_speed -) - : trigger_function { tick_function }, refresh_function { update_function }, is_paused { start_paused } { - last_polled_time = std::chrono::high_resolution_clock::now(); - set_simulation_speed(starting_speed); -} - -void GameAdvancementHook::set_simulation_speed(speed_t speed) { - if (speed < 0) { - current_speed = 0; - } else if (speed >= GAME_SPEEDS.size()) { - current_speed = GAME_SPEEDS.size() - 1; - } else { - current_speed = speed; - } -} - -void GameAdvancementHook::increase_simulation_speed() { - set_simulation_speed(current_speed + 1); -} - -void GameAdvancementHook::decrease_simulation_speed() { - set_simulation_speed(current_speed - 1); -} - -bool GameAdvancementHook::can_increase_simulation_speed() const { - return current_speed + 1 < GAME_SPEEDS.size(); -} - -bool GameAdvancementHook::can_decrease_simulation_speed() const { - return current_speed > 0; -} - -GameAdvancementHook& GameAdvancementHook::operator++() { - increase_simulation_speed(); - return *this; -}; - -GameAdvancementHook& GameAdvancementHook::operator--() { - decrease_simulation_speed(); - return *this; -}; - -void GameAdvancementHook::conditionally_advance_game() { - if (!is_paused) { - time_point_t currentTime = std::chrono::high_resolution_clock::now(); - if (std::chrono::duration_cast(currentTime - last_polled_time) >= GAME_SPEEDS[current_speed]) { - last_polled_time = currentTime; - if (trigger_function) { - trigger_function(); - } - } - } - if (refresh_function) { - refresh_function(); - } -} - -void GameAdvancementHook::reset() { - is_paused = true; - current_speed = 0; -} diff --git a/src/openvic-simulation/misc/GameAdvancementHook.hpp b/src/openvic-simulation/misc/GameAdvancementHook.hpp deleted file mode 100644 index 75af718..0000000 --- a/src/openvic-simulation/misc/GameAdvancementHook.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include -#include -#include "openvic-simulation/utility/Getters.hpp" - -namespace OpenVic { - // Conditionally advances game with provided behaviour - // Class governs game speed and pause state - class GameAdvancementHook { - public: - using AdvancementFunction = std::function; - using RefreshFunction = std::function; - using speed_t = int8_t; - - // Minimum number of miliseconds before the simulation advances - static const std::vector GAME_SPEEDS; - - private: - using time_point_t = std::chrono::time_point; - - time_point_t last_polled_time; - // A function pointer that advances the simulation, intended to be a capturing - // lambda or something similar. May need to be reworked later - AdvancementFunction trigger_function; - RefreshFunction refresh_function; - speed_t PROPERTY_CUSTOM_NAME(current_speed, get_simulation_speed); - - public: - bool is_paused; - - GameAdvancementHook( - AdvancementFunction tick_function, RefreshFunction update_function, bool start_paused = true, speed_t starting_speed = 0 - ); - - void set_simulation_speed(speed_t speed); - void increase_simulation_speed(); - void decrease_simulation_speed(); - bool can_increase_simulation_speed() const; - bool can_decrease_simulation_speed() const; - GameAdvancementHook& operator++(); - GameAdvancementHook& operator--(); - void conditionally_advance_game(); - void reset(); - }; -} diff --git a/src/openvic-simulation/misc/SimulationClock.cpp b/src/openvic-simulation/misc/SimulationClock.cpp new file mode 100644 index 0000000..324811c --- /dev/null +++ b/src/openvic-simulation/misc/SimulationClock.cpp @@ -0,0 +1,69 @@ +#include "SimulationClock.hpp" + +#include + +using namespace OpenVic; + +SimulationClock::SimulationClock( + tick_function_t new_tick_function, update_function_t new_update_function, + state_changed_function_t new_state_changed_function +) : tick_function { new_tick_function ? std::move(new_tick_function) : []() {} }, + update_function { new_update_function ? std::move(new_update_function) : []() {} }, + state_changed_function { new_state_changed_function ? std::move(new_state_changed_function) : []() {} } { + reset(); +} + +void SimulationClock::set_paused(bool new_paused) { + if (paused != new_paused) { + toggle_paused(); + } +} + +void SimulationClock::toggle_paused() { + paused = !paused; + state_changed_function(); +} + +void SimulationClock::set_simulation_speed(speed_t speed) { + speed = std::clamp(speed, MIN_SPEED, MAX_SPEED); + if (current_speed != speed) { + current_speed = speed; + state_changed_function(); + } +} + +void SimulationClock::increase_simulation_speed() { + set_simulation_speed(current_speed + 1); +} + +void SimulationClock::decrease_simulation_speed() { + set_simulation_speed(current_speed - 1); +} + +bool SimulationClock::can_increase_simulation_speed() const { + return current_speed < MAX_SPEED; +} + +bool SimulationClock::can_decrease_simulation_speed() const { + return current_speed > MIN_SPEED; +} + +void SimulationClock::conditionally_advance_game() { + if (!paused) { + const time_point_t current_time = std::chrono::high_resolution_clock::now(); + const std::chrono::milliseconds time_since_last_tick = + std::chrono::duration_cast(current_time - last_tick_time); + if (time_since_last_tick >= GAME_SPEEDS[current_speed]) { + last_tick_time = current_time; + tick_function(); + } + } + update_function(); +} + +void SimulationClock::reset() { + paused = true; + current_speed = 0; + last_tick_time = std::chrono::high_resolution_clock::now(); + state_changed_function(); +} diff --git a/src/openvic-simulation/misc/SimulationClock.hpp b/src/openvic-simulation/misc/SimulationClock.hpp new file mode 100644 index 0000000..fbf7930 --- /dev/null +++ b/src/openvic-simulation/misc/SimulationClock.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include + +#include "openvic-simulation/utility/Getters.hpp" + +namespace OpenVic { + /* Conditionally advances game depending on speed and pause state. */ + class SimulationClock { + public: + using tick_function_t = std::function; + using update_function_t = std::function; + using state_changed_function_t = std::function; + using speed_t = int8_t; + + /* Minimum number of miliseconds before the simulation advances + * (in descending duration order, hence increasing speed order). */ + static constexpr std::chrono::milliseconds GAME_SPEEDS[] { + std::chrono::milliseconds { 3000 }, std::chrono::milliseconds { 2000 }, std::chrono::milliseconds { 1000 }, + std::chrono::milliseconds { 100 }, std::chrono::milliseconds { 1 } + }; + static constexpr speed_t MIN_SPEED = 0, MAX_SPEED = std::size(GAME_SPEEDS) - 1; + + private: + using time_point_t = std::chrono::time_point; + + /* Advance simulation (triggered while unpaused at interval determined by speed). */ + tick_function_t tick_function; + /* Refresh game state (triggered with every call to conditionally_advance_game). */ + update_function_t update_function; + /* Callback for when speed or pause state is changed. */ + state_changed_function_t state_changed_function; + + time_point_t last_tick_time; + speed_t PROPERTY_CUSTOM_NAME(current_speed, get_simulation_speed); + bool PROPERTY_CUSTOM_PREFIX(paused, is); + + public: + + SimulationClock( + tick_function_t new_tick_function, update_function_t new_update_function, + state_changed_function_t new_state_changed_function + ); + + void set_paused(bool new_paused); + void toggle_paused(); + + void set_simulation_speed(speed_t speed); + void increase_simulation_speed(); + void decrease_simulation_speed(); + bool can_increase_simulation_speed() const; + bool can_decrease_simulation_speed() const; + + void conditionally_advance_game(); + void reset(); + }; +} diff --git a/src/openvic-simulation/types/Vector.hpp b/src/openvic-simulation/types/Vector.hpp index 89fe12f..5514cc3 100644 --- a/src/openvic-simulation/types/Vector.hpp +++ b/src/openvic-simulation/types/Vector.hpp @@ -20,7 +20,7 @@ namespace OpenVic { constexpr vec2_t& operator=(vec2_t&&) = default; template - constexpr explicit operator vec2_t() { + constexpr explicit operator vec2_t() const { return { static_cast(x), static_cast(y) }; } -- cgit v1.2.3-56-ga3b1