OpenTTD Source 20260108-master-g8ba1860eaa
cargopacket.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
10#include "stdafx.h"
11#include "station_base.h"
12#include "core/pool_func.hpp"
13#include "core/random_func.hpp"
14#include "economy_base.h"
15#include "cargoaction.h"
16#include "order_type.h"
17
18#include "safeguards.h"
19
20/* Initialize the cargopacket-pool */
21CargoPacketPool _cargopacket_pool("CargoPacket");
23
24
28CargoPacket::CargoPacket(CargoPacketID index) : CargoPacketPool::PoolItem<&_cargopacket_pool>(index)
29{
30}
31
41CargoPacket::CargoPacket(CargoPacketID index, StationID first_station,uint16_t count, Source source) :
42 CargoPacketPool::PoolItem<&_cargopacket_pool>(index),
43 count(count),
44 source(source),
45 first_station(first_station)
46{
47 assert(count != 0);
48}
49
60CargoPacket::CargoPacket(CargoPacketID index, uint16_t count, uint16_t periods_in_transit, StationID first_station, TileIndex source_xy, Money feeder_share) :
61 CargoPacketPool::PoolItem<&_cargopacket_pool>(index),
62 count(count),
63 periods_in_transit(periods_in_transit),
64 feeder_share(feeder_share),
65 source_xy(source_xy),
66 first_station(first_station)
67{
68 assert(count != 0);
69}
70
79CargoPacket::CargoPacket(CargoPacketID index, uint16_t count, Money feeder_share, CargoPacket &original) :
80 CargoPacketPool::PoolItem<&_cargopacket_pool>(index),
81 count(count),
82 periods_in_transit(original.periods_in_transit),
83 feeder_share(feeder_share),
84 source_xy(original.source_xy),
85 travelled(original.travelled),
86 source(original.source),
87#ifdef WITH_ASSERT
88 in_vehicle(original.in_vehicle),
89#endif /* WITH_ASSERT */
90 first_station(original.first_station),
91 next_hop(original.next_hop)
92{
93 assert(count != 0);
94}
95
102{
103 if (!CargoPacket::CanAllocateItem()) return nullptr;
104
105 Money fs = this->GetFeederShare(new_size);
106 CargoPacket *cp_new = CargoPacket::Create(new_size, fs, *this);
107 this->feeder_share -= fs;
108 this->count -= new_size;
109 return cp_new;
110}
111
117{
118 this->count += cp->count;
119 this->feeder_share += cp->feeder_share;
120 delete cp;
121}
122
127void CargoPacket::Reduce(uint count)
128{
129 assert(count < this->count);
130 this->feeder_share -= this->GetFeederShare(count);
131 this->count -= count;
132}
133
140{
141 for (CargoPacket *cp : CargoPacket::Iterate()) {
142 if (cp->source == src) cp->source.MakeInvalid();
143 }
144}
145
151{
152 for (CargoPacket *cp : CargoPacket::Iterate()) {
153 if (cp->first_station == sid) cp->first_station = StationID::Invalid();
154 }
155}
156
157/*
158 *
159 * Cargo list implementation
160 *
161 */
162
166template <class Tinst, class Tcont>
168{
169 for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
170 delete *it;
171 }
172}
173
178template <class Tinst, class Tcont>
180{
181 this->packets.clear();
182}
183
190template <class Tinst, class Tcont>
192{
193 assert(count <= cp->count);
194 this->count -= count;
195 this->cargo_periods_in_transit -= static_cast<uint64_t>(cp->periods_in_transit) * count;
196}
197
203template <class Tinst, class Tcont>
205{
206 this->count += cp->count;
207 this->cargo_periods_in_transit += static_cast<uint64_t>(cp->periods_in_transit) * cp->count;
208}
209
211template <class Tinst, class Tcont>
213{
214 this->count = 0;
215 this->cargo_periods_in_transit = 0;
216
217 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
218 static_cast<Tinst *>(this)->AddToCache(*it);
219 }
220}
221
229template <class Tinst, class Tcont>
231{
232 if (Tinst::AreMergable(icp, cp) &&
233 icp->count + cp->count <= CargoPacket::MAX_COUNT) {
234 icp->Merge(cp);
235 return true;
236 } else {
237 return false;
238 }
239}
240
241/*
242 *
243 * Vehicle cargo list implementation.
244 *
245 */
246
262void VehicleCargoList::Append(CargoPacket *cp, MoveToAction action)
263{
264 assert(cp != nullptr);
265 assert(action == MTA_LOAD ||
266 (action == MTA_KEEP && this->action_counts[MTA_LOAD] == 0));
267 this->AddToMeta(cp, action);
268
269 if (this->count == cp->count) {
270 this->packets.push_back(cp);
271 return;
272 }
273
274 uint sum = cp->count;
275 for (ReverseIterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
276 CargoPacket *icp = *it;
277 if (VehicleCargoList::TryMerge(icp, cp)) return;
278 sum += icp->count;
279 if (sum >= this->action_counts[action]) {
280 this->packets.push_back(cp);
281 return;
282 }
283 }
284
285 NOT_REACHED();
286}
287
296template <class Taction>
298{
299 Iterator it(this->packets.begin());
300 while (it != this->packets.end() && action.MaxMove() > 0) {
301 CargoPacket *cp = *it;
302 if (action(cp)) {
303 it = this->packets.erase(it);
304 } else {
305 break;
307 }
308}
309
318template <class Taction>
319void VehicleCargoList::PopCargo(Taction action)
320{
321 if (this->packets.empty()) return;
322 Iterator it(--(this->packets.end()));
323 Iterator begin(this->packets.begin());
324 while (action.MaxMove() > 0) {
325 CargoPacket *cp = *it;
326 if (action(cp)) {
327 if (it != begin) {
328 this->packets.erase(it--);
329 } else {
330 this->packets.erase(it);
331 break;
332 }
333 } else {
334 break;
335 }
336 }
337}
338
346{
347 this->feeder_share -= cp->GetFeederShare(count);
349}
350
357{
358 this->feeder_share += cp->feeder_share;
359 this->Parent::AddToCache(cp);
360}
361
368void VehicleCargoList::RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count)
369{
370 assert(count <= this->action_counts[action]);
372 this->RemoveFromCache(cp, count);
373 this->action_counts[action] -= count;
375}
376
382void VehicleCargoList::AddToMeta(const CargoPacket *cp, MoveToAction action)
383{
385 this->AddToCache(cp);
386 this->action_counts[action] += cp->count;
388}
389
394{
395 for (const auto &cp : this->packets) {
396 /* If we're at the maximum, then we can't increase no more. */
397 if (cp->periods_in_transit == UINT16_MAX) continue;
398
399 cp->periods_in_transit++;
400 this->cargo_periods_in_transit += cp->count;
401 }
402}
403
414 StationID current_station, bool accepted, std::span<const StationID> next_station)
415{
416 if (cargo_next == StationID::Invalid()) {
417 return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
418 } else if (cargo_next == current_station) {
419 return MTA_DELIVER;
420 } else if (std::ranges::find(next_station, cargo_next) != std::end(next_station)) {
421 return MTA_KEEP;
422 } else {
423 return MTA_TRANSFER;
424 }
425}
426
442bool VehicleCargoList::Stage(bool accepted, StationID current_station, std::span<const StationID> next_station, OrderUnloadType unload_type, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
443{
445 assert(this->action_counts[MTA_LOAD] == 0);
447 Iterator deliver = this->packets.end();
448 Iterator it = this->packets.begin();
449 uint sum = 0;
450
451 static const FlowStatMap EMPTY_FLOW_STAT_MAP = {};
452 const FlowStatMap &flows = ge->HasData() ? ge->GetData().flows : EMPTY_FLOW_STAT_MAP;
453
454 bool force_keep = unload_type == OrderUnloadType::NoUnload;
455 bool force_unload = unload_type == OrderUnloadType::Unload;
456 bool force_transfer = unload_type == OrderUnloadType::Transfer || unload_type == OrderUnloadType::Unload;
457 assert(this->count > 0 || it == this->packets.end());
458 while (sum < this->count) {
459 CargoPacket *cp = *it;
460
461 this->packets.erase(it++);
462 StationID cargo_next = StationID::Invalid();
463 MoveToAction action = MTA_LOAD;
464 if (force_keep) {
465 action = MTA_KEEP;
466 } else if (force_unload && accepted && cp->first_station != current_station) {
467 action = MTA_DELIVER;
468 } else if (force_transfer) {
469 action = MTA_TRANSFER;
470 /* We cannot send the cargo to any of the possible next hops and
471 * also not to the current station. */
472 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
473 if (flow_it == flows.end()) {
474 cargo_next = StationID::Invalid();
475 } else {
476 FlowStat new_shares = flow_it->second;
477 new_shares.ChangeShare(current_station, INT_MIN);
478 for (auto station_it = next_station.rbegin(); station_it != next_station.rend(); ++station_it) {
479 if (new_shares.GetShares()->empty()) break;
480 new_shares.ChangeShare(*station_it, INT_MIN);
481 }
482 if (new_shares.GetShares()->empty()) {
483 cargo_next = StationID::Invalid();
484 } else {
485 cargo_next = new_shares.GetVia();
486 }
487 }
488 } else {
489 /* Rewrite an invalid source station to some random other one to
490 * avoid keeping the cargo in the vehicle forever. */
491 if (cp->first_station == StationID::Invalid() && !flows.empty()) {
492 cp->first_station = flows.begin()->first;
493 }
494 bool restricted = false;
495 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
496 if (flow_it == flows.end()) {
497 cargo_next = StationID::Invalid();
498 } else {
499 cargo_next = flow_it->second.GetViaWithRestricted(restricted);
500 }
501 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
502 if (restricted && action == MTA_TRANSFER) {
503 /* If the flow is restricted we can't transfer to it. Choose an
504 * unrestricted one instead. */
505 cargo_next = flow_it->second.GetVia();
506 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
507 }
508 }
509 Money share;
510 switch (action) {
511 case MTA_KEEP:
512 this->packets.push_back(cp);
513 if (deliver == this->packets.end()) --deliver;
514 break;
515 case MTA_DELIVER:
516 this->packets.insert(deliver, cp);
517 break;
518 case MTA_TRANSFER:
519 this->packets.push_front(cp);
520 /* Add feeder share here to allow reusing field for next station. */
521 share = payment->PayTransfer(cargo, cp, cp->count, current_tile);
522 cp->AddFeederShare(share);
523 this->feeder_share += share;
524 cp->next_hop = cargo_next;
525 break;
526 default:
527 NOT_REACHED();
528 }
529 this->action_counts[action] += cp->count;
530 sum += cp->count;
531 }
533 return this->action_counts[MTA_DELIVER] > 0 || this->action_counts[MTA_TRANSFER] > 0;
534}
535
538{
539 this->feeder_share = 0;
541}
542
555template <VehicleCargoList::MoveToAction Tfrom, VehicleCargoList::MoveToAction Tto>
556uint VehicleCargoList::Reassign(uint max_move)
557{
558 static_assert(Tfrom != MTA_TRANSFER && Tto != MTA_TRANSFER);
559 static_assert(Tfrom - Tto == 1 || Tto - Tfrom == 1);
560 max_move = std::min(this->action_counts[Tfrom], max_move);
561 this->action_counts[Tfrom] -= max_move;
562 this->action_counts[Tto] += max_move;
563 return max_move;
564}
565
572template <>
573uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(uint max_move)
574{
575 max_move = std::min(this->action_counts[MTA_DELIVER], max_move);
576
577 uint sum = 0;
578 for (Iterator it(this->packets.begin()); sum < this->action_counts[MTA_TRANSFER] + max_move;) {
579 CargoPacket *cp = *it++;
580 sum += cp->Count();
581 if (sum <= this->action_counts[MTA_TRANSFER]) continue;
582 if (sum > this->action_counts[MTA_TRANSFER] + max_move) {
583 CargoPacket *cp_split = cp->Split(sum - this->action_counts[MTA_TRANSFER] + max_move);
584 sum -= cp_split->Count();
585 this->packets.insert(it, cp_split);
586 }
587 cp->next_hop = StationID::Invalid();
588 }
589
590 this->action_counts[MTA_DELIVER] -= max_move;
591 this->action_counts[MTA_TRANSFER] += max_move;
592 return max_move;
593}
594
603uint VehicleCargoList::Return(uint max_move, StationCargoList *dest, StationID next, TileIndex current_tile)
604{
605 max_move = std::min(this->action_counts[MTA_LOAD], max_move);
606 this->PopCargo(CargoReturn(this, dest, max_move, next, current_tile));
607 return max_move;
608}
609
617{
618 max_move = std::min(this->count, max_move);
619 this->PopCargo(CargoShift(this, dest, max_move));
620 return max_move;
621}
622
633uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
634{
635 uint moved = 0;
636 if (this->action_counts[MTA_TRANSFER] > 0) {
637 uint move = std::min(this->action_counts[MTA_TRANSFER], max_move);
638 this->ShiftCargo(CargoTransfer(this, dest, move, current_tile));
639 moved += move;
640 }
641 if (this->action_counts[MTA_TRANSFER] == 0 && this->action_counts[MTA_DELIVER] > 0 && moved < max_move) {
642 uint move = std::min(this->action_counts[MTA_DELIVER], max_move - moved);
643 this->ShiftCargo(CargoDelivery(this, move, cargo, payment, current_tile));
644 moved += move;
645 }
646 return moved;
647}
648
655uint VehicleCargoList::Truncate(uint max_move)
656{
657 max_move = std::min(this->count, max_move);
658 this->PopCargo(CargoRemoval<VehicleCargoList>(this, max_move));
659 return max_move;
660}
661
670uint VehicleCargoList::Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
671{
672 max_move = std::min(this->action_counts[MTA_TRANSFER], max_move);
673 this->ShiftCargo(VehicleCargoReroute(this, dest, max_move, avoid, avoid2, ge));
674 return max_move;
675}
676
677/*
678 *
679 * Station cargo list implementation.
680 *
681 */
682
692{
693 assert(cp != nullptr);
694 this->AddToCache(cp);
695
696 StationCargoPacketMap::List &list = this->packets[next];
697 for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
698 it != list.rend(); it++) {
699 if (StationCargoList::TryMerge(*it, cp)) return;
700 }
701
702 /* The packet could not be merged with another one */
703 list.push_back(cp);
704}
705
718template <class Taction>
719bool StationCargoList::ShiftCargo(Taction &action, StationID next)
720{
721 std::pair<Iterator, Iterator> range(this->packets.equal_range(next));
722 for (Iterator it(range.first); it != range.second && it.GetKey() == next;) {
723 if (action.MaxMove() == 0) return false;
724 CargoPacket *cp = *it;
725 if (action(cp)) {
726 it = this->packets.erase(it);
727 } else {
728 return false;
729 }
730 }
731 return true;
732}
733
748template <class Taction>
749uint StationCargoList::ShiftCargo(Taction action, std::span<const StationID> next, bool include_invalid)
750{
751 uint max_move = action.MaxMove();
752 for (auto it = next.rbegin(); it != next.rend(); ++it) {
753 this->ShiftCargo(action, *it);
754 if (action.MaxMove() == 0) break;
755 }
756 if (include_invalid && action.MaxMove() > 0) {
757 this->ShiftCargo(action, StationID::Invalid());
758 }
759 return max_move - action.MaxMove();
760}
761
770uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_source)
771{
772 max_move = std::min(max_move, this->count);
773 uint prev_count = this->count;
774 uint moved = 0;
775 uint loop = 0;
776 bool do_count = cargo_per_source != nullptr;
777 while (max_move > moved) {
778 for (Iterator it(this->packets.begin()); it != this->packets.end();) {
779 CargoPacket *cp = *it;
780 if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
781 if (do_count && loop == 0) {
782 (*cargo_per_source)[cp->first_station] += cp->count;
783 }
784 ++it;
785 continue;
786 }
787 uint diff = max_move - moved;
788 if (cp->count > diff) {
789 if (diff > 0) {
790 this->RemoveFromCache(cp, diff);
791 cp->Reduce(diff);
792 moved += diff;
793 }
794 if (loop > 0) {
795 if (do_count) (*cargo_per_source)[cp->first_station] -= diff;
796 return moved;
797 } else {
798 if (do_count) (*cargo_per_source)[cp->first_station] += cp->count;
799 ++it;
800 }
801 } else {
802 it = this->packets.erase(it);
803 if (do_count && loop > 0) {
804 (*cargo_per_source)[cp->first_station] -= cp->count;
805 }
806 moved += cp->count;
807 this->RemoveFromCache(cp, cp->count);
808 delete cp;
809 }
810 }
811 loop++;
812 }
813 return moved;
814}
815
824uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, std::span<const StationID> next_station, TileIndex current_tile)
825{
826 return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true);
827}
828
841uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, std::span<const StationID> next_station, TileIndex current_tile)
842{
843 uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
844 if (move > 0) {
845 this->reserved_count -= move;
847 return move;
848 } else {
849 return this->ShiftCargo(CargoLoad{this, dest, max_move, current_tile}, next_station, true);
850 }
851}
852
861uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
862{
863 return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), {&avoid, 1}, false);
864}
865
866/*
867 * We have to instantiate everything we want to be usable.
868 */
871template uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_KEEP>(uint);
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:21
Actions to be applied to cargo packets.
Action of final delivery of cargo.
Definition cargoaction.h:39
Simple collection class for a list of cargo packets.
Tcont::reverse_iterator ReverseIterator
The reverse iterator for our container.
void OnCleanPool()
Empty the cargo list, but don't free the cargo packets; the cargo packets are cleaned by CargoPacket'...
CargoPacketList packets
The cargo packets in this list.
~CargoList()
Destroy the cargolist ("frees" all cargo packets).
Tcont::const_iterator ConstIterator
The const iterator for our container.
uint count
Cache for the number of cargo entities.
uint64_t cargo_periods_in_transit
Cache for the sum of number of cargo aging periods in transit of each entity; comparable to man-hours...
static bool TryMerge(CargoPacket *cp, CargoPacket *icp)
Tries to merge the second packet into the first and return if that was successful.
Tcont::iterator Iterator
The iterator for our container.
MoveToAction
Kind of actions that could be done with packets on move.
@ MTA_KEEP
Keep the cargo in the vehicle.
@ MTA_DELIVER
Deliver the cargo to some town or industry.
@ MTA_LOAD
Load the cargo from the station.
@ MTA_TRANSFER
Transfer the cargo to the station.
void AddToCache(const CargoPacket *cp)
Update the cache to reflect adding of this packet.
void InvalidateCache()
Invalidates the cached data and rebuilds it.
void RemoveFromCache(const CargoPacket *cp, uint count)
Update the cached values to reflect the removal of this packet or part of it.
Action of loading cargo from a station onto a vehicle.
Definition cargoaction.h:83
Abstract action of removing cargo from a vehicle or a station.
Definition cargoaction.h:20
Action of reserving cargo from a station to be loaded onto a vehicle.
Definition cargoaction.h:93
Action of returning previously reserved cargo from the vehicle to the station.
Action of shifting cargo from one vehicle to another.
Action of transferring cargo from a vehicle to a station.
Definition cargoaction.h:73
Flow descriptions by origin stations.
Flow statistics telling how much flow should be sent along a link.
StationID GetVia() const
Get a station a package can be routed to.
const SharesMap * GetShares() const
Get the actual shares as a const pointer so that they can be iterated over.
void ChangeShare(StationID st, int flow)
Change share for specified station.
iterator erase(iterator it)
Erase the value pointed to by an iterator.
Definition multimap.hpp:243
std::pair< iterator, iterator > equal_range(const Tkey &key)
Get a pair of iterators specifying a range of items with equal keys.
Definition multimap.hpp:301
CargoList that is used for stations.
uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
Routes packets with station "avoid" as next hop to a different place.
uint Load(uint max_move, VehicleCargoList *dest, std::span< const StationID > next, TileIndex current_tile)
Loads cargo onto a vehicle.
void Append(CargoPacket *cp, StationID next)
Appends the given cargo packet to the range of packets with the same next station.
uint Truncate(uint max_move=UINT_MAX, StationCargoAmountMap *cargo_per_source=nullptr)
Truncates where each destination loses roughly the same percentage of its cargo.
bool ShiftCargo(Taction &action, StationID next)
Shifts cargo from the front of the packet list for a specific station and applies some action to it.
uint reserved_count
Amount of cargo being reserved for loading.
uint Reserve(uint max_move, VehicleCargoList *dest, std::span< const StationID > next, TileIndex current_tile)
Reserves cargo for loading onto the vehicle.
Action of rerouting cargo in a station.
CargoList that is used for vehicles.
uint Shift(uint max_move, VehicleCargoList *dest)
Shifts cargo between two vehicles.
void AddToMeta(const CargoPacket *cp, MoveToAction action)
Adds a packet to the metadata.
void PopCargo(Taction action)
Pops cargo from the back of the packet list and applies some action to it.
uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
Routes packets with station "avoid" as next hop to a different place.
uint ActionCount(MoveToAction action) const
Returns the amount of cargo designated for a given purpose.
static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next, StationID current_station, bool accepted, std::span< const StationID > next_station)
Choose action to be performed with the given cargo packet.
uint Truncate(uint max_move=UINT_MAX)
Truncates the cargo in this list to the given amount.
void AssertCountConsistency() const
Assert that the designation counts add up.
void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count)
Removes a packet or part of it from the metadata.
uint Return(uint max_move, StationCargoList *dest, StationID next_station, TileIndex current_tile)
Returns reserved cargo to the station and removes it from the cache.
uint action_counts[NUM_MOVE_TO_ACTION]
Counts of cargo to be transferred, delivered, kept and loaded.
Money feeder_share
Cache for the feeder share.
void Append(CargoPacket *cp, MoveToAction action=MTA_KEEP)
Appends the given cargo packet.
void RemoveFromCache(const CargoPacket *cp, uint count)
Update the cached values to reflect the removal of this packet or part of it.
uint Reassign(uint max_move)
Moves some cargo from one designation to another.
void InvalidateCache()
Invalidates the cached data and rebuild it.
void AddToCache(const CargoPacket *cp)
Update the cache to reflect adding of this packet.
void AgeCargo()
Ages the all cargo in this list.
uint Unload(uint max_move, StationCargoList *dest, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
Unloads cargo at the given station.
bool Stage(bool accepted, StationID current_station, std::span< const StationID > next_station, OrderUnloadType unload_type, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
Stages cargo for unloading.
void ShiftCargo(Taction action)
Shifts cargo from the front of the packet list and applies some action to it.
Action of rerouting cargo staged for transfer in a vehicle.
Base classes related to the economy.
Types related to orders.
OrderUnloadType
Unloading order types.
Definition order_type.h:67
@ Transfer
Transfer all cargo onto the platform.
@ NoUnload
Totally no unloading will be done.
@ Unload
Force unloading all cargo onto the platform, possibly not getting paid.
Some methods of Pool are placed here in order to reduce compilation time and binary size.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
A number of safeguards to prevent using unsafe methods.
Base classes/functions for stations.
Definition of base types and functions in a cross-platform compatible way.
Container for cargo from the same location and time.
Definition cargopacket.h:41
void Reduce(uint count)
Reduce the packet by the given amount and remove the feeder share.
uint16_t Count() const
Gets the number of 'items' in this packet.
void Merge(CargoPacket *cp)
Merge another packet into this one.
Money feeder_share
Value of feeder pickup to be paid for on delivery of cargo.
Definition cargopacket.h:52
static const uint16_t MAX_COUNT
Maximum number of items in a single cargo packet.
Definition cargopacket.h:74
CargoPacket * Split(uint new_size)
Split this packet in two and return the split off part.
StationID next_hop
Station where the cargo wants to go next.
Definition cargopacket.h:64
void AddFeederShare(Money new_share)
Adds some feeder share to the packet.
CargoPacket(CargoPacketID index)
Create a new packet for savegame loading.
uint16_t count
The amount of cargo in this packet.
Definition cargopacket.h:49
Money GetFeederShare() const
Gets the amount of money already paid to earlier vehicles in the feeder chain.
StationID first_station
The station where the cargo came from first.
Definition cargopacket.h:63
static void InvalidateAllFrom(Source src)
Invalidates (sets source_id to INVALID_SOURCE) all cargo packets from given source.
uint16_t periods_in_transit
Amount of cargo aging periods this packet has been in transit.
Definition cargopacket.h:50
Helper class to perform the cargo payment.
Money PayTransfer(CargoType cargo, const CargoPacket *cp, uint count, TileIndex current_tile)
Handle payment for transfer of the given cargo packet.
Definition economy.cpp:1228
FlowStatMap flows
Planned flows through 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.
Templated helper to make a PoolID a single POD value.
Definition pool_type.hpp:47
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static T * Create(Targs &&... args)
Creates a new T-object in the associated pool.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Base class for all pools.
A location from where cargo can come from (or go to).
Definition source_type.h:32