OpenTTD Source 20250524-master-gc366e6a48e
cachecheck.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "aircraft.h"
12#include "company_base.h"
13#include "debug.h"
14#include "industry.h"
15#include "roadstop_base.h"
16#include "roadveh.h"
17#include "ship.h"
18#include "station_base.h"
19#include "station_map.h"
20#include "subsidy_func.h"
21#include "town.h"
22#include "train.h"
23#include "vehicle_base.h"
24
25#include "safeguards.h"
26
27extern void AfterLoadCompanyStats();
28extern void RebuildTownCaches();
29
37{
38 /* Return here so it is easy to add checks that are run
39 * always to aid testing of caches. */
40 if (_debug_desync_level <= 1) return;
41
42 /* Check the town caches. */
43 std::vector<TownCache> old_town_caches;
44 for (const Town *t : Town::Iterate()) {
45 old_town_caches.push_back(t->cache);
46 }
47
50
51 uint i = 0;
52 for (Town *t : Town::Iterate()) {
53 if (old_town_caches[i] != t->cache) {
54 Debug(desync, 2, "warning: town cache mismatch: town {}", t->index);
55 }
56 i++;
57 }
58
59 /* Check company infrastructure cache. */
60 std::vector<CompanyInfrastructure> old_infrastructure;
61 for (const Company *c : Company::Iterate()) old_infrastructure.push_back(c->infrastructure);
62
64
65 i = 0;
66 for (const Company *c : Company::Iterate()) {
67 if (old_infrastructure[i] != c->infrastructure) {
68 Debug(desync, 2, "warning: infrastructure cache mismatch: company {}", c->index);
69 }
70 i++;
71 }
72
73 /* Strict checking of the road stop cache entries */
74 for (const RoadStop *rs : RoadStop::Iterate()) {
75 if (IsBayRoadStopTile(rs->xy)) continue;
76
77 rs->GetEntry(DIAGDIR_NE).CheckIntegrity(rs);
78 rs->GetEntry(DIAGDIR_NW).CheckIntegrity(rs);
79 }
80
81 std::vector<NewGRFCache> grf_cache;
82 std::vector<VehicleCache> veh_cache;
83 std::vector<GroundVehicleCache> gro_cache;
84 std::vector<TrainCache> tra_cache;
85
86 for (Vehicle *v : Vehicle::Iterate()) {
87 if (v != v->First() || v->vehstatus.Test(VehState::Crashed) || !v->IsPrimaryVehicle()) continue;
88
89 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
91 grf_cache.emplace_back(u->grf_cache);
92 veh_cache.emplace_back(u->vcache);
93 switch (u->type) {
94 case VEH_TRAIN:
95 gro_cache.emplace_back(Train::From(u)->gcache);
96 tra_cache.emplace_back(Train::From(u)->tcache);
97 break;
98 case VEH_ROAD:
99 gro_cache.emplace_back(RoadVehicle::From(u)->gcache);
100 break;
101 default:
102 break;
103 }
104 }
105
106 switch (v->type) {
107 case VEH_TRAIN: Train::From(v)->ConsistChanged(CCF_TRACK); break;
110 case VEH_SHIP: Ship::From(v)->UpdateCache(); break;
111 default: break;
112 }
113
114 uint length = 0;
115 for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
117 if (grf_cache[length] != u->grf_cache) {
118 Debug(desync, 2, "warning: newgrf cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
119 }
120 if (veh_cache[length] != u->vcache) {
121 Debug(desync, 2, "warning: vehicle cache mismatch: type {}, vehicle {}, company {}, unit number {}, wagon {}", v->type, v->index, v->owner, v->unitnumber, length);
122 }
123 switch (u->type) {
124 case VEH_TRAIN:
125 if (gro_cache[length] != Train::From(u)->gcache) {
126 Debug(desync, 2, "warning: train ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
127 }
128 if (tra_cache[length] != Train::From(u)->tcache) {
129 Debug(desync, 2, "warning: train cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
130 }
131 break;
132 case VEH_ROAD:
133 if (gro_cache[length] != RoadVehicle::From(u)->gcache) {
134 Debug(desync, 2, "warning: road vehicle ground vehicle cache mismatch: vehicle {}, company {}, unit number {}, wagon {}", v->index, v->owner, v->unitnumber, length);
135 }
136 break;
137 default:
138 break;
139 }
140 length++;
141 }
142
143 grf_cache.clear();
144 veh_cache.clear();
145 gro_cache.clear();
146 tra_cache.clear();
147 }
148
149 /* Check whether the caches are still valid */
150 for (Vehicle *v : Vehicle::Iterate()) {
151 [[maybe_unused]] const auto a = v->cargo.PeriodsInTransit();
152 [[maybe_unused]] const auto b = v->cargo.TotalCount();
153 [[maybe_unused]] const auto c = v->cargo.GetFeederShare();
154 v->cargo.InvalidateCache();
155 assert(a == v->cargo.PeriodsInTransit());
156 assert(b == v->cargo.TotalCount());
157 assert(c == v->cargo.GetFeederShare());
158 }
159
160 /* Backup stations_near */
161 std::vector<StationList> old_town_stations_near;
162 for (Town *t : Town::Iterate()) old_town_stations_near.push_back(t->stations_near);
163
164 std::vector<StationList> old_industry_stations_near;
165 for (Industry *ind : Industry::Iterate()) old_industry_stations_near.push_back(ind->stations_near);
166
167 std::vector<IndustryList> old_station_industries_near;
168 for (Station *st : Station::Iterate()) old_station_industries_near.push_back(st->industries_near);
169
170 for (Station *st : Station::Iterate()) {
171 for (GoodsEntry &ge : st->goods) {
172 if (!ge.HasData()) continue;
173
174 StationCargoList &cargo_list = ge.GetData().cargo;
175 [[maybe_unused]] const auto a = cargo_list.PeriodsInTransit();
176 [[maybe_unused]] const auto b = cargo_list.TotalCount();
177 cargo_list.InvalidateCache();
178 assert(a == cargo_list.PeriodsInTransit());
179 assert(b == cargo_list.TotalCount());
180 }
181
182 /* Check docking tiles */
183 TileArea ta;
184 std::map<TileIndex, bool> docking_tiles;
185 for (TileIndex tile : st->docking_station) {
186 ta.Add(tile);
187 docking_tiles[tile] = IsDockingTile(tile);
188 }
189 UpdateStationDockingTiles(st);
190 if (ta.tile != st->docking_station.tile || ta.w != st->docking_station.w || ta.h != st->docking_station.h) {
191 Debug(desync, 2, "warning: station docking mismatch: station {}, company {}", st->index, st->owner);
192 }
193 for (TileIndex tile : ta) {
194 if (docking_tiles[tile] != IsDockingTile(tile)) {
195 Debug(desync, 2, "warning: docking tile mismatch: tile {}", tile);
196 }
197 }
198 }
199
201
202 /* Check industries_near */
203 i = 0;
204 for (Station *st : Station::Iterate()) {
205 if (st->industries_near != old_station_industries_near[i]) {
206 Debug(desync, 2, "warning: station industries near mismatch: station {}", st->index);
207 }
208 i++;
209 }
210
211 /* Check stations_near */
212 i = 0;
213 for (Town *t : Town::Iterate()) {
214 if (t->stations_near != old_town_stations_near[i]) {
215 Debug(desync, 2, "warning: town stations near mismatch: town {}", t->index);
216 }
217 i++;
218 }
219 i = 0;
220 for (Industry *ind : Industry::Iterate()) {
221 if (ind->stations_near != old_industry_stations_near[i]) {
222 Debug(desync, 2, "warning: industry stations near mismatch: industry {}", ind->index);
223 }
224 i++;
225 }
226}
Base for aircraft.
void UpdateAircraftCache(Aircraft *v, bool update_range=false)
Update cached values of an aircraft.
void RebuildTownCaches()
Rebuild all the cached variables of towns.
Definition town_sl.cpp:27
void AfterLoadCompanyStats()
Rebuilding of company statistics after loading a savegame.
void CheckCaches()
Check the validity of some of the caches.
uint PeriodsInTransit() const
Returns average number of cargo aging periods in transit for a cargo entity.
void InvalidateCache()
Invalidates the cached data and rebuilds it.
CargoList that is used for stations.
uint TotalCount() const
Returns total count of cargo at the station, including cargo which is already reserved for loading.
Definition of stuff that is very close to a company, like the company struct itself.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
Base of all industries.
void FillNewGRFVehicleCache(const Vehicle *v)
Fill the grf_cache of the given vehicle.
Base class for roadstops.
Road vehicle states.
void RoadVehUpdateCache(RoadVehicle *v, bool same_length=false)
Update the cache of a road vehicle.
A number of safeguards to prevent using unsafe methods.
Base for ships.
Base classes/functions for stations.
Maps accessors for stations.
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
Definition of base types and functions in a cross-platform compatible way.
Stores station stats for a single cargo.
Defines the internal data of a functional industry.
Definition industry.h:64
Represents the covered area of e.g.
uint16_t w
The width of the area.
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition tilearea.cpp:43
TileIndex tile
The base tile of the area.
uint16_t h
The height of the area.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
A Stop for a Road Vehicle.
void UpdateCache()
Update the caches of this ship.
Definition ship_cmd.cpp:232
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Station data structure.
static void RecomputeCatchmentForAll()
Recomputes catchment of all stations.
Definition station.cpp:534
Town data structure.
Definition town.h:52
Vehicle data structure.
Vehicle * Next() const
Get the next vehicle of this vehicle.
void RebuildSubsidisedSourceAndDestinationCache()
Perform a full rebuild of the subsidies cache.
Definition subsidy.cpp:103
Functions related to subsidies.
Base of the town class.
Base for the train class.
static constexpr ConsistChangeFlags CCF_TRACK
Valid changes while vehicle is driving, and possibly changing tracks.
Definition train.h:52
Base class for all vehicles.
@ Crashed
Vehicle is crashed.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:371