# station_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 "../station_base.h"
    00014 #include "../waypoint_base.h"
    00015 #include "../roadstop_base.h"
    00016 #include "../vehicle_base.h"
    00017 #include "../newgrf_station.h"
    00018
    00019 #include "saveload.h"
    00020 #include "table/strings.h"
    00021
    00026 static void UpdateWaypointOrder(Order *o)
    00027 {
    00028   if (!o->IsType(OT_GOTO_STATION)) return;
    00029
    00030   const Station *st = Station::Get(o->GetDestination());
    00031   if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) return;
    00032
    00033   o->MakeGoToWaypoint(o->GetDestination());
    00034 }
    00035
    00040 void MoveBuoysToWaypoints()
    00041 {
    00042   /* Buoy orders become waypoint orders */
    00043   OrderList *ol;
    00044   FOR_ALL_ORDER_LISTS(ol) {
    00045     VehicleType vt = ol->GetFirstSharedVehicle()->type;
    00046     if (vt != VEH_SHIP && vt != VEH_TRAIN) continue;
    00047
    00048     for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o);
    00049   }
    00050
    00051   Vehicle *v;
    00052   FOR_ALL_VEHICLES(v) {
    00053     VehicleType vt = v->type;
    00054     if (vt != VEH_SHIP && vt != VEH_TRAIN) continue;
    00055
    00056     UpdateWaypointOrder(&v->current_order);
    00057   }
    00058
    00059   /* Now make the stations waypoints */
    00060   Station *st;
    00061   FOR_ALL_STATIONS(st) {
    00062     if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) continue;
    00063
    00064     StationID index    = st->index;
    00065     TileIndex xy       = st->xy;
    00066     Town *town         = st->town;
    00067     StringID string_id = st->string_id;
    00068     char *name         = st->name;
    00069     st->name           = NULL;
    00070     Date build_date    = st->build_date;
    00071     /* TTDPatch could use "buoys with rail station" for rail waypoints */
    00072     bool train         = st->train_station.tile != INVALID_TILE;
    00073     TileArea train_st  = st->train_station;
    00074
    00075     /* Delete the station, so we can make it a real waypoint. */
    00076     delete st;
    00077
    00078     /* Stations and waypoints are in the same pool, so if a station
    00079      * is deleted there must be place for a Waypoint. */
    00080     assert(Waypoint::CanAllocateItem());
    00081     Waypoint *wp   = new (index) Waypoint(xy);
    00082     wp->town       = town;
    00083     wp->string_id  = train ? STR_SV_STNAME_WAYPOINT : STR_SV_STNAME_BUOY;
    00084     wp->name       = name;
    00085     wp->delete_ctr = 0; // Just reset delete counter for once.
    00086     wp->build_date = build_date;
    00087     wp->owner      = train ? GetTileOwner(xy) : OWNER_NONE;
    00088
    00089     if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = string_id - STR_SV_STNAME_BUOY;
    00090
    00091     if (train) {
    00092       /* When we make a rail waypoint of the station, convert the map as well. */
    00093       TILE_AREA_LOOP(t, train_st) {
    00094         if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != index) continue;
    00095
    00096         SB(_m[t].m6, 3, 3, STATION_WAYPOINT);
    00097         wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
    00098       }
    00099
    00100       wp->train_station = train_st;
    00101       wp->facilities |= FACIL_TRAIN;
    00102     } else if (IsBuoyTile(xy) && GetStationIndex(xy) == index) {
    00103       wp->rect.BeforeAddTile(xy, StationRect::ADD_FORCE);
    00104       wp->facilities |= FACIL_DOCK;
    00105     }
    00106   }
    00107 }
    00108
    00109 void AfterLoadStations()
    00110 {
    00111   /* Update the speclists of all stations to point to the currently loaded custom stations. */
    00112   BaseStation *st;
    00113   FOR_ALL_BASE_STATIONS(st) {
    00114     for (uint i = 0; i < st->num_specs; i++) {
    00115       if (st->speclist[i].grfid == 0) continue;
    00116
    00117       st->speclist[i].spec = StationClass::GetByGrf(st->speclist[i].grfid, st->speclist[i].localidx, NULL);
    00118     }
    00119
    00120     if (Station::IsExpected(st)) {
    00121       Station *sta = Station::From(st);
    00122       for (const RoadStop *rs = sta->bus_stops; rs != NULL; rs = rs->next) sta->bus_station.Add(rs->xy);
    00123       for (const RoadStop *rs = sta->truck_stops; rs != NULL; rs = rs->next) sta->truck_station.Add(rs->xy);
    00124     }
    00125
    00126     StationUpdateCachedTriggers(st);
    00127   }
    00128 }
    00129
    00133 void AfterLoadRoadStops()
    00134 {
    00135   /* First construct the drive through entries */
    00136   RoadStop *rs;
    00137   FOR_ALL_ROADSTOPS(rs) {
    00138     if (IsDriveThroughStopTile(rs->xy)) rs->MakeDriveThrough();
    00139   }
    00140   /* And then rebuild the data in those entries */
    00141   FOR_ALL_ROADSTOPS(rs) {
    00142     if (!HasBit(rs->status, RoadStop::RSSFB_BASE_ENTRY)) continue;
    00143
    00144     rs->GetEntry(DIAGDIR_NE)->Rebuild(rs);
    00145     rs->GetEntry(DIAGDIR_NW)->Rebuild(rs);
    00146   }
    00147 }
    00148
    00149 static const SaveLoad _roadstop_desc[] = {
    00150   SLE_VAR(RoadStop, xy,           SLE_UINT32),
    00151   SLE_CONDNULL(1, 0, 44),
    00152   SLE_VAR(RoadStop, status,       SLE_UINT8),
    00153   /* Index was saved in some versions, but this is not needed */
    00154   SLE_CONDNULL(4, 0, 8),
    00155   SLE_CONDNULL(2, 0, 44),
    00156   SLE_CONDNULL(1, 0, 25),
    00157
    00158   SLE_REF(RoadStop, next,         REF_ROADSTOPS),
    00159   SLE_CONDNULL(2, 0, 44),
    00160
    00161   SLE_CONDNULL(4, 0, 24),
    00162   SLE_CONDNULL(1, 25, 25),
    00163
    00164   SLE_END()
    00165 };
    00166
    00167 static const SaveLoad _old_station_desc[] = {
    00168   SLE_CONDVAR(Station, xy,                         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
    00169   SLE_CONDVAR(Station, xy,                         SLE_UINT32,                  6, SL_MAX_VERSION),
    00170   SLE_CONDNULL(4, 0, 5),
    00171   SLE_CONDVAR(Station, train_station.tile,         SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
    00172   SLE_CONDVAR(Station, train_station.tile,         SLE_UINT32,                  6, SL_MAX_VERSION),
    00173   SLE_CONDVAR(Station, airport.tile,               SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
    00174   SLE_CONDVAR(Station, airport.tile,               SLE_UINT32,                  6, SL_MAX_VERSION),
    00175   SLE_CONDVAR(Station, dock_tile,                  SLE_FILE_U16 | SLE_VAR_U32,  0, 5),
    00176   SLE_CONDVAR(Station, dock_tile,                  SLE_UINT32,                  6, SL_MAX_VERSION),
    00177       SLE_REF(Station, town,                       REF_TOWN),
    00178       SLE_VAR(Station, train_station.w,            SLE_FILE_U8 | SLE_VAR_U16),
    00179   SLE_CONDVAR(Station, train_station.h,            SLE_FILE_U8 | SLE_VAR_U16,   2, SL_MAX_VERSION),
    00180
    00181   SLE_CONDNULL(1, 0, 3),
    00182
    00183       SLE_VAR(Station, string_id,                  SLE_STRINGID),
    00184   SLE_CONDSTR(Station, name,                       SLE_STR | SLF_ALLOW_CONTROL, 0, 84, SL_MAX_VERSION),
    00185   SLE_CONDVAR(Station, indtype,                    SLE_UINT8,                 103, SL_MAX_VERSION),
    00186   SLE_CONDVAR(Station, had_vehicle_of_type,        SLE_FILE_U16 | SLE_VAR_U8,   0, 121),
    00187   SLE_CONDVAR(Station, had_vehicle_of_type,        SLE_UINT8,                 122, SL_MAX_VERSION),
    00188
    00189       SLE_VAR(Station, time_since_load,            SLE_UINT8),
    00190       SLE_VAR(Station, time_since_unload,          SLE_UINT8),
    00191       SLE_VAR(Station, delete_ctr,                 SLE_UINT8),
    00192       SLE_VAR(Station, owner,                      SLE_UINT8),
    00193       SLE_VAR(Station, facilities,                 SLE_UINT8),
    00194       SLE_VAR(Station, airport.type,               SLE_UINT8),
    00195
    00196   SLE_CONDNULL(2, 0, 5),
    00197   SLE_CONDNULL(1, 0, 4),
    00198
    00199   SLE_CONDVAR(Station, airport.flags,              SLE_VAR_U64 | SLE_FILE_U16,  0,  2),
    00200   SLE_CONDVAR(Station, airport.flags,              SLE_VAR_U64 | SLE_FILE_U32,  3, 45),
    00201   SLE_CONDVAR(Station, airport.flags,              SLE_UINT64,                 46, SL_MAX_VERSION),
    00202
    00203   SLE_CONDNULL(2, 0, 25),
    00204   SLE_CONDVAR(Station, last_vehicle_type,          SLE_UINT8,                  26, SL_MAX_VERSION),
    00205
    00206   SLE_CONDNULL(2, 3, 25),
    00207   SLE_CONDVAR(Station, build_date,                 SLE_FILE_U16 | SLE_VAR_I32,  3, 30),
    00208   SLE_CONDVAR(Station, build_date,                 SLE_INT32,                  31, SL_MAX_VERSION),
    00209
    00210   SLE_CONDREF(Station, bus_stops,                  REF_ROADSTOPS,               6, SL_MAX_VERSION),
    00211   SLE_CONDREF(Station, truck_stops,                REF_ROADSTOPS,               6, SL_MAX_VERSION),
    00212
    00213   /* Used by newstations for graphic variations */
    00214   SLE_CONDVAR(Station, random_bits,                SLE_UINT16,                 27, SL_MAX_VERSION),
    00215   SLE_CONDVAR(Station, waiting_triggers,           SLE_UINT8,                  27, SL_MAX_VERSION),
    00216   SLE_CONDVAR(Station, num_specs,                  SLE_UINT8,                  27, SL_MAX_VERSION),
    00217
    00218   SLE_CONDLST(Station, loading_vehicles,           REF_VEHICLE,                57, SL_MAX_VERSION),
    00219
    00220   /* reserve extra space in savegame here. (currently 32 bytes) */
    00221   SLE_CONDNULL(32, 2, SL_MAX_VERSION),
    00222
    00223   SLE_END()
    00224 };
    00225
    00226 static uint16 _waiting_acceptance;
    00227 static uint32 _num_flows;
    00228 static uint16 _cargo_source;
    00229 static uint32 _cargo_source_xy;
    00230 static uint8  _cargo_days;
    00231 static Money  _cargo_feeder_share;
    00232
    00233 static const SaveLoad _station_speclist_desc[] = {
    00234   SLE_CONDVAR(StationSpecList, grfid,    SLE_UINT32, 27, SL_MAX_VERSION),
    00235   SLE_CONDVAR(StationSpecList, localidx, SLE_UINT8,  27, SL_MAX_VERSION),
    00236
    00237   SLE_END()
    00238 };
    00239
    00240 std::list<CargoPacket *> _packets;
    00241 uint32 _num_dests;
    00242
    00243 struct FlowSaveLoad {
    00244   FlowSaveLoad() : via(0), share(0) {}
    00245   StationID source;
    00246   StationID via;
    00247   uint32 share;
    00248 };
    00249
    00250 static const SaveLoad _flow_desc[] = {
    00251   SLE_CONDVAR(FlowSaveLoad, source, SLE_UINT16, SL_FLOWS, SL_MAX_VERSION),
    00252   SLE_CONDVAR(FlowSaveLoad, via,    SLE_UINT16, SL_FLOWS, SL_MAX_VERSION),
    00253   SLE_CONDVAR(FlowSaveLoad, share,  SLE_UINT32, SL_FLOWS, SL_MAX_VERSION),
    00254   SLE_END()
    00255 };
    00256
    00262 const SaveLoad *GetGoodsDesc()
    00263 {
    00264   static const SaveLoad goods_desc[] = {
    00265     SLEG_CONDVAR(            _waiting_acceptance, SLE_UINT16,                  0, 67),
    00266      SLE_CONDVAR(GoodsEntry, acceptance_pickup,   SLE_UINT8,                  68, SL_MAX_VERSION),
    00267     SLE_CONDNULL(2,                                                           51, 67),
    00268          SLE_VAR(GoodsEntry, time_since_pickup,   SLE_UINT8),
    00269          SLE_VAR(GoodsEntry, rating,              SLE_UINT8),
    00270     SLEG_CONDVAR(            _cargo_source,       SLE_FILE_U8 | SLE_VAR_U16,   0, 6),
    00271     SLEG_CONDVAR(            _cargo_source,       SLE_UINT16,                  7, 67),
    00272     SLEG_CONDVAR(            _cargo_source_xy,    SLE_UINT32,                 44, 67),
    00273     SLEG_CONDVAR(            _cargo_days,         SLE_UINT8,                   0, 67),
    00274          SLE_VAR(GoodsEntry, last_speed,          SLE_UINT8),
    00275          SLE_VAR(GoodsEntry, last_age,            SLE_UINT8),
    00276     SLEG_CONDVAR(            _cargo_feeder_share, SLE_FILE_U32 | SLE_VAR_I64, 14, 64),
    00277     SLEG_CONDVAR(            _cargo_feeder_share, SLE_INT64,                  65, 67),
    00278      SLE_CONDVAR(GoodsEntry, amount_fract,        SLE_UINT8,                 150, SL_MAX_VERSION),
    00279     SLEG_CONDLST(            _packets,            REF_CARGO_PACKET,           68, SL_CARGOMAP - 1),
    00280     SLEG_CONDVAR(            _num_dests,          SLE_UINT32,        SL_CARGOMAP, SL_MAX_VERSION),
    00281      SLE_CONDVAR(GoodsEntry, cargo.reserved_count,SLE_UINT,                  181, SL_MAX_VERSION),
    00282      SLE_CONDVAR(GoodsEntry, link_graph,          SLE_UINT16,           SL_FLOWS, SL_MAX_VERSION),
    00283      SLE_CONDVAR(GoodsEntry, node,                SLE_UINT16,           SL_FLOWS, SL_MAX_VERSION),
    00284     SLEG_CONDVAR(            _num_flows,          SLE_UINT32,           SL_FLOWS, SL_MAX_VERSION),
    00285      SLE_CONDVAR(GoodsEntry, max_waiting_cargo,   SLE_UINT32,      SL_EXT_RATING, SL_MAX_VERSION),
    00286     SLE_END()
    00287   };
    00288
    00289   return goods_desc;
    00290 }
    00291
    00292 typedef std::pair<const StationID, std::list<CargoPacket *> > StationCargoPair;
    00293
    00294 static const SaveLoad _cargo_list_desc[] = {
    00295   SLE_VAR(StationCargoPair, first,  SLE_UINT16),
    00296   SLE_LST(StationCargoPair, second, REF_CARGO_PACKET),
    00297   SLE_END()
    00298 };
    00299
    00305 static void SwapPackets(GoodsEntry *ge)
    00306 {
    00307   StationCargoPacketMap &ge_packets = const_cast<StationCargoPacketMap &>(*ge->cargo.Packets());
    00308
    00309   if (_packets.empty()) {
    00310     std::map<StationID, std::list<CargoPacket *> >::iterator it(ge_packets.find(INVALID_STATION));
    00311     if (it == ge_packets.end()) {
    00312       return;
    00313     } else {
    00314       it->second.swap(_packets);
    00315     }
    00316   } else {
    00317     assert(ge_packets[INVALID_STATION].empty());
    00318     ge_packets[INVALID_STATION].swap(_packets);
    00319   }
    00320 }
    00321
    00322 static void Load_STNS()
    00323 {
    00324   int index;
    00325   while ((index = SlIterateArray()) != -1) {
    00326     Station *st = new (index) Station();
    00327
    00328     SlObject(st, _old_station_desc);
    00329
    00330     _waiting_acceptance = 0;
    00331
    00332     uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO;
    00333     for (CargoID i = 0; i < num_cargo; i++) {
    00334       GoodsEntry *ge = &st->goods[i];
    00335       SlObject(ge, GetGoodsDesc());
    00336       SwapPackets(ge);
    00337       if (IsSavegameVersionBefore(68)) {
    00338         SB(ge->acceptance_pickup, GoodsEntry::GES_ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
    00339         if (GB(_waiting_acceptance, 0, 12) != 0) {
    00340           /* In old versions, enroute_from used 0xFF as INVALID_STATION */
    00341           StationID source = (IsSavegameVersionBefore(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
    00342
    00343           /* Make sure we can allocate the CargoPacket. This is safe
    00344            * as there can only be ~64k stations and 32 cargoes in these
    00345            * savegame versions. As the CargoPacketPool has more than
    00346            * 16 million entries; it fits by an order of magnitude. */
    00347           assert(CargoPacket::CanAllocateItem());
    00348
    00349           /* Don't construct the packet with station here, because that'll fail with old savegames */
    00350           CargoPacket *cp = new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_days, source, _cargo_source_xy, _cargo_source_xy, _cargo_feeder_share);
    00351           ge->cargo.Append(cp, INVALID_STATION);
    00352           SB(ge->acceptance_pickup, GoodsEntry::GES_PICKUP, 1, 1);
    00353         }
    00354       }
    00355     }
    00356
    00357     if (st->num_specs != 0) {
    00358       /* Allocate speclist memory when loading a game */
    00359       st->speclist = CallocT<StationSpecList>(st->num_specs);
    00360       for (uint i = 0; i < st->num_specs; i++) {
    00361         SlObject(&st->speclist[i], _station_speclist_desc);
    00362       }
    00363     }
    00364   }
    00365 }
    00366
    00367 static void Ptrs_STNS()
    00368 {
    00369   /* Don't run when savegame version is higher than or equal to 123. */
    00370   if (!IsSavegameVersionBefore(123)) return;
    00371
    00372   Station *st;
    00373   FOR_ALL_STATIONS(st) {
    00374     if (!IsSavegameVersionBefore(68)) {
    00375       for (CargoID i = 0; i < NUM_CARGO; i++) {
    00376         GoodsEntry *ge = &st->goods[i];
    00377         SwapPackets(ge);
    00378         SlObject(ge, GetGoodsDesc());
    00379         SwapPackets(ge);
    00380       }
    00381     }
    00382     SlObject(st, _old_station_desc);
    00383   }
    00384 }
    00385
    00386
    00387 static const SaveLoad _base_station_desc[] = {
    00388         SLE_VAR(BaseStation, xy,                     SLE_UINT32),
    00389         SLE_REF(BaseStation, town,                   REF_TOWN),
    00390         SLE_VAR(BaseStation, string_id,              SLE_STRINGID),
    00391         SLE_STR(BaseStation, name,                   SLE_STR | SLF_ALLOW_CONTROL, 0),
    00392         SLE_VAR(BaseStation, delete_ctr,             SLE_UINT8),
    00393         SLE_VAR(BaseStation, owner,                  SLE_UINT8),
    00394         SLE_VAR(BaseStation, facilities,             SLE_UINT8),
    00395         SLE_VAR(BaseStation, build_date,             SLE_INT32),
    00396
    00397   /* Used by newstations for graphic variations */
    00398         SLE_VAR(BaseStation, random_bits,            SLE_UINT16),
    00399         SLE_VAR(BaseStation, waiting_triggers,       SLE_UINT8),
    00400         SLE_VAR(BaseStation, num_specs,              SLE_UINT8),
    00401
    00402         SLE_END()
    00403 };
    00404
    00405 static OldPersistentStorage _old_st_persistent_storage;
    00406
    00407 static const SaveLoad _station_desc[] = {
    00408   SLE_WRITEBYTE(Station, facilities,                 FACIL_NONE),
    00409   SLE_ST_INCLUDE(),
    00410
    00411         SLE_VAR(Station, train_station.tile,         SLE_UINT32),
    00412         SLE_VAR(Station, train_station.w,            SLE_FILE_U8 | SLE_VAR_U16),
    00413         SLE_VAR(Station, train_station.h,            SLE_FILE_U8 | SLE_VAR_U16),
    00414
    00415         SLE_REF(Station, bus_stops,                  REF_ROADSTOPS),
    00416         SLE_REF(Station, truck_stops,                REF_ROADSTOPS),
    00417         SLE_VAR(Station, dock_tile,                  SLE_UINT32),
    00418         SLE_VAR(Station, airport.tile,               SLE_UINT32),
    00419     SLE_CONDVAR(Station, airport.w,                  SLE_FILE_U8 | SLE_VAR_U16, 140, SL_MAX_VERSION),
    00420     SLE_CONDVAR(Station, airport.h,                  SLE_FILE_U8 | SLE_VAR_U16, 140, SL_MAX_VERSION),
    00421         SLE_VAR(Station, airport.type,               SLE_UINT8),
    00422     SLE_CONDVAR(Station, airport.layout,             SLE_UINT8,                 145, SL_MAX_VERSION),
    00423         SLE_VAR(Station, airport.flags,              SLE_UINT64),
    00424     SLE_CONDVAR(Station, airport.rotation,           SLE_UINT8,                 145, SL_MAX_VERSION),
    00425    SLEG_CONDARR(_old_st_persistent_storage.storage,  SLE_UINT32, 16,            145, 160),
    00426     SLE_CONDREF(Station, airport.psa,                REF_STORAGE,               161, SL_MAX_VERSION),
    00427
    00428         SLE_VAR(Station, indtype,                    SLE_UINT8),
    00429
    00430         SLE_VAR(Station, time_since_load,            SLE_UINT8),
    00431         SLE_VAR(Station, time_since_unload,          SLE_UINT8),
    00432         SLE_VAR(Station, last_vehicle_type,          SLE_UINT8),
    00433         SLE_VAR(Station, had_vehicle_of_type,        SLE_UINT8),
    00434         SLE_LST(Station, loading_vehicles,           REF_VEHICLE),
    00435     SLE_CONDVAR(Station, always_accepted,            SLE_UINT32, 127, SL_MAX_VERSION),
    00436
    00437         SLE_END()
    00438 };
    00439
    00440 static const SaveLoad _waypoint_desc[] = {
    00441   SLE_WRITEBYTE(Waypoint, facilities,                FACIL_WAYPOINT),
    00442   SLE_ST_INCLUDE(),
    00443
    00444         SLE_VAR(Waypoint, town_cn,                   SLE_UINT16),
    00445
    00446     SLE_CONDVAR(Waypoint, train_station.tile,        SLE_UINT32,                  124, SL_MAX_VERSION),
    00447     SLE_CONDVAR(Waypoint, train_station.w,           SLE_FILE_U8 | SLE_VAR_U16,   124, SL_MAX_VERSION),
    00448     SLE_CONDVAR(Waypoint, train_station.h,           SLE_FILE_U8 | SLE_VAR_U16,   124, SL_MAX_VERSION),
    00449
    00450         SLE_END()
    00451 };
    00452
    00457 const SaveLoad *GetBaseStationDescription()
    00458 {
    00459   return _base_station_desc;
    00460 }
    00461
    00462 static void RealSave_STNN(BaseStation *bst)
    00463 {
    00464   bool waypoint = (bst->facilities & FACIL_WAYPOINT) != 0;
    00465   SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
    00466
    00467   if (!waypoint) {
    00468     Station *st = Station::From(bst);
    00469     for (CargoID i = 0; i < NUM_CARGO; i++) {
    00470       _num_dests = (uint32)st->goods[i].cargo.Packets()->MapSize();
    00471       _num_flows = 0;
    00472       for (FlowStatMap::const_iterator it(st->goods[i].flows.begin()); it != st->goods[i].flows.end(); ++it) {
    00473         _num_flows += (uint32)it->second.GetShares()->size();
    00474       }
    00475       SlObject(&st->goods[i], GetGoodsDesc());
    00476       for (FlowStatMap::const_iterator outer_it(st->goods[i].flows.begin()); outer_it != st->goods[i].flows.end(); ++outer_it) {
    00477         const FlowStat::SharesMap *shares = outer_it->second.GetShares();
    00478         uint32 sum_shares = 0;
    00479         FlowSaveLoad flow;
    00480         flow.source = outer_it->first;
    00481         for (FlowStat::SharesMap::const_iterator inner_it(shares->begin()); inner_it != shares->end(); ++inner_it) {
    00482           flow.via = inner_it->second;
    00483           flow.share = inner_it->first - sum_shares;
    00484           sum_shares = inner_it->first;
    00485           assert(flow.share > 0);
    00486           SlObject(&flow, _flow_desc);
    00487         }
    00488       }
    00489       for (StationCargoPacketMap::ConstMapIterator it(st->goods[i].cargo.Packets()->begin()); it != st->goods[i].cargo.Packets()->end(); ++it) {
    00490         SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), _cargo_list_desc);
    00491       }
    00492     }
    00493   }
    00494
    00495   for (uint i = 0; i < bst->num_specs; i++) {
    00496     SlObject(&bst->speclist[i], _station_speclist_desc);
    00497   }
    00498 }
    00499
    00500 static void Save_STNN()
    00501 {
    00502   BaseStation *st;
    00503   /* Write the stations */
    00504   FOR_ALL_BASE_STATIONS(st) {
    00505     SlSetArrayIndex(st->index);
    00506     SlAutolength((AutolengthProc*)RealSave_STNN, st);
    00507   }
    00508 }
    00509
    00510 static void Load_STNN()
    00511 {
    00512   int index;
    00513
    00514   while ((index = SlIterateArray()) != -1) {
    00515     bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
    00516
    00517     BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
    00518     SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
    00519
    00520     if (!waypoint) {
    00521       Station *st = Station::From(bst);
    00522
    00523       /* Before savegame version 161, persistent storages were not stored in a pool. */
    00524       if (IsSavegameVersionBefore(161) && !IsSavegameVersionBefore(145) && st->facilities & FACIL_AIRPORT) {
    00525         /* Store the old persistent storage. The GRFID will be added later. */
    00526         assert(PersistentStorage::CanAllocateItem());
    00527         st->airport.psa = new PersistentStorage(0);
    00528         memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(st->airport.psa->storage));
    00529       }
    00530
    00531       for (CargoID i = 0; i < NUM_CARGO; i++) {
    00532         SlObject(&st->goods[i], GetGoodsDesc());
    00533         FlowSaveLoad flow;
    00534         FlowStat *fs = NULL;
    00535         StationID prev_source = INVALID_STATION;
    00536         for (uint32 j = 0; j < _num_flows; ++j) {
    00537           SlObject(&flow, _flow_desc);
    00538           if (fs == NULL || prev_source != flow.source) {
    00539             fs = &(st->goods[i].flows.insert(std::make_pair(flow.source, FlowStat(flow.via, flow.share))).first->second);
    00540           } else {
    00541             fs->AppendShare(flow.via, flow.share);
    00542           }
    00543           prev_source = flow.source;
    00544         }
    00545         if (IsSavegameVersionBefore(SL_CARGOMAP)) {
    00546           SwapPackets(&st->goods[i]);
    00547         } else {
    00548           StationCargoPair pair;
    00549           for (uint j = 0; j < _num_dests; ++j) {
    00550             SlObject(&pair, _cargo_list_desc);
    00551             const_cast<StationCargoPacketMap &>(*(st->goods[i].cargo.Packets()))[pair.first].swap(pair.second);
    00552             assert(pair.second.empty());
    00553           }
    00554         }
    00555       }
    00556     }
    00557
    00558     if (bst->num_specs != 0) {
    00559       /* Allocate speclist memory when loading a game */
    00560       bst->speclist = CallocT<StationSpecList>(bst->num_specs);
    00561       for (uint i = 0; i < bst->num_specs; i++) {
    00562         SlObject(&bst->speclist[i], _station_speclist_desc);
    00563       }
    00564     }
    00565   }
    00566 }
    00567
    00568 static void Ptrs_STNN()
    00569 {
    00570   /* Don't run when savegame version lower than 123. */
    00571   if (IsSavegameVersionBefore(123)) return;
    00572
    00573   Station *st;
    00574   FOR_ALL_STATIONS(st) {
    00575     for (CargoID i = 0; i < NUM_CARGO; i++) {
    00576       GoodsEntry *ge = &st->goods[i];
    00577       if (IsSavegameVersionBefore(SL_CARGOMAP)) {
    00578         SwapPackets(ge);
    00579         SlObject(ge, GetGoodsDesc());
    00580         SwapPackets(ge);
    00581       } else {
    00582         SlObject(ge, GetGoodsDesc());
    00583         for (StationCargoPacketMap::ConstMapIterator it = ge->cargo.Packets()->begin(); it != ge->cargo.Packets()->end(); ++it) {
    00584           SlObject(const_cast<StationCargoPair *>(&(*it)), _cargo_list_desc);
    00585         }
    00586       }
    00587     }
    00588     SlObject(st, _station_desc);
    00589   }
    00590
    00591   Waypoint *wp;
    00592   FOR_ALL_WAYPOINTS(wp) {
    00593     SlObject(wp, _waypoint_desc);
    00594   }
    00595 }
    00596
    00597 static void Save_ROADSTOP()
    00598 {
    00599   RoadStop *rs;
    00600
    00601   FOR_ALL_ROADSTOPS(rs) {
    00602     SlSetArrayIndex(rs->index);
    00603     SlObject(rs, _roadstop_desc);
    00604   }
    00605 }
    00606
    00607 static void Load_ROADSTOP()
    00608 {
    00609   int index;
    00610
    00611   while ((index = SlIterateArray()) != -1) {
    00612     RoadStop *rs = new (index) RoadStop(INVALID_TILE);
    00613
    00614     SlObject(rs, _roadstop_desc);
    00615   }
    00616 }
    00617
    00618 static void Ptrs_ROADSTOP()
    00619 {
    00620   RoadStop *rs;
    00621   FOR_ALL_ROADSTOPS(rs) {
    00622     SlObject(rs, _roadstop_desc);
    00623   }
    00624 }
    00625
    00626 extern const ChunkHandler _station_chunk_handlers[] = {
    00627   { 'STNS', NULL,          Load_STNS,     Ptrs_STNS,     NULL, CH_ARRAY },
    00628   { 'STNN', Save_STNN,     Load_STNN,     Ptrs_STNN,     NULL, CH_ARRAY },
    00629   { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, NULL, CH_ARRAY | CH_LAST},
    00630 };