OpenTTD Source 20260206-master-g4d4e37dbf1
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
9
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 */
23
24
31
49
70
81 count(count),
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 */
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
128{
129 assert(count < this->count);
130 this->feeder_share -= this->GetFeederShare(count);
131 this->count -= count;
132}
133
139{
140 for (CargoPacket *cp : CargoPacket::Iterate()) {
141 if (cp->source == src) cp->source.MakeInvalid();
142 }
143}
144
149/* static */ void CargoPacket::InvalidateAllFrom(StationID sid)
150{
151 for (CargoPacket *cp : CargoPacket::Iterate()) {
152 if (cp->first_station == sid) cp->first_station = StationID::Invalid();
153 }
154}
155
156/*
157 *
158 * Cargo list implementation
159 *
160 */
161
165template <class Tinst, class Tcont>
167{
168 for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
169 delete *it;
170 }
171}
172
177template <class Tinst, class Tcont>
179{
180 this->packets.clear();
181}
182
189template <class Tinst, class Tcont>
191{
192 assert(count <= cp->count);
193 this->count -= count;
194 this->cargo_periods_in_transit -= static_cast<uint64_t>(cp->periods_in_transit) * count;
195}
196
202template <class Tinst, class Tcont>
204{
205 this->count += cp->count;
206 this->cargo_periods_in_transit += static_cast<uint64_t>(cp->periods_in_transit) * cp->count;
207}
208
210template <class Tinst, class Tcont>
212{
213 this->count = 0;
214 this->cargo_periods_in_transit = 0;
215
216 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
217 static_cast<Tinst *>(this)->AddToCache(*it);
218 }
219}
220
228template <class Tinst, class Tcont>
230{
231 if (Tinst::AreMergable(icp, cp) &&
232 icp->count + cp->count <= CargoPacket::MAX_COUNT) {
233 icp->Merge(cp);
234 return true;
235 } else {
236 return false;
237 }
238}
239
240/*
241 *
242 * Vehicle cargo list implementation.
243 *
244 */
245
262{
263 assert(cp != nullptr);
264 assert(action == MTA_LOAD ||
265 (action == MTA_KEEP && this->action_counts[MTA_LOAD] == 0));
266 this->AddToMeta(cp, action);
267
268 if (this->count == cp->count) {
269 this->packets.push_back(cp);
270 return;
271 }
272
273 uint sum = cp->count;
274 for (ReverseIterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
275 CargoPacket *icp = *it;
276 if (VehicleCargoList::TryMerge(icp, cp)) return;
277 sum += icp->count;
278 if (sum >= this->action_counts[action]) {
279 this->packets.push_back(cp);
280 return;
281 }
282 }
283
284 NOT_REACHED();
285}
286
295template <class Taction>
297{
298 Iterator it(this->packets.begin());
299 while (it != this->packets.end() && action.MaxMove() > 0) {
300 CargoPacket *cp = *it;
301 if (action(cp)) {
302 it = this->packets.erase(it);
303 } else {
304 break;
305 }
306 }
307}
308
317template <class Taction>
318void VehicleCargoList::PopCargo(Taction action)
319{
320 if (this->packets.empty()) return;
321 Iterator it(--(this->packets.end()));
322 Iterator begin(this->packets.begin());
323 while (action.MaxMove() > 0) {
324 CargoPacket *cp = *it;
325 if (action(cp)) {
326 if (it != begin) {
327 this->packets.erase(it--);
328 } else {
329 this->packets.erase(it);
330 break;
331 }
332 } else {
333 break;
334 }
335 }
336}
337
345{
346 this->feeder_share -= cp->GetFeederShare(count);
348}
349
356{
357 this->feeder_share += cp->feeder_share;
358 this->Parent::AddToCache(cp);
359}
360
368{
369 assert(count <= this->action_counts[action]);
371 this->RemoveFromCache(cp, count);
372 this->action_counts[action] -= count;
374}
375
382{
384 this->AddToCache(cp);
385 this->action_counts[action] += cp->count;
387}
388
393{
394 for (const auto &cp : this->packets) {
395 /* If we're at the maximum, then we can't increase no more. */
396 if (cp->periods_in_transit == UINT16_MAX) continue;
397
398 cp->periods_in_transit++;
399 this->cargo_periods_in_transit += cp->count;
400 }
401}
402
413 StationID current_station, bool accepted, std::span<const StationID> next_station)
414{
415 if (cargo_next == StationID::Invalid()) {
416 return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP;
417 } else if (cargo_next == current_station) {
418 return MTA_DELIVER;
419 } else if (std::ranges::find(next_station, cargo_next) != std::end(next_station)) {
420 return MTA_KEEP;
421 } else {
422 return MTA_TRANSFER;
423 }
424}
425
441bool 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)
442{
444 assert(this->action_counts[MTA_LOAD] == 0);
446 Iterator deliver = this->packets.end();
447 Iterator it = this->packets.begin();
448 uint sum = 0;
449
450 static const FlowStatMap EMPTY_FLOW_STAT_MAP = {};
451 const FlowStatMap &flows = ge->HasData() ? ge->GetData().flows : EMPTY_FLOW_STAT_MAP;
452
453 bool force_keep = unload_type == OrderUnloadType::NoUnload;
454 bool force_unload = unload_type == OrderUnloadType::Unload;
455 bool force_transfer = unload_type == OrderUnloadType::Transfer || unload_type == OrderUnloadType::Unload;
456 assert(this->count > 0 || it == this->packets.end());
457 while (sum < this->count) {
458 CargoPacket *cp = *it;
459
460 this->packets.erase(it++);
461 StationID cargo_next = StationID::Invalid();
462 MoveToAction action = MTA_LOAD;
463 if (force_keep) {
464 action = MTA_KEEP;
465 } else if (force_unload && accepted && cp->first_station != current_station) {
466 action = MTA_DELIVER;
467 } else if (force_transfer) {
468 action = MTA_TRANSFER;
469 /* We cannot send the cargo to any of the possible next hops and
470 * also not to the current station. */
471 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
472 if (flow_it == flows.end()) {
473 cargo_next = StationID::Invalid();
474 } else {
475 FlowStat new_shares = flow_it->second;
476 new_shares.ChangeShare(current_station, INT_MIN);
477 for (auto station_it = next_station.rbegin(); station_it != next_station.rend(); ++station_it) {
478 if (new_shares.GetShares()->empty()) break;
479 new_shares.ChangeShare(*station_it, INT_MIN);
480 }
481 if (new_shares.GetShares()->empty()) {
482 cargo_next = StationID::Invalid();
483 } else {
484 cargo_next = new_shares.GetVia();
485 }
486 }
487 } else {
488 /* Rewrite an invalid source station to some random other one to
489 * avoid keeping the cargo in the vehicle forever. */
490 if (cp->first_station == StationID::Invalid() && !flows.empty()) {
491 cp->first_station = flows.begin()->first;
492 }
493 bool restricted = false;
494 FlowStatMap::const_iterator flow_it(flows.find(cp->first_station));
495 if (flow_it == flows.end()) {
496 cargo_next = StationID::Invalid();
497 } else {
498 cargo_next = flow_it->second.GetViaWithRestricted(restricted);
499 }
500 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
501 if (restricted && action == MTA_TRANSFER) {
502 /* If the flow is restricted we can't transfer to it. Choose an
503 * unrestricted one instead. */
504 cargo_next = flow_it->second.GetVia();
505 action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
506 }
507 }
508 Money share;
509 switch (action) {
510 case MTA_KEEP:
511 this->packets.push_back(cp);
512 if (deliver == this->packets.end()) --deliver;
513 break;
514 case MTA_DELIVER:
515 this->packets.insert(deliver, cp);
516 break;
517 case MTA_TRANSFER:
518 this->packets.push_front(cp);
519 /* Add feeder share here to allow reusing field for next station. */
520 share = payment->PayTransfer(cargo, cp, cp->count, current_tile);
521 cp->AddFeederShare(share);
522 this->feeder_share += share;
523 cp->next_hop = cargo_next;
524 break;
525 default:
526 NOT_REACHED();
527 }
528 this->action_counts[action] += cp->count;
529 sum += cp->count;
530 }
532 return this->action_counts[MTA_DELIVER] > 0 || this->action_counts[MTA_TRANSFER] > 0;
533}
534
537{
538 this->feeder_share = 0;
540}
541
554template <VehicleCargoList::MoveToAction Tfrom, VehicleCargoList::MoveToAction Tto>
555uint VehicleCargoList::Reassign(uint max_move)
556{
557 static_assert(Tfrom != MTA_TRANSFER && Tto != MTA_TRANSFER);
558 static_assert(Tfrom - Tto == 1 || Tto - Tfrom == 1);
559 max_move = std::min(this->action_counts[Tfrom], max_move);
560 this->action_counts[Tfrom] -= max_move;
561 this->action_counts[Tto] += max_move;
562 return max_move;
563}
564
571template <>
573{
574 max_move = std::min(this->action_counts[MTA_DELIVER], max_move);
575
576 uint sum = 0;
577 for (Iterator it(this->packets.begin()); sum < this->action_counts[MTA_TRANSFER] + max_move;) {
578 CargoPacket *cp = *it++;
579 sum += cp->Count();
580 if (sum <= this->action_counts[MTA_TRANSFER]) continue;
581 if (sum > this->action_counts[MTA_TRANSFER] + max_move) {
582 CargoPacket *cp_split = cp->Split(sum - this->action_counts[MTA_TRANSFER] + max_move);
583 sum -= cp_split->Count();
584 this->packets.insert(it, cp_split);
585 }
586 cp->next_hop = StationID::Invalid();
587 }
588
589 this->action_counts[MTA_DELIVER] -= max_move;
590 this->action_counts[MTA_TRANSFER] += max_move;
591 return max_move;
592}
593
602uint VehicleCargoList::Return(uint max_move, StationCargoList *dest, StationID next, TileIndex current_tile)
603{
604 max_move = std::min(this->action_counts[MTA_LOAD], max_move);
605 this->PopCargo(CargoReturn(this, dest, max_move, next, current_tile));
606 return max_move;
607}
608
616{
617 max_move = std::min(this->count, max_move);
618 this->PopCargo(CargoShift(this, dest, max_move));
619 return max_move;
620}
621
632uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoType cargo, CargoPayment *payment, TileIndex current_tile)
633{
634 uint moved = 0;
635 if (this->action_counts[MTA_TRANSFER] > 0) {
636 uint move = std::min(this->action_counts[MTA_TRANSFER], max_move);
637 this->ShiftCargo(CargoTransfer(this, dest, move, current_tile));
638 moved += move;
639 }
640 if (this->action_counts[MTA_TRANSFER] == 0 && this->action_counts[MTA_DELIVER] > 0 && moved < max_move) {
641 uint move = std::min(this->action_counts[MTA_DELIVER], max_move - moved);
642 this->ShiftCargo(CargoDelivery(this, move, cargo, payment, current_tile));
643 moved += move;
644 }
645 return moved;
646}
647
654uint VehicleCargoList::Truncate(uint max_move)
655{
656 max_move = std::min(this->count, max_move);
657 this->PopCargo(CargoRemoval<VehicleCargoList>(this, max_move));
658 return max_move;
659}
660
669uint VehicleCargoList::Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
670{
671 max_move = std::min(this->action_counts[MTA_TRANSFER], max_move);
672 this->ShiftCargo(VehicleCargoReroute(this, dest, max_move, avoid, avoid2, ge));
673 return max_move;
674}
675
676/*
677 *
678 * Station cargo list implementation.
679 *
680 */
681
690void StationCargoList::Append(CargoPacket *cp, StationID next)
691{
692 assert(cp != nullptr);
693 this->AddToCache(cp);
694
695 StationCargoPacketMap::List &list = this->packets[next];
696 for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
697 it != list.rend(); it++) {
698 if (StationCargoList::TryMerge(*it, cp)) return;
699 }
700
701 /* The packet could not be merged with another one */
702 list.push_back(cp);
703}
704
717template <class Taction>
718bool StationCargoList::ShiftCargo(Taction &action, StationID next)
719{
720 std::pair<Iterator, Iterator> range(this->packets.equal_range(next));
721 for (Iterator it(range.first); it != range.second && it.GetKey() == next;) {
722 if (action.MaxMove() == 0) return false;
723 CargoPacket *cp = *it;
724 if (action(cp)) {
725 it = this->packets.erase(it);
726 } else {
727 return false;
728 }
729 }
730 return true;
731}
732
747template <class Taction>
748uint StationCargoList::ShiftCargo(Taction action, std::span<const StationID> next, bool include_invalid)
749{
750 uint max_move = action.MaxMove();
751 for (auto it = next.rbegin(); it != next.rend(); ++it) {
752 this->ShiftCargo(action, *it);
753 if (action.MaxMove() == 0) break;
754 }
755 if (include_invalid && action.MaxMove() > 0) {
756 this->ShiftCargo(action, StationID::Invalid());
757 }
758 return max_move - action.MaxMove();
759}
760
769uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_source)
770{
771 max_move = std::min(max_move, this->count);
772 uint prev_count = this->count;
773 uint moved = 0;
774 uint loop = 0;
775 bool do_count = cargo_per_source != nullptr;
776 while (max_move > moved) {
777 for (Iterator it(this->packets.begin()); it != this->packets.end();) {
778 CargoPacket *cp = *it;
779 if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
780 if (do_count && loop == 0) {
781 (*cargo_per_source)[cp->first_station] += cp->count;
782 }
783 ++it;
784 continue;
785 }
786 uint diff = max_move - moved;
787 if (cp->count > diff) {
788 if (diff > 0) {
789 this->RemoveFromCache(cp, diff);
790 cp->Reduce(diff);
791 moved += diff;
792 }
793 if (loop > 0) {
794 if (do_count) (*cargo_per_source)[cp->first_station] -= diff;
795 return moved;
796 } else {
797 if (do_count) (*cargo_per_source)[cp->first_station] += cp->count;
798 ++it;
799 }
800 } else {
801 it = this->packets.erase(it);
802 if (do_count && loop > 0) {
803 (*cargo_per_source)[cp->first_station] -= cp->count;
804 }
805 moved += cp->count;
806 this->RemoveFromCache(cp, cp->count);
807 delete cp;
808 }
809 }
810 loop++;
811 }
812 return moved;
813}
814
823uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, std::span<const StationID> next_station, TileIndex current_tile)
824{
825 return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true);
826}
827
840uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, std::span<const StationID> next_station, TileIndex current_tile)
841{
842 uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
843 if (move > 0) {
844 this->reserved_count -= move;
846 return move;
847 } else {
848 return this->ShiftCargo(CargoLoad{this, dest, max_move, current_tile}, next_station, true);
849 }
850}
851
860uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
861{
862 return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), {&avoid, 1}, false);
863}
864
865/*
866 * We have to instantiate everything we want to be usable.
867 */
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.
CargoPacketPool _cargopacket_pool
The actual pool with cargo packets.
PoolID< uint32_t, struct CargoPacketIDTag, 0xFFF000, 0xFFFFFF > CargoPacketID
Unique identifier for a single cargo packet.
Definition cargopacket.h:24
Pool< CargoPacket, CargoPacketID, 1024, PoolType::Normal, true > CargoPacketPool
Type of the pool for cargo packets for a little over 16 million packets.
Definition cargopacket.h:28
Simple collection class for a list of cargo packets.
CargoPacketList::reverse_iterator ReverseIterator
void OnCleanPool()
Empty the cargo list, but don't free the cargo packets; the cargo packets are cleaned by CargoPacket'...
Tcont 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.
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.
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.
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.
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.
friend class StationCargoList
The station cargo list needs to control the unloading.
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.
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.
Definition order_type.h:70
@ NoUnload
Totally no unloading will be done.
Definition order_type.h:71
@ Unload
Force unloading all cargo onto the platform, possibly not getting paid.
Definition order_type.h:69
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
TileIndex source_xy
The origin of the cargo.
Definition cargopacket.h:54
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
Source source
Source of the cargo.
Definition cargopacket.h:57
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
Vector travelled
If cargo is in station: the vector from the unload tile to the source tile. If in vehicle: an interme...
Definition cargopacket.h:55
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.
static Pool::IterateWrapper< CargoPacket > Iterate(size_t from=0)
A location from where cargo can come from (or go to).
Definition source_type.h:32
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