# linkgraph_sl.cpp

Go to the documentation of this file.

    00001 /* $Id: linkgraph_sl.cpp 25898 2013-10-22 16:13:28Z fonsinchen $ */
    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_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 };