OpenTTD
linkgraph_sl.cpp
Go to the documentation of this file.
1 /* $Id: linkgraph_sl.cpp 27178 2015-03-07 18:27:01Z frosch $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "../stdafx.h"
13 #include "../linkgraph/linkgraph.h"
14 #include "../linkgraph/linkgraphjob.h"
15 #include "../linkgraph/linkgraphschedule.h"
16 #include "../settings_internal.h"
17 #include "saveload.h"
18 
19 #include "../safeguards.h"
20 
23 
24 const SettingDesc *GetSettingDescription(uint index);
25 
26 static uint16 _num_nodes;
27 
33 {
34  static const SaveLoad link_graph_desc[] = {
35  SLE_VAR(LinkGraph, last_compression, SLE_INT32),
36  SLEG_VAR(_num_nodes, SLE_UINT16),
37  SLE_VAR(LinkGraph, cargo, SLE_UINT8),
38  SLE_END()
39  };
40  return link_graph_desc;
41 }
42 
53 {
54  static SmallVector<SaveLoad, 16> saveloads;
55  static const char *prefix = "linkgraph.";
56 
57  /* Build the SaveLoad array on first call and don't touch it later on */
58  if (saveloads.Length() == 0) {
59  size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
60  size_t offset_component = cpp_offsetof(LinkGraphJob, settings);
61 
62  size_t prefixlen = strlen(prefix);
63 
64  int setting = 0;
65  const SettingDesc *desc = GetSettingDescription(setting);
66  while (desc->save.cmd != SL_END) {
67  if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) {
68  SaveLoad sl = desc->save;
69  char *&address = reinterpret_cast<char *&>(sl.address);
70  address -= offset_gamesettings;
71  address += offset_component;
72  *(saveloads.Append()) = sl;
73  }
74  desc = GetSettingDescription(++setting);
75  }
76 
77  const SaveLoad job_desc[] = {
78  SLE_VAR(LinkGraphJob, join_date, SLE_INT32),
79  SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
80  SLE_END()
81  };
82 
83  int i = 0;
84  do {
85  *(saveloads.Append()) = job_desc[i++];
86  } while (saveloads[saveloads.Length() - 1].cmd != SL_END);
87  }
88 
89  return &saveloads[0];
90 }
91 
97 {
98  static const SaveLoad schedule_desc[] = {
101  SLE_END()
102  };
103  return schedule_desc;
104 }
105 
106 /* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
107 
111 static const SaveLoad _node_desc[] = {
112  SLE_CONDVAR(Node, xy, SLE_UINT32, 191, SL_MAX_VERSION),
113  SLE_VAR(Node, supply, SLE_UINT32),
114  SLE_VAR(Node, demand, SLE_UINT32),
115  SLE_VAR(Node, station, SLE_UINT16),
116  SLE_VAR(Node, last_update, SLE_INT32),
117  SLE_END()
118 };
119 
123 static const SaveLoad _edge_desc[] = {
124  SLE_CONDNULL(4, 0, 190), // distance
125  SLE_VAR(Edge, capacity, SLE_UINT32),
126  SLE_VAR(Edge, usage, SLE_UINT32),
127  SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
128  SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, 187, SL_MAX_VERSION),
129  SLE_VAR(Edge, next_edge, SLE_UINT16),
130  SLE_END()
131 };
132 
138 {
139  uint size = lg.Size();
140  for (NodeID from = 0; from < size; ++from) {
141  Node *node = &lg.nodes[from];
142  SlObject(node, _node_desc);
143  if (IsSavegameVersionBefore(191)) {
144  /* We used to save the full matrix ... */
145  for (NodeID to = 0; to < size; ++to) {
146  SlObject(&lg.edges[from][to], _edge_desc);
147  }
148  } else {
149  /* ... but as that wasted a lot of space we save a sparse matrix now. */
150  for (NodeID to = from; to != INVALID_NODE; to = lg.edges[from][to].next_edge) {
151  SlObject(&lg.edges[from][to], _edge_desc);
152  }
153  }
154  }
155 }
156 
161 static void DoSave_LGRJ(LinkGraphJob *lgj)
162 {
164  _num_nodes = lgj->Size();
165  SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
166  SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
167 }
168 
173 static void DoSave_LGRP(LinkGraph *lg)
174 {
175  _num_nodes = lg->Size();
176  SlObject(lg, GetLinkGraphDesc());
177  SaveLoad_LinkGraph(*lg);
178 }
179 
183 static void Load_LGRP()
184 {
185  int index;
186  while ((index = SlIterateArray()) != -1) {
188  /* Impossible as they have been present in previous game. */
189  NOT_REACHED();
190  }
191  LinkGraph *lg = new (index) LinkGraph();
192  SlObject(lg, GetLinkGraphDesc());
193  lg->Init(_num_nodes);
194  SaveLoad_LinkGraph(*lg);
195  }
196 }
197 
201 static void Load_LGRJ()
202 {
203  int index;
204  while ((index = SlIterateArray()) != -1) {
206  /* Impossible as they have been present in previous game. */
207  NOT_REACHED();
208  }
209  LinkGraphJob *lgj = new (index) LinkGraphJob();
211  LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
212  SlObject(&lg, GetLinkGraphDesc());
213  lg.Init(_num_nodes);
214  SaveLoad_LinkGraph(lg);
215  }
216 }
217 
221 static void Load_LGRS()
222 {
224 }
225 
231 {
232  if (IsSavegameVersionBefore(191)) {
233  LinkGraph *lg;
234  FOR_ALL_LINK_GRAPHS(lg) {
235  for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
236  (*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
237  }
238  }
239 
240  LinkGraphJob *lgj;
241  FOR_ALL_LINK_GRAPH_JOBS(lgj) {
242  lg = &(const_cast<LinkGraph &>(lgj->Graph()));
243  for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
244  (*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
245  }
246  }
247  }
248 
250 }
251 
255 static void Save_LGRP()
256 {
257  LinkGraph *lg;
258  FOR_ALL_LINK_GRAPHS(lg) {
259  SlSetArrayIndex(lg->index);
260  SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
261  }
262 }
263 
267 static void Save_LGRJ()
268 {
269  LinkGraphJob *lgj;
270  FOR_ALL_LINK_GRAPH_JOBS(lgj) {
271  SlSetArrayIndex(lgj->index);
272  SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
273  }
274 }
275 
279 static void Save_LGRS()
280 {
282 }
283 
287 static void Ptrs_LGRS()
288 {
290 }
291 
292 extern const ChunkHandler _linkgraph_chunk_handlers[] = {
293  { 'LGRP', Save_LGRP, Load_LGRP, NULL, NULL, CH_ARRAY },
294  { 'LGRJ', Save_LGRJ, Load_LGRJ, NULL, NULL, CH_ARRAY },
295  { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, NULL, CH_LAST }
296 };