diff --git a/src/order_base.h b/src/order_base.h index 11cb78c47b..73582d926e 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -28,6 +28,12 @@ typedef Pool OrderListPool; extern OrderPool _order_pool; extern OrderListPool _orderlist_pool; +struct OrderExtraInfo { + uint8 cargo_type_flags[NUM_CARGO]; ///< Load/unload types for each cargo type. + + OrderExtraInfo(); +}; + /* If you change this, keep in mind that it is saved on 3 places: * - Load_ORDR, all the global orders * - Vehicle -> current_order @@ -38,6 +44,8 @@ private: friend const struct SaveLoad *GetVehicleDescription(VehicleType vt); ///< Saving and loading the current order of vehicles. friend void Load_VEHS(); ///< Loading of ancient vehicles. friend const struct SaveLoad *GetOrderDescription(); ///< Saving and loading of orders. + friend void Load_ORDX(); ///< Saving and loading of orders. + friend void Save_ORDX(); ///< Saving and loading of orders. uint8 type; ///< The type of order + non-stop flags uint8 flags; ///< Load/unload types, depot order/action types. @@ -45,20 +53,41 @@ private: CargoID refit_cargo; ///< Refit CargoID - uint8 cargo_type_flags[NUM_CARGO]; ///< Load/unload types for each cargo type. + OrderExtraInfo *extra;///< Extra order info uint16 wait_time; ///< How long in ticks to wait at the destination. uint16 travel_time; ///< How long in ticks the journey to this destination should take. uint16 max_speed; ///< How fast the vehicle may go on the way to the destination. + void AllocExtraInfo(); + void DeAllocExtraInfo(); + + inline void CheckExtraInfoAlloced() + { + if (!this->extra) this->AllocExtraInfo(); + } + public: Order *next; ///< Pointer to next order. If NULL, end of list - Order() : refit_cargo(CT_NO_REFIT), max_speed(UINT16_MAX) {} + Order() : refit_cargo(CT_NO_REFIT), extra(NULL), max_speed(UINT16_MAX) {} ~Order(); Order(uint32 packed); + Order(const Order& other) : extra(NULL) + { + *this = other; + } + + inline Order& operator=(Order const& other) + { + AssignOrder(other); + this->next = other.next; + this->index = other.index; + return *this; + } + /** * Check whether this order is of the given type. * @param type the type to check against. @@ -141,7 +170,8 @@ public: inline OrderLoadFlags GetCargoLoadTypeRaw(CargoID cargo_id) const { assert(cargo_id < NUM_CARGO); - return (OrderLoadFlags) GB(this->cargo_type_flags[cargo_id], 4, 4); + if (!this->extra) return OLF_LOAD_IF_POSSIBLE; + return (OrderLoadFlags) GB(this->extra->cargo_type_flags[cargo_id], 4, 4); } /** @@ -169,7 +199,8 @@ public: inline OrderUnloadFlags GetCargoUnloadTypeRaw(CargoID cargo_id) const { assert(cargo_id < NUM_CARGO); - return (OrderUnloadFlags) GB(this->cargo_type_flags[cargo_id], 0, 4); + if (!this->extra) return OUF_UNLOAD_IF_POSSIBLE; + return (OrderUnloadFlags) GB(this->extra->cargo_type_flags[cargo_id], 0, 4); } /** @@ -214,7 +245,8 @@ public: inline void SetLoadType(OrderLoadFlags load_type, CargoID cargo_id) { assert(cargo_id < NUM_CARGO); - SB(this->cargo_type_flags[cargo_id], 4, 4, load_type); + this->CheckExtraInfoAlloced(); + SB(this->extra->cargo_type_flags[cargo_id], 4, 4, load_type); } /** Set how the consist must be unloaded. */ @@ -229,7 +261,8 @@ public: inline void SetUnloadType(OrderUnloadFlags unload_type, CargoID cargo_id) { assert(cargo_id < NUM_CARGO); - SB(this->cargo_type_flags[cargo_id], 0, 4, unload_type); + this->CheckExtraInfoAlloced(); + SB(this->extra->cargo_type_flags[cargo_id], 0, 4, unload_type); } /** Set whether we must stop at stations or not. */ diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 9d93ba1cbc..55815c3e47 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -48,6 +48,7 @@ INSTANTIATE_POOL_METHODS(OrderList) /** Clean everything up. */ Order::~Order() { + DeAllocExtraInfo(); if (CleaningPool()) return; /* We can visit oil rigs and buoys that are not our own. They will be shown in @@ -68,6 +69,7 @@ void Order::Free() this->flags = 0; this->dest = 0; this->next = NULL; + DeAllocExtraInfo(); } /** @@ -238,6 +240,7 @@ Order::Order(uint32 packed) this->type = (OrderType)GB(packed, 0, 8); this->flags = GB(packed, 8, 8); this->dest = GB(packed, 16, 16); + this->extra = NULL; this->next = NULL; this->refit_cargo = CT_NO_REFIT; this->wait_time = 0; @@ -284,13 +287,34 @@ void Order::AssignOrder(const Order &other) this->travel_time = other.travel_time; this->max_speed = other.max_speed; - if (this->GetUnloadType() == OUFB_CARGO_TYPE_UNLOAD || this->GetLoadType() == OLFB_CARGO_TYPE_LOAD) { - for (uint i = 0; i < NUM_CARGO; i++) { - this->cargo_type_flags[i] = other.cargo_type_flags[i]; - } + if ((this->GetUnloadType() == OUFB_CARGO_TYPE_UNLOAD || this->GetLoadType() == OLFB_CARGO_TYPE_LOAD) && other.extra != NULL) { + this->AllocExtraInfo(); + *(this->extra) = *(other.extra); + } else { + this->DeAllocExtraInfo(); } } +void Order::AllocExtraInfo() +{ + if (this->extra == NULL) { + this->extra = new OrderExtraInfo(); + } +} + +void Order::DeAllocExtraInfo() +{ + if (this->extra != NULL) { + delete this->extra; + this->extra = NULL; + } +} + +OrderExtraInfo::OrderExtraInfo() +{ + memset(cargo_type_flags, 0, sizeof(cargo_type_flags)); +} + void CargoStationIDStackSet::FillNextStoppingStation(const Vehicle *v, const OrderList *o, const Order *first, uint hops) { this->more.clear(); diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 4a2a7f1cf2..2966516881 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -45,7 +45,7 @@ std::vector _sl_xv_discardable_chunk_ids; ///< list of chunks static const uint32 _sl_xv_slxi_chunk_version = 0; ///< current version os SLXI chunk const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { - { XSLFI_CARGO_TYPE_ORDERS, XSCF_NULL, 1, 1, "cargo_type_orders", NULL, NULL, NULL }, + { XSLFI_CARGO_TYPE_ORDERS, XSCF_NULL, 1, 1, "cargo_type_orders", NULL, NULL, "ORDX" }, { XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker }; diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp index f6a8fae441..4e3d5ff391 100644 --- a/src/saveload/order_sl.cpp +++ b/src/saveload/order_sl.cpp @@ -113,7 +113,6 @@ const SaveLoad *GetOrderDescription() SLE_CONDVAR(Order, wait_time, SLE_UINT16, 67, SL_MAX_VERSION), SLE_CONDVAR(Order, travel_time, SLE_UINT16, 67, SL_MAX_VERSION), SLE_CONDVAR(Order, max_speed, SLE_UINT16, 172, SL_MAX_VERSION), - SLE_CONDARR_X(Order, cargo_type_flags, SLE_UINT8, NUM_CARGO, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CARGO_TYPE_ORDERS, 1)), /* Leftover from the minor savegame version stuff * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */ @@ -195,6 +194,39 @@ static void Load_ORDR() } } +const SaveLoad *GetOrderExtraInfoDescription() +{ + static const SaveLoad _order_extra_info_desc[] = { + SLE_ARR(OrderExtraInfo, cargo_type_flags, SLE_UINT8, NUM_CARGO), + SLE_END() + }; + + return _order_extra_info_desc; +} + +void Save_ORDX() +{ + Order *order; + + FOR_ALL_ORDERS(order) { + if (order->extra != NULL) { + SlSetArrayIndex(order->index); + SlObject(order->extra, GetOrderExtraInfoDescription()); + } + } +} + +void Load_ORDX() +{ + int index; + while ((index = SlIterateArray()) != -1) { + Order *order = Order::GetIfValid(index); + assert(order != NULL); + order->AllocExtraInfo(); + SlObject(order->extra, GetOrderExtraInfoDescription()); + } +} + static void Ptrs_ORDR() { /* Orders from old savegames have pointers corrected in Load_ORDR */ @@ -309,5 +341,6 @@ static void Ptrs_BKOR() extern const ChunkHandler _order_chunk_handlers[] = { { 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, NULL, CH_ARRAY}, { 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, NULL, CH_ARRAY}, - { 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, NULL, CH_ARRAY | CH_LAST}, + { 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, NULL, CH_ARRAY}, + { 'ORDX', Save_ORDX, Load_ORDX, NULL, NULL, CH_SPARSE_ARRAY | CH_LAST}, };