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
pull/647/head
Jonathan G Rennison 4 months ago
parent 0ea57528c9
commit d39236d50c

@ -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 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 uint64_t _scaled_tick_counter; ///< Tick counter in daylength-scaled ticks
StateTicks _state_ticks; ///< Current state tick 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 uint32_t _quit_after_days; ///< Quit after this many days of run time
YearMonthDay _game_load_cur_date_ymd; YearMonthDay _game_load_cur_date_ymd;
@ -45,14 +45,14 @@ extern void ClearOutOfDateSignalSpeedRestrictions();
void CheckStateTicksWrap() void CheckStateTicksWrap()
{ {
StateTicksDelta tick_adjust = 0; 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; 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)) { 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)) { } 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 { } else {
return; return;
} }
@ -70,23 +70,12 @@ void CheckStateTicksWrap()
AdjustLinkGraphStateTicksBase(-tick_adjust); 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. * Set the date.
* @param date New date * @param date New date
* @param fract The number of ticks that have passed on this 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); assert(fract < DAY_TICKS);
@ -94,17 +83,18 @@ void SetDate(Date date, DateFract fract, bool preserve_state_tick)
_date_fract = fract; _date_fract = fract;
YearMonthDay ymd = ConvertDateToYMD(date); YearMonthDay ymd = ConvertDateToYMD(date);
_cur_date_ymd = ymd; _cur_date_ymd = ymd;
if (preserve_state_tick) { RecalculateStateTicksOffset();
RebaseStateTicksBase();
} else {
SetScaledTickVariables();
}
UpdateCachedSnowLine(); 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) #define M(a, b) ((a << 5) | b)
@ -270,7 +260,7 @@ static void OnNewYear()
LinkGraphSchedule::instance.ShiftDates(-days_this_year); LinkGraphSchedule::instance.ShiftDates(-days_this_year);
ShiftOrderDates(-days_this_year); ShiftOrderDates(-days_this_year);
ShiftVehicleDates(-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 /* 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 */ * all of them if the date is set back, else those messages will hang for ever */

@ -21,17 +21,18 @@ extern uint64_t _tick_counter;
extern uint8_t _tick_skip_counter; extern uint8_t _tick_skip_counter;
extern uint64_t _scaled_tick_counter; extern uint64_t _scaled_tick_counter;
extern StateTicks _state_ticks; extern StateTicks _state_ticks;
extern StateTicks _state_ticks_offset; extern StateTicksDelta _state_ticks_offset;
extern uint32_t _quit_after_days; extern uint32_t _quit_after_days;
extern YearMonthDay _game_load_cur_date_ymd; extern YearMonthDay _game_load_cur_date_ymd;
extern DateFract _game_load_date_fract; extern DateFract _game_load_date_fract;
extern uint8_t _game_load_tick_skip_counter; 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); YearMonthDay ConvertDateToYMD(Date date);
Date ConvertYMDToDate(Year year, Month month, Day day); Date ConvertYMDToDate(Year year, Month month, Day day);
void SetScaledTickVariables(); StateTicks GetStateTicksFromCurrentDateWithoutOffset();
void RecalculateStateTicksOffset();
inline Date ConvertYMDToDate(const YearMonthDay &ymd) inline Date ConvertYMDToDate(const YearMonthDay &ymd)
{ {

@ -200,6 +200,9 @@ static const Year MAX_YEAR = 5000000;
/** The number of days till the last day */ /** The number of days till the last day */
static constexpr Date MAX_DATE = DateAtStartOfYear(MAX_YEAR + 1) - 1; 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). * Data structure to convert between Date and triplet (year, month, and day).
* @see ConvertDateToYMD(), ConvertYMDToDate() * @see ConvertDateToYMD(), ConvertYMDToDate()

@ -131,6 +131,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
_tick_counter = 0; _tick_counter = 0;
_tick_skip_counter = 0; _tick_skip_counter = 0;
_scaled_tick_counter = 0; _scaled_tick_counter = 0;
_state_ticks = INITIAL_STATE_TICKS_VALUE;
_state_ticks_offset = 0; _state_ticks_offset = 0;
_cur_tileloop_tile = 1; _cur_tileloop_tile = 1;
_aux_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(); _newgrf_profilers.clear();
if (reset_date) { 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(); InitializeOldNames();
} else { } else {
SetScaledTickVariables(); RecalculateStateTicksOffset();
} }
SetupTileLoopCounts(); SetupTileLoopCounts();
UpdateCargoScalers(); UpdateCargoScalers();

