OpenTTD Source 20260917-master-gec444f7315
station_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 "../station_base.h"
16#include "../waypoint_base.h"
17#include "../roadstop_base.h"
18#include "../vehicle_base.h"
19#include "../newgrf_station.h"
20#include "../newgrf_roadstop.h"
21#include "../town.h"
23
24#include "table/strings.h"
25
26#include "../safeguards.h"
27
33{
34 if (!o.IsType(OT_GOTO_STATION)) return;
35
36 const Station *st = Station::Get(o.GetDestination().ToStationID());
37 if (!st->had_vehicle_of_type.Test(StationVehicleType::Waypoint)) return;
38
39 o.MakeGoToWaypoint(o.GetDestination().ToStationID());
40}
41
47{
48 /* Buoy orders become waypoint orders */
49 for (OrderList *ol : OrderList::Iterate()) {
50 VehicleType vt = ol->GetFirstSharedVehicle()->type;
51 if (vt != VehicleType::Ship && vt != VehicleType::Train) continue;
52
53 for (Order &o : ol->GetOrders()) UpdateWaypointOrder(o);
54 }
55
56 for (Vehicle *v : Vehicle::Iterate()) {
57 VehicleType vt = v->type;
58 if (vt != VehicleType::Ship && vt != VehicleType::Train) continue;
59
60 UpdateWaypointOrder(v->current_order);
61 }
62
63 /* Now make the stations waypoints */
64 for (Station *st : Station::Iterate()) {
65 if (!st->had_vehicle_of_type.Test(StationVehicleType::Waypoint)) continue;
66
67 StationID index = st->index;
68 TileIndex xy = st->xy;
69 Town *town = st->town;
70 StringID string_id = st->string_id;
71 std::string name = st->name;
72 TimerGameCalendar::Date build_date = st->build_date;
73 /* TTDPatch could use "buoys with rail station" for rail waypoints */
74 bool train = !st->train_station.IsEmpty();
75 TileArea train_st = st->train_station;
76
77 /* Delete the station, so we can make it a real waypoint. */
78 delete st;
79
80 /* Stations and waypoints are in the same pool, so if a station
81 * is deleted there must be place for a Waypoint. */
83 Waypoint *wp = Waypoint::CreateAtIndex(index, xy);
84 wp->town = town;
85 wp->string_id = train ? STR_SV_STNAME_WAYPOINT : STR_SV_STNAME_BUOY;
86 wp->name = std::move(name);
87 wp->delete_ctr = 0; // Just reset delete counter for once.
88 wp->build_date = build_date;
89 wp->owner = train ? GetTileOwner(xy) : OWNER_NONE;
90
91 if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = (string_id - STR_SV_STNAME_BUOY).base();
92
93 if (train) {
94 /* When we make a rail waypoint of the station, convert the map as well. */
95 for (TileIndex t : train_st) {
96 Tile tile(t);
97 if (!IsTileType(tile, TileType::Station) || GetStationIndex(tile) != index) continue;
98
100 wp->spread.Add(t);
101 }
102
103 wp->train_station = train_st;
105 } else if (IsBuoyTile(xy) && GetStationIndex(xy) == index) {
106 wp->spread.Add(xy);
108 }
109 }
110}
111
112void AfterLoadStations()
113{
114 /* Update the speclists of all stations to point to the currently loaded custom stations. */
115 for (BaseStation *st : BaseStation::Iterate()) {
116 for (auto &sm : GetStationSpecList<StationSpec>(st)) {
117 if (sm.grfid.Empty()) continue;
118 sm.spec = StationClass::GetByGrf(sm.grfid, sm.localidx);
119 }
120 for (auto &sm : GetStationSpecList<RoadStopSpec>(st)) {
121 if (sm.grfid.Empty()) continue;
122 sm.spec = RoadStopClass::GetByGrf(sm.grfid, sm.localidx);
123 }
124
125 if (Station::IsExpected(st)) {
126 Station *sta = Station::From(st);
127 for (const RoadStop *rs = sta->bus_stops; rs != nullptr; rs = rs->next) sta->bus_station.Add(rs->xy);
128 for (const RoadStop *rs = sta->truck_stops; rs != nullptr; rs = rs->next) sta->truck_station.Add(rs->xy);
129 }
130
133 }
134
135 /* Station blocked, wires and pylon flags need to be stored in the map. This is effectively cached data, so no
136 * version check is necessary. */
137 for (const auto t : Map::Iterate()) {
138 if (HasStationTileRail(t)) SetRailStationTileFlags(t, GetStationSpec(t));
139 }
140}
141
146{
147 /* First construct the drive through entries */
148 for (RoadStop *rs : RoadStop::Iterate()) {
149 if (IsDriveThroughStopTile(rs->xy)) rs->MakeDriveThrough();
150 }
151 /* And then rebuild the data in those entries */
152 for (RoadStop *rs : RoadStop::Iterate()) {
153 if (!rs->status.Test(RoadStop::RoadStopStatusFlag::BaseEntry)) continue;
154
155 rs->GetEntry(DiagDirection::NE).Rebuild(rs);
156 rs->GetEntry(DiagDirection::NW).Rebuild(rs);
157 }
158}
159
160static const SaveLoad _roadstop_desc[] = {
164};
165
166static uint16_t _waiting_acceptance;
167static uint32_t _old_num_flows;
168static uint16_t _cargo_source;
169static uint32_t _cargo_source_xy;
170static uint8_t _cargo_periods;
171static Money _cargo_feeder_share;
172
173std::list<CargoPacket *> _packets;
174uint32_t _old_num_dests;
175
177 StationID source;
178 StationID via;
179 uint32_t share;
180 bool restricted;
181};
182
183typedef std::pair<const StationID, std::list<CargoPacket *> > StationCargoPair;
184
185static OldPersistentStorage _old_st_persistent_storage;
186
192static void SwapPackets(GoodsEntry *ge)
193{
194 StationCargoPacketMap &ge_packets = const_cast<StationCargoPacketMap &>(*ge->GetOrCreateData().cargo.Packets());
195
196 if (_packets.empty()) {
197 std::map<StationID, std::list<CargoPacket *> >::iterator it(ge_packets.find(StationID::Invalid()));
198 if (it == ge_packets.end()) {
199 return;
200 } else {
201 it->second.swap(_packets);
202 }
203 } else {
204 assert(ge_packets[StationID::Invalid()].empty());
205 ge_packets[StationID::Invalid()].swap(_packets);
206 }
207}
208
209template <typename T>
210class SlStationSpecList : public VectorSaveLoadHandler<SlStationSpecList<T>, BaseStation, SpecMapping<T>> {
211public:
212 static inline const SaveLoad description[] = {
216 };
217 static inline const SaveLoadCompatTable compat_description = _station_spec_list_sl_compat;
218
219 static inline uint8_t last_num_specs;
220
221 std::vector<SpecMapping<T>> &GetVector(BaseStation *bst) const override { return GetStationSpecList<T>(bst); }
222
227};
228
229/* Instantiate SlStationSpecList classes. */
230template class SlStationSpecList<StationSpec>;
232
234public:
235 using StationWaitingTriggersPair = std::pair<const TileIndex, StationRandomTriggers>;
236
237 static inline const SaveLoad description[] = {
238 SaveLoad::Variable<VarFileType::U32>("first", SLE_OBJECT_ADDRESS(StationWaitingTriggersPair, first)),
239 SaveLoad::Variable<VarFileType::U8>("second", SLE_OBJECT_ADDRESS(StationWaitingTriggersPair, second)),
240 };
241 static inline const SaveLoadCompatTable compat_description = _station_cargo_sl_compat;
242
243 void Save(BaseStation *st) const override
244 {
245 SlSetStructListLength(st->tile_waiting_random_triggers.size());
246 for (const auto &pair : st->tile_waiting_random_triggers) {
247 SlObject(const_cast<StationWaitingTriggersPair *>(&pair), this->GetDescription());
248 }
249 }
250
251 void Load(BaseStation *st) const override
252 {
253 size_t num = SlGetStructListLength(UINT32_MAX);
254 if (num == 0) return;
255
256 StationWaitingTriggersPair pair;
257 for (uint j = 0; j < num; ++j) {
258 SlObject(&pair, this->GetLoadDescription());
259 st->tile_waiting_random_triggers.emplace(pair.first, pair.second);
260 }
261 }
262};
263
265public:
266 static inline const SaveLoad description[] = {
267 SaveLoad::Variable<VarFileType::U16>("first", SLE_OBJECT_ADDRESS(StationCargoPair, first)),
268 SaveLoad::ReferenceList<SLRefType::CargoPacket>("second", SLE_OBJECT_ADDRESS(StationCargoPair, second)),
269 };
270 static inline const SaveLoadCompatTable compat_description = _station_cargo_sl_compat;
271
272 void Save(GoodsEntry *ge) const override
273 {
274 if (!ge->HasData()) {
276 return;
277 }
278
279 const auto *packets = ge->GetData().cargo.Packets();
280 SlSetStructListLength(packets->MapSize());
281 for (StationCargoPacketMap::ConstMapIterator it(packets->begin()); it != packets->end(); ++it) {
282 SlObject(const_cast<StationCargoPacketMap::value_type *>(&(*it)), this->GetDescription());
283 }
284 }
285
286 void Load(GoodsEntry *ge) const override
287 {
288 size_t num_dests = IsSavegameVersionBefore(SaveLoadVersion::SaveloadListLength) ? _old_num_dests : SlGetStructListLength(UINT32_MAX);
289 if (num_dests == 0) return;
290
292 StationCargoPair pair;
293 for (uint j = 0; j < num_dests; ++j) {
294 SlObject(&pair, this->GetLoadDescription());
295 const_cast<StationCargoPacketMap &>(*(data.cargo.Packets()))[pair.first].swap(pair.second);
296 assert(pair.second.empty());
297 }
298 }
299
300 void FixPointers(GoodsEntry *ge) const override
301 {
302 if (!ge->HasData()) return;
303
304 for (StationCargoPacketMap::ConstMapIterator it = ge->GetData().cargo.Packets()->begin(); it != ge->GetData().cargo.Packets()->end(); ++it) {
305 SlObject(const_cast<StationCargoPair *>(&(*it)), this->GetDescription());
306 }
307 }
308};
309
311public:
312 static inline const SaveLoad description[] = {
317 };
318 static inline const SaveLoadCompatTable compat_description = _station_flow_sl_compat;
319
320 void Save(GoodsEntry *ge) const override
321 {
322 if (!ge->HasData()) {
324 return;
325 }
326
327 size_t num_flows = 0;
328 for (const auto &it : ge->GetData().flows) {
329 num_flows += it.second.GetShares()->size();
330 }
331 SlSetStructListLength(num_flows);
332
333 for (const auto &outer_it : ge->GetData().flows) {
334 const FlowStat::SharesMap *shares = outer_it.second.GetShares();
335 uint32_t sum_shares = 0;
336 FlowSaveLoad flow{};
337 flow.source = outer_it.first;
338 for (auto &inner_it : *shares) {
339 flow.via = inner_it.second;
340 flow.share = inner_it.first - sum_shares;
341 flow.restricted = inner_it.first > outer_it.second.GetUnrestricted();
342 sum_shares = inner_it.first;
343 assert(flow.share > 0);
344 SlObject(&flow, this->GetDescription());
345 }
346 }
347 }
348
349 void Load(GoodsEntry *ge) const override
350 {
351 size_t num_flows = IsSavegameVersionBefore(SaveLoadVersion::SaveloadListLength) ? _old_num_flows : SlGetStructListLength(UINT32_MAX);
352 if (num_flows == 0) return;
353
355 FlowSaveLoad flow{};
356 FlowStat *fs = nullptr;
357 StationID prev_source = StationID::Invalid();
358 for (uint32_t j = 0; j < num_flows; ++j) {
359 SlObject(&flow, this->GetLoadDescription());
360 if (fs == nullptr || prev_source != flow.source) {
361 fs = &(data.flows.emplace(flow.source, FlowStat(flow.via, flow.share, flow.restricted))).first->second;
362 } else {
363 fs->AppendShare(flow.via, flow.share, flow.restricted);
364 }
365 prev_source = flow.source;
366 }
367 }
368};
369
371public:
372 static inline uint cargo_reserved_count;
373
374 static inline const SaveLoad description[] = {
377 SaveLoad::Variable<VarFileType::U8>("time_since_pickup", SLE_OBJECT_ADDRESS(GoodsEntry, time_since_pickup)),
390 SaveLoad::Variable<VarFileType::U32>("cargo.reserved_count", SLE_GLOBAL_ADDRESS(SlStationGoods::cargo_reserved_count), SaveLoadVersion::CargoReservation),
397 };
398
399 static inline const SaveLoadCompatTable compat_description = _station_goods_sl_compat;
400
405 size_t GetNumCargo() const
406 {
410 /* Read from the savegame how long the list is. */
412 }
413
414 void Save(BaseStation *bst) const override
415 {
416 Station *st = Station::From(bst);
417
419
420 for (GoodsEntry &ge : st->goods) {
421 SlStationGoods::cargo_reserved_count = ge.HasData() ? ge.GetData().cargo.reserved_count : 0;
422 SlObject(&ge, this->GetDescription());
423 }
424 }
425
426 void Load(BaseStation *bst) const override
427 {
428 Station *st = Station::From(bst);
429
430 /* Before savegame version 161, persistent storages were not stored in a pool. */
432 /* Store the old persistent storage. The GRFID will be added later. */
435 std::copy(std::begin(_old_st_persistent_storage.storage), std::end(_old_st_persistent_storage.storage), std::begin(st->airport.psa->storage));
436 }
437
438 auto end = std::next(std::begin(st->goods), std::min(this->GetNumCargo(), std::size(st->goods)));
439 for (auto it = std::begin(st->goods); it != end; ++it) {
440 GoodsEntry &ge = *it;
441 SlObject(&ge, this->GetLoadDescription());
442 if (!IsSavegameVersionBefore(SaveLoadVersion::CargoReservation) && SlStationGoods::cargo_reserved_count != 0) {
443 ge.GetOrCreateData().cargo.reserved_count = SlStationGoods::cargo_reserved_count;
444 }
446 SwapPackets(&ge);
447 }
449 ge.status.Set(GoodsEntry::State::Acceptance, HasBit(_waiting_acceptance, 15));
450 if (GB(_waiting_acceptance, 0, 12) != 0) {
451 /* In old versions, enroute_from used 0xFF as StationID::Invalid() */
452 StationID source = (IsSavegameVersionBefore(SaveLoadVersion::LargerCargoSource) && _cargo_source == 0xFF) ? StationID::Invalid() : static_cast<StationID>(_cargo_source);
453
454 /* Make sure we can allocate the CargoPacket. This is safe
455 * as there can only be ~64k stations and 32 cargoes in these
456 * savegame versions. As the CargoPacketPool has more than
457 * 16 million entries; it fits by an order of magnitude. */
459
460 /* Don't construct the packet with station here, because that'll fail with old savegames */
461 CargoPacket *cp = CargoPacket::Create(GB(_waiting_acceptance, 0, 12), _cargo_periods, source, TileIndex{_cargo_source_xy}, _cargo_feeder_share);
462 ge.GetOrCreateData().cargo.Append(cp, StationID::Invalid());
464 }
465 }
466 }
467 }
468
469 void FixPointers(BaseStation *bst) const override
470 {
471 Station *st = Station::From(bst);
472
474 auto end = std::next(std::begin(st->goods), std::min(num_cargo, std::size(st->goods)));
475 for (auto it = std::begin(st->goods); it != end; ++it) {
476 GoodsEntry &ge = *it;
478 SwapPackets(&ge); // We have to swap back again to be in the format pre-183 expects.
479 SlObject(&ge, this->GetDescription());
480 SwapPackets(&ge);
481 } else {
482 SlObject(&ge, this->GetDescription());
483 }
484 }
485 }
486};
487
488static const SaveLoad _old_station_desc[] = {
496 SaveLoad::Variable<VarFileType::U8>("train_station.w", SLE_OBJECT_ADDRESS(Station, train_station.w)),
498
504
505 SaveLoad::Variable<VarFileType::U8>("time_since_load", SLE_OBJECT_ADDRESS(Station, time_since_load)),
506 SaveLoad::Variable<VarFileType::U8>("time_since_unload", SLE_OBJECT_ADDRESS(Station, time_since_unload)),
510 SaveLoad::Variable<VarFileType::U8>("airport.type", SLE_OBJECT_ADDRESS(Station, airport.type)),
514
516
519
522
523 /* Used by newstations for graphic variations */
527
529
532};
533
534struct STNSChunkHandler : ChunkHandler {
535 STNSChunkHandler() : ChunkHandler("STNS", ChunkType::ReadOnly) {}
536
537 void Load() const override
538 {
539 const std::vector<SaveLoad> slt = SlCompatTableHeader(_old_station_desc, _old_station_sl_compat);
540
541 _cargo_source_xy = 0;
542 _cargo_periods = 0;
543 _cargo_feeder_share = 0;
544
545 int index;
546 while ((index = SlIterateArray()) != -1) {
547 Station *st = Station::CreateAtIndex(StationID(index));
548
549 _waiting_acceptance = 0;
550 SlObject(st, slt);
551 }
552 }
553
554 void FixPointers() const override
555 {
556 /* From SaveLoadVersion::UnifyWaypointAndStation we store stations in STNN; before that in STNS. So do not
557 * fix pointers when the version is SaveLoadVersion::UnifyWaypointAndStation or up, as that would fix
558 * pointers twice: once in STNN chunk and once here. */
560
561 for (Station *st : Station::Iterate()) {
562 SlObject(st, _old_station_desc);
563 }
564 }
565};
566
568public:
569 static inline const SaveLoad description[] = {
572 SaveLoad::Variable<VarFileType::U8>("animation_frame", SLE_OBJECT_ADDRESS(RoadStopTileData, animation_frame)),
573 };
574 static inline const SaveLoadCompatTable compat_description = {};
575
576 std::vector<RoadStopTileData> &GetVector(BaseStation *bst) const override { return bst->custom_roadstop_tile_data; }
577};
578
584public:
585 static inline const SaveLoad description[] = {
594
595 /* Used by newstations for graphic variations */
597 SaveLoad::Variable<VarFileType::U8>("waiting_triggers", SLE_OBJECT_ADDRESS(BaseStation, waiting_random_triggers)),
598 SaveLoad::StructList<SlStationWaitingTriggers>("tile_waiting_triggers"),
600 };
601 static inline const SaveLoadCompatTable compat_description = _station_base_sl_compat;
602
603 void Save(BaseStation *bst) const override
604 {
605 SlObject(bst, this->GetDescription());
606 }
607
608 void Load(BaseStation *bst) const override
609 {
610 SlObject(bst, this->GetLoadDescription());
611 }
612
613 void FixPointers(BaseStation *bst) const override
614 {
615 SlObject(bst, this->GetDescription());
616 }
617};
618
623public:
624 static inline const SaveLoad description[] = {
626 SaveLoad::Variable<VarFileType::U32>("train_station.tile", SLE_OBJECT_ADDRESS(Station, train_station.tile)),
627 SaveLoad::Variable<VarFileType::U8>("train_station.w", SLE_OBJECT_ADDRESS(Station, train_station.w)),
628 SaveLoad::Variable<VarFileType::U8>("train_station.h", SLE_OBJECT_ADDRESS(Station, train_station.h)),
629
641 SaveLoad::Variable<VarFileType::U8>("airport.type", SLE_OBJECT_ADDRESS(Station, airport.type)),
643 SaveLoad::Variable<VarFileType::U64>("airport.flags", SLE_OBJECT_ADDRESS(Station, airport.blocks)),
647
649
650 SaveLoad::Variable<VarFileType::U8>("time_since_load", SLE_OBJECT_ADDRESS(Station, time_since_load)),
651 SaveLoad::Variable<VarFileType::U8>("time_since_unload", SLE_OBJECT_ADDRESS(Station, time_since_unload)),
652 SaveLoad::Variable<VarFileType::U8>("last_vehicle_type", SLE_OBJECT_ADDRESS(Station, last_vehicle_type)),
653 SaveLoad::Variable<VarFileType::U8>("had_vehicle_of_type", SLE_OBJECT_ADDRESS(Station, had_vehicle_of_type)),
654 SaveLoad::ReferenceList<SLRefType::Vehicle>("loading_vehicles", SLE_OBJECT_ADDRESS(Station, loading_vehicles)),
659 };
660 static inline const SaveLoadCompatTable compat_description = _station_normal_sl_compat;
661
662 void Save(BaseStation *bst) const override
663 {
664 if (bst->facilities.Test(StationFacility::Waypoint)) return;
665 SlObject(bst, this->GetDescription());
666 }
667
668 void Load(BaseStation *bst) const override
669 {
670 if (bst->facilities.Test(StationFacility::Waypoint)) return;
671 SlObject(bst, this->GetLoadDescription());
672 }
673
674 void FixPointers(BaseStation *bst) const override
675 {
676 if (bst->facilities.Test(StationFacility::Waypoint)) return;
677 SlObject(bst, this->GetDescription());
678 }
679};
680
682public:
683 static inline const SaveLoad description[] = {
686
691 SaveLoad::Variable<VarFileType::U32>("road_waypoint_area.tile", SLE_OBJECT_ADDRESS(Waypoint, road_waypoint_area.tile), SaveLoadVersion::RoadWaypoints),
694 };
695 static inline const SaveLoadCompatTable compat_description = _station_waypoint_sl_compat;
696
697 void Save(BaseStation *bst) const override
698 {
699 if (!bst->facilities.Test(StationFacility::Waypoint)) return;
700 SlObject(bst, this->GetDescription());
701 }
702
703 void Load(BaseStation *bst) const override
704 {
705 if (!bst->facilities.Test(StationFacility::Waypoint)) return;
706 SlObject(bst, this->GetLoadDescription());
707 }
708
709 void FixPointers(BaseStation *bst) const override
710 {
711 if (!bst->facilities.Test(StationFacility::Waypoint)) return;
712 SlObject(bst, this->GetDescription());
713 }
714};
715
716static const SaveLoad _station_desc[] = {
717 SaveLoad::SaveByte("facilities", SLE_OBJECT_ADDRESS(BaseStation, facilities)),
723};
724
725struct STNNChunkHandler : ChunkHandler {
726 STNNChunkHandler() : ChunkHandler("STNN", ChunkType::Table) {}
727
728 void Save() const override
729 {
730 SlTableHeader(_station_desc);
731
732 /* Write the stations */
733 for (BaseStation *st : BaseStation::Iterate()) {
734 SlSetArrayIndex(st->index);
735 SlObject(st, _station_desc);
736 }
737 }
738
739
740 void Load() const override
741 {
742 const std::vector<SaveLoad> slt = SlCompatTableHeader(_station_desc, _station_sl_compat);
743
744 _old_num_flows = 0;
745
746 int index;
747 while ((index = SlIterateArray()) != -1) {
748 bool waypoint = static_cast<StationFacilities>(SlReadByte()).Test(StationFacility::Waypoint);
749
750 BaseStation *bst = waypoint ? (BaseStation *)Waypoint::CreateAtIndex(StationID(index)) : Station::CreateAtIndex(StationID(index));
751 SlObject(bst, slt);
752 }
753 }
754
755 void FixPointers() const override
756 {
757 /* From SaveLoadVersion::UnifyWaypointAndStation we store stations in STNN; before that in STNS. So do not
758 * fix pointers when the version is below SaveLoadVersion::UnifyWaypointAndStation, as that would fix
759 * pointers twice: once in STNS chunk and once here. */
761
762 for (BaseStation *bst : BaseStation::Iterate()) {
763 SlObject(bst, _station_desc);
764 }
765 }
766};
767
768struct ROADChunkHandler : ChunkHandler {
769 ROADChunkHandler() : ChunkHandler("ROAD", ChunkType::Table) {}
770
771 void Save() const override
772 {
773 SlTableHeader(_roadstop_desc);
774
775 for (RoadStop *rs : RoadStop::Iterate()) {
776 SlSetArrayIndex(rs->index);
777 SlObject(rs, _roadstop_desc);
778 }
779 }
780
781 void Load() const override
782 {
783 const std::vector<SaveLoad> slt = SlCompatTableHeader(_roadstop_desc, _roadstop_sl_compat);
784
785 int index;
786
787 while ((index = SlIterateArray()) != -1) {
788 RoadStop *rs = RoadStop::CreateAtIndex(RoadStopID(index), INVALID_TILE);
789
790 SlObject(rs, slt);
791 }
792 }
793
794 void FixPointers() const override
795 {
796 for (RoadStop *rs : RoadStop::Iterate()) {
797 SlObject(rs, _roadstop_desc);
798 }
799 }
800};
801
802static const STNSChunkHandler STNS;
803static const STNNChunkHandler STNN;
804static const ROADChunkHandler ROAD;
805static const ChunkHandlerRef station_chunk_handlers[] = {
806 STNS,
807 STNN,
808 ROAD,
809};
810
811extern const ChunkHandlerTable _station_chunk_handlers(station_chunk_handlers);
std::vector< SpecMapping< T > > & GetStationSpecList(BaseStation *bst)
Get spec mapping list for each supported custom spec type.
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
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 bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
static constexpr CargoType NUM_CARGO
Maximum number of cargo types in a game.
Definition cargo_type.h:75
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
const Tcont * Packets() const
Returns a pointer to the cargo packet list (so you can iterate over it etc).
Default handler for saving/loading an object to/from disk.
Definition saveload.h:586
Flow statistics telling how much flow should be sent along a link.
void AppendShare(StationID st, uint flow, bool restricted=false)
Add some flow to the end of the shares map.
static const StationSpec * GetByGrf(GrfID grfid, uint16_t local_id)
SaveLoadTable GetLoadDescription() const
Get the description for how to load the chunk.
std::vector< RoadStopTileData > & GetVector(BaseStation *bst) const override
Get instance of vector to load/save.
SaveLoad handler for the BaseStation, which all other stations / waypoints make use of.
void Save(BaseStation *bst) const override
Save the object to disk.
void Load(BaseStation *bst) const override
Load the object from disk.
void FixPointers(BaseStation *bst) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Save(GoodsEntry *ge) const override
Save the object to disk.
void FixPointers(GoodsEntry *ge) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Load(GoodsEntry *ge) const override
Load the object from disk.
void Load(GoodsEntry *ge) const override
Load the object from disk.
void Save(GoodsEntry *ge) const override
Save the object to disk.
size_t GetNumCargo() const
Get the number of cargoes used by this savegame version.
void FixPointers(BaseStation *bst) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Load(BaseStation *bst) const override
Load the object from disk.
void Save(BaseStation *bst) const override
Save the object to disk.
SaveLoad handler for a normal station (read: not a waypoint).
void FixPointers(BaseStation *bst) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Load(BaseStation *bst) const override
Load the object from disk.
void Save(BaseStation *bst) const override
Save the object to disk.
size_t GetLength() const override
Get number of elements to load into vector.
static uint8_t last_num_specs
Number of specs of the last loaded station.
std::vector< SpecMapping< T > > & GetVector(BaseStation *bst) const override
Get instance of vector to load/save.
void Load(BaseStation *st) const override
Load the object from disk.
void Save(BaseStation *st) const override
Save the object to disk.
void Save(BaseStation *bst) const override
Save the object to disk.
void FixPointers(BaseStation *bst) const override
A post-load callback to fix SaveLoadType::Reference integers into pointers.
void Load(BaseStation *bst) const override
Load the object from disk.
void Append(CargoPacket *cp, StationID next)
Appends the given cargo packet to the range of packets with the same next station.
uint reserved_count
Amount of cargo being reserved for loading.
Wrapper class to abstract away the way the tiles are stored.
Definition map_func.h:25
uint8_t & m6()
General purpose.
Definition map_func.h:167
StrongType::Typedef< int32_t, DateTag< struct Calendar >, StrongType::Compare, StrongType::Integer > Date
Default handler for saving/loading a vector to/from disk.
Definition saveload.h:1341
static constexpr Owner OWNER_NONE
The tile has no ownership.
@ NW
Northwest.
@ NE
Northeast, upper right on your monitor.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
@ Invalid
An invalid spec feature.
Definition newgrf.h:110
void RoadStopUpdateCachedTriggers(BaseStation *st)
Update the cached animation trigger bitmask for a station.
NewGRF definitions and structures for road stops.
void StationUpdateCachedTriggers(BaseStation *st)
Update the cached animation trigger bitmask for a station.
Header file for NewGRF stations.
Label< struct GrfIDTag > GrfID
The unique identifier of a NewGRF.
Definition newgrf_type.h:17
Base class for roadstops.
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.
size_t SlGetStructListLength(size_t limit)
Get the length of this list; if it exceeds the limit, error out.
int SlIterateArray()
Iterate through the elements of an array and read the whole thing.
Definition saveload.cpp:745
uint8_t SlReadByte()
Wrapper for reading a byte from the buffer.
Definition saveload.cpp:410
void SlObject(void *object, const SaveLoadTable &slt)
Main SaveLoad function.
std::vector< SaveLoad > SlTableHeader(const SaveLoadTable &slt)
Save or Load a table header.
void SlSetStructListLength(size_t length)
Set the length of this list.
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
#define SLE_GLOBAL_ADDRESS(variable)
Macro to be able to pass the variable type and construct the SaveLoad::AddressFunction given a global...
Definition saveload.h:761
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
@ BigDates
Saveload version: 31, SVN revision: 5999 Change date from 1920 - 2090 to 0 - 5 000 000.
Definition saveload.h:87
@ ExtendCargotypes
Saveload version: 199, GitHub pull request: 6802 Extend cargotypes to 64.
Definition saveload.h:288
@ UnifyWaypointAndStation
Saveload version: 123, SVN revision: 16909 Unify stations and waypoints.
Definition saveload.h:197
@ UnifyCurrency
Saveload version: 65, SVN revision: 10210 Make all variables related to currency 64 bits.
Definition saveload.h:128
@ LinkgraphRestrictedFlow
Saveload version: 187, SVN revision: 25899 Linkgraph - restricted flows.
Definition saveload.h:274
@ CargoReservation
Saveload version: 181, SVN revision: 25012 Persist the reservation of cargo for vehicles instead of ...
Definition saveload.h:267
@ FifoLoading
Saveload version: 57, SVN revision: 9691 First-in-first-out loading of vehicles.
Definition saveload.h:118
@ RoadWaypoints
Saveload version: 338, GitHub pull request: 12572 Road waypoints.
Definition saveload.h:391
@ ReplaceCustomNameArray
Saveload version: 84, SVN revision: 11822 Replace single fixed size array of custom names,...
Definition saveload.h:150
@ LastVehicleType
Saveload version: 26, SVN revision: 4466 Store the last vehicle type at stations instead of the vehi...
Definition saveload.h:81
@ NewGRFSuppliedStationName
Saveload version: 103, SVN revision: 14598 NewGRF industry supplying default names for nearby statio...
Definition saveload.h:173
@ VehicleCurrencyStationChanges
Saveload version: 2.0, release: 0.3.0 Adding vehicle state, larger currency size for statistics,...
Definition saveload.h:40
@ MultitileDocks
Saveload version: 216, GitHub pull request: 7380 Multiple docks per station.
Definition saveload.h:309
@ LargerCargoSource
Saveload version: 7.0, SVN revision: 1770 With more stations, the size of the cargo source needed to...
Definition saveload.h:55
@ TownAcceptance
Saveload version: 127, SVN revision: 17439 Store mask of cargos accepted by town houses and head qua...
Definition saveload.h:202
@ TransferOrder
Saveload version: 14.0, SVN revision: 2441 Transfer orders for feeder systems.
Definition saveload.h:64
@ FractionalCargoDelivery
Saveload version: 150, SVN revision: 20857 When spreading cargo over stations, spread fractional amo...
Definition saveload.h:230
@ NewGRFRoadStops
Saveload version: 303, GitHub pull request: 10144 NewGRF road stops.
Definition saveload.h:349
@ CargoSourceTile
Saveload version: 44, SVN revision: 8144 Store the source tile of the cargo, so accurate payment can...
Definition saveload.h:102
@ StoreAirportSize
Saveload version: 140, SVN revision: 19382 Store the size of the airport in the station.
Definition saveload.h:218
@ ExtendEntityMapping
Saveload version: 311, GitHub pull request: 10672 Extend entity mapping range.
Definition saveload.h:359
@ MultipleRoadStops
Saveload version: 6.0, SVN revision: 1721 Multi tile road stops, and some map size related fixes.
Definition saveload.h:53
@ RoadStopTileData
Saveload version: 340, GitHub pull request: 12883 Move storage of road stop tile data,...
Definition saveload.h:394
@ Cargodist
Saveload version: 183, SVN revision: 25363 Cargodist.
Definition saveload.h:269
@ MoreAirportBlocks
Saveload version: 46, SVN revision: 8705 Increase number of blocks an airport can have.
Definition saveload.h:105
@ MinVersion
First savegame version.
Definition saveload.h:37
@ WaypointMoreLikeStation
Saveload version: 122, SVN revision: 16855 Make waypoint data look more like stations.
Definition saveload.h:196
@ BiggerStationVariables
Saveload version: 3.0 Increase size of airport blocks/station build date.
Definition saveload.h:43
@ NewGRFAirportSmoke
Saveload version: 145, SVN revision: 20376 NewGRF support for airport and configurable amount of smo...
Definition saveload.h:224
@ SaveloadListLength
Saveload version: 293, GitHub pull request: 9374 Consistency in list length with SaveLoadType::Struc...
Definition saveload.h:337
@ MultiTileWaypoints
Saveload version: 124, SVN revision: 16993 Waypoints can be bigger than a single tile.
Definition saveload.h:198
@ NewGRFCargo
Saveload version: 55, SVN revision: 9638 Increase number of cargos and NewGRF control of cargos.
Definition saveload.h:116
@ CargoPackets
Saveload version: 68, SVN revision: 10266 Account for individual units of cargo, i....
Definition saveload.h:131
@ NewGRFStations
Saveload version: 27, SVN revision: 4757 NewGRF graphics for stations.
Definition saveload.h:82
@ PersistentStoragePool
Saveload version: 161, SVN revision: 22567 Store persistent storage in a pool.
Definition saveload.h:243
@ ReadOnly
Chunk is never saved.
Definition saveload.h:454
@ Table
An Array with a header describing the elements.
Definition saveload.h:450
Base classes/functions for stations.
void SetRailStationTileFlags(TileIndex tile, const StationSpec *statspec)
Set rail station tile flags for the given tile.
bool IsDriveThroughStopTile(Tile t)
Is tile t a drive through road stop station or waypoint?
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition station_map.h:28
bool HasStationTileRail(Tile t)
Has this station tile a rail?
bool IsBuoyTile(Tile t)
Is tile t a buoy tile?
void MoveBuoysToWaypoints()
Perform all steps to upgrade from the old station buoys to the new version that uses waypoints.
static void UpdateWaypointOrder(Order &o)
Update the buoy orders to be waypoint orders.
void AfterLoadRoadStops()
(Re)building of road stop caches after loading a savegame.
static void SwapPackets(GoodsEntry *ge)
Swap the temporary packets with the packets without specific destination in the given goods entry.
Loading of station chunks before table headers were added.
const SaveLoadCompat _station_base_sl_compat[]
Original field order for SlStationBase.
const SaveLoadCompat _roadstop_sl_compat[]
Original field order for _roadstop_desc.
const SaveLoadCompat _station_sl_compat[]
Original field order for _station_desc.
const SaveLoadCompat _station_cargo_sl_compat[]
Original field order for SlStationCargo.
const SaveLoadCompat _station_goods_sl_compat[]
Original field order for SlStationGoods.
const SaveLoadCompat _station_flow_sl_compat[]
Original field order for SlStationFlow.
const SaveLoadCompat _station_waypoint_sl_compat[]
Original field order for SlStationWaypoint.
const SaveLoadCompat _station_normal_sl_compat[]
Original field order for SlStationNormal.
const SaveLoadCompat _old_station_sl_compat[]
Original field order for _old_station_desc.
const SaveLoadCompat _station_spec_list_sl_compat[]
Original field order for SlStationSpecList.
@ Dock
Station with a dock.
@ Waypoint
Station is a waypoint.
@ Train
Station with train station.
@ Airport
Station with an airport.
@ RailWaypoint
Waypoint for trains.
EnumBitSet< StationFacility, uint8_t > StationFacilities
Bitset of StationFacility elements.
@ Waypoint
Station is a waypoint (Save load conversion and NewGRF only!).
Definition of base types and functions in a cross-platform compatible way.
@ AllowControlCode
Allow the special control codes.
Definition string_type.h:47
StrongType::Typedef< uint32_t, struct StringIDTag, StrongType::Compare, StrongType::Integer > StringID
Numeric value that represents a string, independent of the selected language.
PersistentStorage * psa
Persistent storage for NewGRF airports.
Base class for all station-ish types.
StringID string_id
Default name (town area) of station.
StationFacilities facilities
The facilities that this station has.
TileArea train_station
Tile area the train 'station' part covers.
Owner owner
The owner of this station.
uint8_t delete_ctr
Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is ...
Town * town
The town this station is associated with.
std::vector< RoadStopTileData > custom_roadstop_tile_data
List of custom road stop tile data.
TimerGameCalendar::Date build_date
Date of construction.
std::string name
Custom name.
TileArea spread
NOSAVE: Station spread tile area.
Container for cargo from the same location and time.
Definition cargopacket.h:41
ChunkHandler(ChunkId id, ChunkType type)
Create this ChunkHandler.
Definition saveload.h:470
FlowStatMap flows
Planned flows through this station.
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Stores station stats for a single cargo.
States status
Status of this cargo, see State.
@ Acceptance
Set when the station accepts the cargo currently for final deliveries.
@ Rating
This indicates whether a cargo has a rating at the station.
const GoodsEntryData & GetData() const
Get optional cargo packet/flow data.
bool HasData() const
Test if this goods entry has optional cargo packet/flow data.
GoodsEntryData & GetOrCreateData()
Get optional cargo packet/flow data.
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:366
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition order_base.h:384
If you change this, keep in mind that it is also saved in 2 other places:
Definition order_base.h:34
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:100
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
void MakeGoToWaypoint(StationID destination)
Makes this order a Go To Waypoint order.
Definition order_cmd.cpp:88
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition tilearea.cpp:43
StorageType storage
Memory for the storage array.
static Pool::IterateWrapper< OrderList > Iterate(size_t from=0)
static T * CreateAtIndex(RoadStopID index, Targs &&... args)
void FixPointers() const override
Fix the pointers.
void Load() const override
Load the chunk.
void Save() const override
Save the chunk.
A Stop for a Road Vehicle.
@ BaseEntry
Non-zero when the entries on this road stop are the primary, i.e. the ones to delete.
RoadStop * next
Next stop of the given type at this station.
void FixPointers() const override
Fix the pointers.
void Save() const override
Save the chunk.
void Load() const override
Load the chunk.
void Load() const override
Load the chunk.
void FixPointers() const override
Fix the pointers.
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 SaveByte(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a byte variable in some savegame versions that is not automatically read by the SaveLoad c...
Definition saveload.h:1125
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 ReferenceList(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a list of references to pool elements in some savegame versions.
Definition saveload.h:1078
static SaveLoad Array(std::string name, AddressFunction< T > address_func, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion, size_t extra=0)
Storage of an array in some savegame versions.
Definition saveload.h:1026
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 Struct(std::string name, SaveLoadVersion from=SaveLoadVersion::MinVersion, SaveLoadVersion to=SaveLoadVersion::MaxVersion)
Storage of a structs, optionally in some savegame versions.
Definition saveload.h:1001
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
static bool IsExpected(const BaseStation *st)
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
static Waypoint * CreateAtIndex(StationID index, Targs &&... args)
static Station * Get(auto index)
static Station * From(BaseStation *st)
Station data structure.
RoadStop * bus_stops
All the road stops.
std::array< GoodsEntry, NUM_CARGO > goods
Goods at this station.
TileArea bus_station
Tile area the bus 'station' part covers.
Airport airport
Tile area the airport covers.
TileArea truck_station
Tile area the truck 'station' part covers.
RoadStop * truck_stops
All the truck stops.
Town data structure.
Definition town.h:64
Vehicle data structure.
Representation of a waypoint.
uint16_t town_cn
The N-1th waypoint for this town (consecutive number).
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
@ Station
A tile of a station or airport.
Definition tile_type.h:54
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition of the game-calendar-timer.
Base of the town class.
Base class for all vehicles.
VehicleType
Available vehicle types.
@ Ship
Ship vehicle type.
@ Train
Train vehicle type.
Base of waypoints.