diff --git a/src/elrail.cpp b/src/elrail.cpp index abfc0ed150..16e82ae3e0 100644 --- a/src/elrail.cpp +++ b/src/elrail.cpp @@ -703,7 +703,11 @@ void DrawRailCatenary(const TileInfo *ti) void SettingsDisableElrail(int32_t new_value) { bool disable = (new_value != 0); + UpdateDisableElrailSettingState(disable, true); +} +void UpdateDisableElrailSettingState(bool disable, bool update_vehicles) +{ /* pick appropriate railtype for elrail engines depending on setting */ const RailType new_railtype = disable ? RAILTYPE_RAIL : RAILTYPE_ELECTRIC; @@ -731,10 +735,12 @@ void SettingsDisableElrail(int32_t new_value) } /* Fix the total power and acceleration for trains */ - for (Train *t : Train::IterateFrontOnly()) { - /* power and acceleration is cached only for front engines */ - if (t->IsFrontEngine()) { - t->ConsistChanged(CCF_TRACK); + if (update_vehicles) { + for (Train *t : Train::IterateFrontOnly()) { + /* power and acceleration is cached only for front engines */ + if (t->IsFrontEngine()) { + t->ConsistChanged(CCF_TRACK); + } } } diff --git a/src/elrail_func.h b/src/elrail_func.h index 124dffb0b9..3f6ca0cee1 100644 --- a/src/elrail_func.h +++ b/src/elrail_func.h @@ -37,5 +37,6 @@ void DrawRailCatenaryOnTunnel(const TileInfo *ti); void DrawRailCatenaryOnBridge(const TileInfo *ti); void SettingsDisableElrail(int32_t new_value); ///< _settings_game.disable_elrail callback +void UpdateDisableElrailSettingState(bool disable, bool update_vehicles); #endif /* ELRAIL_FUNC_H */ diff --git a/src/order_base.h b/src/order_base.h index 559d78c5c9..80e44bc33e 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -890,7 +890,7 @@ static_assert(DispatchSchedule::DEPARTURE_TAG_COUNT == 1 + (DispatchSlot::SDSF_L */ struct OrderList : OrderListPool::PoolItem<&_orderlist_pool> { private: - friend void AfterLoadVehicles(bool part_of_load); ///< For instantiating the shared vehicle chain + friend void AfterLoadVehiclesPhase1(bool part_of_load); ///< For instantiating the shared vehicle chain friend SaveLoadTable GetOrderListDescription(); ///< Saving and loading of order lists. friend upstream_sl::SaveLoadTable upstream_sl::GetOrderListDescription(); ///< Saving and loading of order lists. friend void Ptrs_ORDL(); ///< Saving and loading of order lists. diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index d3e432e9d4..e849ce2693 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -985,17 +985,6 @@ bool AfterLoadGame() * filled; and that could eventually lead to desyncs. */ CargoPacket::AfterLoad(); - /* Oilrig was moved from id 15 to 9. We have to do this conversion - * here as AfterLoadVehicles can check it indirectly via the newgrf - * code. */ - if (IsSavegameVersionBefore(SLV_139)) { - for (Station *st : Station::Iterate()) { - if (st->airport.tile != INVALID_TILE && st->airport.type == 15) { - st->airport.type = AT_OILRIG; - } - } - } - if (SlXvIsFeaturePresent(XSLFI_SPRINGPP)) { /* * Reject huge airports @@ -1061,8 +1050,8 @@ bool AfterLoadGame() extern void AnalyseHouseSpriteGroups(); AnalyseHouseSpriteGroups(); - /* Update all vehicles */ - AfterLoadVehicles(true); + /* Update all vehicles: Phase 1 */ + AfterLoadVehiclesPhase1(true); CargoPacket::PostVehiclesAfterLoad(); @@ -1747,11 +1736,6 @@ bool AfterLoadGame() SetSecondaryRailType(t, GetRailType(t)); } } - - for (Train *v : Train::IterateFrontOnly()) { - if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(CCF_TRACK); - } - } /* In version 16.1 of the savegame a company can decide if trains, which get @@ -1900,7 +1884,7 @@ bool AfterLoadGame() * preference of a user, let elrails enabled; it can be disabled manually */ if (IsSavegameVersionBefore(SLV_38)) _settings_game.vehicle.disable_elrails = false; /* do the same as when elrails were enabled/disabled manually just now */ - SettingsDisableElrail(_settings_game.vehicle.disable_elrails); + UpdateDisableElrailSettingState(_settings_game.vehicle.disable_elrails, false); InitializeRailGUI(); /* From version 53, the map array was changed for house tiles to allow @@ -2872,6 +2856,14 @@ bool AfterLoadGame() } } + if (IsSavegameVersionBefore(SLV_139)) { + for (Station *st : Station::Iterate()) { + if (st->airport.tile != INVALID_TILE && st->airport.type == 15) { + st->airport.type = AT_OILRIG; + } + } + } + if (IsSavegameVersionBefore(SLV_140)) { for (Station *st : Station::Iterate()) { if (st->airport.tile != INVALID_TILE) { @@ -3469,6 +3461,14 @@ bool AfterLoadGame() } } + /* Beyond this point, tile types which can be accessed by vehicles must be in a valid state. */ + + /* Update all vehicles: Phase 2 */ + AfterLoadVehiclesPhase2(true); + + /* The center of train vehicles was changed, fix up spacing. */ + if (IsSavegameVersionBefore(SLV_164)) FixupTrainLengths(); + /* In version 2.2 of the savegame, we have new airports, so status of all aircraft is reset. * This has to be called after all map array updates */ if (IsSavegameVersionBefore(SLV_2, 2)) UpdateOldAircraft(); @@ -4580,7 +4580,8 @@ void ReloadNewGRFData() AnalyseIndustryTileSpriteGroups(); extern void AnalyseHouseSpriteGroups(); AnalyseHouseSpriteGroups(); - AfterLoadVehicles(false); + AfterLoadVehiclesPhase1(false); + AfterLoadVehiclesPhase2(false); StartupEngines(); GroupStatistics::UpdateAfterLoad(); /* update station graphics */ diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 11413034b4..8a37546990 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -28,7 +28,6 @@ #include "../safeguards.h" -void AfterLoadVehicles(bool part_of_load); bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // From train_cmd.cpp void ReverseTrainDirection(Train *v); void ReverseTrainSwapVeh(Train *v, int l, int r); diff --git a/src/sl/saveload_internal.h b/src/sl/saveload_internal.h index d97a574ba9..fe8baaccac 100644 --- a/src/sl/saveload_internal.h +++ b/src/sl/saveload_internal.h @@ -25,7 +25,8 @@ void MoveBuoysToWaypoints(); void MoveWaypointsToBaseStations(); SaveLoadTable GetBaseStationDescription(); -void AfterLoadVehicles(bool part_of_load); +void AfterLoadVehiclesPhase1(bool part_of_load); +void AfterLoadVehiclesPhase2(bool part_of_load); void AfterLoadVehiclesRemoveAnyFoundInvalid(); void AfterLoadEngines(); void FixupTrainLengths(); diff --git a/src/sl/vehicle_sl.cpp b/src/sl/vehicle_sl.cpp index 27268c75ea..5e76094215 100644 --- a/src/sl/vehicle_sl.cpp +++ b/src/sl/vehicle_sl.cpp @@ -262,13 +262,13 @@ extern uint8_t _age_cargo_skip_counter; // From misc_sl.cpp static std::vector _load_invalid_vehicles_to_delete; -/** Called after load to update coordinates */ -void AfterLoadVehicles(bool part_of_load) +/** Called after load for phase 1 of vehicle initialisation */ +void AfterLoadVehiclesPhase1(bool part_of_load) { _load_invalid_vehicles_to_delete.clear(); const Vehicle *si_v = nullptr; - SCOPE_INFO_FMT([&si_v], "AfterLoadVehicles: %s", scope_dumper().VehicleInfo(si_v)); + SCOPE_INFO_FMT([&si_v], "AfterLoadVehiclesPhase1: %s", scope_dumper().VehicleInfo(si_v)); for (Vehicle *v : Vehicle::Iterate()) { si_v = v; /* Reinstate the previous pointer */ @@ -420,15 +420,6 @@ void AfterLoadVehicles(bool part_of_load) } } - if (SlXvIsFeaturePresent(XSLFI_TEMPLATE_REPLACEMENT) && (_network_server || !_networking)) { - for (Train *t : Train::Iterate()) { - si_v = t; - if (t->IsVirtual() && t->First() == t) { - delete t; - } - } - } - if (IsSavegameVersionBefore(SLV_VEHICLE_ECONOMY_AGE) && SlXvIsFeatureMissing(XSLFI_VEHICLE_ECONOMY_AGE)) { /* Set vehicle economy age based on calendar age. */ for (Vehicle *v : Vehicle::Iterate()) { @@ -439,10 +430,16 @@ void AfterLoadVehicles(bool part_of_load) si_v = nullptr; CheckValidVehicles(); +} +/** Called after load for phase 2 of vehicle initialisation */ +void AfterLoadVehiclesPhase2(bool part_of_load) +{ + const Vehicle *si_v = nullptr; + SCOPE_INFO_FMT([&si_v], "AfterLoadVehiclesPhase2: %s", scope_dumper().VehicleInfo(si_v)); for (Vehicle *v : Vehicle::IterateFrontOnly()) { si_v = v; - assert(v->first != nullptr); + assert(v->First() != nullptr); v->trip_occupancy = CalcPercentVehicleFilled(v, nullptr); @@ -498,6 +495,16 @@ void AfterLoadVehicles(bool part_of_load) } } + if (part_of_load && SlXvIsFeaturePresent(XSLFI_TEMPLATE_REPLACEMENT) && (_network_server || !_networking)) { + for (Train *t : Train::IterateFrontOnly()) { + si_v = t; + if (t->IsVirtual()) { + t->unitnumber = 0; + delete t; + } + } + } + /* Stop non-front engines */ if (part_of_load && IsSavegameVersionBefore(SLV_112)) { for (Vehicle *v : Vehicle::Iterate()) { diff --git a/src/vehicle_base.h b/src/vehicle_base.h index b0fe4bfb46..2a672d8d0b 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -323,7 +323,7 @@ private: public: friend SaveLoadTable GetVehicleDescription(VehicleType vt); ///< So we can use private/protected variables in the saveload code friend void FixOldVehicles(); - friend void AfterLoadVehicles(bool part_of_load); ///< So we can set the #previous and #first pointers while loading + friend void AfterLoadVehiclesPhase1(bool part_of_load); ///< So we can set the #previous and #first pointers while loading friend bool LoadOldVehicle(LoadgameState *ls, int num); ///< So we can set the proper next pointer while loading friend upstream_sl::SlVehicleCommon;