OpenTTD Source 20260917-master-gec444f7315
order_sl.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "../stdafx.h"
11
12#include "saveload.h"
14
15#include "saveload_internal.h"
16#include "../order_backup.h"
17#include "../settings_type.h"
18#include "../vehicle_base.h"
19#include "../network/network.h"
20
21#include "../safeguards.h"
22
28{
29 uint8_t old_flags = this->flags;
30 this->flags = 0;
31
32 /* First handle non-stop - use value from savegame if possible, else use value from config file */
34 /* OFB_NON_STOP */
36 } else {
38 }
39
40 switch (this->GetType()) {
41 /* Only a few types need the other savegame conversions. */
42 case OT_GOTO_DEPOT: case OT_GOTO_STATION: case OT_LOADING: break;
43 default: return;
44 }
45
46 if (this->GetType() != OT_GOTO_DEPOT) {
47 /* Then the load flags */
48 if ((old_flags & 2) != 0) { // OFB_UNLOAD
50 } else if ((old_flags & 4) == 0) { // !OFB_FULL_LOAD
52 } else {
53 /* old OTTD versions stored full_load_any in config file - assume it was enabled when loading */
55 }
56
57 if (this->IsType(OT_GOTO_STATION)) this->SetStopLocation(OrderStopLocation::FarEnd);
58
59 /* Finally fix the unload flags */
60 if ((old_flags & 1) != 0) { // OFB_TRANSFER
62 } else if ((old_flags & 2) != 0) { // OFB_UNLOAD
64 } else {
66 }
67 } else {
68 /* Then the depot action flags */
69 OrderDepotActionFlags action_flags{};
70 if ((old_flags & 6) == 4) action_flags.Set(OrderDepotActionFlag::Halt);
71 this->SetDepotActionType(action_flags);
72
73 /* Finally fix the depot type flags */
74 OrderDepotTypeFlags type_flags{};
75 if ((old_flags & 6) == 6) type_flags.Set(OrderDepotTypeFlag::Service);
76 if ((old_flags & 2) != 0) type_flags.Set(OrderDepotTypeFlag::PartOfOrders);
77 this->SetDepotOrderType(type_flags);
78 }
79}
80
86static Order UnpackVersion4Order(uint16_t packed)
87{
88 return Order(GB(packed, 0, 4), GB(packed, 4, 4), GB(packed, 8, 8));
89}
90
96Order UnpackOldOrder(uint16_t packed)
97{
98 Order order = UnpackVersion4Order(packed);
99
100 /*
101 * Sanity check
102 * TTD stores invalid orders as OT_NOTHING with non-zero flags/station
103 */
104 if (order.IsType(OT_NOTHING) && packed != 0) order.MakeDummy();
105
106 return order;
107}
108
110static std::vector<OldOrderSaveLoadItem> _old_order_saveload_pool;
111
116{
118 _old_order_saveload_pool.shrink_to_fit();
119}
120
127{
128 if (ref_index == 0) return nullptr;
129 assert(ref_index <= _old_order_saveload_pool.size());
130 return &_old_order_saveload_pool[ref_index - 1];
131}
132
139{
140 assert(pool_index < UINT32_MAX);
141 if (pool_index >= _old_order_saveload_pool.size()) _old_order_saveload_pool.resize(pool_index + 1);
142 return _old_order_saveload_pool[pool_index];
143}
144
161
162struct ORDRChunkHandler : ChunkHandler {
163 ORDRChunkHandler() : ChunkHandler("ORDR", ChunkType::ReadOnly) {}
164
165 void Load() const override
166 {
168 /* Version older than 5.2 did not have a ->next pointer. Convert them
169 * (in the old days, the orderlist was 5000 items big) */
170 size_t len = SlGetFieldLength();
171
173 /* Pre-version 5 had another layout for orders
174 * (uint16_t instead of uint32_t) */
175 len /= sizeof(uint16_t);
176 std::vector<uint16_t> orders(len);
177
179
180 for (size_t i = 0; i < len; ++i) {
181 auto &item = AllocateOldOrder(i);
182 item.order.AssignOrder(UnpackVersion4Order(orders[i]));
183 }
185 len /= sizeof(uint32_t);
186 std::vector<uint32_t> orders(len);
187
189
190 for (size_t i = 0; i < len; ++i) {
191 auto &item = AllocateOldOrder(i);
192 item.order = Order(GB(orders[i], 0, 8), GB(orders[i], 8, 8), GB(orders[i], 16, 16));
193 }
194 }
195
196 /* Update all the next pointer. The orders were built like this:
197 * While the order is valid, the previous order will get its next pointer set */
198 for (uint32_t num = 1; const OldOrderSaveLoadItem &item : _old_order_saveload_pool) {
199 if (!item.order.IsType(OT_NOTHING) && num > 1) {
200 OldOrderSaveLoadItem *prev = GetOldOrder(num - 1);
201 if (prev != nullptr) prev->next = num;
202 }
203 ++num;
204 }
205 } else {
206 const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderDescription(), _order_sl_compat);
207
208 int index;
209
210 while ((index = SlIterateArray()) != -1) {
211 auto &item = AllocateOldOrder(index);
212 SlObject(&item, slt);
213 }
214 }
215 }
216};
217
218template <typename T>
219class SlOrders : public VectorSaveLoadHandler<SlOrders<T>, T, Order> {
220public:
221 static inline const SaveLoad description[] = {
229 };
230 static inline const SaveLoadCompatTable compat_description = {};
231
232 std::vector<Order> &GetVector(T *container) const override { return container->orders; }
233
234 void LoadCheck(T *container) const override { this->Load(container); }
235};
236
237/* Instantiate SlOrders classes. */
238template class SlOrders<OrderList>;
239template class SlOrders<OrderBackup>;
240
251
252struct ORDLChunkHandler : ChunkHandler {
253 ORDLChunkHandler() : ChunkHandler("ORDL", ChunkType::Table) {}
254
255 void Save() const override
256 {
257 const SaveLoadTable slt = GetOrderListDescription();
258 SlTableHeader(slt);
259
260 for (OrderList *list : OrderList::Iterate()) {
261 SlSetArrayIndex(list->index);
262 SlObject(list, slt);
263 }
264 }
265
266 void Load() const override
267 {
268 const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderListDescription(), _orderlist_sl_compat);
269
270 int index;
271
272 while ((index = SlIterateArray()) != -1) {
273 OrderList *list = OrderList::CreateAtIndex(OrderListID(index));
274 SlObject(list, slt);
275 }
276
277 }
278
279 void FixPointers() const override
280 {
282
283 for (OrderList *list : OrderList::Iterate()) {
284 SlObject(list, GetOrderListDescription());
285
286 if (migrate_orders) {
287 std::vector<Order> orders;
288 for (OldOrderSaveLoadItem *old_order = GetOldOrder(list->old_order_index); old_order != nullptr; old_order = GetOldOrder(old_order->next)) {
289 orders.push_back(std::move(old_order->order));
290 }
291 list->orders = std::move(orders);
292 }
293 }
294 }
295};
296
298{
299 static const SaveLoad _order_backup_desc[] = {
318 };
319
320 return _order_backup_desc;
321}
322
323struct BKORChunkHandler : ChunkHandler {
324 BKORChunkHandler() : ChunkHandler("BKOR", ChunkType::Table) {}
325
326 void Save() const override
327 {
328 const SaveLoadTable slt = GetOrderBackupDescription();
329 SlTableHeader(slt);
330
331 /* We only save this when we're a network server
332 * as we want this information on our clients. For
333 * normal games this information isn't needed. */
334 if (!_networking || !_network_server) return;
335
336 for (OrderBackup *ob : OrderBackup::Iterate()) {
337 SlSetArrayIndex(ob->index);
338 SlObject(ob, slt);
339 }
340 }
341
342 void Load() const override
343 {
344 const std::vector<SaveLoad> slt = SlCompatTableHeader(GetOrderBackupDescription(), _order_backup_sl_compat);
345
346 int index;
347
348 while ((index = SlIterateArray()) != -1) {
349 /* set num_orders to 0 so it's a valid OrderList */
351 SlObject(ob, slt);
352 }
353 }
354
355 void FixPointers() const override
356 {
358
359 for (OrderBackup *ob : OrderBackup::Iterate()) {
360 SlObject(ob, GetOrderBackupDescription());
361
362 if (migrate_orders) {
363 std::vector<Order> orders;
364 for (OldOrderSaveLoadItem *old_order = GetOldOrder(ob->old_order_index); old_order != nullptr; old_order = GetOldOrder(old_order->next)) {
365 orders.push_back(std::move(old_order->order));
366 }
367 ob->orders = std::move(orders);
368 }
369 }
370 }
371};
372
373static const BKORChunkHandler BKOR;
374static const ORDRChunkHandler ORDR;
375static const ORDLChunkHandler ORDL;
376static const ChunkHandlerRef order_chunk_handlers[] = {
377 BKOR,
378 ORDR,
379 ORDL,
380};
381
382extern const ChunkHandlerTable _order_chunk_handlers(order_chunk_handlers);
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr Timpl & Set()
Set all bits.
std::vector< Order > & GetVector(T *container) const override
Get instance of vector to load/save.
Definition order_sl.cpp:232
void LoadCheck(T *container) const override
Similar to load, but used only to validate savegames.
Definition order_sl.cpp:234
Default handler for saving/loading a vector to/from disk.
Definition saveload.h:1341
void Load(T *object) const override
Definition saveload.h:1367
#define T
Climate temperate.
Definition engines.h:91
SavegameType _savegame_type
type of savegame we are loading
Definition saveload.cpp:77
bool _networking
are we in networking mode?
Definition network.cpp:67
bool _network_server
network-server is active
Definition network.cpp:68
Basic functions/variables used all over the place.
@ Order
Something wrong with the order, e.g. invalid or duplicate entries, too few entries.
Definition news_type.h:54
Functions related to order backups.
PoolID< uint8_t, struct OrderBackupIDTag, 255, 0xFF > OrderBackupID
Unique identifier for an order backup.
static std::vector< OldOrderSaveLoadItem > _old_order_saveload_pool
Temporary storage for conversion from old order pool.
Definition order_sl.cpp:110
Order UnpackOldOrder(uint16_t packed)
Unpacks a order from savegames made with TTD(Patch).
Definition order_sl.cpp:96
static Order UnpackVersion4Order(uint16_t packed)
Unpacks a order from savegames with version 4 and lower.
Definition order_sl.cpp:86
void ClearOldOrders()
Clear all old orders.
Definition order_sl.cpp:115
OldOrderSaveLoadItem & AllocateOldOrder(size_t pool_index)
Allocate an old order with the given pool index.
Definition order_sl.cpp:138
OldOrderSaveLoadItem * GetOldOrder(size_t ref_index)
Get a pointer to an old order with the given reference index.
Definition order_sl.cpp:126
Loading of order chunks before table headers were added.
const SaveLoadCompat _order_sl_compat[]
Original field order for _order_desc.
const SaveLoadCompat _orderlist_sl_compat[]
Original field order for _orderlist_desc.
const SaveLoadCompat _order_backup_sl_compat[]
Original field order for _order_backup_desc.
@ Transfer
Transfer all cargo onto the platform.
Definition order_type.h:70
@ UnloadIfPossible
Unload all cargo that the station accepts.
Definition order_type.h:68
@ Unload
Force unloading all cargo onto the platform, possibly not getting paid.
Definition order_type.h:69
@ FarEnd
Stop at the far end of the platform.
Definition order_type.h:101
EnumBitSet< OrderNonStopFlag, uint8_t > OrderNonStopFlags
Bitset of OrderNonStopFlag elements.
Definition order_type.h:93
@ NonStop
The vehicle will not stop at any stations it passes except the destination, aka non-stop.
Definition order_type.h:88
@ GoVia
The vehicle will stop at any station it passes except the destination, aka via.
Definition order_type.h:89
EnumBitSet< OrderDepotActionFlag, uint8_t > OrderDepotActionFlags
Bitset of OrderDepotActionFlag elements.
Definition order_type.h:126
EnumBitSet< OrderDepotTypeFlag, uint8_t > OrderDepotTypeFlags
Bitset of OrderDepotTypeFlag elements.
Definition order_type.h:114
@ FullLoad
Full load all cargoes of the consist.
Definition order_type.h:79
@ NoLoad
Do not load anything.
Definition order_type.h:81
@ FullLoadAny
Full load a single cargo of the consist.
Definition order_type.h:80
@ LoadIfPossible
Load as long as there is cargo that fits in the train.
Definition order_type.h:78
@ Halt
Service the vehicle and then halt it.
Definition order_type.h:120
@ PartOfOrders
This depot order is because of a regular order.
Definition order_type.h:110
@ Service
This depot order is because of the servicing limit.
Definition order_type.h:109
A number of safeguards to prevent using unsafe methods.
std::vector< SaveLoad > SlCompatTableHeader(const SaveLoadTable &slt, const SaveLoadCompatTable &slct)
Load a table header in a savegame compatible way.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition saveload.cpp:745
void SlCopy(void *object, size_t length, VarType conv)
Copy a list of SaveLoadType::Variables to/from a savegame.
size_t SlGetFieldLength()
Get the length of the current object.
Definition saveload.cpp:871
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
Functions/types related to saving and loading games.
#define SLE_OBJECT_ADDRESS(base, variable)
Macro to be able to pass the variable type and construct the SaveLoad::AddressFunction given a base c...
Definition saveload.h:754
@ TTO
TTO savegame.
Definition saveload.h:438
@ TTD
TTD savegame (can be detected incorrectly).
Definition saveload.h:434
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition saveload.h:513
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition saveload.h:516
std::span< const struct SaveLoadCompat > SaveLoadCompatTable
A table of SaveLoadCompat entries.
Definition saveload.h:519
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition saveload.h:1226
@ BackupOrderState
Saveload version: 176, SVN revision: 24446 Put more of the state of a vehicle's orders (like latenes...
Definition saveload.h:261
@ OrdersOwnedByOrderlist
Saveload version: 354, GitHub pull request: 13948 Orders stored in OrderList, pool removed.
Definition saveload.h:410
@ TimetableStartTicksFix
Saveload version: 322, GitHub pull request: 11557 Fix for missing convert timetable start from a dat...
Definition saveload.h:372
@ SavePatches
Saveload version: 22, SVN revision: 3726 Save state of patches (precursor of settings) in the savega...
Definition saveload.h:76
@ BigMap
Saveload version: 5.0, SVN revision: 1429 Making maps a different size than 256x256.
Definition saveload.h:50
@ MoreCargoPackets
Saveload version: 69, SVN revision: 10319 Allow more than ~65k cargo packets.
Definition saveload.h:132
@ RefitOrders
Saveload version: 36, SVN revision: 6624 Vehicles can be refitted as part of an order.
Definition saveload.h:93
@ ServiceIntervalPercent
Saveload version: 180, SVN revision: 24998, release: 1.3.x Service interval in percent or days store...
Definition saveload.h:266
@ MinVersion
First savegame version.
Definition saveload.h:37
@ OrderMaxSpeed
Saveload version: 172, SVN revision: 23947 Set maximum speed for orders.
Definition saveload.h:256
@ Timetables
Saveload version: 67, SVN revision: 10236 Introduce timetables for vehicles.
Definition saveload.h:130
@ FixOrderBackup
Saveload version: 192, SVN revision: 26700 Fix saving of order backups.
Definition saveload.h:280
@ ReadOnly
Chunk is never saved.
Definition saveload.h:454
@ Table
An Array with a header describing the elements.
Definition saveload.h:450
Declaration of functions used in more save/load files.
std::span< const struct SaveLoad > SaveLoadTable
A table of SaveLoad entries.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
Types related to global configuration settings.
Definition of base types and functions in a cross-platform compatible way.
void Save() const override
Save the chunk.
Definition order_sl.cpp:326
void Load() const override
Load the chunk.
Definition order_sl.cpp:342
void FixPointers() const override
Fix the pointers.
Definition order_sl.cpp:355
std::string name
Name of vehicle.
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
VehicleFlags vehicle_flags
Used for gradual loading and other miscellaneous things (.
VehicleOrderID cur_implicit_order_index
The index to the current implicit order.
TimerGameTick::TickCounter timetable_start
At what tick of TimerGameTick::counter the vehicle should start its timetable.
TimerGameTick::Ticks lateness_counter
How many ticks late (or early if negative) this vehicle is.
uint16_t service_interval
The interval for (automatic) servicing; either in days or %.
ChunkHandler(ChunkId id, ChunkType type)
Create this ChunkHandler.
Definition saveload.h:470
void FixPointers() const override
Fix the pointers.
Definition order_sl.cpp:279
void Save() const override
Save the chunk.
Definition order_sl.cpp:255
void Load() const override
Load the chunk.
Definition order_sl.cpp:266
void Load() const override
Load the chunk.
Definition order_sl.cpp:165
Compatibility struct to allow saveload of pool-based orders.
Definition order_base.h:368
uint32_t next
The next order index (1-based).
Definition order_base.h:370
Data for backing up an order of a vehicle so it can be restored after a vehicle is rebuilt in the sam...
OrderBackup(OrderBackupID index)
Create an order backup for savegame loading.
const Vehicle * clone
Vehicle this vehicle was a clone of.
friend SaveLoadTable GetOrderBackupDescription()
Saving and loading of order backups.
Definition order_sl.cpp:297
TileIndex tile
Tile of the depot where the order was changed.
GroupID group
The group the vehicle was part of.
ClientID user
The user that requested the backup.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition order_base.h:384
friend SaveLoadTable GetOrderListDescription()
Saving and loading of order lists.
Definition order_sl.cpp:241
OrderList(OrderListID index)
Default constructor producing an invalid order list.
Definition order_base.h:406
If you change this, keep in mind that it is also saved in 2 other places:
Definition order_base.h:34
void ConvertFromOldSavegame()
Converts this order from an old savegame's version; it moves all bits to the new location.
Definition order_sl.cpp:27
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
void SetNonStopType(OrderNonStopFlags non_stop_type)
Set whether we must stop at stations or not.
Definition order_base.h:218
OrderType GetType() const
Get the type of order of this order.
Definition order_base.h:73
void SetDepotOrderType(OrderDepotTypeFlags depot_order_type)
Set the cause to go to the depot.
Definition order_base.h:230
void SetStopLocation(OrderStopLocation stop_location)
Set where we must stop at the platform.
Definition order_base.h:224
void MakeDummy()
Makes this order a Dummy order.
uint8_t flags
Load/unload types, depot order/action types.
Definition order_base.h:49
friend SaveLoadTable GetOrderDescription()
Saving and loading of orders.
Definition order_sl.cpp:145
void SetDepotActionType(OrderDepotActionFlags depot_service_type)
Set what we are going to do in the depot.
Definition order_base.h:236
void SetUnloadType(OrderUnloadType unload_type)
Set how the consist must be unloaded.
Definition order_base.h:212
void SetLoadType(OrderLoadType load_type)
Set how the consist must be loaded.
Definition order_base.h:206
static Pool::IterateWrapper< OrderList > Iterate(size_t from=0)
static T * CreateAtIndex(OrderListID index, Targs &&... args)
SaveLoad type struct.
Definition saveload.h:764
static SaveLoad StructList(std::string name, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a list of structs, optionally in some savegame versions.
Definition saveload.h:1103
static SaveLoad Variable(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion, size_t extra=0)
Storage of a variable in some savegame versions.
Definition saveload.h:926
static SaveLoad Reference(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a reference to a pool element in some savegame versions.
Definition saveload.h:951
static SaveLoad String(std::string name, AddressFunction< T > address_func, StringValidationSettings string_validation_settings={}, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion, size_t extra=0)
Storage of a string in some savegame versions.
Definition saveload.h:977
Base class for all vehicles.