OpenTTD Source 20260206-master-g4d4e37dbf1
cargopacket_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 "../vehicle_base.h"
16#include "../station_base.h"
17
18#include "../safeguards.h"
19
23/* static */ void CargoPacket::AfterLoad()
24{
26 /* If we remove a station while cargo from it is still en route, payment calculation will assume
27 * 0, 0 to be the source of the cargo, resulting in very high payments usually. v->source_xy
28 * stores the coordinates, preserving them even if the station is removed. However, if a game is loaded
29 * where this situation exists, the cargo-source information is lost. in this case, we set the source
30 * to the current tile of the vehicle to prevent excessive profits
31 */
32 for (const Vehicle *v : Vehicle::Iterate()) {
33 const CargoPacketList *packets = v->cargo.Packets();
34 for (VehicleCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
35 CargoPacket *cp = *it;
37 }
38 }
39
40 /* Store position of the station where the goods come from, so there
41 * are no very high payments when stations get removed. However, if the
42 * station where the goods came from is already removed, the source
43 * information is lost. In that case we set it to the position of this
44 * station */
45 for (Station *st : Station::Iterate()) {
46 for (GoodsEntry &ge : st->goods) {
47 if (!ge.HasData()) continue;
48 const StationCargoPacketMap *packets = ge.GetData().cargo.Packets();
49 for (StationCargoList::ConstIterator it(packets->begin()); it != packets->end(); it++) {
50 CargoPacket *cp = *it;
52 }
53 }
54 }
55 }
56
58 /* CargoPacket's source should be either StationID::Invalid() or a valid station */
59 for (CargoPacket *cp : CargoPacket::Iterate()) {
60 if (!Station::IsValidID(cp->first_station)) cp->first_station = StationID::Invalid();
61 }
62 }
63
65 /* Only since version 68 we have cargo packets. Savegames from before used
66 * 'new CargoPacket' + cargolist.Append so their caches are already
67 * correct and do not need rebuilding. */
68 for (Vehicle *v : Vehicle::Iterate()) v->cargo.InvalidateCache();
69
70 for (Station *st : Station::Iterate()) {
71 for (GoodsEntry &ge : st->goods) {
72 if (!ge.HasData()) continue;
74 }
75 }
76 }
77
79 for (Vehicle *v : Vehicle::Iterate()) v->cargo.KeepAll();
80 }
81
82 /* Before this version, we didn't track how far cargo actually traveled in vehicles. Make best-effort estimates of this. */
84 /* Update the cargo-traveled in stations as if they arrived from the source tile. */
85 for (Station *st : Station::Iterate()) {
86 for (GoodsEntry &ge : st->goods) {
87 if (!ge.HasData()) continue;
88 StationCargoList &cargo_list = ge.GetData().cargo;
89 for (auto it = cargo_list.Packets()->begin(); it != cargo_list.Packets()->end(); ++it) {
90 for (CargoPacket *cp : it->second) {
91 if (cp->source_xy != INVALID_TILE && cp->source_xy != st->xy) {
92 cp->travelled.x = TileX(cp->source_xy) - TileX(st->xy);
93 cp->travelled.y = TileY(cp->source_xy) - TileY(st->xy);
94 }
95 }
96 }
97 }
98 }
99
100 /* Update the cargo-traveled in vehicles as if they were loaded at the source tile. */
101 for (Vehicle *v : Vehicle::Iterate()) {
102 for (auto it = v->cargo.Packets()->begin(); it != v->cargo.Packets()->end(); it++) {
103 if ((*it)->source_xy != INVALID_TILE) {
104 (*it)->UpdateLoadingTile((*it)->source_xy);
105 }
106 }
107 }
108 }
109
110#ifdef WITH_ASSERT
111 /* in_vehicle is a NOSAVE; it tells if cargo is in a vehicle or not. Restore the value in here. */
112 for (Vehicle *v : Vehicle::Iterate()) {
113 for (auto it = v->cargo.Packets()->begin(); it != v->cargo.Packets()->end(); it++) {
114 (*it)->in_vehicle = true;
115 }
116 }
117#endif /* WITH_ASSERT */
118}
119
126{
127 static const SaveLoad _cargopacket_desc[] = {
128 SLE_VARNAME(CargoPacket, first_station, "source", SLE_UINT16),
129 SLE_VAR(CargoPacket, source_xy, SLE_UINT32),
130 SLE_CONDVARNAME(CargoPacket, next_hop, "loaded_at_xy", SLE_FILE_U32 | SLE_VAR_U16, SL_MIN_VERSION, SLV_REMOVE_LOADED_AT_XY),
132 SLE_VAR(CargoPacket, count, SLE_UINT16),
133 SLE_CONDVARNAME(CargoPacket, periods_in_transit, "days_in_transit", SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_MORE_CARGO_AGE),
136 SLE_VAR(CargoPacket, feeder_share, SLE_INT64),
137 SLE_CONDVARNAME(CargoPacket, source.type, "source_type", SLE_UINT8, SLV_125, SL_MAX_VERSION),
138 SLE_CONDVARNAME(CargoPacket, source.id, "source_id", SLE_UINT16, SLV_125, SL_MAX_VERSION),
141 };
142 return _cargopacket_desc;
143}
144
145struct CAPAChunkHandler : ChunkHandler {
146 CAPAChunkHandler() : ChunkHandler('CAPA', CH_TABLE) {}
147
148 void Save() const override
149 {
151
152 for (CargoPacket *cp : CargoPacket::Iterate()) {
153 SlSetArrayIndex(cp->index);
155 }
156 }
157
158 void Load() const override
159 {
160 const std::vector<SaveLoad> slt = SlCompatTableHeader(GetCargoPacketDesc(), _cargopacket_sl_compat);
161
162 int index;
163
164 while ((index = SlIterateArray()) != -1) {
166 SlObject(cp, slt);
167 }
168 }
169};
170
171static const CAPAChunkHandler CAPA;
172static const ChunkHandlerRef cargopacket_chunk_handlers[] = {
173 CAPA,
174};
175
176extern const ChunkHandlerTable _cargopacket_chunk_handlers(cargopacket_chunk_handlers);
PoolID< uint32_t, struct CargoPacketIDTag, 0xFFF000, 0xFFFFFF > CargoPacketID
Unique identifier for a single cargo packet.
Definition cargopacket.h:24
SaveLoadTable GetCargoPacketDesc()
Wrapper function to get the CargoPacket's internal structure while some of the variables itself are p...
Loading for cargopacket chunks before table headers were added.
const SaveLoadCompat _cargopacket_sl_compat[]
Original field order for _cargopacket_desc.
const Tcont * Packets() const
Returns a pointer to the cargo packet list (so you can iterate over it etc).
CargoPacketList::const_iterator ConstIterator
void InvalidateCache()
Invalidates the cached data and rebuilds it.
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:427
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:417
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:677
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_VARNAME(base, variable, name, type)
Storage of a variable in every version of a savegame.
Definition saveload.h:1047
std::reference_wrapper< const ChunkHandler > ChunkHandlerRef
A reference to ChunkHandler.
Definition saveload.h:526
std::span< const ChunkHandlerRef > ChunkHandlerTable
A table of ChunkHandler entries.
Definition saveload.h:529
#define SLE_CONDVAR(base, variable, type, from, to)
Storage of a variable in some savegame versions.
Definition saveload.h:904
bool IsSavegameVersionBefore(SaveLoadVersion major, uint8_t minor=0)
Checks whether the savegame is below major.
Definition saveload.h:1299
@ SLV_44
44 8144
Definition saveload.h:95
@ SLV_181
181 25012
Definition saveload.h:260
@ SLV_120
120 16439
Definition saveload.h:187
@ SLV_125
125 17113
Definition saveload.h:193
@ SL_MAX_VERSION
Highest possible saveload version.
Definition saveload.h:418
@ SL_MIN_VERSION
First savegame version.
Definition saveload.h:31
@ SLV_CARGO_TRAVELLED
319 PR#11283 CargoPacket now tracks how far it travelled inside a vehicle.
Definition saveload.h:362
@ SLV_68
68 10266
Definition saveload.h:124
@ SLV_PERIODS_IN_TRANSIT_RENAME
316 PR#11112 Rename days in transit to (cargo) periods in transit.
Definition saveload.h:359
@ SLV_MORE_CARGO_AGE
307 PR#10596 Track cargo age for a longer period.
Definition saveload.h:348
@ SLV_REMOVE_LOADED_AT_XY
318 PR#11276 Remove loaded_at_xy variable from CargoPacket.
Definition saveload.h:361
std::span< const struct SaveLoad > SaveLoadTable
A table of SaveLoad entries.
Definition saveload.h:532
#define SLE_VAR(base, variable, type)
Storage of a variable in every version of a savegame.
Definition saveload.h:1038
#define SLE_CONDVARNAME(base, variable, name, type, from, to)
Storage of a variable in some savegame versions.
Definition saveload.h:915
Base classes/functions for stations.
Definition of base types and functions in a cross-platform compatible way.
TileIndex xy
Base tile of the station.
void Load() const override
Load the chunk.
void Save() const override
Save the chunk.
Container for cargo from the same location and time.
Definition cargopacket.h:41
Money feeder_share
Value of feeder pickup to be paid for on delivery of cargo.
Definition cargopacket.h:52
TileIndex source_xy
The origin of the cargo.
Definition cargopacket.h:54
StationID next_hop
Station where the cargo wants to go next.
Definition cargopacket.h:64
Source source
Source of the cargo.
Definition cargopacket.h:57
CargoPacket(CargoPacketID index)
Create a new packet for savegame loading.
static void AfterLoad()
Savegame conversion for cargopackets.
uint16_t count
The amount of cargo in this packet.
Definition cargopacket.h:49
StationID first_station
The station where the cargo came from first.
Definition cargopacket.h:63
Vector travelled
If cargo is in station: the vector from the unload tile to the source tile. If in vehicle: an interme...
Definition cargopacket.h:55
uint16_t periods_in_transit
Amount of cargo aging periods this packet has been in transit.
Definition cargopacket.h:50
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Stores station stats for a single cargo.
const GoodsEntryData & GetData() const
Get optional cargo packet/flow data.
bool HasData() const
Test if this goods entry has optional cargo packet/flow data.
static Pool::IterateWrapper< Vehicle > Iterate(size_t from=0)
static T * CreateAtIndex(CargoPacketID index, Targs &&... args)
SaveLoad type struct.
Definition saveload.h:753
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
static Station * Get(auto index)
Station data structure.
Vehicle data structure.
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
Base class for all vehicles.