From d39236d50c27fd1928c8ab58192d86f4b6d74f30 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 7 Feb 2024 20:05:11 +0000 Subject: [PATCH] Store state ticks directly in savegame instead of the offset Initialise the state ticks value to a constant for new games, instead of using an implicit offset of 0 --- src/date.cpp | 40 ++++++++++++++------------------------ src/date_func.h | 7 ++++--- src/date_type.h | 3 +++ src/misc.cpp | 5 +++-- src/newgrf.cpp | 9 +++++---- src/openttd.cpp | 2 +- src/saveload/afterload.cpp | 7 +++++-- src/settings.cpp | 3 +-- src/sl/extended_ver_sl.cpp | 2 +- src/sl/misc_sl.cpp | 7 ++++--- 10 files changed, 42 insertions(+), 43 deletions(-) diff --git a/src/date.cpp b/src/date.cpp index 5276512e7e..b477d94f5e 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -33,7 +33,7 @@ uint64_t _tick_counter; ///< Ever incrementing tick counter f uint8_t _tick_skip_counter; ///< Counter for ticks, when only vehicles are moving and nothing else happens uint64_t _scaled_tick_counter; ///< Tick counter in daylength-scaled ticks StateTicks _state_ticks; ///< Current state tick -StateTicks _state_ticks_offset; ///< Offset to add when calculating a StateTicks value from a date/date fract/tick skip counter +StateTicksDelta _state_ticks_offset; ///< Offset to add when calculating a StateTicks value from a date/date fract/tick skip counter uint32_t _quit_after_days; ///< Quit after this many days of run time YearMonthDay _game_load_cur_date_ymd; @@ -45,14 +45,14 @@ extern void ClearOutOfDateSignalSpeedRestrictions(); void CheckStateTicksWrap() { StateTicksDelta tick_adjust = 0; - auto get_tick_adjust = [&](StateTicks target) { + auto get_tick_adjust = [&](StateTicksDelta target) { int32_t rounding = _settings_time.time_in_minutes * 1440; - return target.AsDelta() - (target.base() % rounding); + return target - (target.base() % rounding); }; if (_state_ticks >= ((int64_t)1 << 60)) { - tick_adjust = get_tick_adjust(_state_ticks); + tick_adjust = get_tick_adjust(_state_ticks - INITIAL_STATE_TICKS_VALUE); } else if (_state_ticks <= -((int64_t)1 << 60)) { - tick_adjust = -get_tick_adjust(-(_state_ticks.base())); + tick_adjust = -get_tick_adjust(INITIAL_STATE_TICKS_VALUE - _state_ticks); } else { return; } @@ -70,23 +70,12 @@ void CheckStateTicksWrap() AdjustLinkGraphStateTicksBase(-tick_adjust); } -void RebaseStateTicksBase() -{ - StateTicks old_state_ticks = _state_ticks; - SetScaledTickVariables(); - _state_ticks_offset += (old_state_ticks - _state_ticks); - SetScaledTickVariables(); - assert(old_state_ticks == _state_ticks); - - CheckStateTicksWrap(); -} - /** * Set the date. * @param date New date * @param fract The number of ticks that have passed on this date. */ -void SetDate(Date date, DateFract fract, bool preserve_state_tick) +void SetDate(Date date, DateFract fract) { assert(fract < DAY_TICKS); @@ -94,17 +83,18 @@ void SetDate(Date date, DateFract fract, bool preserve_state_tick) _date_fract = fract; YearMonthDay ymd = ConvertDateToYMD(date); _cur_date_ymd = ymd; - if (preserve_state_tick) { - RebaseStateTicksBase(); - } else { - SetScaledTickVariables(); - } + RecalculateStateTicksOffset(); UpdateCachedSnowLine(); } -void SetScaledTickVariables() +StateTicks GetStateTicksFromCurrentDateWithoutOffset() +{ + return ((int64_t)(DateToDateTicks(_date, _date_fract).base()) * _settings_game.economy.day_length_factor) + _tick_skip_counter; +} + +void RecalculateStateTicksOffset() { - _state_ticks = ((int64_t)(DateToDateTicks(_date, _date_fract).base()) * _settings_game.economy.day_length_factor) + _tick_skip_counter + _state_ticks_offset; + _state_ticks_offset = _state_ticks - GetStateTicksFromCurrentDateWithoutOffset(); } #define M(a, b) ((a << 5) | b) @@ -270,7 +260,7 @@ static void OnNewYear() LinkGraphSchedule::instance.ShiftDates(-days_this_year); ShiftOrderDates(-days_this_year); ShiftVehicleDates(-days_this_year); - _state_ticks_offset += ((int64_t)days_this_year) * (DAY_TICKS * _settings_game.economy.day_length_factor); + RecalculateStateTicksOffset(); /* Because the _date wraps here, and text-messages expire by game-days, we have to clean out * all of them if the date is set back, else those messages will hang for ever */ diff --git a/src/date_func.h b/src/date_func.h index 397a54c536..525848fdb8 100644 --- a/src/date_func.h +++ b/src/date_func.h @@ -21,17 +21,18 @@ extern uint64_t _tick_counter; extern uint8_t _tick_skip_counter; extern uint64_t _scaled_tick_counter; extern StateTicks _state_ticks; -extern StateTicks _state_ticks_offset; +extern StateTicksDelta _state_ticks_offset; extern uint32_t _quit_after_days; extern YearMonthDay _game_load_cur_date_ymd; extern DateFract _game_load_date_fract; extern uint8_t _game_load_tick_skip_counter; -void SetDate(Date date, DateFract fract, bool preserve_scaled_ticks = true); +void SetDate(Date date, DateFract fract); YearMonthDay ConvertDateToYMD(Date date); Date ConvertYMDToDate(Year year, Month month, Day day); -void SetScaledTickVariables(); +StateTicks GetStateTicksFromCurrentDateWithoutOffset(); +void RecalculateStateTicksOffset(); inline Date ConvertYMDToDate(const YearMonthDay &ymd) { diff --git a/src/date_type.h b/src/date_type.h index 027b95d0d9..9d78c9388e 100644 --- a/src/date_type.h +++ b/src/date_type.h @@ -200,6 +200,9 @@ static const Year MAX_YEAR = 5000000; /** The number of days till the last day */ static constexpr Date MAX_DATE = DateAtStartOfYear(MAX_YEAR + 1) - 1; +/** An initial value for StateTicks when starting a new game */ +static constexpr StateTicks INITIAL_STATE_TICKS_VALUE = 1 << 24; + /** * Data structure to convert between Date and triplet (year, month, and day). * @see ConvertDateToYMD(), ConvertYMDToDate() diff --git a/src/misc.cpp b/src/misc.cpp index 9115e3be9b..0982264926 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -131,6 +131,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin _tick_counter = 0; _tick_skip_counter = 0; _scaled_tick_counter = 0; + _state_ticks = INITIAL_STATE_TICKS_VALUE; _state_ticks_offset = 0; _cur_tileloop_tile = 1; _aux_tileloop_tile = 1; @@ -153,10 +154,10 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin _newgrf_profilers.clear(); if (reset_date) { - SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0, false); + SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0); InitializeOldNames(); } else { - SetScaledTickVariables(); + RecalculateStateTicksOffset(); } SetupTileLoopCounts(); UpdateCargoScalers(); diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 2f61a248a5..73ac1a2f0d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -11605,7 +11605,8 @@ void LoadNewGRF(uint load_index, uint num_baseset) uint64_t tick_counter = _tick_counter; uint8_t tick_skip_counter = _tick_skip_counter; uint64_t scaled_tick_counter = _scaled_tick_counter; - StateTicks state_ticks_offset = _state_ticks_offset; + StateTicks state_ticks = _state_ticks; + StateTicksDelta state_ticks_offset = _state_ticks_offset; byte display_opt = _display_opt; if (_networking) { @@ -11615,10 +11616,10 @@ void LoadNewGRF(uint load_index, uint num_baseset) _tick_counter = 0; _tick_skip_counter = 0; _scaled_tick_counter = 0; - _state_ticks_offset = 0; + _state_ticks = 0; _display_opt = 0; UpdateCachedSnowLine(); - SetScaledTickVariables(); + RecalculateStateTicksOffset(); } InitializeGRFSpecial(); @@ -11722,10 +11723,10 @@ void LoadNewGRF(uint load_index, uint num_baseset) _tick_counter = tick_counter; _tick_skip_counter = tick_skip_counter; _scaled_tick_counter = scaled_tick_counter; + _state_ticks = state_ticks; _state_ticks_offset = state_ticks_offset; _display_opt = display_opt; UpdateCachedSnowLine(); - SetScaledTickVariables(); } /** diff --git a/src/openttd.cpp b/src/openttd.cpp index cdde270b16..eeecb32092 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -2149,7 +2149,7 @@ void StateGameLoop() _tick_skip_counter++; _scaled_tick_counter++; if (_game_mode != GM_MENU && _game_mode != GM_BOOTSTRAP) { - _state_ticks++; // This must update in lock-step with _tick_skip_counter, such that it always matches what SetScaledTickVariables would return. + _state_ticks++; // This must update in lock-step with _tick_skip_counter, such that _state_ticks_offset doesn't need to be changed. } if (!(_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) && !_settings_client.gui.autosave_realtime && diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 26d75f361f..a66ae98086 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -862,10 +862,13 @@ bool AfterLoadGame() if (SlXvIsFeatureMissing(XSLFI_VARIABLE_DAY_LENGTH, 3)) { _scaled_tick_counter = (uint64_t)((_tick_counter * _settings_game.economy.day_length_factor) + _tick_skip_counter); } + if (SlXvIsFeaturePresent(XSLFI_VARIABLE_DAY_LENGTH, 1, 3)) { + _state_ticks = GetStateTicksFromCurrentDateWithoutOffset() + _state_ticks_offset; + } /* Update current year * must be done before loading sprites as some newgrfs check it */ - SetDate(_date, _date_fract, false); + SetDate(_date, _date_fract); SetupTileLoopCounts(); /* @@ -1796,7 +1799,7 @@ bool AfterLoadGame() * Account for this in older games by adding an offset */ if (IsSavegameVersionBefore(SLV_31)) { _date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); - SetScaledTickVariables(); + RecalculateStateTicksOffset(); _cur_date_ymd = ConvertDateToYMD(_date); UpdateCachedSnowLine(); diff --git a/src/settings.cpp b/src/settings.cpp index da11c2bcbd..3c8e4a9254 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1850,8 +1850,7 @@ static bool DayLengthPreChange(int32_t &new_value) static void DayLengthChanged(int32_t new_value) { - extern void RebaseStateTicksBase(); - RebaseStateTicksBase(); + RecalculateStateTicksOffset(); SetupTileLoopCounts(); UpdateCargoScalers(); diff --git a/src/sl/extended_ver_sl.cpp b/src/sl/extended_ver_sl.cpp index 4487ad4655..ec24f41081 100644 --- a/src/sl/extended_ver_sl.cpp +++ b/src/sl/extended_ver_sl.cpp @@ -103,7 +103,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_VEHICLE_REPAIR_COST, XSCF_NULL, 2, 2, "vehicle_repair_cost", nullptr, nullptr, nullptr }, { XSLFI_ENH_VIEWPORT_PLANS, XSCF_IGNORABLE_ALL, 4, 4, "enh_viewport_plans", nullptr, nullptr, "PLAN" }, { XSLFI_INFRA_SHARING, XSCF_NULL, 2, 2, "infra_sharing", nullptr, nullptr, "CPDP" }, - { XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 3, 3, "variable_day_length", nullptr, nullptr, nullptr }, + { XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 4, 4, "variable_day_length", nullptr, nullptr, nullptr }, { XSLFI_ORDER_OCCUPANCY, XSCF_NULL, 2, 2, "order_occupancy", nullptr, nullptr, nullptr }, { XSLFI_MORE_COND_ORDERS, XSCF_NULL, 17, 17, "more_cond_orders", nullptr, nullptr, nullptr }, { XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", nullptr, nullptr, nullptr }, diff --git a/src/sl/misc_sl.cpp b/src/sl/misc_sl.cpp index a827ee1831..732c28109a 100644 --- a/src/sl/misc_sl.cpp +++ b/src/sl/misc_sl.cpp @@ -91,7 +91,8 @@ static const SaveLoad _date_desc[] = { SLEG_CONDVAR_X(_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)), SLEG_CONDVAR_X(_tick_skip_counter, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH)), SLEG_CONDVAR_X(_scaled_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)), - SLEG_CONDVAR_X(_state_ticks_offset, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)), + SLEG_CONDVAR_X(_state_ticks_offset, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3, 3)), + SLEG_CONDVAR_X(_state_ticks, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 4)), SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157), // _vehicle_id_ctr_day SLEG_CONDVAR(_age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162), SLE_CONDNULL(1, SL_MIN_VERSION, SLV_46), @@ -128,7 +129,8 @@ static const SaveLoad _date_check_desc[] = { SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER)), // _tick_counter SLE_CONDNULL_X(1, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH)), // _tick_skip_counter SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)), // _scaled_tick_counter - SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3)), // _state_ticks_offset + SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3, 3)), // _state_ticks_offset + SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 4)), // _state_ticks SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157), // _vehicle_id_ctr_day SLE_CONDNULL(1, SL_MIN_VERSION, SLV_162), // _age_cargo_skip_counter SLE_CONDNULL(1, SL_MIN_VERSION, SLV_46), @@ -160,7 +162,6 @@ static const SaveLoad _date_check_desc[] = { static void SaveLoad_DATE() { SlGlobList(_date_desc); - SetScaledTickVariables(); } static void Check_DATE()