linkgraph_sl.cpp

Go to the documentation of this file.
00001 /* $Id: linkgraph_sl.cpp 26596 2014-05-18 11:26:09Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "../stdafx.h"
00013 #include "../linkgraph/linkgraph.h"
00014 #include "../linkgraph/linkgraphjob.h"
00015 #include "../linkgraph/linkgraphschedule.h"
00016 #include "../settings_internal.h"
00017 #include "saveload.h"
00018 
00019 typedef LinkGraph::BaseNode Node;
00020 typedef LinkGraph::BaseEdge Edge;
00021 
00022 const SettingDesc *GetSettingDescription(uint index);
00023 
00024 static uint16 _num_nodes;
00025 
00030 const SaveLoad *GetLinkGraphDesc()
00031 {
00032   static const SaveLoad link_graph_desc[] = {
00033      SLE_VAR(LinkGraph, last_compression, SLE_INT32),
00034     SLEG_VAR(_num_nodes,                  SLE_UINT16),
00035      SLE_VAR(LinkGraph, cargo,            SLE_UINT8),
00036      SLE_END()
00037   };
00038   return link_graph_desc;
00039 }
00040 
00050 const SaveLoad *GetLinkGraphJobDesc()
00051 {
00052   static SmallVector<SaveLoad, 16> saveloads;
00053   static const char *prefix = "linkgraph.";
00054 
00055   /* Build the SaveLoad array on first call and don't touch it later on */
00056   if (saveloads.Length() == 0) {
00057     size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
00058     size_t offset_component = cpp_offsetof(LinkGraphJob, settings);
00059 
00060     size_t prefixlen = strlen(prefix);
00061 
00062     int setting = 0;
00063     const SettingDesc *desc = GetSettingDescription(setting);
00064     while (desc->save.cmd != SL_END) {
00065       if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) {
00066         SaveLoad sl = desc->save;
00067         char *&address = reinterpret_cast<char *&>(sl.address);
00068         address -= offset_gamesettings;
00069         address += offset_component;
00070         *(saveloads.Append()) = sl;
00071       }
00072       desc = GetSettingDescription(++setting);
00073     }
00074 
00075     const SaveLoad job_desc[] = {
00076       SLE_VAR(LinkGraphJob, join_date,        SLE_INT32),
00077       SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16),
00078       SLE_END()
00079     };
00080 
00081     int i = 0;
00082     do {
00083       *(saveloads.Append()) = job_desc[i++];
00084     } while (saveloads[saveloads.Length() - 1].cmd != SL_END);
00085   }
00086 
00087   return &saveloads[0];
00088 }
00089 
00094 const SaveLoad *GetLinkGraphScheduleDesc()
00095 {
00096   static const SaveLoad schedule_desc[] = {
00097     SLE_LST(LinkGraphSchedule, schedule, REF_LINK_GRAPH),
00098     SLE_LST(LinkGraphSchedule, running,  REF_LINK_GRAPH_JOB),
00099     SLE_END()
00100   };
00101   return schedule_desc;
00102 }
00103 
00104 /* Edges and nodes are saved in the correct order, so we don't need to save their IDs. */
00105 
00109 static const SaveLoad _node_desc[] = {
00110   SLE_VAR(Node, supply,      SLE_UINT32),
00111   SLE_VAR(Node, demand,      SLE_UINT32),
00112   SLE_VAR(Node, station,     SLE_UINT16),
00113   SLE_VAR(Node, last_update, SLE_INT32),
00114   SLE_END()
00115 };
00116 
00120 static const SaveLoad _edge_desc[] = {
00121       SLE_VAR(Edge, distance,                 SLE_UINT32),
00122       SLE_VAR(Edge, capacity,                 SLE_UINT32),
00123       SLE_VAR(Edge, usage,                    SLE_UINT32),
00124       SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
00125   SLE_CONDVAR(Edge, last_restricted_update,   SLE_INT32, 187, SL_MAX_VERSION),
00126       SLE_VAR(Edge, next_edge,                SLE_UINT16),
00127       SLE_END()
00128 };
00129 
00134 void SaveLoad_LinkGraph(LinkGraph &lg)
00135 {
00136   uint size = lg.Size();
00137   for (NodeID from = 0; from < size; ++from) {
00138     Node *node = &lg.nodes[from];
00139     SlObject(node, _node_desc);
00140     for (NodeID to = 0; to < size; ++to) {
00141       SlObject(&lg.edges[from][to], _edge_desc);
00142     }
00143   }
00144 }
00145 
00150 static void DoSave_LGRJ(LinkGraphJob *lgj)
00151 {
00152   SlObject(lgj, GetLinkGraphJobDesc());
00153   _num_nodes = lgj->Size();
00154   SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
00155   SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
00156 }
00157 
00162 static void DoSave_LGRP(LinkGraph *lg)
00163 {
00164   _num_nodes = lg->Size();
00165   SlObject(lg, GetLinkGraphDesc());
00166   SaveLoad_LinkGraph(*lg);
00167 }
00168 
00172 static void Load_LGRP()
00173 {
00174   int index;
00175   while ((index = SlIterateArray()) != -1) {
00176     if (!LinkGraph::CanAllocateItem()) {
00177       /* Impossible as they have been present in previous game. */
00178       NOT_REACHED();
00179     }
00180     LinkGraph *lg = new (index) LinkGraph();
00181     SlObject(lg, GetLinkGraphDesc());
00182     lg->Init(_num_nodes);
00183     SaveLoad_LinkGraph(*lg);
00184   }
00185 }
00186 
00190 static void Load_LGRJ()
00191 {
00192   int index;
00193   while ((index = SlIterateArray()) != -1) {
00194     if (!LinkGraphJob::CanAllocateItem()) {
00195       /* Impossible as they have been present in previous game. */
00196       NOT_REACHED();
00197     }
00198     LinkGraphJob *lgj = new (index) LinkGraphJob();
00199     SlObject(lgj, GetLinkGraphJobDesc());
00200     LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
00201     SlObject(&lg, GetLinkGraphDesc());
00202     lg.Init(_num_nodes);
00203     SaveLoad_LinkGraph(lg);
00204   }
00205 }
00206 
00210 static void Load_LGRS()
00211 {
00212   SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc());
00213 }
00214 
00219 void AfterLoadLinkGraphs()
00220 {
00221   LinkGraphSchedule::Instance()->SpawnAll();
00222 }
00223 
00227 static void Save_LGRP()
00228 {
00229   LinkGraph *lg;
00230   FOR_ALL_LINK_GRAPHS(lg) {
00231     SlSetArrayIndex(lg->index);
00232     SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
00233   }
00234 }
00235 
00239 static void Save_LGRJ()
00240 {
00241   LinkGraphJob *lgj;
00242   FOR_ALL_LINK_GRAPH_JOBS(lgj) {
00243     SlSetArrayIndex(lgj->index);
00244     SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
00245   }
00246 }
00247 
00251 static void Save_LGRS()
00252 {
00253   SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc());
00254 }
00255 
00259 static void Ptrs_LGRS()
00260 {
00261   SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc());
00262 }
00263 
00264 extern const ChunkHandler _linkgraph_chunk_handlers[] = {
00265   { 'LGRP', Save_LGRP, Load_LGRP, NULL,      NULL, CH_ARRAY },
00266   { 'LGRJ', Save_LGRJ, Load_LGRJ, NULL,      NULL, CH_ARRAY },
00267   { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, NULL, CH_LAST  }
00268 };