@ -11605,7 +11605,8 @@ void LoadNewGRF(uint load_index, uint num_baseset)
uint64_t tick_counter = _tick_counter; uint64_t tick_counter = _tick_counter;
uint8_t tick_skip_counter = _tick_skip_counter; uint8_t tick_skip_counter = _tick_skip_counter;
uint64_t scaled_tick_counter = _scaled_tick_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; byte display_opt = _display_opt;
if (_networking) { if (_networking) {
@ -11615,10 +11616,10 @@ void LoadNewGRF(uint load_index, uint num_baseset)
_tick_counter = 0; _tick_counter = 0;
_tick_skip_counter = 0; _tick_skip_counter = 0;
_scaled_tick_counter = 0; _scaled_tick_counter = 0;
_state_ticks_offset = 0; _state_ticks = 0;
_display_opt = 0; _display_opt = 0;
UpdateCachedSnowLine(); UpdateCachedSnowLine();
SetScaledTickVariables(); RecalculateStateTicksOffset();
} }
InitializeGRFSpecial(); InitializeGRFSpecial();
@ -11722,10 +11723,10 @@ void LoadNewGRF(uint load_index, uint num_baseset)
_tick_counter = tick_counter; _tick_counter = tick_counter;
_tick_skip_counter = tick_skip_counter; _tick_skip_counter = tick_skip_counter;
_scaled_tick_counter = scaled_tick_counter; _scaled_tick_counter = scaled_tick_counter;
_state_ticks = state_ticks;
_state_ticks_offset = state_ticks_offset; _state_ticks_offset = state_ticks_offset;
_display_opt = display_opt; _display_opt = display_opt;
UpdateCachedSnowLine(); UpdateCachedSnowLine();
SetScaledTickVariables();
} }
/** /**

@ -2149,7 +2149,7 @@ void StateGameLoop()
_tick_skip_counter++; _tick_skip_counter++;
_scaled_tick_counter++; _scaled_tick_counter++;
if (_game_mode != GM_MENU && _game_mode != GM_BOOTSTRAP) { 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 && if (!(_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) && !_settings_client.gui.autosave_realtime &&

@ -862,10 +862,13 @@ bool AfterLoadGame()
if (SlXvIsFeatureMissing(XSLFI_VARIABLE_DAY_LENGTH, 3)) { if (SlXvIsFeatureMissing(XSLFI_VARIABLE_DAY_LENGTH, 3)) {
_scaled_tick_counter = (uint64_t)((_tick_counter * _settings_game.economy.day_length_factor) + _tick_skip_counter); _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 /* Update current year
* must be done before loading sprites as some newgrfs check it */ * must be done before loading sprites as some newgrfs check it */
SetDate(_date, _date_fract, false); SetDate(_date, _date_fract);
SetupTileLoopCounts(); SetupTileLoopCounts();
/* /*
@ -1796,7 +1799,7 @@ bool AfterLoadGame()
* Account for this in older games by adding an offset */ * Account for this in older games by adding an offset */
if (IsSavegameVersionBefore(SLV_31)) { if (IsSavegameVersionBefore(SLV_31)) {
_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); _date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
SetScaledTickVariables(); RecalculateStateTicksOffset();
_cur_date_ymd = ConvertDateToYMD(_date); _cur_date_ymd = ConvertDateToYMD(_date);
UpdateCachedSnowLine(); UpdateCachedSnowLine();

@ -1850,8 +1850,7 @@ static bool DayLengthPreChange(int32_t &new_value)
static void DayLengthChanged(int32_t new_value) static void DayLengthChanged(int32_t new_value)
{ {
extern void RebaseStateTicksBase(); RecalculateStateTicksOffset();
RebaseStateTicksBase();
SetupTileLoopCounts(); SetupTileLoopCounts();
UpdateCargoScalers(); UpdateCargoScalers();

@ -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_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_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_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_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_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 }, { XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", nullptr, nullptr, nullptr },

@ -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_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(_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(_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 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), SLEG_CONDVAR(_age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162),
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_46), 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(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(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)), // _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(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_162), // _age_cargo_skip_counter
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_46), SLE_CONDNULL(1, SL_MIN_VERSION, SLV_46),
@ -160,7 +162,6 @@ static const SaveLoad _date_check_desc[] = {
static void SaveLoad_DATE() static void SaveLoad_DATE()
{ {
SlGlobList(_date_desc); SlGlobList(_date_desc);
SetScaledTickVariables();
} }
static void Check_DATE() static void Check_DATE()

Loading…
Cancel
Save