OpenTTD Source  20241108-master-g80f628063a
linkgraph_sl.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 
12 #include "saveload.h"
14 
15 #include "../linkgraph/linkgraph.h"
16 #include "../linkgraph/linkgraphjob.h"
17 #include "../linkgraph/linkgraphschedule.h"
18 #include "../network/network.h"
19 #include "../settings_internal.h"
20 #include "../settings_table.h"
21 
22 #include "../safeguards.h"
23 
26 
27 static uint16_t _num_nodes;
29 static NodeID _linkgraph_from;
30 
31 class SlLinkgraphEdge : public DefaultSaveLoadHandler<SlLinkgraphEdge, Node> {
32 public:
33  inline static const SaveLoad description[] = {
34  SLE_VAR(Edge, capacity, SLE_UINT32),
35  SLE_VAR(Edge, usage, SLE_UINT32),
36  SLE_CONDVAR(Edge, travel_time_sum, SLE_UINT64, SLV_LINKGRAPH_TRAVEL_TIME, SL_MAX_VERSION),
37  SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
38  SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION),
39  SLE_VAR(Edge, dest_node, SLE_UINT16),
40  SLE_CONDVARNAME(Edge, dest_node, "next_edge", SLE_UINT16, SL_MIN_VERSION, SLV_LINKGRAPH_EDGES),
41  };
42  inline const static SaveLoadCompatTable compat_description = _linkgraph_edge_sl_compat;
43 
44  void Save(Node *bn) const override
45  {
46  SlSetStructListLength(bn->edges.size());
47  for (Edge &e : bn->edges) {
48  SlObject(&e, this->GetDescription());
49  }
50  }
51 
52  void Load(Node *bn) const override
53  {
55  uint16_t max_size = _linkgraph->Size();
56  std::vector<Edge> edges(max_size);
57 
59  /* We used to save the full matrix ... */
60  for (NodeID to = 0; to < max_size; ++to) {
61  SlObject(&edges[to], this->GetLoadDescription());
62  }
63  } else {
64  size_t used_size = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? max_size : SlGetStructListLength(UINT16_MAX);
65 
66  /* ... but as that wasted a lot of space we save a sparse matrix now. */
67  for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = edges[to].dest_node) {
68  if (used_size == 0) SlErrorCorrupt("Link graph structure overflow");
69  used_size--;
70 
71  if (to >= max_size) SlErrorCorrupt("Link graph structure overflow");
72  SlObject(&edges[to], this->GetLoadDescription());
73  }
74 
75  if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph");
76  }
77 
78  /* Build edge list from edge matrix. */
79  for (NodeID to = edges[_linkgraph_from].dest_node; to != INVALID_NODE; to = edges[to].dest_node) {
80  bn->edges.push_back(edges[to]);
81  bn->edges.back().dest_node = to;
82  }
83  /* Sort by destination. */
84  std::sort(bn->edges.begin(), bn->edges.end());
85  } else {
86  /* Edge data is now a simple vector and not any kind of matrix. */
87  size_t size = SlGetStructListLength(UINT16_MAX);
88  for (size_t i = 0; i < size; i++) {
89  bn->edges.emplace_back();
90  SlObject(&bn->edges.back(), this->GetLoadDescription());
91  }
92  }
93  }
94 };
95 
96 class SlLinkgraphNode : public DefaultSaveLoadHandler<SlLinkgraphNode, LinkGraph> {
97 public:
98  inline static const SaveLoad description[] = {
99  SLE_CONDVAR(Node, xy, SLE_UINT32, SLV_191, SL_MAX_VERSION),
100  SLE_VAR(Node, supply, SLE_UINT32),
101  SLE_VAR(Node, demand, SLE_UINT32),
102  SLE_VAR(Node, station, SLE_UINT16),
103  SLE_VAR(Node, last_update, SLE_INT32),
105  };
106  inline const static SaveLoadCompatTable compat_description = _linkgraph_node_sl_compat;
107 
108  void Save(LinkGraph *lg) const override
109  {
110  _linkgraph = lg;
111 
113  for (NodeID from = 0; from < lg->Size(); ++from) {
114  _linkgraph_from = from;
115  SlObject(&lg->nodes[from], this->GetDescription());
116  }
117  }
118 
119  void Load(LinkGraph *lg) const override
120  {
121  _linkgraph = lg;
122 
123  uint16_t length = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? _num_nodes : (uint16_t)SlGetStructListLength(UINT16_MAX);
124  lg->Init(length);
125  for (NodeID from = 0; from < length; ++from) {
126  _linkgraph_from = from;
127  SlObject(&lg->nodes[from], this->GetLoadDescription());
128  }
129  }
130 };
131 
137 {
138  static const SaveLoad link_graph_desc[] = {
139  SLE_VAR(LinkGraph, last_compression, SLE_INT32),
140  SLEG_CONDVAR("num_nodes", _num_nodes, SLE_UINT16, SL_MIN_VERSION, SLV_SAVELOAD_LIST_LENGTH),
141  SLE_VAR(LinkGraph, cargo, SLE_UINT8),
143  };
144  return link_graph_desc;
145 }
146 
154 class SlLinkgraphJobProxy : public DefaultSaveLoadHandler<SlLinkgraphJobProxy, LinkGraphJob> {
155 public:
156  inline static const SaveLoad description[] = {{}}; // Needed to keep DefaultSaveLoadHandler happy.
157  SaveLoadTable GetDescription() const override { return GetLinkGraphDesc(); }
158  inline const static SaveLoadCompatTable compat_description = _linkgraph_sl_compat;
159 
160  void Save(LinkGraphJob *lgj) const override
161  {
162  SlObject(const_cast<LinkGraph *>(&lgj->Graph()), this->GetDescription());
163  }
164 
165  void Load(LinkGraphJob *lgj) const override
166  {
167  SlObject(const_cast<LinkGraph *>(&lgj->Graph()), this->GetLoadDescription());
168  }
169 };
170 
181 {
182  static std::vector<SaveLoad> saveloads;
183 
184  static const SaveLoad job_desc[] = {
185  SLE_VAR(LinkGraphJob, join_date, SLE_INT32),
186  SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
187  SLEG_STRUCT("linkgraph", SlLinkgraphJobProxy),
188  };
189 
190  /* The member offset arithmetic below is only valid if the types in question
191  * are standard layout types. Otherwise, it would be undefined behaviour. */
192  static_assert(std::is_standard_layout<LinkGraphSettings>::value, "LinkGraphSettings needs to be a standard layout type");
193 
194  /* We store the offset of each member of the #LinkGraphSettings in the
195  * extra data of the saveload struct. Use it together with the address
196  * of the settings struct inside the job to find the final memory address. */
197  static SaveLoadAddrProc * const proc = [](void *b, size_t extra) -> void * { return const_cast<void *>(static_cast<const void *>(reinterpret_cast<const char *>(std::addressof(static_cast<LinkGraphJob *>(b)->settings)) + extra)); };
198 
199  /* Build the SaveLoad array on first call and don't touch it later on */
200  if (saveloads.empty()) {
201  GetSaveLoadFromSettingTable(_linkgraph_settings, saveloads);
202 
203  for (auto &sl : saveloads) {
204  sl.address_proc = proc;
205  }
206 
207  for (auto &sld : job_desc) {
208  saveloads.push_back(sld);
209  }
210  }
211 
212  return saveloads;
213 }
214 
220 {
221  static const SaveLoad schedule_desc[] = {
224  };
225  return schedule_desc;
226 }
227 
233 {
235  for (LinkGraph *lg : LinkGraph::Iterate()) {
236  for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
237  const Station *st = Station::GetIfValid((*lg)[node_id].station);
238  if (st != nullptr) (*lg)[node_id].UpdateLocation(st->xy);
239  }
240  }
241 
242  for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
243  LinkGraph *lg = &(const_cast<LinkGraph &>(lgj->Graph()));
244  for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
245  const Station *st = Station::GetIfValid((*lg)[node_id].station);
246  if (st != nullptr) (*lg)[node_id].UpdateLocation(st->xy);
247  }
248  }
249  }
250 
252 
253  if (!_networking || _network_server) {
255  }
256 }
257 
262  LGRPChunkHandler() : ChunkHandler('LGRP', CH_TABLE) {}
263 
264  void Save() const override
265  {
267 
268  for (LinkGraph *lg : LinkGraph::Iterate()) {
269  SlSetArrayIndex(lg->index);
270  SlObject(lg, GetLinkGraphDesc());
271  }
272  }
273 
274  void Load() const override
275  {
276  const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphDesc(), _linkgraph_sl_compat);
277 
278  int index;
279  while ((index = SlIterateArray()) != -1) {
280  LinkGraph *lg = new (index) LinkGraph();
281  SlObject(lg, slt);
282  }
283  }
284 };
285 
290  LGRJChunkHandler() : ChunkHandler('LGRJ', CH_TABLE) {}
291 
292  void Save() const override
293  {
295 
296  for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
297  SlSetArrayIndex(lgj->index);
299  }
300  }
301 
302  void Load() const override
303  {
304  const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphJobDesc(), _linkgraph_job_sl_compat);
305 
306  int index;
307  while ((index = SlIterateArray()) != -1) {
308  LinkGraphJob *lgj = new (index) LinkGraphJob();
309  SlObject(lgj, slt);
310  }
311  }
312 };
313 
318  LGRSChunkHandler() : ChunkHandler('LGRS', CH_TABLE) {}
319 
320  void Save() const override
321  {
323 
324  SlSetArrayIndex(0);
326  }
327 
328  void Load() const override
329  {
330  const std::vector<SaveLoad> slt = SlCompatTableHeader(GetLinkGraphScheduleDesc(), _linkgraph_schedule_sl_compat);
331 
334  if (!IsSavegameVersionBefore(SLV_RIFF_TO_ARRAY) && SlIterateArray() != -1) SlErrorCorrupt("Too many LGRS entries");
335  }
336 
337  void FixPointers() const override
338  {
340  }
341 };
342 
343 static const LGRPChunkHandler LGRP;
344 static const LGRJChunkHandler LGRJ;
345 static const LGRSChunkHandler LGRS;
346 static const ChunkHandlerRef linkgraph_chunk_handlers[] = {
347  LGRP,
348  LGRJ,
349  LGRS,
350 };
351 
352 extern const ChunkHandlerTable _linkgraph_chunk_handlers(linkgraph_chunk_handlers);
Default handler for saving/loading an object to/from disk.
Definition: saveload.h:577
SaveLoadTable GetDescription() const override
Definition: saveload.h:579
Class for calculation jobs to be run on link graphs.
Definition: linkgraphjob.h:29
const LinkGraph & Graph() const
Get a reference to the underlying link graph.
Definition: linkgraphjob.h:269
static LinkGraphSchedule instance
Static instance of LinkGraphSchedule.
void SpawnAll()
Start all threads in the running list.
A connected component of a link graph.
Definition: linkgraph.h:37
void Init(uint size)
Resize the component and fill it with empty nodes and edges.
Definition: linkgraph.cpp:251
NodeVector nodes
Nodes in the component.
Definition: linkgraph.h:266
NodeID Size() const
Get the current size of the component.
Definition: linkgraph.h:230
SaveLoadTable GetLoadDescription() const
Get the description for how to load the chunk.
Definition: saveload.cpp:3288
Proxy to reuse LinkGraph to save/load a LinkGraphJob.
SaveLoadTable GetDescription() const override
Get the description of the fields in the savegame.
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
SaveLoadTable GetLinkGraphDesc()
Get a SaveLoad array for a link graph.
SaveLoadTable GetLinkGraphScheduleDesc()
Get a SaveLoad array for the link graph schedule.
static LinkGraph * _linkgraph
Contains the current linkgraph being saved/loaded.
void AfterLoadLinkGraphs()
Spawn the threads for running link graph calculations.
SaveLoadTable GetLinkGraphJobDesc()
Get a SaveLoad array for a link graph job.
static NodeID _linkgraph_from
Contains the current "from" node being saved/loaded.
Loading of linkgraph chunks before table headers were added.
const SaveLoadCompat _linkgraph_node_sl_compat[]
Original field order for SlLinkgraphNode.
const SaveLoadCompat _linkgraph_edge_sl_compat[]
Original field order for SlLinkgraphEdge.
const SaveLoadCompat _linkgraph_schedule_sl_compat[]
Original field order for schedule_desc.
const SaveLoadCompat _linkgraph_job_sl_compat[]
Original field order for job_desc.
const SaveLoadCompat _linkgraph_sl_compat[]
Original field order for link_graph_desc.
void AfterLoad_LinkGraphPauseControl()
Pause the game on load if we would do a join with the next link graph job, but it is still running,...
bool _networking
are we in networking mode?
Definition: network.cpp:65
bool _network_server
network-server is active
Definition: network.cpp:66
size_t SlGetStructListLength(size_t limit)
Get the length of this list; if it exceeds the limit, error out.
Definition: saveload.cpp:1684
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition: saveload.cpp:658
void SlErrorCorrupt(const std::string &msg)
Error handler for corrupt savegames.
Definition: saveload.cpp:351
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
Definition: saveload.cpp:1888
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Definition: saveload.cpp:1750
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
Definition: saveload.cpp:1697
void SlSetStructListLength(size_t length)
Set the length of this list.
Definition: saveload.cpp:1668
Functions/types related to saving and loading games.
#define SLEG_STRUCTLIST(name, handler)
Storage of a list of structs in every savegame version.
Definition: saveload.h:1205
#define SLEG_CONDVAR(name, variable, type, from, to)
Storage of a global variable in some savegame versions.
Definition: saveload.h:1074
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition: saveload.h:505
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition: saveload.h:508
#define SLE_REFLIST(base, variable, type)
Storage of a list of SL_REF elements in every savegame version.
Definition: saveload.h:1036
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition: saveload.h:514
#define SLEG_STRUCT(name, handler)
Storage of a structs in every savegame version.
Definition: saveload.h:1182
#define SLE_CONDVAR(base, variable, type, from, to)
Storage of a variable in some savegame versions.
Definition: saveload.h:861
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition: saveload.h:1227
@ SLV_SAVELOAD_LIST_LENGTH
293 PR#9374 Consistency in list length with SL_STRUCT / SL_STRUCTLIST / SL_DEQUE / SL_REFLIST.
Definition: saveload.h:331
@ SLV_191
191 26636 FS#6026 Fix disaster vehicle storage (No bump) 191 26646 FS#6041 Linkgraph - store location...
Definition: saveload.h:272
@ SLV_RIFF_TO_ARRAY
294 PR#9375 Changed many CH_RIFF chunks to CH_ARRAY chunks.
Definition: saveload.h:332
@ SLV_LINKGRAPH_EDGES
304 PR#10314 Explicitly store link graph edges destination, PR#10471 int64_t instead of uint64_t leag...
Definition: saveload.h:344
@ SL_MAX_VERSION
Highest possible saveload version.
Definition: saveload.h:395
@ SL_MIN_VERSION
First savegame version.
Definition: saveload.h:31
@ SLV_187
187 25899 Linkgraph - restricted flows
Definition: saveload.h:267
@ SLV_LINKGRAPH_TRAVEL_TIME
297 PR#9457 v12.0-RC1 Store travel time in the linkgraph.
Definition: saveload.h:336
@ REF_LINK_GRAPH_JOB
Load/save a reference to a link graph job.
Definition: saveload.h:608
@ REF_LINK_GRAPH
Load/save a reference to a link graph.
Definition: saveload.h:607
std::span< const struct SaveLoad > SaveLoadTable
A table of SaveLoad entries.
Definition: saveload.h:511
#define SLE_VAR(base, variable, type)
Storage of a variable in every version of a savegame.
Definition: saveload.h:975
#define SLE_CONDVARNAME(base, variable, name, type, from, to)
Storage of a variable in some savegame versions.
Definition: saveload.h:872
void GetSaveLoadFromSettingTable(SettingTable settings, std::vector< SaveLoad > &saveloads)
Get the SaveLoad for all settings in the settings table.
Definition: settings.cpp:1641
TileIndex xy
Base tile of the station.
Handlers and description of chunk.
Definition: saveload.h:459
All link graph jobs.
void Save() const override
Save the chunk.
void Load() const override
Load the chunk.
All link graphs.
void Load() const override
Load the chunk.
void Save() const override
Save the chunk.
Link graph schedule.
void FixPointers() const override
Fix the pointers.
void Load() const override
Load the chunk.
void Save() const override
Save the chunk.
An edge in the link graph.
Definition: linkgraph.h:42
Node of the link graph.
Definition: linkgraph.h:90
std::vector< BaseEdge > edges
Sorted list of outgoing edges from this node.
Definition: linkgraph.h:97
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
SaveLoad type struct.
Definition: saveload.h:711
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.
Station data structure.
Definition: station_base.h:439