From 28716548d2ec1bcd9ff7565257e503fa592d96b2 Mon Sep 17 00:00:00 2001 From: Tyler Trahan Date: Fri, 26 Jan 2024 10:25:25 -0500 Subject: [PATCH] Feature: Setting to automatically restart server based on hours played (#11142) --- src/network/network_server.cpp | 80 +++++++++++++++++-------- src/network/network_server.h | 1 + src/openttd.cpp | 7 ++- src/settings_type.h | 1 + src/table/settings/network_settings.ini | 11 ++++ 5 files changed, 75 insertions(+), 25 deletions(-) diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 121223a4cf..d970456644 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -33,6 +33,7 @@ #include "../timer/timer.h" #include "../timer/timer_game_calendar.h" #include "../timer/timer_game_economy.h" +#include "../timer/timer_game_realtime.h" #include #include @@ -1491,29 +1492,6 @@ void NetworkUpdateClientInfo(ClientID client_id) NetworkAdminClientUpdate(ci); } -/** Check if we want to restart the map */ -static void NetworkCheckRestartMap() -{ - if (_settings_client.network.restart_game_year != 0 && TimerGameCalendar::year >= _settings_client.network.restart_game_year) { - Debug(net, 3, "Auto-restarting map: year {} reached", TimerGameCalendar::year); - - _settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED; - switch(_file_to_saveload.abstract_ftype) { - case FT_SAVEGAME: - case FT_SCENARIO: - _switch_mode = SM_LOAD_GAME; - break; - - case FT_HEIGHTMAP: - _switch_mode = SM_START_HEIGHTMAP; - break; - - default: - _switch_mode = SM_NEWGAME; - } - } -} - /** Check if the server has autoclean_companies activated * Two things happen: * 1) If a company is not protected, it is closed after 1 year (for example) @@ -1811,11 +1789,65 @@ void NetworkServer_Tick(bool send_frame) } } +/** Helper function to restart the map. */ +static void NetworkRestartMap() +{ + _settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED; + switch (_file_to_saveload.abstract_ftype) { + case FT_SAVEGAME: + case FT_SCENARIO: + _switch_mode = SM_LOAD_GAME; + break; + + case FT_HEIGHTMAP: + _switch_mode = SM_START_HEIGHTMAP; + break; + + default: + _switch_mode = SM_NEWGAME; + } +} + +/** Timer to restart a network server automatically based on real-time hours played. Initialized at zero to disable until settings are loaded. */ +static IntervalTimer _network_restart_map_timer({std::chrono::hours::zero(), TimerGameRealtime::UNPAUSED}, [](auto) +{ + if (!_network_server) return; + + /* If setting is 0, this feature is disabled. */ + if (_settings_client.network.restart_hours == 0) return; + + Debug(net, 3, "Auto-restarting map: {} hours played", _settings_client.network.restart_hours); + NetworkRestartMap(); +}); + +/** + * Reset the automatic network restart time interval. + * @param reset Whether to reset the timer to zero. + */ +void ChangeNetworkRestartTime(bool reset) +{ + if (!_network_server) return; + + _network_restart_map_timer.SetInterval({ std::chrono::hours(_settings_client.network.restart_hours), TimerGameRealtime::UNPAUSED }, reset); +} + +/** Check if we want to restart the map based on the year. */ +static void NetworkCheckRestartMapYear() +{ + /* If setting is 0, this feature is disabled. */ + if (_settings_client.network.restart_game_year == 0) return; + + if (TimerGameCalendar::year >= _settings_client.network.restart_game_year) { + Debug(net, 3, "Auto-restarting map: year {} reached", TimerGameCalendar::year); + NetworkRestartMap(); + } +} + /** Calendar yearly "callback". Called whenever the calendar year changes. */ static IntervalTimer _calendar_network_yearly({ TimerGameCalendar::YEAR, TimerGameCalendar::Priority::NONE }, [](auto) { if (!_network_server) return; - NetworkCheckRestartMap(); + NetworkCheckRestartMapYear(); }); /** Economy yearly "callback". Called whenever the economy year changes. */ diff --git a/src/network/network_server.h b/src/network/network_server.h index fa3608e974..171a89233d 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -120,6 +120,7 @@ public: }; void NetworkServer_Tick(bool send_frame); +void ChangeNetworkRestartTime(bool reset); void NetworkServerSetCompanyPassword(CompanyID company_id, const std::string &password, bool already_hashed = true); void NetworkServerUpdateCompanyPassworded(CompanyID company_id, bool passworded); diff --git a/src/openttd.cpp b/src/openttd.cpp index 200b9d3d87..04388b181d 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -34,6 +34,7 @@ #include "console_func.h" #include "screenshot.h" #include "network/network.h" +#include "network/network_server.h" #include "network/network_func.h" #include "ai/ai.hpp" #include "ai/ai_config.hpp" @@ -917,7 +918,11 @@ static void MakeNewGameDone() CheckIndustries(); MarkWholeScreenDirty(); - if (_network_server && !_network_dedicated) ShowClientList(); + if (_network_server) { + ChangeNetworkRestartTime(true); + + if (!_network_dedicated) ShowClientList(); + } } static void MakeNewGame(bool from_heightmap, bool reset_settings) diff --git a/src/settings_type.h b/src/settings_type.h index 06ced9330f..e9c6a60038 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -325,6 +325,7 @@ struct NetworkSettings { uint8_t max_companies; ///< maximum amount of companies uint8_t max_clients; ///< maximum amount of clients TimerGameCalendar::Year restart_game_year; ///< year the server restarts + uint16_t restart_hours; ///< number of hours to run the server before automatic restart uint8_t min_active_clients; ///< minimum amount of active clients to unpause the game bool reload_cfg; ///< reload the config file before restarting std::string last_joined; ///< Last joined server diff --git a/src/table/settings/network_settings.ini b/src/table/settings/network_settings.ini index ae31973433..92f570ca37 100644 --- a/src/table/settings/network_settings.ini +++ b/src/table/settings/network_settings.ini @@ -8,6 +8,7 @@ [pre-amble] static void UpdateClientConfigValues(); +void ChangeNetworkRestartTime(bool reset); static constexpr std::initializer_list _server_game_type{"local", "public", "invite-only"}; @@ -241,6 +242,16 @@ min = CalendarTime::MIN_YEAR max = CalendarTime::MAX_YEAR interval = 1 +[SDTC_VAR] +var = network.restart_hours +type = SLE_UINT16 +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_0_IS_SPECIAL | SF_NETWORK_ONLY +def = 0 +min = 0 +max = UINT16_MAX +interval = 1 +post_cb = [](auto) { ChangeNetworkRestartTime(false); } + [SDTC_VAR] var = network.min_active_clients type = SLE_UINT8