OpenTTD Source  20241120-master-g6d3adc6169
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 */
21 CargoPacketPool _cargopacket_pool("CargoPacket");
23 
24 
28 {
29  this->source_type = SourceType::Industry;
30  this->source_id = INVALID_SOURCE;
31 }
32 
42 CargoPacket::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 
60 CargoPacket::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 
77 CargoPacket::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 
125 void 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 
164 template <class Tinst, class Tcont>
166 {
167  for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
168  delete *it;
169  }
170 }
171 
176 template <class Tinst, class Tcont>
178 {
179  this->packets.clear();
180 }
181 
188 template <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 
201 template <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 
209 template <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 
227 template <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 
260 void 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 
294 template<class Taction>
295 void VehicleCargoList::ShiftCargo(Taction action)
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 
316 template<class Taction>
317 void 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);
346  this->Parent::RemoveFromCache(cp, count);
347 }
348 
355 {
356  this->feeder_share += cp->feeder_share;
357  this->Parent::AddToCache(cp);
358 }
359 
366 void VehicleCargoList::RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count)
367 {
368  assert(count <= this->action_counts[action]);
369  this->AssertCountConsistency();
370  this->RemoveFromCache(cp, count);
371  this->action_counts[action] -= count;
372  this->AssertCountConsistency();
373 }
374 
380 void VehicleCargoList::AddToMeta(const CargoPacket *cp, MoveToAction action)
381 {
382  this->AssertCountConsistency();
383  this->AddToCache(cp);
384  this->action_counts[action] += cp->count;
385  this->AssertCountConsistency();
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 
411 /* static */ VehicleCargoList::MoveToAction VehicleCargoList::ChooseAction(const CargoPacket *cp, StationID cargo_next,
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 
440 bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoID cargo, CargoPayment *payment, TileIndex current_tile)
441 {
442  this->AssertCountConsistency();
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  bool force_keep = (order_flags & OUFB_NO_UNLOAD) != 0;
450  bool force_unload = (order_flags & OUFB_UNLOAD) != 0;
451  bool force_transfer = (order_flags & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0;
452  assert(this->count > 0 || it == this->packets.end());
453  while (sum < this->count) {
454  CargoPacket *cp = *it;
455 
456  this->packets.erase(it++);
457  StationID cargo_next = INVALID_STATION;
458  MoveToAction action = MTA_LOAD;
459  if (force_keep) {
460  action = MTA_KEEP;
461  } else if (force_unload && accepted && cp->first_station != current_station) {
462  action = MTA_DELIVER;
463  } else if (force_transfer) {
464  action = MTA_TRANSFER;
465  /* We cannot send the cargo to any of the possible next hops and
466  * also not to the current station. */
467  FlowStatMap::const_iterator flow_it(ge->flows.find(cp->first_station));
468  if (flow_it == ge->flows.end()) {
469  cargo_next = INVALID_STATION;
470  } else {
471  FlowStat new_shares = flow_it->second;
472  new_shares.ChangeShare(current_station, INT_MIN);
473  StationIDStack excluded = next_station;
474  while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) {
475  new_shares.ChangeShare(excluded.Pop(), INT_MIN);
476  }
477  if (new_shares.GetShares()->empty()) {
478  cargo_next = INVALID_STATION;
479  } else {
480  cargo_next = new_shares.GetVia();
481  }
482  }
483  } else {
484  /* Rewrite an invalid source station to some random other one to
485  * avoid keeping the cargo in the vehicle forever. */
486  if (cp->first_station == INVALID_STATION && !ge->flows.empty()) {
487  cp->first_station = ge->flows.begin()->first;
488  }
489  bool restricted = false;
490  FlowStatMap::const_iterator flow_it(ge->flows.find(cp->first_station));
491  if (flow_it == ge->flows.end()) {
492  cargo_next = INVALID_STATION;
493  } else {
494  cargo_next = flow_it->second.GetViaWithRestricted(restricted);
495  }
496  action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
497  if (restricted && action == MTA_TRANSFER) {
498  /* If the flow is restricted we can't transfer to it. Choose an
499  * unrestricted one instead. */
500  cargo_next = flow_it->second.GetVia();
501  action = VehicleCargoList::ChooseAction(cp, cargo_next, current_station, accepted, next_station);
502  }
503  }
504  Money share;
505  switch (action) {
506  case MTA_KEEP:
507  this->packets.push_back(cp);
508  if (deliver == this->packets.end()) --deliver;
509  break;
510  case MTA_DELIVER:
511  this->packets.insert(deliver, cp);
512  break;
513  case MTA_TRANSFER:
514  this->packets.push_front(cp);
515  /* Add feeder share here to allow reusing field for next station. */
516  share = payment->PayTransfer(cargo, cp, cp->count, current_tile);
517  cp->AddFeederShare(share);
518  this->feeder_share += share;
519  cp->next_hop = cargo_next;
520  break;
521  default:
522  NOT_REACHED();
523  }
524  this->action_counts[action] += cp->count;
525  sum += cp->count;
526  }
527  this->AssertCountConsistency();
528  return this->action_counts[MTA_DELIVER] > 0 || this->action_counts[MTA_TRANSFER] > 0;
529 }
530 
533 {
534  this->feeder_share = 0;
535  this->Parent::InvalidateCache();
536 }
537 
550 template<VehicleCargoList::MoveToAction Tfrom, VehicleCargoList::MoveToAction Tto>
551 uint VehicleCargoList::Reassign(uint max_move)
552 {
553  static_assert(Tfrom != MTA_TRANSFER && Tto != MTA_TRANSFER);
554  static_assert(Tfrom - Tto == 1 || Tto - Tfrom == 1);
555  max_move = std::min(this->action_counts[Tfrom], max_move);
556  this->action_counts[Tfrom] -= max_move;
557  this->action_counts[Tto] += max_move;
558  return max_move;
559 }
560 
567 template<>
568 uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(uint max_move)
569 {
570  max_move = std::min(this->action_counts[MTA_DELIVER], max_move);
571 
572  uint sum = 0;
573  for (Iterator it(this->packets.begin()); sum < this->action_counts[MTA_TRANSFER] + max_move;) {
574  CargoPacket *cp = *it++;
575  sum += cp->Count();
576  if (sum <= this->action_counts[MTA_TRANSFER]) continue;
577  if (sum > this->action_counts[MTA_TRANSFER] + max_move) {
578  CargoPacket *cp_split = cp->Split(sum - this->action_counts[MTA_TRANSFER] + max_move);
579  sum -= cp_split->Count();
580  this->packets.insert(it, cp_split);
581  }
582  cp->next_hop = INVALID_STATION;
583  }
584 
585  this->action_counts[MTA_DELIVER] -= max_move;
586  this->action_counts[MTA_TRANSFER] += max_move;
587  return max_move;
588 }
589 
598 uint VehicleCargoList::Return(uint max_move, StationCargoList *dest, StationID next, TileIndex current_tile)
599 {
600  max_move = std::min(this->action_counts[MTA_LOAD], max_move);
601  this->PopCargo(CargoReturn(this, dest, max_move, next, current_tile));
602  return max_move;
603 }
604 
611 uint VehicleCargoList::Shift(uint max_move, VehicleCargoList *dest)
612 {
613  max_move = std::min(this->count, max_move);
614  this->PopCargo(CargoShift(this, dest, max_move));
615  return max_move;
616 }
617 
628 uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoID cargo, CargoPayment *payment, TileIndex current_tile)
629 {
630  uint moved = 0;
631  if (this->action_counts[MTA_TRANSFER] > 0) {
632  uint move = std::min(this->action_counts[MTA_TRANSFER], max_move);
633  this->ShiftCargo(CargoTransfer(this, dest, move, current_tile));
634  moved += move;
635  }
636  if (this->action_counts[MTA_TRANSFER] == 0 && this->action_counts[MTA_DELIVER] > 0 && moved < max_move) {
637  uint move = std::min(this->action_counts[MTA_DELIVER], max_move - moved);
638  this->ShiftCargo(CargoDelivery(this, move, cargo, payment, current_tile));
639  moved += move;
640  }
641  return moved;
642 }
643 
650 uint VehicleCargoList::Truncate(uint max_move)
651 {
652  max_move = std::min(this->count, max_move);
653  this->PopCargo(CargoRemoval<VehicleCargoList>(this, max_move));
654  return max_move;
655 }
656 
665 uint VehicleCargoList::Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
666 {
667  max_move = std::min(this->action_counts[MTA_TRANSFER], max_move);
668  this->ShiftCargo(VehicleCargoReroute(this, dest, max_move, avoid, avoid2, ge));
669  return max_move;
670 }
671 
672 /*
673  *
674  * Station cargo list implementation.
675  *
676  */
677 
686 void StationCargoList::Append(CargoPacket *cp, StationID next)
687 {
688  assert(cp != nullptr);
689  this->AddToCache(cp);
690 
691  StationCargoPacketMap::List &list = this->packets[next];
692  for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
693  it != list.rend(); it++) {
694  if (StationCargoList::TryMerge(*it, cp)) return;
695  }
696 
697  /* The packet could not be merged with another one */
698  list.push_back(cp);
699 }
700 
713 template <class Taction>
714 bool StationCargoList::ShiftCargo(Taction &action, StationID next)
715 {
716  std::pair<Iterator, Iterator> range(this->packets.equal_range(next));
717  for (Iterator it(range.first); it != range.second && it.GetKey() == next;) {
718  if (action.MaxMove() == 0) return false;
719  CargoPacket *cp = *it;
720  if (action(cp)) {
721  it = this->packets.erase(it);
722  } else {
723  return false;
724  }
725  }
726  return true;
727 }
728 
743 template <class Taction>
744 uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool include_invalid)
745 {
746  uint max_move = action.MaxMove();
747  while (!next.IsEmpty()) {
748  this->ShiftCargo(action, next.Pop());
749  if (action.MaxMove() == 0) break;
750  }
751  if (include_invalid && action.MaxMove() > 0) {
752  this->ShiftCargo(action, INVALID_STATION);
753  }
754  return max_move - action.MaxMove();
755 }
756 
765 uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_source)
766 {
767  max_move = std::min(max_move, this->count);
768  uint prev_count = this->count;
769  uint moved = 0;
770  uint loop = 0;
771  bool do_count = cargo_per_source != nullptr;
772  while (max_move > moved) {
773  for (Iterator it(this->packets.begin()); it != this->packets.end();) {
774  CargoPacket *cp = *it;
775  if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
776  if (do_count && loop == 0) {
777  (*cargo_per_source)[cp->first_station] += cp->count;
778  }
779  ++it;
780  continue;
781  }
782  uint diff = max_move - moved;
783  if (cp->count > diff) {
784  if (diff > 0) {
785  this->RemoveFromCache(cp, diff);
786  cp->Reduce(diff);
787  moved += diff;
788  }
789  if (loop > 0) {
790  if (do_count) (*cargo_per_source)[cp->first_station] -= diff;
791  return moved;
792  } else {
793  if (do_count) (*cargo_per_source)[cp->first_station] += cp->count;
794  ++it;
795  }
796  } else {
797  it = this->packets.erase(it);
798  if (do_count && loop > 0) {
799  (*cargo_per_source)[cp->first_station] -= cp->count;
800  }
801  moved += cp->count;
802  this->RemoveFromCache(cp, cp->count);
803  delete cp;
804  }
805  }
806  loop++;
807  }
808  return moved;
809 }
810 
819 uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
820 {
821  return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true);
822 }
823 
836 uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile)
837 {
838  uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
839  if (move > 0) {
840  this->reserved_count -= move;
842  return move;
843  } else {
844  return this->ShiftCargo(CargoLoad(this, dest, max_move, current_tile), next_station, true);
845  }
846 }
847 
856 uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge)
857 {
858  return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false);
859 }
860 
861 /*
862  * We have to instantiate everything we want to be usable.
863  */
866 template uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_KEEP>(uint);
uint8_t CargoID
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:143
static const SourceID INVALID_SOURCE
Invalid/unknown index of source.
Definition: cargo_type.h:144
SourceType
Types of cargo source and destination.
Definition: cargo_type.h:137
@ Industry
Source/destination is an industry.
Actions to be applied to cargo packets.
CargoPacketPool _cargopacket_pool
The actual pool with cargo packets.
Action of final delivery of cargo.
Definition: cargoaction.h:39
Tcont::reverse_iterator ReverseIterator
The reverse iterator for our container.
Definition: cargopacket.h:288
void OnCleanPool()
Empty the cargo list, but don't free the cargo packets; the cargo packets are cleaned by CargoPacket'...
MoveToAction
Kind of actions that could be done with packets on move.
Definition: cargopacket.h:295
@ MTA_KEEP
Keep the cargo in the vehicle.
Definition: cargopacket.h:299
@ MTA_DELIVER
Deliver the cargo to some town or industry.
Definition: cargopacket.h:298
@ MTA_LOAD
Load the cargo from the station.
Definition: cargopacket.h:300
@ MTA_TRANSFER
Transfer the cargo to the station.
Definition: cargopacket.h:297
CargoPacketList packets
The cargo packets in this list.
Definition: cargopacket.h:309
~CargoList()
Destroy the cargolist ("frees" all cargo packets).
Tcont::const_iterator ConstIterator
The const iterator for our container.
Definition: cargopacket.h:290
uint count
Cache for the number of cargo entities.
Definition: cargopacket.h:306
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...
Definition: cargopacket.h:307
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.
Definition: cargopacket.h:286
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
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.
Definition: cargoaction.h:101
Action of shifting cargo from one vehicle to another.
Definition: cargoaction.h:112
Action of transferring cargo from a vehicle to a station.
Definition: cargoaction.h:73
Flow statistics telling how much flow should be sent along a link.
Definition: station_base.h:32
StationID GetVia() const
Get a station a package can be routed to.
Definition: station_base.h:130
void ChangeShare(StationID st, int flow)
Change share for specified station.
const SharesMap * GetShares() const
Get the actual shares as a const pointer so that they can be iterated over.
Definition: station_base.h:88
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.
Definition: cargopacket.h:529
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.
Definition: cargopacket.h:534
uint Load(uint max_move, VehicleCargoList *dest, StationIDStack next, TileIndex current_tile)
Loads cargo onto a vehicle.
Action of rerouting cargo in a station.
Definition: cargoaction.h:132
CargoList that is used for vehicles.
Definition: cargopacket.h:351
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.
bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoID cargo, CargoPayment *payment, TileIndex current_tile)
Stages cargo for unloading.
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.
Definition: cargopacket.h:424
uint Truncate(uint max_move=UINT_MAX)
Truncates the cargo in this list to the given amount.
uint Unload(uint max_move, StationCargoList *dest, CargoID cargo, CargoPayment *payment, TileIndex current_tile)
Unloads cargo at the given station.
void AssertCountConsistency() const
Assert that the designation counts add up.
Definition: cargopacket.h:368
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.
Definition: cargopacket.h:357
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.
Definition: cargopacket.h:356
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.
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.
Definition: cargoaction.h:140
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.
Definition: pool_func.hpp:237
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.
Definition: random_func.hpp:88
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.
Definition: cargopacket.h:158
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.
Definition: cargopacket.cpp:99
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.
Definition: cargopacket.h:149
uint16_t count
The amount of cargo in this packet.
Definition: cargopacket.h:48
CargoPacket()
Create a new packet for savegame loading.
Definition: cargopacket.cpp:27
Money GetFeederShare() const
Gets the amount of money already paid to earlier vehicles in the feeder chain.
Definition: cargopacket.h:168
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.
Definition: economy_base.h:24
Money PayTransfer(CargoID cargo, const CargoPacket *cp, uint count, TileIndex current_tile)
Handle payment for transfer of the given cargo packet.
Definition: economy.cpp:1261
Stores station stats for a single cargo.
Definition: station_base.h:166
FlowStatMap flows
Planned flows through this station.
Definition: station_base.h:211
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Base class for all pools.
Definition: pool_type.hpp:80