72 feeder_share(feeder_share),
74 days_in_transit(days_in_transit),
78 loaded_at_xy(loaded_at_xy)
96 this->
count -= new_size;
117 assert(count < this->count);
119 this->count -=
count;
130 if (cp->source_type == src_type && cp->source_id == src) cp->source_id =
INVALID_SOURCE;
141 if (cp->source == sid) cp->source = INVALID_STATION;
154 template <
class Tinst,
class Tcont>
157 for (
Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
166 template <
class Tinst,
class Tcont>
169 this->packets.clear();
178 template <
class Tinst,
class Tcont>
181 assert(count <= cp->count);
182 this->count -=
count;
191 template <
class Tinst,
class Tcont>
199 template <
class Tinst,
class Tcont>
203 this->cargo_days_in_transit = 0;
205 for (
ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
206 static_cast<Tinst *
>(
this)->AddToCache(*it);
217 template <
class Tinst,
class Tcont>
220 if (Tinst::AreMergable(icp, cp) &&
252 assert(cp !=
nullptr);
253 assert(action == MTA_LOAD ||
254 (action == MTA_KEEP && this->action_counts[MTA_LOAD] == 0));
255 this->AddToMeta(cp, action);
258 this->packets.push_back(cp);
262 uint sum = cp->
count;
263 for (
ReverseIterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
267 if (sum >= this->action_counts[action]) {
268 this->packets.push_back(cp);
284 template<
class Taction>
288 while (it != this->packets.end() && action.MaxMove() > 0) {
291 it = this->packets.erase(it);
306 template<
class Taction>
309 if (this->packets.empty())
return;
310 Iterator it(--(this->packets.end()));
311 Iterator begin(this->packets.begin());
312 while (action.MaxMove() > 0) {
316 this->packets.erase(it--);
318 this->packets.erase(it);
336 this->Parent::RemoveFromCache(cp, count);
347 this->Parent::AddToCache(cp);
358 assert(count <= this->action_counts[action]);
359 this->AssertCountConsistency();
360 this->RemoveFromCache(cp, count);
361 this->action_counts[action] -=
count;
362 this->AssertCountConsistency();
372 this->AssertCountConsistency();
373 this->AddToCache(cp);
374 this->action_counts[action] += cp->
count;
375 this->AssertCountConsistency();
383 for (
ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
389 this->cargo_days_in_transit += cp->
count;
403 for (
Iterator it = this->packets.begin(); sum < this->action_counts[MTA_TRANSFER]; ++it) {
422 if (cargo_next == INVALID_STATION) {
423 return (accepted && cp->
source != current_station) ? MTA_DELIVER : MTA_KEEP;
424 }
else if (cargo_next == current_station) {
426 }
else if (next_station.
Contains(cargo_next)) {
448 this->AssertCountConsistency();
449 assert(this->action_counts[MTA_LOAD] == 0);
450 this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_DELIVER] = this->action_counts[MTA_KEEP] = 0;
451 Iterator deliver = this->packets.end();
452 Iterator it = this->packets.begin();
456 bool force_unload = (order_flags &
OUFB_UNLOAD) != 0;
458 assert(this->
count > 0 || it == this->packets.end());
459 while (sum < this->
count) {
462 this->packets.erase(it++);
463 StationID cargo_next = INVALID_STATION;
464 MoveToAction action = MTA_LOAD;
467 }
else if (force_unload && accepted && cp->
source != current_station) {
468 action = MTA_DELIVER;
469 }
else if (force_transfer) {
470 action = MTA_TRANSFER;
473 FlowStatMap::const_iterator flow_it(ge->
flows.find(cp->
source));
474 if (flow_it == ge->
flows.end()) {
475 cargo_next = INVALID_STATION;
477 FlowStat new_shares = flow_it->second;
484 cargo_next = INVALID_STATION;
486 cargo_next = new_shares.
GetVia();
492 if (cp->
source == INVALID_STATION && !ge->
flows.empty()) {
495 bool restricted =
false;
496 FlowStatMap::const_iterator flow_it(ge->
flows.find(cp->
source));
497 if (flow_it == ge->
flows.end()) {
498 cargo_next = INVALID_STATION;
500 cargo_next = flow_it->second.GetViaWithRestricted(restricted);
503 if (restricted && action == MTA_TRANSFER) {
506 cargo_next = flow_it->second.GetVia();
513 this->packets.push_back(cp);
514 if (deliver == this->packets.end()) --deliver;
517 this->packets.insert(deliver, cp);
520 this->packets.push_front(cp);
530 this->action_counts[action] += cp->
count;
533 this->AssertCountConsistency();
534 return this->action_counts[MTA_DELIVER] > 0 || this->action_counts[MTA_TRANSFER] > 0;
541 this->Parent::InvalidateCache();
556 template<VehicleCargoList::MoveToAction Tfrom, VehicleCargoList::MoveToAction Tto>
559 assert_tcompile(Tfrom != MTA_TRANSFER && Tto != MTA_TRANSFER);
560 assert_tcompile(Tfrom - Tto == 1 || Tto - Tfrom == 1);
561 max_move =
min(this->action_counts[Tfrom], max_move);
562 this->action_counts[Tfrom] -= max_move;
563 this->action_counts[Tto] += max_move;
575 uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(uint max_move, TileOrStationID
next_station)
577 max_move =
min(this->action_counts[MTA_DELIVER], max_move);
580 for (Iterator it(this->packets.begin()); sum < this->action_counts[MTA_TRANSFER] + max_move;) {
583 if (sum <= this->action_counts[MTA_TRANSFER])
continue;
584 if (sum > this->action_counts[MTA_TRANSFER] + max_move) {
585 CargoPacket *cp_split = cp->
Split(sum - this->action_counts[MTA_TRANSFER] + max_move);
586 sum -= cp_split->
Count();
587 this->packets.insert(it, cp_split);
592 this->action_counts[MTA_DELIVER] -= max_move;
593 this->action_counts[MTA_TRANSFER] += max_move;
606 max_move =
min(this->action_counts[MTA_LOAD], max_move);
607 this->PopCargo(
CargoReturn(
this, dest, max_move, next));
619 max_move =
min(this->
count, max_move);
620 this->PopCargo(
CargoShift(
this, dest, max_move));
635 if (this->action_counts[MTA_TRANSFER] > 0) {
636 uint move =
min(this->action_counts[MTA_TRANSFER], max_move);
640 if (this->action_counts[MTA_TRANSFER] == 0 && this->action_counts[MTA_DELIVER] > 0 && moved < max_move) {
641 uint move =
min(this->action_counts[MTA_DELIVER], max_move - moved);
656 max_move =
min(this->
count, max_move);
671 max_move =
min(this->action_counts[MTA_TRANSFER], max_move);
692 assert(cp !=
nullptr);
693 this->AddToCache(cp);
695 StationCargoPacketMap::List &list = this->packets[next];
696 for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
697 it != list.rend(); it++) {
717 template <
class Taction>
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;
725 it = this->packets.erase(it);
747 template <
class Taction>
750 uint max_move = action.MaxMove();
752 this->ShiftCargo(action, next.
Pop());
753 if (action.MaxMove() == 0)
break;
755 if (include_invalid && action.MaxMove() > 0) {
756 this->ShiftCargo(action, INVALID_STATION);
758 return max_move - action.MaxMove();
771 max_move =
min(max_move, this->
count);
772 uint prev_count = this->
count;
775 bool do_count = cargo_per_source !=
nullptr;
776 while (max_move > moved) {
777 for (
Iterator it(this->packets.begin()); it != this->packets.end();) {
779 if (prev_count > max_move &&
RandomRange(prev_count) < prev_count - max_move) {
780 if (do_count && loop == 0) {
786 uint diff = max_move - moved;
787 if (cp->
count > diff) {
789 this->RemoveFromCache(cp, diff);
794 if (do_count) (*cargo_per_source)[cp->
source] -= diff;
797 if (do_count) (*cargo_per_source)[cp->
source] += cp->
count;
801 it = this->packets.erase(it);
802 if (do_count && loop > 0) {
806 this->RemoveFromCache(cp, cp->
count);
825 return this->ShiftCargo(
CargoReservation(
this, dest, max_move, load_place), next_station,
true);
844 this->reserved_count -= move;
848 return this->ShiftCargo(
CargoLoad(
this, dest, max_move, load_place), next_station,
true);
862 return this->ShiftCargo(
StationCargoReroute(
this, dest, max_move, avoid, avoid2, ge), avoid,
false);
870 template uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_KEEP>(uint, TileOrStationID);
SourceType
Types of cargo source and destination.
Action of rerouting cargo in a station.
void AddFeederShare(Money new_share)
Adds some feeder share to the packet.
CargoPacketList ::reverse_iterator ReverseIterator
The reverse iterator for our container.
Minimal stack that uses a pool to avoid pointers.
void Append(CargoPacket *cp, MoveToAction action=MTA_KEEP)
Appends the given cargo packet.
CargoPacketPool _cargopacket_pool("CargoPacket")
The actual pool with cargo packets.
CargoList that is used for stations.
void AddToCache(const CargoPacket *cp)
Update the cache to reflect adding of this packet.
void PopCargo(Taction action)
Pops cargo from the back of the packet list and applies some action to it.
void AddToMeta(const CargoPacket *cp, MoveToAction action)
Adds a packet to the metadata.
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.
CargoPacket()
Create a new packet for savegame loading.
void SetTransferLoadPlace(TileIndex xy)
Sets loaded_at_xy to the current station for all cargo to be transferred.
uint Truncate(uint max_move=UINT_MAX)
Truncates the cargo in this list to the given amount.
Money FeederShare() const
Gets the amount of money already paid to earlier vehicles in the feeder chain.
Action of shifting cargo from one vehicle to another.
Stores station stats for a single cargo.
Action of rerouting cargo staged for transfer in a vehicle.
static void InvalidateAllFrom(SourceType src_type, SourceID src)
Invalidates (sets source_id to INVALID_SOURCE) all cargo packets from given source.
uint Return(uint max_move, StationCargoList *dest, StationID next_station)
Returns reserved cargo to the station and removes it from the cache.
uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next)
Loads cargo onto a vehicle.
static uint32 RandomRange(uint32 limit)
Pick a random number between 0 and limit - 1, inclusive.
static const SourceID INVALID_SOURCE
Invalid/unknown index of source.
uint16 count
The amount of cargo in this packet.
void RemoveFromCache(const CargoPacket *cp, uint count)
Update the cached values to reflect the removal of this packet or part of it.
void OnCleanPool()
Empty the cargo list, but don't free the cargo packets; the cargo packets are cleaned by CargoPacket'...
Pseudo random number generator.
~CargoList()
Destroy the cargolist ("frees" all cargo packets).
bool IsEmpty() const
Check if the stack is empty.
Some methods of Pool are placed here in order to reduce compilation time and binary size...
SourceType source_type
Type of source_id.
void ShiftCargo(Taction action)
Shifts cargo from the front of the packet list and applies some action to it.
SourceID source_id
Index of source, INVALID_SOURCE if unknown/invalid.
Actions to be applied to cargo packets.
StationID GetVia() const
Get a station a package can be routed to.
uint Reassign(uint max_move, TileOrStationID update=INVALID_TILE)
Moves some cargo from one designation to another.
Money PayTransfer(const CargoPacket *cp, uint count)
Handle payment for transfer of the given cargo packet.
Container for cargo from the same location and time.
Definition of base types and functions in a cross-platform compatible way.
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.
A number of safeguards to prevent using unsafe methods.
TileOrStationID next_station
Station where the cargo wants to go next.
Titem Pop()
Pop an item from the stack.
bool Contains(const Titem &item) const
Check if the given item is contained in the stack.
uint ActionCount(MoveToAction action) const
Returns the amount of cargo designated for a given purpose.
void InvalidateCache()
Invalidates the cached data and rebuild it.
CargoPacket * Split(uint new_size)
Split this packet in two and return the split off part.
uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next)
Reserves cargo for loading onto the vehicle.
static T min(const T a, const T b)
Returns the minimum of two values.
Helper class to perform the cargo payment.
Action of transferring cargo from a vehicle to a station.
MoveToAction
Kind of actions that could be done with packets on move.
Transfer all cargo onto the platform.
Action of reserving cargo from a station to be loaded onto a vehicle.
Base class for all pools.
FlowStatMap flows
Planned flows through this 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.
void ChangeShare(StationID st, int flow)
Change share for specified station.
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Keep the cargo in the vehicle.
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...
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
CargoList that is used for vehicles.
StationCargoPacketMap ::const_iterator ConstIterator
The const iterator for our container.
uint32 TileIndex
The index/ID of a Tile.
Action of returning previously reserved cargo from the vehicle to the station.
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.
uint16 SourceID
Contains either industry ID, town ID or company ID (or INVALID_SOURCE)
const SharesMap * GetShares() const
Get the actual shares as a const pointer so that they can be iterated over.
TileIndex xy
Base tile of the station.
void AgeCargo()
Ages the all cargo in this list.
StationID source
The station where the cargo came from first.
uint Shift(uint max_move, VehicleCargoList *dest)
Shifts cargo between two vehicles.
Totally no unloading will be done.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Flow statistics telling how much flow should be sent along a link.
uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment)
Unloads cargo at the given station.
void Reduce(uint count)
Reduce the packet by the given amount and remove the feeder share.
Base classes related to the economy.
void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count)
Removes a packet or part of it from the metadata.
Load the cargo from the station.
bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment)
Stages cargo for unloading.
void Merge(CargoPacket *cp)
Merge another packet into this one.
uint16 Count() const
Gets the number of 'items' in this packet.
static const uint16 MAX_COUNT
Maximum number of items in a single cargo packet.
Money feeder_share
Value of feeder pickup to be paid for on delivery of cargo.
Action of final delivery of cargo.
void InvalidateCache()
Invalidates the cached data and rebuilds it.
TileOrStationID loaded_at_xy
Location where this cargo has been loaded into the vehicle.
TileIndex source_xy
The origin of the cargo (first station in feeder chain).
void RemoveFromCache(const CargoPacket *cp, uint count)
Update the cached values to reflect the removal of this packet or part of it.
Force unloading all cargo onto the platform, possibly not getting paid.
Action of loading cargo from a station onto a vehicle.
StationCargoPacketMap ::iterator Iterator
The iterator for our container.
Base classes/functions for stations.
void AddToCache(const CargoPacket *cp)
Update the cache to reflect adding of this packet.
byte days_in_transit
Amount of days this packet has been in transit.
void Append(CargoPacket *cp, StationID next)
Appends the given cargo packet to the range of packets with the same next station.
static bool TryMerge(CargoPacket *cp, CargoPacket *icp)
Tries to merge the second packet into the first and return if that was successful.
Source/destination is an industry.