# order_sl.cpp

Go to the documentation of this file.

    00001 /* $Id: order_sl.cpp 15903 2009-03-30 23:15:05Z rubidium $ */
    00002
    00005 #include "../stdafx.h"
    00006 #include "../order_base.h"
    00007 #include "../core/alloc_func.hpp"
    00008 #include "../settings_type.h"
    00009
    00010 #include "saveload.h"
    00011
    00012 void Order::ConvertFromOldSavegame()
    00013 {
    00014   uint8 old_flags = this->flags;
    00015   this->flags = 0;
    00016
    00017   /* First handle non-stop - use value from savegame if possible, else use value from config file */
    00018   if (_settings_client.gui.sg_new_nonstop || (CheckSavegameVersion(22) && _settings_client.gui.new_nonstop)) {
    00019     /* OFB_NON_STOP */
    00020     this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_ANY_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
    00021   } else {
    00022     this->SetNonStopType((old_flags & 8) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
    00023   }
    00024
    00025   switch (this->GetType()) {
    00026     /* Only a few types need the other savegame conversions. */
    00027     case OT_GOTO_DEPOT: case OT_GOTO_STATION: case OT_LOADING: break;
    00028     default: return;
    00029   }
    00030
    00031   if (this->GetType() != OT_GOTO_DEPOT) {
    00032     /* Then the load flags */
    00033     if ((old_flags & 2) != 0) { // OFB_UNLOAD
    00034       this->SetLoadType(OLFB_NO_LOAD);
    00035     } else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD
    00036       this->SetLoadType(OLF_LOAD_IF_POSSIBLE);
    00037     } else {
    00038       /* old OTTD versions stored full_load_any in config file - assume it was enabled when loading */
    00039       this->SetLoadType(_settings_client.gui.sg_full_load_any || CheckSavegameVersion(22) ? OLF_FULL_LOAD_ANY : OLFB_FULL_LOAD);
    00040     }
    00041
    00042     /* Finally fix the unload flags */
    00043     if ((old_flags & 1) != 0) { // OFB_TRANSFER
    00044       this->SetUnloadType(OUFB_TRANSFER);
    00045     } else if ((old_flags & 2) != 0) { // OFB_UNLOAD
    00046       this->SetUnloadType(OUFB_UNLOAD);
    00047     } else {
    00048       this->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
    00049     }
    00050   } else {
    00051     /* Then the depot action flags */
    00052     this->SetDepotActionType(((old_flags & 6) == 4) ? ODATFB_HALT : ODATF_SERVICE_ONLY);
    00053
    00054     /* Finally fix the depot type flags */
    00055     uint t = ((old_flags & 6) == 6) ? ODTFB_SERVICE : ODTF_MANUAL;
    00056     if ((old_flags & 2) != 0) t |= ODTFB_PART_OF_ORDERS;
    00057     this->SetDepotOrderType((OrderDepotTypeFlags)t);
    00058   }
    00059 }
    00060
    00065 static Order UnpackVersion4Order(uint16 packed)
    00066 {
    00067   return Order(GB(packed, 8, 8) << 16 | GB(packed, 4, 4) << 8 | GB(packed, 0, 4));
    00068 }
    00069
    00074 Order UnpackOldOrder(uint16 packed)
    00075 {
    00076   Order order = UnpackVersion4Order(packed);
    00077
    00078   /*
    00079    * Sanity check
    00080    * TTD stores invalid orders as OT_NOTHING with non-zero flags/station
    00081    */
    00082   if (!order.IsValid() && packed != 0) order.MakeDummy();
    00083
    00084   return order;
    00085 }
    00086
    00087 const SaveLoad *GetOrderDescription()
    00088 {
    00089   static const SaveLoad _order_desc[] = {
    00090          SLE_VAR(Order, type,           SLE_UINT8),
    00091          SLE_VAR(Order, flags,          SLE_UINT8),
    00092          SLE_VAR(Order, dest,           SLE_UINT16),
    00093          SLE_REF(Order, next,           REF_ORDER),
    00094      SLE_CONDVAR(Order, refit_cargo,    SLE_UINT8,   36, SL_MAX_VERSION),
    00095      SLE_CONDVAR(Order, refit_subtype,  SLE_UINT8,   36, SL_MAX_VERSION),
    00096      SLE_CONDVAR(Order, wait_time,      SLE_UINT16,  67, SL_MAX_VERSION),
    00097      SLE_CONDVAR(Order, travel_time,    SLE_UINT16,  67, SL_MAX_VERSION),
    00098
    00099     /* Leftover from the minor savegame version stuff
    00100      * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */
    00101     SLE_CONDNULL(10,                                  5,  35),
    00102          SLE_END()
    00103   };
    00104
    00105   return _order_desc;
    00106 }
    00107
    00108 static void Save_ORDR()
    00109 {
    00110   Order *order;
    00111
    00112   FOR_ALL_ORDERS(order) {
    00113     SlSetArrayIndex(order->index);
    00114     SlObject(order, GetOrderDescription());
    00115   }
    00116 }
    00117
    00118 static void Load_ORDR()
    00119 {
    00120   if (CheckSavegameVersionOldStyle(5, 2)) {
    00121     /* Version older than 5.2 did not have a ->next pointer. Convert them
    00122         (in the old days, the orderlist was 5000 items big) */
    00123     size_t len = SlGetFieldLength();
    00124     uint i;
    00125
    00126     if (CheckSavegameVersion(5)) {
    00127       /* Pre-version 5 had an other layout for orders
    00128           (uint16 instead of uint32) */
    00129       len /= sizeof(uint16);
    00130       uint16 *orders = MallocT<uint16>(len + 1);
    00131
    00132       SlArray(orders, len, SLE_UINT16);
    00133
    00134       for (i = 0; i < len; ++i) {
    00135         Order *order = new (i) Order();
    00136         order->AssignOrder(UnpackVersion4Order(orders[i]));
    00137       }
    00138
    00139       free(orders);
    00140     } else if (CheckSavegameVersionOldStyle(5, 2)) {
    00141       len /= sizeof(uint16);
    00142       uint16 *orders = MallocT<uint16>(len + 1);
    00143
    00144       SlArray(orders, len, SLE_UINT32);
    00145
    00146       for (i = 0; i < len; ++i) {
    00147         new (i) Order(orders[i]);
    00148       }
    00149
    00150       free(orders);
    00151     }
    00152
    00153     /* Update all the next pointer */
    00154     for (i = 1; i < len; ++i) {
    00155       /* The orders were built like this:
    00156        *   While the order is valid, set the previous will get it's next pointer set
    00157        *   We start with index 1 because no order will have the first in it's next pointer */
    00158       if (GetOrder(i)->IsValid())
    00159         GetOrder(i - 1)->next = GetOrder(i);
    00160     }
    00161   } else {
    00162     int index;
    00163
    00164     while ((index = SlIterateArray()) != -1) {
    00165       Order *order = new (index) Order();
    00166       SlObject(order, GetOrderDescription());
    00167     }
    00168   }
    00169 }
    00170
    00171 const SaveLoad *GetOrderListDescription()
    00172 {
    00173   static const SaveLoad _orderlist_desc[] = {
    00174     SLE_REF(OrderList, first,              REF_ORDER),
    00175     SLE_END()
    00176   };
    00177
    00178   return _orderlist_desc;
    00179 }
    00180
    00181 static void Save_ORDL()
    00182 {
    00183   OrderList *list;
    00184
    00185   FOR_ALL_ORDER_LISTS(list) {
    00186     SlSetArrayIndex(list->index);
    00187     SlObject(list, GetOrderListDescription());
    00188   }
    00189 }
    00190
    00191 static void Load_ORDL()
    00192 {
    00193   int index;
    00194
    00195   while ((index = SlIterateArray()) != -1) {
    00196     OrderList *list = new (index) OrderList();
    00197     SlObject(list, GetOrderListDescription());
    00198   }
    00199 }
    00200
    00201 extern const ChunkHandler _order_chunk_handlers[] = {
    00202   { 'ORDR', Save_ORDR, Load_ORDR, CH_ARRAY},
    00203   { 'ORDL', Save_ORDL, Load_ORDL, CH_ARRAY | CH_LAST},
    00204 };