Timetable: Implement automate for taken conditional orders.
[openttd-joker.git] / src / saveload / linkgraph_sl.cpp
blob67af34bc6f688bedd8a4755f960753c15a7e5d71
1 /* $Id$ */
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 */
10 /** @file linkgraph_sl.cpp Code handling saving and loading of link graphs */
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"
19 #include "../safeguards.h"
21 typedef LinkGraph::BaseNode Node;
22 typedef LinkGraph::BaseEdge Edge;
24 const SettingDesc *GetSettingDescription(uint index);
26 static uint16 _num_nodes;
28 /**
29 * Get a SaveLoad array for a link graph.
30 * @return SaveLoad array for link graph.
32 const SaveLoad *GetLinkGraphDesc()
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()
40 return link_graph_desc;
43 void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj)
45 lgj->join_date_ticks *= DAY_TICKS;
46 lgj->join_date_ticks += LinkGraphSchedule::SPAWN_JOIN_TICK;
47 lgj->start_date_ticks = lgj->join_date_ticks - (lgj->Settings().recalc_time * DAY_TICKS);
50 /**
51 * Get a SaveLoad array for a link graph job. The settings struct is derived from
52 * the global settings saveload array. The exact entries are calculated when the function
53 * is called the first time.
54 * It's necessary to keep a copy of the settings for each link graph job so that you can
55 * change the settings while in-game and still not mess with current link graph runs.
56 * Of course the settings have to be saved and loaded, too, to avoid desyncs.
57 * @return Array of SaveLoad structs.
59 const SaveLoad *GetLinkGraphJobDesc()
61 static SmallVector<SaveLoad, 16> saveloads;
62 static const char *prefix = "linkgraph.";
64 /* Build the SaveLoad array on first call and don't touch it later on */
65 if (saveloads.Length() == 0) {
66 size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
67 size_t offset_component = cpp_offsetof(LinkGraphJob, settings);
69 size_t prefixlen = strlen(prefix);
71 int setting = 0;
72 const SettingDesc *desc = GetSettingDescription(setting);
73 while (desc->save.cmd != SL_END) {
74 if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) {
75 SaveLoad sl = desc->save;
76 char *&address = reinterpret_cast<char *&>(sl.address);
77 address -= offset_gamesettings;
78 address += offset_component;
79 *(saveloads.Append()) = sl;
81 desc = GetSettingDescription(++setting);
84 const SaveLoad job_desc[] = {
85 SLE_VAR(LinkGraphJob, join_date_ticks, SLE_INT32),
86 SLE_CONDVAR(LinkGraphJob, start_date_ticks, SLE_INT32, SL_PATCH_PACK_1_21, SL_MAX_VERSION),
87 SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
88 SLE_END()
91 int i = 0;
92 do {
93 *(saveloads.Append()) = job_desc[i++];
94 } while (saveloads[saveloads.Length() - 1].cmd != SL_END);
97 return &saveloads[0];
101 * Get a SaveLoad array for the link graph schedule.
102 * @return SaveLoad array for the link graph schedule.
104 const SaveLoad *GetLinkGraphScheduleDesc()
106 static const SaveLoad schedule_desc[] = {
107 SLE_LST(LinkGraphSchedule, schedule, REF_LINK_GRAPH),
108 SLE_LST(LinkGraphSchedule, running, REF_LINK_GRAPH_JOB),
109 SLE_END()
111 return schedule_desc;
114 /* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
117 * SaveLoad desc for a link graph node.
119 static const SaveLoad _node_desc[] = {
120 SLE_CONDVAR(Node, xy, SLE_UINT32, 191, SL_PATCH_PACK - 1),
121 SLE_CONDVAR(Node, xy, SLE_UINT32, SL_PATCH_PACK_1_8, SL_MAX_VERSION),
122 SLE_VAR(Node, supply, SLE_UINT32),
123 SLE_VAR(Node, demand, SLE_UINT32),
124 SLE_VAR(Node, station, SLE_UINT16),
125 SLE_VAR(Node, last_update, SLE_INT32),
126 SLE_END()
130 * SaveLoad desc for a link graph edge.
132 static const SaveLoad _edge_desc[] = {
133 SLE_CONDNULL(4, 0, 190), // distance
134 SLE_CONDNULL(4, SL_PATCH_PACK, SL_PATCH_PACK_1_7), // distance
135 SLE_VAR(Edge, capacity, SLE_UINT32),
136 SLE_VAR(Edge, usage, SLE_UINT32),
137 SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
138 SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, 187, SL_MAX_VERSION),
139 SLE_VAR(Edge, next_edge, SLE_UINT16),
140 SLE_END()
144 * Save/load a link graph.
145 * @param comp Link graph to be saved or loaded.
147 void SaveLoad_LinkGraph(LinkGraph &lg)
149 uint size = lg.Size();
150 for (NodeID from = 0; from < size; ++from) {
151 Node *node = &lg.nodes[from];
152 SlObject(node, _node_desc);
153 if (IsSavegameVersionBefore(191) || IsPatchPackSavegameVersionBefore(SL_PATCH_PACK_1_8)) {
154 /* We used to save the full matrix ... */
155 for (NodeID to = 0; to < size; ++to) {
156 SlObject(&lg.edges[from][to], _edge_desc);
159 else {
160 /* ... but as that wasted a lot of space we save a sparse matrix now. */
161 for (NodeID to = from; to != INVALID_NODE; to = lg.edges[from][to].next_edge) {
162 SlObject(&lg.edges[from][to], _edge_desc);
169 * Save a link graph job.
170 * @param lgj LinkGraphJob to be saved.
172 static void DoSave_LGRJ(LinkGraphJob *lgj)
174 SlObject(lgj, GetLinkGraphJobDesc());
175 _num_nodes = lgj->Size();
176 SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
177 SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
181 * Save a link graph.
182 * @param lg LinkGraph to be saved.
184 static void DoSave_LGRP(LinkGraph *lg)
186 _num_nodes = lg->Size();
187 SlObject(lg, GetLinkGraphDesc());
188 SaveLoad_LinkGraph(*lg);
192 * Load all link graphs.
194 static void Load_LGRP()
196 int index;
197 while ((index = SlIterateArray()) != -1) {
198 if (!LinkGraph::CanAllocateItem()) {
199 /* Impossible as they have been present in previous game. */
200 NOT_REACHED();
202 LinkGraph *lg = new (index) LinkGraph();
203 SlObject(lg, GetLinkGraphDesc());
204 lg->Init(_num_nodes);
205 SaveLoad_LinkGraph(*lg);
210 * Load all link graph jobs.
212 static void Load_LGRJ()
214 int index;
215 while ((index = SlIterateArray()) != -1) {
216 if (!LinkGraphJob::CanAllocateItem()) {
217 /* Impossible as they have been present in previous game. */
218 NOT_REACHED();
220 LinkGraphJob *lgj = new (index) LinkGraphJob();
221 SlObject(lgj, GetLinkGraphJobDesc());
222 if (IsSavegameVersionBefore(SL_PATCH_PACK_1_21)) {
223 GetLinkGraphJobDayLengthScaleAfterLoad(lgj);
225 LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
226 SlObject(&lg, GetLinkGraphDesc());
227 lg.Init(_num_nodes);
228 SaveLoad_LinkGraph(lg);
233 * Load the link graph schedule.
235 static void Load_LGRS()
237 SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
241 * Spawn the threads for running link graph calculations.
242 * Has to be done after loading as the cargo classes might have changed.
244 void AfterLoadLinkGraphs()
246 if (IsSavegameVersionBefore(191) || IsPatchPackSavegameVersionBefore(SL_PATCH_PACK_1_8)) {
247 LinkGraph *lg;
248 FOR_ALL_LINK_GRAPHS(lg) {
249 for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
250 (*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
254 LinkGraphJob *lgj;
255 FOR_ALL_LINK_GRAPH_JOBS(lgj) {
256 lg = &(const_cast<LinkGraph &>(lgj->Graph()));
257 for (NodeID node_id = 0; node_id < lg->Size(); ++node_id) {
258 (*lg)[node_id].UpdateLocation(Station::Get((*lg)[node_id].Station())->xy);
263 LinkGraphSchedule::instance.SpawnAll();
267 * Save all link graphs.
269 static void Save_LGRP()
271 LinkGraph *lg;
272 FOR_ALL_LINK_GRAPHS(lg) {
273 SlSetArrayIndex(lg->index);
274 SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
279 * Save all link graph jobs.
281 static void Save_LGRJ()
283 LinkGraphJob *lgj;
284 FOR_ALL_LINK_GRAPH_JOBS(lgj) {
285 SlSetArrayIndex(lgj->index);
286 SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
291 * Save the link graph schedule.
293 static void Save_LGRS()
295 SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
299 * Substitute pointers in link graph schedule.
301 static void Ptrs_LGRS()
303 SlObject(&LinkGraphSchedule::instance, GetLinkGraphScheduleDesc());
306 extern const ChunkHandler _linkgraph_chunk_handlers[] = {
307 { 'LGRP', Save_LGRP, Load_LGRP, NULL, NULL, CH_ARRAY },
308 { 'LGRJ', Save_LGRJ, Load_LGRJ, NULL, NULL, CH_ARRAY },
309 { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, NULL, CH_LAST }