OpenTTD Source 20250205-master-gfd85ab1e2c
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
28{
29 this->source_type = SourceType::Industry;
30 this->source_id = INVALID_SOURCE;
31}
32
42CargoPacket::CargoPacket(StationID first_station,uint16_t count, SourceType source_type, SourceID source_id) :
43 count(count),
44 source_id(source_id),
45 source_type(source_type),
46 first_station(first_station)
47{
48 assert(count != 0);
49}
50
60CargoPacket::CargoPacket(uint16_t count, uint16_t periods_in_transit, StationID first_station, TileIndex source_xy, Money feeder_share) :
61 count(count),
62 periods_in_transit(periods_in_transit),
63 feeder_share(feeder_share),
64 source_xy(source_xy),
65 first_station(first_station)
66{
67 assert(count != 0);
68}
69
77CargoPacket::CargoPacket(uint16_t count, Money feeder_share, CargoPacket &original) :
78 count(count),
79 periods_in_transit(original.periods_in_transit),
80 feeder_share(feeder_share),
81 source_xy(original.source_xy),
82 travelled(original.travelled),
83 source_id(original.source_id),
84 source_type(original.source_type),
85#ifdef WITH_ASSERT
86 in_vehicle(original.in_vehicle),
87#endif /* WITH_ASSERT */
88 first_station(original.first_station),
89 next_hop(original.next_hop)
90{
91 assert(count != 0);
92}
93
100{
101 if (!CargoPacket::CanAllocateItem()) return nullptr;
102
103 Money fs = this->GetFeederShare(new_size);
104 CargoPacket *cp_new = new CargoPacket(new_size, fs, *this);
105 this->feeder_share -= fs;
106 this->count -= new_size;
107 return cp_new;
108}
109
115{
116 this->count += cp->count;
117 this->feeder_share += cp->feeder_share;
118 delete cp;
119}
120
125void CargoPacket::Reduce(uint count)
126{
127 assert(count < this->count);
128 this->feeder_share -= this->GetFeederShare(count);
129 this->count -= count;
130}
131
137/* static */ void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
138{
139 for (CargoPacket *cp : CargoPacket::Iterate()) {
140 if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE;
141 }
142}
143
148/* static */ void CargoPacket::InvalidateAllFrom(StationID sid)
149{
150 for (CargoPacket *cp : CargoPacket::Iterate()) {
151 if (cp->first_station == sid) cp->first_station = INVALID_STATION;
152 }
153}
154
155/*
156 *
157 * Cargo list implementation
158 *
159 */
160
164template <class Tinst, class Tcont>
166{
167 for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
168 delete *it;
169 }
170}
171
176template <class Tinst, class Tcont>
178{
179 this->packets.clear();
180}
181
188template <class Tinst, class Tcont>
190{
191 assert(count <= cp->count);
192 this->count -= count;
193 this->cargo_periods_in_transit -= static_cast<uint64_t>(cp->periods_in_transit) * count;
194}
195
201template <class Tinst, class Tcont>
203{
204 this->count += cp->count;
205 this->cargo_periods_in_transit += static_cast<uint64_t>(cp->periods_in_transit) * cp->count;
206}
207
209template <class Tinst, class Tcont>
211{
212 this->count = 0;
213 this->cargo_periods_in_transit = 0;
214
215 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
216 static_cast<Tinst *>(this)->AddToCache(*it);
217 }
218}
219
227template <class Tinst, class Tcont>
229{
230 if (Tinst::AreMergable(icp, cp) &&
231 icp->count + cp->count <= CargoPacket::MAX_COUNT) {
232 icp->Merge(cp);
233 return true;
234 } else {
235 return false;
236 }
237}
238
239/*
240 *
241 * Vehicle cargo list implementation.
242 *
243 */
244
260void VehicleCargoList::Append(CargoPacket *cp, MoveToAction action)
261{
262 assert(cp != nullptr);
263 assert(action == MTA_LOAD ||
264 (action == MTA_KEEP && this->action_counts[MTA_LOAD] == 0));
265 this->AddToMeta(cp, action);
266
267 if (this->count == cp->count) {
268 this->packets.push_back(cp);
269 return;
270 }
271
272 uint sum = cp->count;
273 for (ReverseIterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
274 CargoPacket *icp = *it;
275 if (VehicleCargoList::TryMerge(icp, cp)) return;
276 sum += icp->count;
277 if (sum >= this->action_counts[action]) {
278 this->packets.push_back(cp);
279 return;
280 }
281 }
282
283 NOT_REACHED();
284}
285
294template <class Taction>
296{
297 Iterator it(this->packets.begin());
298 while (it != this->packets.end() && action.MaxMove() > 0) {
299 CargoPacket *cp = *it;
300 if (action(cp)) {
301 it = this->packets.erase(it);
302 } else {
303 break;
304 }
305 }
306}
307
316template <class Taction>
317void VehicleCargoList::PopCargo(Taction action)
318{
319 if (this->packets.empty()) return;
320 Iterator it(--(this->packets.end()));
321 Iterator begin(this->packets.begin());
322 while (action.MaxMove() > 0) {
323 CargoPacket *cp = *it;
324 if (action(cp)) {
325 if (it != begin) {
326 this->packets.erase(it--);
327 } else {
328 this->packets.erase(it);
329 break;
330 }
331 } else {
332 break;
333 }
334 }
335}
336
344{
345 this->feeder_share -= cp->GetFeederShare(count);
347}
348
355{
356 this->feeder_share += cp->feeder_share;
357 this->Parent::AddToCache(cp);
358}
359
366void VehicleCargoList::RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count)
367{
368 assert(count <= this->action_counts[action]);
370 this->RemoveFromCache(cp, count);
371 this->action_counts[action] -= count;
373}
374
380void VehicleCargoList::AddToMeta(const CargoPacket *cp, MoveToAction action)
381{
383 this->AddToCache(cp);
384 this->action_counts[action] += cp->count;
386}
387
392{
393 for (const auto &cp : this->packets) {
394 /* If we're at the maximum, then we can't increase no more. */
395 if (cp->periods_in_transit == UINT16_MAX) continue;
396
397 cp->periods_in_transit++;
398 this->cargo_periods_in_transit += cp->count;
399 }
400}
401
412 StationID current_station, bool accepted, StationIDStack next_station)
413{
414 if (cargo_next == INVALID_STATION) {
415 return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
416 } else if (cargo_next == current_station) {
417 return MTA_DELIVER;
418 } else if (next_station.Contains(cargo_next)) {
419 return MTA_KEEP;
420 } else {
421 return MTA_TRANSFER;
422 }
423}
424
440bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
441{
443 assert(this->action_counts[MTA_LOAD] == 0);
445 Iterator deliver = this->packets.end();
446 Iterator it = this->packets.begin();
447 uint sum = 0;
448
449 static const FlowStatMap EMPTY_FLOW_STAT_MAP = {};
450 const FlowStatMap &flows = ge->HasData() ? ge->GetData().flows : EMPTY_FLOW_STAT_MAP;
451
452 bool force_keep = (order_flags & OUFB_NO_UNLOAD) != 0;
453 bool force_unload = (order_flags & OUFB_UNLOAD) != 0;
454 bool force_transfer = (order_flags & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0;
455 assert(this->count > 0 || it == this->packets.end());
456 while (sum < this->count) {
457 CargoPacket *cp = *it;
458
459 this->packets.erase(it++);
460 StationID cargo_next = INVALID_STATION;
461 MoveToAction action = MTA_LOAD;
462 if (force_keep) {
463 action = MTA_KEEP;
464 } else if (force_unload && accepted && cp->first_station != current_station) {
465 action = MTA_DELIVER;
466 } else if (force_transfer) {
467 action = MTA_TRANSFER;
468 /* We cannot send the cargo to any of the possible next hops and
469 * also not to the current station. */
470 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
471 if (flow_it == flows.end()) {
472 cargo_next = INVALID_STATION;
473 } else {
474 FlowStat new_shares = flow_it->second;
475 new_shares.ChangeShare(current_station, INT_MIN);
476 StationIDStack excluded = next_station;
477 while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
478 new_shares.ChangeShare(excluded.Pop(), INT_MIN);
479 }
480 if (new_shares.GetShares()->empty()) {
481 cargo_next = INVALID_STATION;
482 } else {
483 cargo_next = new_shares.GetVia();
484 }
485 }
486 } else {
487 /* Rewrite an invalid source station to some random other one to
488 * avoid keeping the cargo in the vehicle forever. */
489 if (cp->first_station == INVALID_STATION && !flows.empty()) {
490 cp->first_station = flows.begin()->first;
491 }
492 bool restricted = false;
493 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
494 if (flow_it == flows.end()) {
495 cargo_next = INVALID_STATION;
496 } else {
497 cargo_next = flow_it->second.GetViaWithRestricted(restricted);
498 }
499 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
500 if (restricted && action == MTA_TRANSFER) {
501 /* If the flow is restricted we can't transfer to it. Choose an
502 * unrestricted one instead. */
503 cargo_next = flow_it->second.GetVia();
504 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
505 }
506 }
507 Money share;
508 switch (action) {
509 case MTA_KEEP:
510 this->packets.push_back(cp);
511 if (deliver == this->packets.end()) --deliver;
512 break;
513 case MTA_DELIVER:
514 this->packets.insert(deliver, cp);
515 break;
516 case MTA_TRANSFER:
517 this->packets.push_front(cp);
518 /* Add feeder share here to allow reusing field for next station. */
519 share = payment->PayTransfer(cargo, cp, cp->count, current_tile);
520 cp->AddFeederShare(share);
521 this->feeder_share += share;
522 cp->next_hop = cargo_next;
523 break;
524 default:
525 NOT_REACHED();
526 }
527 this->action_counts[action] += cp->count;
528 sum += cp->count;
529 }
531 return this->action_counts[MTA_DELIVER] > 0 || this->action_counts[MTA_TRANSFER] > 0;
532}
533
536{
537 this->feeder_share = 0;
539}
540
553template <VehicleCargoList::MoveToAction Tfrom, VehicleCargoList::MoveToAction Tto>
554uint VehicleCargoList::Reassign(uint max_move)
555{
556 static_assert(Tfrom != MTA_TRANSFER && Tto != MTA_TRANSFER);
557 static_assert(Tfrom - Tto == 1 || Tto - Tfrom == 1);
558 max_move = std::min(this->action_counts[Tfrom], max_move);
559 this->action_counts[Tfrom] -= max_move;
560 this->action_counts[Tto] += max_move;
561 return max_move;
562}
563
570template <>
571uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(uint max_move)
572{
573 max_move = std::min(this->action_counts[MTA_DELIVER], max_move);
574
575 uint sum = 0;
576 for (Iterator it(this->packets.begin()); sum < this->action_counts[MTA_TRANSFER] + max_move;) {
577 CargoPacket *cp = *it++;
578 sum += cp->Count();
579 if (sum <= this->action_counts[MTA_TRANSFER]) continue;
580 if (sum > this->action_counts[MTA_TRANSFER] + max_move) {
581 CargoPacket *cp_split = cp->Split(sum - this->action_counts[MTA_TRANSFER] + max_move);
582 sum -= cp_split->Count();
583 this->packets.insert(it, cp_split);
584 }
585 cp->next_hop = INVALID_STATION;
586 }
587
588 this->action_counts[MTA_DELIVER] -= max_move;
589 this->action_counts[MTA_TRANSFER] += max_move;
590 return max_move;
591}
592
601uint VehicleCargoList::Return(uint max_move, StationCargoList *dest, StationID next, TileIndex current_tile)
602{
603 max_move = std::min(this->action_counts[MTA_LOAD], max_move);
604 this->PopCargo(CargoReturn(this, dest, max_move, next, current_tile));
605 return max_move;
606}
607
615{
616 max_move = std::min(this->count, max_move);
617 this->PopCargo(CargoShift(this, dest, max_move));
618 return max_move;
619}
620
631uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
632{
633 uint moved = 0;
634 if (this->action_counts[MTA_TRANSFER] > 0) {
635 uint move = std::min(this->action_counts[MTA_TRANSFER], max_move);
636 this->ShiftCargo(CargoTransfer(this, dest, move, current_tile));
637 moved += move;
638 }
639 if (this->action_counts[MTA_TRANSFER] == 0 && this->action_counts[MTA_DELIVER] > 0 && moved < max_move) {
640 uint move = std::min(this->action_counts[MTA_DELIVER], max_move - moved);
641 this->ShiftCargo(CargoDelivery(this, move, cargo, payment, current_tile));
642 moved += move;
643 }
644 return moved;
645}
646
653uint VehicleCargoList::Truncate(uint max_move)
654{
655 max_move = std::min(this->count, max_move);
656 this->PopCargo(CargoRemoval<VehicleCargoList>(this, max_move));
657 return max_move;
658}
659
668uint VehicleCargoList::Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
669{
670 max_move = std::min(this->action_counts[MTA_TRANSFER], max_move);
671 this->ShiftCargo(VehicleCargoReroute(this, dest, max_move, avoid, avoid2, ge));
672 return max_move;
673}
674
675/*
676 *
677 * Station cargo list implementation.
678 *
679 */
680
689void StationCargoList::Append(CargoPacket *cp, StationID next)
690{
691 assert(cp != nullptr);
692 this->AddToCache(cp);
693
694 StationCargoPacketMap::List &list = this->packets[next];
695 for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
696 it != list.rend(); it++) {
697 if (StationCargoList::TryMerge(*it, cp)) return;
698 }
699
700 /* The packet could not be merged with another one */
701 list.push_back(cp);
702}
703
716template <class Taction>
717bool StationCargoList::ShiftCargo(Taction &action, StationID next)
718{
719 std::pair<Iterator, Iterator> range(this->packets.equal_range(next));
720 for (Iterator it(range.first); it != range.second && it.GetKey() == next;) {
721 if (action.MaxMove() == 0) return false;
722 CargoPacket *cp = *it;
723 if (action(cp)) {
724 it = this->packets.erase(it);
725 } else {
726 return false;
727 }
728 }
729 return true;
730}
731
746template <class Taction>
747uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool include_invalid)
748{
749 uint max_move = action.MaxMove();
750 while (!next.IsEmpty()) {
751 this->ShiftCargo(action, next.Pop());
752 if (action.MaxMove() == 0) break;
753 }
754 if (include_invalid && action.MaxMove() > 0) {
755 this->ShiftCargo(action, INVALID_STATION);
756 }
757 return max_move - action.MaxMove();
758}
759
768uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_source)
769{
770 max_move = std::min(max_move, this->count);
771 uint prev_count = this->count;
772 uint moved = 0;
773 uint loop = 0;
774 bool do_count = cargo_per_source != nullptr;
775 while (max_move > moved) {
776 for (Iterator it(this->packets.begin()); it != this->packets.end();) {
777 CargoPacket *cp = *it;
778 if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
779 if (do_count && loop == 0) {
780 (*cargo_per_source)[cp->first_station] += cp->count;
781 }
782 ++it;
783 continue;
784 }
785 uint diff = max_move - moved;
786 if (cp->count > diff) {
787 if (diff > 0) {
788 this->RemoveFromCache(cp, diff);
789 cp->Reduce(diff);
790 moved += diff;
791 }
792 if (loop > 0) {
793 if (do_count) (*cargo_per_source)[cp->first_station] -= diff;
794 return moved;
795 } else {
796 if (do_count) (*cargo_per_source)[cp->first_station] += cp->count;
797 ++it;
798 }
799 } else {
800 it = this->packets.erase(it);
801 if (do_count && loop > 0) {
802 (*cargo_per_source)[cp->first_station] -= cp->count;
803 }
804 moved += cp->count;
805 this->RemoveFromCache(cp, cp->count);
806 delete cp;
807 }
808 }
809 loop++;
810 }
811 return moved;
812}
813
822uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
823{
824 return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true);
825}
826
839uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
840{
841 uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
842 if (move > 0) {
843 this->reserved_count -= move;
845 return move;
846 } else {
847 return this->ShiftCargo(CargoLoad(this, dest, max_move, current_tile), next_station, true);
848 }
849}
850
859uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
860{
861 return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false);
862}
863
864/*
865 * We have to instantiate everything we want to be usable.
866 */
869template 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:22
uint16_t SourceID
Contains either industry ID, town ID or company ID (or INVALID_SOURCE)
Definition cargo_type.h:141
static const SourceID INVALID_SOURCE
Invalid/unknown index of source.
Definition cargo_type.h:142
SourceType
Types of cargo source and destination.
Definition cargo_type.h:135
@ Industry
Source/destination is an industry.
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:299
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:357
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:55
@ OUFB_NO_UNLOAD
Totally no unloading will be done.
Definition order_type.h:56
@ OUFB_UNLOAD
Force unloading all cargo onto the platform, possibly not getting paid.
Definition order_type.h:54
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:40
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:51
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:48
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(SourceType src_type, SourceID 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:49
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:1258
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.
Definition pool_type.hpp:79