# order_sl.cpp

Go to the documentation of this file.

    00001 /* $Id: order_sl.cpp 26790 2014-09-07 15:09:05Z 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 "../order_backup.h"
    00014 #include "../settings_type.h"
    00015 #include "../network/network.h"
    00016 #include "../network/network_server.h"
    00017
    00018 #include "saveload_internal.h"
    00019
    00024 void Order::ConvertFromOldSavegame()
    00025 {
    00026   uint8 old_flags = this->flags;
    00027   this->flags = 0;
    00028
    00029   /* First handle non-stop - use value from savegame if possible, else use value from config file */
    00030   if (_settings_client.gui.sg_new_nonstop || (IsSavegameVersionBefore(22) && _savegame_type != SGT_TTO && _savegame_type != SGT_TTD && _settings_client.gui.new_nonstop)) {
    00031     /* OFB_NON_STOP */
    00032     this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
    00033   } else {
    00034     this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
    00035   }
    00036
    00037   switch (this->GetType()) {
    00038     /* Only a few types need the other savegame conversions. */
    00039     case OT_GOTO_DEPOT: case OT_GOTO_STATION: case OT_LOADING: break;
    00040     default: return;
    00041   }
    00042
    00043   if (this->GetType() != OT_GOTO_DEPOT) {
    00044     /* Then the load flags */
    00045     if ((old_flags & 2) != 0) { // OFB_UNLOAD
    00046       this->SetLoadType(OLFB_NO_LOAD);
    00047     } else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD
    00048       this->SetLoadType(OLF_LOAD_IF_POSSIBLE);
    00049     } else {
    00050       /* old OTTD versions stored full_load_any in config file - assume it was enabled when loading */
    00051       this->SetLoadType(_settings_client.gui.sg_full_load_any || IsSavegameVersionBefore(22) ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD);
    00052     }
    00053
    00054     if (this->IsType(OT_GOTO_STATION)) this->SetStopLocation(OSL_PLATFORM_FAR_END);
    00055
    00056     /* Finally fix the unload flags */
    00057     if ((old_flags & 1) != 0) { // OFB_TRANSFER
    00058       this->SetUnloadType(OUFB_TRANSFER);
    00059     } else if ((old_flags & 2) != 0) { // OFB_UNLOAD
    00060       this->SetUnloadType(OUFB_UNLOAD);
    00061     } else {
    00062       this->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
    00063     }
    00064   } else {
    00065     /* Then the depot action flags */
    00066     this->SetDepotActionType(((old_flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY);
    00067
    00068     /* Finally fix the depot type flags */
    00069     uint t = ((old_flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL;
    00070     if ((old_flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS;
    00071     this->SetDepotOrderType((OrderDepotTypeFlags)t);
    00072   }
    00073 }
    00074
    00080 static Order UnpackVersion4Order(uint16 packed)
    00081 {
    00082   return Order(GB(packed, 8, 8) << 16 | GB(packed, 4, 4) << 8 | GB(packed, 0, 4));
    00083 }
    00084
    00090 Order UnpackOldOrder(uint16 packed)
    00091 {
    00092   Order order = UnpackVersion4Order(packed);
    00093
    00094   /*
    00095    * Sanity check
    00096    * TTD stores invalid orders as OT_NOTHING with non-zero flags/station
    00097    */
    00098   if (order.IsType(OT_NOTHING) && packed != 0) order.MakeDummy();
    00099
    00100   return order;
    00101 }
    00102
    00103 const SaveLoad *GetOrderDescription()
    00104 {
    00105   static const SaveLoad _order_desc[] = {
    00106          SLE_VAR(Order, type,           SLE_UINT8),
    00107          SLE_VAR(Order, flags,          SLE_UINT8),
    00108          SLE_VAR(Order, dest,           SLE_UINT16),
    00109          SLE_REF(Order, next,           REF_ORDER),
    00110      SLE_CONDVAR(Order, refit_cargo,    SLE_UINT8,   36, SL_MAX_VERSION),
    00111     SLE_CONDNULL(1,                                  36, 181), // refit_subtype
    00112      SLE_CONDVAR(Order, wait_time,      SLE_UINT16,  67, SL_MAX_VERSION),
    00113      SLE_CONDVAR(Order, travel_time,    SLE_UINT16,  67, SL_MAX_VERSION),
    00114      SLE_CONDVAR(Order, max_speed,      SLE_UINT16, 172, SL_MAX_VERSION),
    00115
    00116     /* Leftover from the minor savegame version stuff
    00117      * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */
    00118     SLE_CONDNULL(10,                                  5,  35),
    00119          SLE_END()
    00120   };
    00121
    00122   return _order_desc;
    00123 }
    00124
    00125 static void Save_ORDR()
    00126 {
    00127   Order *order;
    00128
    00129   FOR_ALL_ORDERS(order) {
    00130     SlSetArrayIndex(order->index);
    00131     SlObject(order, GetOrderDescription());
    00132   }
    00133 }
    00134
    00135 static void Load_ORDR()
    00136 {
    00137   if (IsSavegameVersionBefore(5, 2)) {
    00138     /* Version older than 5.2 did not have a ->next pointer. Convert them
    00139      * (in the old days, the orderlist was 5000 items big) */
    00140     size_t len = SlGetFieldLength();
    00141
    00142     if (IsSavegameVersionBefore(5)) {
    00143       /* Pre-version 5 had another layout for orders
    00144        * (uint16 instead of uint32) */
    00145       len /= sizeof(uint16);
    00146       uint16 *orders = MallocT<uint16>(len + 1);
    00147
    00148       SlArray(orders, len, SLE_UINT16);
    00149
    00150       for (size_t i = 0; i < len; ++i) {
    00151         Order *o = new (i) Order();
    00152         o->AssignOrder(UnpackVersion4Order(orders[i]));
    00153       }
    00154
    00155       free(orders);
    00156     } else if (IsSavegameVersionBefore(5, 2)) {
    00157       len /= sizeof(uint32);
    00158       uint32 *orders = MallocT<uint32>(len + 1);
    00159
    00160       SlArray(orders, len, SLE_UINT32);
    00161
    00162       for (size_t i = 0; i < len; ++i) {
    00163         new (i) Order(orders[i]);
    00164       }
    00165
    00166       free(orders);
    00167     }
    00168
    00169     /* Update all the next pointer */
    00170     Order *o;
    00171     FOR_ALL_ORDERS(o) {
    00172       /* Delete invalid orders */
    00173       if (o->IsType(OT_NOTHING)) {
    00174         delete o;
    00175         continue;
    00176       }
    00177       /* The orders were built like this:
    00178        * While the order is valid, set the previous will get its next pointer set */
    00179       Order *prev = Order::GetIfValid(order_index - 1);
    00180       if (prev != NULL) prev->next = o;
    00181     }
    00182   } else {
    00183     int index;
    00184
    00185     while ((index = SlIterateArray()) != -1) {
    00186       Order *order = new (index) Order();
    00187       SlObject(order, GetOrderDescription());
    00188     }
    00189   }
    00190 }
    00191
    00192 static void Ptrs_ORDR()
    00193 {
    00194   /* Orders from old savegames have pointers corrected in Load_ORDR */
    00195   if (IsSavegameVersionBefore(5, 2)) return;
    00196
    00197   Order *o;
    00198
    00199   FOR_ALL_ORDERS(o) {
    00200     SlObject(o, GetOrderDescription());
    00201   }
    00202 }
    00203
    00204 const SaveLoad *GetOrderListDescription()
    00205 {
    00206   static const SaveLoad _orderlist_desc[] = {
    00207     SLE_REF(OrderList, first,              REF_ORDER),
    00208     SLE_END()
    00209   };
    00210
    00211   return _orderlist_desc;
    00212 }
    00213
    00214 static void Save_ORDL()
    00215 {
    00216   OrderList *list;
    00217
    00218   FOR_ALL_ORDER_LISTS(list) {
    00219     SlSetArrayIndex(list->index);
    00220     SlObject(list, GetOrderListDescription());
    00221   }
    00222 }
    00223
    00224 static void Load_ORDL()
    00225 {
    00226   int index;
    00227
    00228   while ((index = SlIterateArray()) != -1) {
    00229     /* set num_orders to 0 so it's a valid OrderList */
    00230     OrderList *list = new (index) OrderList(0);
    00231     SlObject(list, GetOrderListDescription());
    00232   }
    00233
    00234 }
    00235
    00236 static void Ptrs_ORDL()
    00237 {
    00238   OrderList *list;
    00239
    00240   FOR_ALL_ORDER_LISTS(list) {
    00241     SlObject(list, GetOrderListDescription());
    00242   }
    00243 }
    00244
    00245 const SaveLoad *GetOrderBackupDescription()
    00246 {
    00247   static const SaveLoad _order_backup_desc[] = {
    00248          SLE_VAR(OrderBackup, user,                     SLE_UINT32),
    00249          SLE_VAR(OrderBackup, tile,                     SLE_UINT32),
    00250          SLE_VAR(OrderBackup, group,                    SLE_UINT16),
    00251          SLE_VAR(OrderBackup, service_interval,         SLE_FILE_U32 | SLE_VAR_U16),
    00252          SLE_STR(OrderBackup, name,                     SLE_STR, 0),
    00253         SLE_NULL(2), // clone (2 bytes of pointer, i.e. garbage)
    00254          SLE_VAR(OrderBackup, cur_real_order_index,     SLE_UINT8),
    00255      SLE_CONDVAR(OrderBackup, cur_implicit_order_index, SLE_UINT8,                 176, SL_MAX_VERSION),
    00256      SLE_CONDVAR(OrderBackup, current_order_time,       SLE_UINT32,                176, SL_MAX_VERSION),
    00257      SLE_CONDVAR(OrderBackup, lateness_counter,         SLE_INT32,                 176, SL_MAX_VERSION),
    00258      SLE_CONDVAR(OrderBackup, timetable_start,          SLE_INT32,                 176, SL_MAX_VERSION),
    00259      SLE_CONDVAR(OrderBackup, vehicle_flags,            SLE_FILE_U8 | SLE_VAR_U16, 176, 179),
    00260      SLE_CONDVAR(OrderBackup, vehicle_flags,            SLE_UINT16,                180, SL_MAX_VERSION),
    00261          SLE_REF(OrderBackup, orders,                   REF_ORDER),
    00262          SLE_END()
    00263   };
    00264
    00265   return _order_backup_desc;
    00266 }
    00267
    00268 static void Save_BKOR()
    00269 {
    00270   /* We only save this when we're a network server
    00271    * as we want this information on our clients. For
    00272    * normal games this information isn't needed. */
    00273   if (!_networking || !_network_server) return;
    00274
    00275   OrderBackup *ob;
    00276   FOR_ALL_ORDER_BACKUPS(ob) {
    00277     SlSetArrayIndex(ob->index);
    00278     SlObject(ob, GetOrderBackupDescription());
    00279   }
    00280 }
    00281
    00282 void Load_BKOR()
    00283 {
    00284   int index;
    00285
    00286   while ((index = SlIterateArray()) != -1) {
    00287     /* set num_orders to 0 so it's a valid OrderList */
    00288     OrderBackup *ob = new (index) OrderBackup();
    00289     SlObject(ob, GetOrderBackupDescription());
    00290   }
    00291
    00292   /* Only load order-backups for network clients.
    00293    * If we are a network server or not networking, then we just loaded a previously
    00294    * saved-by-server savegame. There are no clients with a backup, so clear it.
    00295    * Furthermore before savegame version 192 the actual content was always corrupt.
    00296    */
    00297   if (!_networking || _network_server || IsSavegameVersionBefore(192)) {
    00298     /* Note: We cannot use CleanPool since that skips part of the destructor
    00299      * and then leaks un-reachable Orders in the order pool. */
    00300     OrderBackup *ob;
    00301     FOR_ALL_ORDER_BACKUPS(ob) {
    00302       delete ob;
    00303     }
    00304   }
    00305 }
    00306
    00307 static void Ptrs_BKOR()
    00308 {
    00309   OrderBackup *ob;
    00310   FOR_ALL_ORDER_BACKUPS(ob) {
    00311     SlObject(ob, GetOrderBackupDescription());
    00312   }
    00313 }
    00314
    00315 extern const ChunkHandler _order_chunk_handlers[] = {
    00316   { 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, NULL, CH_ARRAY},
    00317   { 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, NULL, CH_ARRAY},
    00318   { 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, NULL, CH_ARRAY | CH_LAST},
    00319 };