linkgraph_sl.cpp

Go to the documentation of this file.
00001 /* $Id$ */
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 uint _num_nodes;
00025 
00030 const SaveLoad *GetLinkGraphDesc()
00031 {
00032   static const SaveLoad link_graph_desc[] = {
00033      SLE_VAR(LinkGraph, last_compression, SLE_UINT32),
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_UINT32),
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_UINT32),
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_update, SLE_UINT32),
00125   SLE_VAR(Edge, next_edge,   SLE_UINT16),
00126   SLE_END()
00127 };
00128 
00133 void SaveLoad_LinkGraph(LinkGraph &lg)
00134 {
00135   uint size = lg.Size();
00136   for (NodeID from = 0; from < size; ++from) {
00137     Node *node = &lg.nodes[from];
00138     SlObject(node, _node_desc);
00139     for (NodeID to = 0; to < size; ++to) {
00140       SlObject(&lg.edges[from][to], _edge_desc);
00141     }
00142   }
00143 }
00144 
00149 static void DoSave_LGRJ(LinkGraphJob *lgj)
00150 {
00151   SlObject(lgj, GetLinkGraphJobDesc());
00152   _num_nodes = lgj->Size();
00153   SlObject(const_cast<LinkGraph *>(&lgj->Graph()), GetLinkGraphDesc());
00154   SaveLoad_LinkGraph(const_cast<LinkGraph &>(lgj->Graph()));
00155 }
00156 
00161 static void DoSave_LGRP(LinkGraph *lg)
00162 {
00163   _num_nodes = lg->Size();
00164   SlObject(lg, GetLinkGraphDesc());
00165   SaveLoad_LinkGraph(*lg);
00166 }
00167 
00171 static void Load_LGRP()
00172 {
00173   int index;
00174   while ((index = SlIterateArray()) != -1) {
00175     if (!LinkGraph::CanAllocateItem()) {
00176       /* Impossible as they have been present in previous game. */
00177       NOT_REACHED();
00178     }
00179     LinkGraph *lg = new (index) LinkGraph();
00180     SlObject(lg, GetLinkGraphDesc());
00181     lg->Init(_num_nodes);
00182     SaveLoad_LinkGraph(*lg);
00183   }
00184 }
00185 
00189 static void Load_LGRJ()
00190 {
00191   int index;
00192   while ((index = SlIterateArray()) != -1) {
00193     if (!LinkGraphJob::CanAllocateItem()) {
00194       /* Impossible as they have been present in previous game. */
00195       NOT_REACHED();
00196     }
00197     LinkGraphJob *lgj = new (index) LinkGraphJob();
00198     SlObject(lgj, GetLinkGraphJobDesc());
00199     LinkGraph &lg = const_cast<LinkGraph &>(lgj->Graph());
00200     SlObject(&lg, GetLinkGraphDesc());
00201     lg.Init(_num_nodes);
00202     SaveLoad_LinkGraph(lg);
00203   }
00204 }
00205 
00209 static void Load_LGRS()
00210 {
00211   SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc());
00212 }
00213 
00218 void AfterLoadLinkGraphs()
00219 {
00220   LinkGraphSchedule::Instance()->SpawnAll();
00221 }
00222 
00226 static void Save_LGRP()
00227 {
00228   LinkGraph *lg;
00229   FOR_ALL_LINK_GRAPHS(lg) {
00230     SlSetArrayIndex(lg->index);
00231     SlAutolength((AutolengthProc*)DoSave_LGRP, lg);
00232   }
00233 }
00234 
00238 static void Save_LGRJ()
00239 {
00240   LinkGraphJob *lgj;
00241   FOR_ALL_LINK_GRAPH_JOBS(lgj) {
00242     SlSetArrayIndex(lgj->index);
00243     SlAutolength((AutolengthProc*)DoSave_LGRJ, lgj);
00244   }
00245 }
00246 
00250 static void Save_LGRS()
00251 {
00252   SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc());
00253 }
00254 
00258 static void Ptrs_LGRS()
00259 {
00260   SlObject(LinkGraphSchedule::Instance(), GetLinkGraphScheduleDesc());
00261 }
00262 
00263 extern const ChunkHandler _linkgraph_chunk_handlers[] = {
00264   { 'LGRP', Save_LGRP, Load_LGRP, NULL,      NULL, CH_ARRAY },
00265   { 'LGRJ', Save_LGRJ, Load_LGRJ, NULL,      NULL, CH_ARRAY },
00266   { 'LGRS', Save_LGRS, Load_LGRS, Ptrs_LGRS, NULL, CH_LAST  }
00267 };