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/demands.h"
00015 #include "../settings_internal.h"
00016 #include "saveload.h"
00017 #include <vector>
00018 
00019 const SettingDesc *GetSettingDescription(uint index);
00020 
00030 const SaveLoad *GetLinkGraphDesc()
00031 {
00032   static std::vector<SaveLoad> saveloads;
00033   static const char *prefix = "linkgraph.";
00034 
00035   /* Build the SaveLoad array on first call and don't touch it later on */
00036   if (saveloads.empty()) {
00037     size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph);
00038     size_t offset_component = cpp_offsetof(LinkGraph, settings);
00039 
00040     size_t prefixlen = strlen(prefix);
00041 
00042     int setting = 0;
00043     const SettingDesc *desc = GetSettingDescription(setting);
00044     while (desc->save.cmd != SL_END) {
00045       if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) {
00046         SaveLoad sl = desc->save;
00047         char *&address = reinterpret_cast<char *&>(sl.address);
00048         address -= offset_gamesettings;
00049         address += offset_component;
00050         saveloads.push_back(sl);
00051       }
00052       desc = GetSettingDescription(++setting);
00053     }
00054 
00055     const SaveLoad component_desc[] = {
00056       SLE_CONDVAR(LinkGraph, num_nodes,          SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
00057       SLE_CONDVAR(LinkGraph, index,              SLE_UINT16, SL_COMPONENTS, SL_MAX_VERSION),
00058       SLE_CONDVAR(LinkGraph, current_station_id, SLE_UINT16, SL_COMPONENTS, SL_MAX_VERSION),
00059       SLE_CONDVAR(LinkGraph, cargo,              SLE_UINT8,  SL_COMPONENTS, SL_MAX_VERSION),
00060       SLE_END()
00061     };
00062 
00063     int i = 0;
00064     do {
00065       saveloads.push_back(component_desc[i++]);
00066     } while (saveloads.back().cmd != SL_END);
00067   }
00068 
00069   return &saveloads[0];
00070 }
00071 
00072 /* Edges and nodes are saved in the correct order, so we don't need to save their ids. */
00073 
00077 static const SaveLoad _node_desc[] = {
00078    SLE_CONDVAR(Node, supply,    SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
00079    SLE_CONDVAR(Node, demand,    SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
00080    SLE_CONDVAR(Node, station,   SLE_UINT16, SL_COMPONENTS, SL_MAX_VERSION),
00081    SLE_END()
00082 };
00083 
00087 static const SaveLoad _edge_desc[] = {
00088    SLE_CONDVAR(Edge, distance,  SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
00089    SLE_CONDVAR(Edge, capacity,  SLE_UINT32, SL_COMPONENTS, SL_MAX_VERSION),
00090    SLE_CONDVAR(Edge, next_edge, SLE_UINT32,        SL_MCF, SL_MAX_VERSION),
00091    SLE_END()
00092 };
00093 
00098 static void SaveLoad_LinkGraphComponent(LinkGraphComponent &comp)
00099 {
00100   uint size = comp.GetSize();
00101   for (NodeID from = 0; from < size; ++from) {
00102     Node *node = &comp.GetNode(from);
00103     SlObject(node, _node_desc);
00104     for (NodeID to = 0; to < size; ++to) {
00105       SlObject(&comp.GetEdge(from, to), _edge_desc);
00106     }
00107   }
00108 }
00109 
00113 static void DoSave_LGRP(void *)
00114 {
00115   for (CargoID cargo = 0; cargo < NUM_CARGO; ++cargo) {
00116     LinkGraph &graph = _link_graphs[cargo];
00117     SlObject(&graph, GetLinkGraphDesc());
00118     SaveLoad_LinkGraphComponent(graph);
00119   }
00120 }
00121 
00125 static void Load_LGRP()
00126 {
00127   for (CargoID cargo = 0; cargo < NUM_CARGO; ++cargo) {
00128     LinkGraph &graph = _link_graphs[cargo];
00129     assert(graph.GetSize() == 0);
00130     SlObject(&graph, GetLinkGraphDesc());
00131     graph.SetSize();
00132     SaveLoad_LinkGraphComponent(graph);
00133     for (uint i = 0; i < graph.GetSize(); ++i) {
00134       Node &node = graph.GetNode(i);
00135       node.undelivered_supply = node.supply;
00136     }
00137   }
00138 }
00139 
00144 void AfterLoadLinkGraphs()
00145 {
00146   for (CargoID cargo = 0; cargo < NUM_CARGO; ++cargo) {
00147     LinkGraph &graph = _link_graphs[cargo];
00148     if (graph.GetSize() > 0) graph.SpawnThread();
00149   }
00150 }
00151 
00152 static void Save_LGRP()
00153 {
00154   SlAutolength((AutolengthProc*)DoSave_LGRP, NULL);
00155 }
00156 
00157 extern const ChunkHandler _linkgraph_chunk_handlers[] = {
00158   { 'LGRP', Save_LGRP, Load_LGRP, NULL, NULL, CH_LAST},
00159 };