OpenTTD Source 20250312-master-gcdcc6b491d
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 <http://www.gnu.org/licenses/>.
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
30
39CargoPacket::CargoPacket(StationID first_station,uint16_t count, Source source) :
40 count(count),
41 source(source),
42 first_station(first_station)
43{
44 assert(count != 0);
45}
46
56CargoPacket::CargoPacket(uint16_t count, uint16_t periods_in_transit, StationID first_station, TileIndex source_xy, Money feeder_share) :
57 count(count),
58 periods_in_transit(periods_in_transit),
59 feeder_share(feeder_share),
60 source_xy(source_xy),
61 first_station(first_station)
62{
63 assert(count != 0);
64}
65
73CargoPacket::CargoPacket(uint16_t count, Money feeder_share, CargoPacket &original) :
74 count(count),
75 periods_in_transit(original.periods_in_transit),
76 feeder_share(feeder_share),
77 source_xy(original.source_xy),
78 travelled(original.travelled),
79 source(original.source),
80#ifdef WITH_ASSERT
81 in_vehicle(original.in_vehicle),
82#endif /* WITH_ASSERT */
83 first_station(original.first_station),
84 next_hop(original.next_hop)
85{
86 assert(count != 0);
87}
88
95{
96 if (!CargoPacket::CanAllocateItem()) return nullptr;
97
98 Money fs = this->GetFeederShare(new_size);
99 CargoPacket *cp_new = new CargoPacket(new_size, fs, *this);
100 this->feeder_share -= fs;
101 this->count -= new_size;
102 return cp_new;
103}
104
110{
111 this->count += cp->count;
112 this->feeder_share += cp->feeder_share;
113 delete cp;
114}
115
120void CargoPacket::Reduce(uint count)
121{
122 assert(count < this->count);
123 this->feeder_share -= this->GetFeederShare(count);
124 this->count -= count;
125}
126
133{
134 for (CargoPacket *cp : CargoPacket::Iterate()) {
135 if (cp->source == src) cp->source.MakeInvalid();
136 }
137}
138
144{
145 for (CargoPacket *cp : CargoPacket::Iterate()) {
146 if (cp->first_station == sid) cp->first_station = StationID::Invalid();
147 }
148}
149
150/*
151 *
152 * Cargo list implementation
153 *
154 */
155
159template <class Tinst, class Tcont>
161{
162 for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
163 delete *it;
164 }
165}
166
171template <class Tinst, class Tcont>
173{
174 this->packets.clear();
175}
176
183template <class Tinst, class Tcont>
185{
186 assert(count <= cp->count);
187 this->count -= count;
188 this->cargo_periods_in_transit -= static_cast<uint64_t>(cp->periods_in_transit) * count;
189}
190
196template <class Tinst, class Tcont>
198{
199 this->count += cp->count;
200 this->cargo_periods_in_transit += static_cast<uint64_t>(cp->periods_in_transit) * cp->count;
201}
202
204template <class Tinst, class Tcont>
206{
207 this->count = 0;
208 this->cargo_periods_in_transit = 0;
209
210 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
211 static_cast<Tinst *>(this)->AddToCache(*it);
212 }
213}
214
222template <class Tinst, class Tcont>
224{
225 if (Tinst::AreMergable(icp, cp) &&
226 icp->count + cp->count <= CargoPacket::MAX_COUNT) {
227 icp->Merge(cp);
228 return true;
229 } else {
230 return false;
231 }
232}
233
234/*
235 *
236 * Vehicle cargo list implementation.
237 *
238 */
239
255void VehicleCargoList::Append(CargoPacket *cp, MoveToAction action)
256{
257 assert(cp != nullptr);
258 assert(action == MTA_LOAD ||
259 (action == MTA_KEEP && this->action_counts[MTA_LOAD] == 0));
260 this->AddToMeta(cp, action);
261
262 if (this->count == cp->count) {
263 this->packets.push_back(cp);
264 return;
265 }
266
267 uint sum = cp->count;
268 for (ReverseIterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
269 CargoPacket *icp = *it;
270 if (VehicleCargoList::TryMerge(icp, cp)) return;
271 sum += icp->count;
272 if (sum >= this->action_counts[action]) {
273 this->packets.push_back(cp);
274 return;
275 }
276 }
277
278 NOT_REACHED();
279}
280
289template <class Taction>
291{
292 Iterator it(this->packets.begin());
293 while (it != this->packets.end() && action.MaxMove() > 0) {
294 CargoPacket *cp = *it;
295 if (action(cp)) {
296 it = this->packets.erase(it);
297 } else {
298 break;
299 }
300 }
301}
311template <class Taction>
312void VehicleCargoList::PopCargo(Taction action)
313{
314 if (this->packets.empty()) return;
315 Iterator it(--(this->packets.end()));
316 Iterator begin(this->packets.begin());
317 while (action.MaxMove() > 0) {
318 CargoPacket *cp = *it;
319 if (action(cp)) {
320 if (it != begin) {
321 this->packets.erase(it--);
322 } else {
323 this->packets.erase(it);
324 break;
325 }
326 } else {
327 break;
328 }
329 }
330}
331
339{
340 this->feeder_share -= cp->GetFeederShare(count);
342}
343
350{
351 this->feeder_share += cp->feeder_share;
352 this->Parent::AddToCache(cp);
353}
354
361void VehicleCargoList::RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count)
362{
363 assert(count <= this->action_counts[action]);
365 this->RemoveFromCache(cp, count);
366 this->action_counts[action] -= count;
368}
369
375void VehicleCargoList::AddToMeta(const CargoPacket *cp, MoveToAction action)
376{
378 this->AddToCache(cp);
379 this->action_counts[action] += cp->count;
381}
382
387{
388 for (const auto &cp : this->packets) {
389 /* If we're at the maximum, then we can't increase no more. */
390 if (cp->periods_in_transit == UINT16_MAX) continue;
391
392 cp->periods_in_transit++;
393 this->cargo_periods_in_transit += cp->count;
394 }
395}
396
407 StationID current_station, bool accepted, StationIDStack next_station)
408{
409 if (cargo_next == StationID::Invalid()) {
410 return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
411 } else if (cargo_next == current_station) {
412 return MTA_DELIVER;
413 } else if (next_station.Contains(cargo_next.base())) {
414 return MTA_KEEP;
415 } else {
416 return MTA_TRANSFER;
417 }
418}
419
435bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
436{
438 assert(this->action_counts[MTA_LOAD] == 0);
440 Iterator deliver = this->packets.end();
441 Iterator it = this->packets.begin();
442 uint sum = 0;
443
444 static const FlowStatMap EMPTY_FLOW_STAT_MAP = {};
445 const FlowStatMap &flows = ge->HasData() ? ge->GetData().flows : EMPTY_FLOW_STAT_MAP;
446
447 bool force_keep = (order_flags & OUFB_NO_UNLOAD) != 0;
448 bool force_unload = (order_flags & OUFB_UNLOAD) != 0;
449 bool force_transfer = (order_flags & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0;
450 assert(this->count > 0 || it == this->packets.end());
451 while (sum < this->count) {
452 CargoPacket *cp = *it;
453
454 this->packets.erase(it++);
455 StationID cargo_next = StationID::Invalid();
456 MoveToAction action = MTA_LOAD;
457 if (force_keep) {
458 action = MTA_KEEP;
459 } else if (force_unload && accepted && cp->first_station != current_station) {
460 action = MTA_DELIVER;
461 } else if (force_transfer) {
462 action = MTA_TRANSFER;
463 /* We cannot send the cargo to any of the possible next hops and
464 * also not to the current station. */
465 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
466 if (flow_it == flows.end()) {
467 cargo_next = StationID::Invalid();
468 } else {
469 FlowStat new_shares = flow_it->second;
470 new_shares.ChangeShare(current_station, INT_MIN);
471 StationIDStack excluded = next_station;
472 while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
473 new_shares.ChangeShare(StationID{excluded.Pop()}, INT_MIN);
474 }
475 if (new_shares.GetShares()->empty()) {
476 cargo_next = StationID::Invalid();
477 } else {
478 cargo_next = new_shares.GetVia();
479 }
480 }
481 } else {
482 /* Rewrite an invalid source station to some random other one to
483 * avoid keeping the cargo in the vehicle forever. */
484 if (cp->first_station == StationID::Invalid() && !flows.empty()) {
485 cp->first_station = flows.begin()->first;
486 }
487 bool restricted = false;
488 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
489 if (flow_it == flows.end()) {
490 cargo_next = StationID::Invalid();
491 } else {
492 cargo_next = flow_it->second.GetViaWithRestricted(restricted);
493 }
494 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
495 if (restricted && action == MTA_TRANSFER) {
496 /* If the flow is restricted we can't transfer to it. Choose an
497 * unrestricted one instead. */
498 cargo_next = flow_it->second.GetVia();
499 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
500 }
501 }
502 Money share;
503 switch (action) {
504 case MTA_KEEP:
505 this->packets.push_back(cp);
506 if (deliver == this->packets.end()) --deliver;
507 break;
508 case MTA_DELIVER:
509 this->packets.insert(deliver, cp);
510 break;
511 case MTA_TRANSFER:
512 this->packets.push_front(cp);
513 /* Add feeder share here to allow reusing field for next station. */
514 share = payment->PayTransfer(cargo, cp, cp->count, current_tile);
515 cp->AddFeederShare(share);
516 this->feeder_share += share;
517 cp->next_hop = cargo_next;
518 break;
519 default:
520 NOT_REACHED();
521 }
522 this->action_counts[action] += cp->count;
523 sum += cp->count;
524 }
526 return this->action_counts[MTA_DELIVER] > 0 || this->action_counts[MTA_TRANSFER] > 0;
527}
528
531{
532 this->feeder_share = 0;
534}
535
548template <VehicleCargoList::MoveToAction Tfrom, VehicleCargoList::MoveToAction Tto>
549uint VehicleCargoList::Reassign(uint max_move)
550{
551 static_assert(Tfrom != MTA_TRANSFER && Tto != MTA_TRANSFER);
552 static_assert(Tfrom - Tto == 1 || Tto - Tfrom == 1);
553 max_move = std::min(this->action_counts[Tfrom], max_move);
554 this->action_counts[Tfrom] -= max_move;
555 this->action_counts[Tto] += max_move;
556 return max_move;
557}
558
565template <>
566uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(uint max_move)
567{
568 max_move = std::min(this->action_counts[MTA_DELIVER], max_move);
569
570 uint sum = 0;
571 for (Iterator it(this->packets.begin()); sum < this->action_counts[MTA_TRANSFER] + max_move;) {
572 CargoPacket *cp = *it++;
573 sum += cp->Count();
574 if (sum <= this->action_counts[MTA_TRANSFER]) continue;
575 if (sum > this->action_counts[MTA_TRANSFER] + max_move) {
576 CargoPacket *cp_split = cp->Split(sum - this->action_counts[MTA_TRANSFER] + max_move);
577 sum -= cp_split->Count();
578 this->packets.insert(it, cp_split);
579 }
580 cp->next_hop = StationID::Invalid();
581 }
582
583 this->action_counts[MTA_DELIVER] -= max_move;
584 this->action_counts[MTA_TRANSFER] += max_move;
585 return max_move;
586}
587
596uint VehicleCargoList::Return(uint max_move, StationCargoList *dest, StationID next, TileIndex current_tile)
597{
598 max_move = std::min(this->action_counts[MTA_LOAD], max_move);
599 this->PopCargo(CargoReturn(this, dest, max_move, next, current_tile));
600 return max_move;
601}
602
610{
611 max_move = std::min(this->count, max_move);
612 this->PopCargo(CargoShift(this, dest, max_move));
613 return max_move;
614}
615
626uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
627{
628 uint moved = 0;
629 if (this->action_counts[MTA_TRANSFER] > 0) {
630 uint move = std::min(this->action_counts[MTA_TRANSFER], max_move);
631 this->ShiftCargo(CargoTransfer(this, dest, move, current_tile));
632 moved += move;
633 }
634 if (this->action_counts[MTA_TRANSFER] == 0 && this->action_counts[MTA_DELIVER] > 0 && moved < max_move) {
635 uint move = std::min(this->action_counts[MTA_DELIVER], max_move - moved);
636 this->ShiftCargo(CargoDelivery(this, move, cargo, payment, current_tile));
637 moved += move;
638 }
639 return moved;
640}
641
648uint VehicleCargoList::Truncate(uint max_move)
649{
650 max_move = std::min(this->count, max_move);
651 this->PopCargo(CargoRemoval<VehicleCargoList>(this, max_move));
652 return max_move;
653}
654
663uint VehicleCargoList::Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
664{
665 max_move = std::min(this->action_counts[MTA_TRANSFER], max_move);
666 this->ShiftCargo(VehicleCargoReroute(this, dest, max_move, avoid, avoid2, ge));
667 return max_move;
668}
669
670/*
671 *
672 * Station cargo list implementation.
673 *
674 */
675
685{
686 assert(cp != nullptr);
687 this->AddToCache(cp);
688
689 StationCargoPacketMap::List &list = this->packets[next];
690 for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
691 it != list.rend(); it++) {
692 if (StationCargoList::TryMerge(*it, cp)) return;
693 }
694
695 /* The packet could not be merged with another one */
696 list.push_back(cp);
697}
698
711template <class Taction>
712bool StationCargoList::ShiftCargo(Taction &action, StationID next)
713{
714 std::pair<Iterator, Iterator> range(this->packets.equal_range(next));
715 for (Iterator it(range.first); it != range.second && it.GetKey() == next;) {
716 if (action.MaxMove() == 0) return false;
717 CargoPacket *cp = *it;
718 if (action(cp)) {
719 it = this->packets.erase(it);
720 } else {
721 return false;
722 }
723 }
724 return true;
725}
726
741template <class Taction>
742uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool include_invalid)
743{
744 uint max_move = action.MaxMove();
745 while (!next.IsEmpty()) {
746 this->ShiftCargo(action, StationID{next.Pop()});
747 if (action.MaxMove() == 0) break;
748 }
749 if (include_invalid && action.MaxMove() > 0) {
750 this->ShiftCargo(action, StationID::Invalid());
751 }
752 return max_move - action.MaxMove();
753}
754
763uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_source)
764{
765 max_move = std::min(max_move, this->count);
766 uint prev_count = this->count;
767 uint moved = 0;
768 uint loop = 0;
769 bool do_count = cargo_per_source != nullptr;
770 while (max_move > moved) {
771 for (Iterator it(this->packets.begin()); it != this->packets.end();) {
772 CargoPacket *cp = *it;
773 if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
774 if (do_count && loop == 0) {
775 (*cargo_per_source)[cp->first_station] += cp->count;
776 }
777 ++it;
778 continue;
779 }
780 uint diff = max_move - moved;
781 if (cp->count > diff) {
782 if (diff > 0) {
783 this->RemoveFromCache(cp, diff);
784 cp->Reduce(diff);
785 moved += diff;
786 }
787 if (loop > 0) {
788 if (do_count) (*cargo_per_source)[cp->first_station] -= diff;
789 return moved;
790 } else {
791 if (do_count) (*cargo_per_source)[cp->first_station] += cp->count;
792 ++it;
793 }
794 } else {
795 it = this->packets.erase(it);
796 if (do_count && loop > 0) {
797 (*cargo_per_source)[cp->first_station] -= cp->count;
798 }
799 moved += cp->count;
800 this->RemoveFromCache(cp, cp->count);
801 delete cp;
802 }
803 }
804 loop++;
805 }
806 return moved;
807}
808
817uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
818{
819 return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true);
820}
821
834uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
835{
836 uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
837 if (move > 0) {
838 this->reserved_count -= move;
840 return move;
841 } else {
842 return this->ShiftCargo(CargoLoad(this, dest, max_move, current_tile), next_station, true);
843 }
844}
845
854uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
855{
856 return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid.base(), false);
857}
858
859/*
860 * We have to instantiate everything we want to be usable.
861 */
864template 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:23
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
Minimal stack that uses a pool to avoid pointers.
bool Contains(const Titem &item) const
Check if the given item is contained in the stack.
Titem Pop()
Pop an item from the stack.
bool IsEmpty() const
Check if the stack is empty.
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.
void Append(CargoPacket *cp, StationID next)
Appends the given cargo packet to the range of packets with the same next station.
uint Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next, TileIndex current_tile)
Reserves cargo for loading onto the vehicle.
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 Load(uint max_move, VehicleCargoList *dest, StationIDStack next, TileIndex current_tile)
Loads cargo onto a 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.
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.
static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next, StationID current_station, bool accepted, StationIDStack next_station)
Choose action to be performed with the given cargo packet.
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.
bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
Stages cargo for unloading.
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.
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.
@ OUFB_TRANSFER
Transfer all cargo onto the platform.
Definition order_type.h:71
@ OUFB_NO_UNLOAD
Totally no unloading will be done.
Definition order_type.h:72
@ OUFB_UNLOAD
Force unloading all cargo onto the platform, possibly not getting paid.
Definition order_type.h:70
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.
uint16_t count
The amount of cargo in this packet.
Definition cargopacket.h:49
CargoPacket()
Create a new packet for savegame loading.
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:1243
FlowStatMap flows
Planned flows through this station.
Stores station stats for a single cargo.
debug_inline const GoodsEntryData & GetData() const
Get optional cargo packet/flow data.
debug_inline bool HasData() const
Test if this goods entry has optional cargo packet/flow data.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
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