OpenTTD
cargopacket.h
Go to the documentation of this file.
1 /* $Id: cargopacket.h 26660 2014-06-21 19:52:52Z fonsinchen $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #ifndef CARGOPACKET_H
13 #define CARGOPACKET_H
14 
15 #include "core/pool_type.hpp"
16 #include "economy_type.h"
17 #include "station_type.h"
18 #include "order_type.h"
19 #include "cargo_type.h"
20 #include "vehicle_type.h"
21 #include "core/multimap.hpp"
22 #include <list>
23 
25 typedef uint32 CargoPacketID;
26 struct CargoPacket;
27 
32 
33 struct GoodsEntry; // forward-declare for Stage() and RerouteStalePackets()
34 
35 template <class Tinst, class Tcont> class CargoList;
36 class StationCargoList; // forward-declare, so we can use it in VehicleCargoList.
37 extern const struct SaveLoad *GetCargoPacketDesc();
38 
39 typedef uint32 TileOrStationID;
40 
44 struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> {
45 private:
47  uint16 count;
51  StationID source;
53  union {
54  TileOrStationID loaded_at_xy;
55  TileOrStationID next_station;
56  };
57 
59  template <class Tinst, class Tcont> friend class CargoList;
60  friend class VehicleCargoList;
61  friend class StationCargoList;
63  friend const struct SaveLoad *GetCargoPacketDesc();
64 public:
66  static const uint16 MAX_COUNT = UINT16_MAX;
67 
68  CargoPacket();
71 
74 
75  CargoPacket *Split(uint new_size);
76  void Merge(CargoPacket *cp);
77  void Reduce(uint count);
78 
83  void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
84 
89  void SetNextStation(StationID next_station) { this->next_station = next_station; }
90 
95  void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
96 
101  inline uint16 Count() const
102  {
103  return this->count;
104  }
105 
111  inline Money FeederShare() const
112  {
113  return this->feeder_share;
114  }
115 
122  inline Money FeederShare(uint part) const
123  {
124  return this->feeder_share * part / static_cast<uint>(this->count);
125  }
126 
133  inline byte DaysInTransit() const
134  {
135  return this->days_in_transit;
136  }
137 
143  {
144  return this->source_type;
145  }
146 
151  inline SourceID SourceSubsidyID() const
152  {
153  return this->source_id;
154  }
155 
160  inline StationID SourceStation() const
161  {
162  return this->source;
163  }
164 
169  inline TileIndex SourceStationXY() const
170  {
171  return this->source_xy;
172  }
173 
178  inline TileIndex LoadedAtXY() const
179  {
180  return this->loaded_at_xy;
181  }
182 
187  inline StationID NextStation() const
188  {
189  return this->next_station;
190  }
191 
192  static void InvalidateAllFrom(SourceType src_type, SourceID src);
193  static void InvalidateAllFrom(StationID sid);
194  static void AfterLoad();
195 };
196 
202 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
203 
208 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
209 
214 template <class Tinst, class Tcont>
215 class CargoList {
216 public:
218  typedef typename Tcont::iterator Iterator;
220  typedef typename Tcont::reverse_iterator ReverseIterator;
222  typedef typename Tcont::const_iterator ConstIterator;
224  typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
225 
228  MTA_BEGIN = 0,
233  MTA_END,
234  NUM_MOVE_TO_ACTION = MTA_END
235  };
236 
237 protected:
238  uint count;
240 
241  Tcont packets;
242 
243  void AddToCache(const CargoPacket *cp);
244 
245  void RemoveFromCache(const CargoPacket *cp, uint count);
246 
247  static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
248 
249 public:
252 
253  ~CargoList();
254 
255  void OnCleanPool();
256 
261  inline const Tcont *Packets() const
262  {
263  return &this->packets;
264  }
265 
270  inline uint DaysInTransit() const
271  {
272  return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
273  }
274 
275  void InvalidateCache();
276 };
277 
278 typedef std::list<CargoPacket *> CargoPacketList;
279 
283 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
284 protected:
287 
289  uint action_counts[NUM_MOVE_TO_ACTION];
290 
291  template<class Taction>
292  void ShiftCargo(Taction action);
293 
294  template<class Taction>
295  void PopCargo(Taction action);
296 
300  inline void AssertCountConsistency() const
301  {
302  assert(this->action_counts[MTA_KEEP] +
303  this->action_counts[MTA_DELIVER] +
304  this->action_counts[MTA_TRANSFER] +
305  this->action_counts[MTA_LOAD] == this->count);
306  }
307 
308  void AddToCache(const CargoPacket *cp);
309  void RemoveFromCache(const CargoPacket *cp, uint count);
310 
311  void AddToMeta(const CargoPacket *cp, MoveToAction action);
312  void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
313 
314  static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
315  StationID current_station, bool accepted, StationIDStack next_station);
316 
317 public:
319  friend class StationCargoList;
321  friend class CargoList<VehicleCargoList, CargoPacketList>;
323  friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
324 
325  friend class CargoShift;
326  friend class CargoTransfer;
327  friend class CargoDelivery;
328  template<class Tsource>
329  friend class CargoRemoval;
330  friend class CargoReturn;
331  friend class VehicleCargoReroute;
332 
337  inline StationID Source() const
338  {
339  return this->count == 0 ? INVALID_STATION : this->packets.front()->source;
340  }
341 
346  inline Money FeederShare() const
347  {
348  return this->feeder_share;
349  }
350 
356  inline uint ActionCount(MoveToAction action) const
357  {
358  return this->action_counts[action];
359  }
360 
366  inline uint StoredCount() const
367  {
368  return this->count - this->action_counts[MTA_LOAD];
369  }
370 
375  inline uint TotalCount() const
376  {
377  return this->count;
378  }
379 
384  inline uint ReservedCount() const
385  {
386  return this->action_counts[MTA_LOAD];
387  }
388 
393  inline uint UnloadCount() const
394  {
395  return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
396  }
397 
402  inline uint RemainingCount() const
403  {
404  return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
405  }
406 
407  void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
408 
409  void AgeCargo();
410 
411  void InvalidateCache();
412 
414 
415  bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
416 
422  inline void KeepAll()
423  {
425  this->action_counts[MTA_KEEP] = this->count;
426  }
427 
428  /* Methods for moving cargo around. First parameter is always maximum
429  * amount of cargo to be moved. Second parameter is destination (if
430  * applicable), return value is amount of cargo actually moved. */
431 
432  template<MoveToAction Tfrom, MoveToAction Tto>
433  uint Reassign(uint max_move, TileOrStationID update = INVALID_TILE);
434  uint Return(uint max_move, StationCargoList *dest, StationID next_station);
435  uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
436  uint Shift(uint max_move, VehicleCargoList *dest);
437  uint Truncate(uint max_move = UINT_MAX);
438  uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
439 
447  static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
448  {
449  return cp1->source_xy == cp2->source_xy &&
450  cp1->days_in_transit == cp2->days_in_transit &&
451  cp1->source_type == cp2->source_type &&
452  cp1->source_id == cp2->source_id &&
453  cp1->loaded_at_xy == cp2->loaded_at_xy;
454  }
455 };
456 
458 typedef std::map<StationID, uint> StationCargoAmountMap;
459 
463 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
464 protected:
467 
469 
470 public:
474  friend const struct SaveLoad *GetGoodsDesc();
475 
476  friend class CargoLoad;
477  friend class CargoTransfer;
478  template<class Tsource>
479  friend class CargoRemoval;
480  friend class CargoReservation;
481  friend class CargoReturn;
482  friend class StationCargoReroute;
483 
484  static void InvalidateAllFrom(SourceType src_type, SourceID src);
485 
486  template<class Taction>
487  bool ShiftCargo(Taction &action, StationID next);
488 
489  template<class Taction>
490  uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid);
491 
492  void Append(CargoPacket *cp, StationID next);
493 
499  inline bool HasCargoFor(StationIDStack next) const
500  {
501  while (!next.IsEmpty()) {
502  if (this->packets.find(next.Pop()) != this->packets.end()) return true;
503  }
504  /* Packets for INVALID_STTION can go anywhere. */
505  return this->packets.find(INVALID_STATION) != this->packets.end();
506  }
507 
512  inline StationID Source() const
513  {
514  return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->source;
515  }
516 
522  inline uint AvailableCount() const
523  {
524  return this->count;
525  }
526 
531  inline uint ReservedCount() const
532  {
533  return this->reserved_count;
534  }
535 
541  inline uint TotalCount() const
542  {
543  return this->count + this->reserved_count;
544  }
545 
546  /* Methods for moving cargo around. First parameter is always maximum
547  * amount of cargo to be moved. Second parameter is destination (if
548  * applicable), return value is amount of cargo actually moved. */
549 
550  uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
551  uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
552  uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
553  uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
554 
562  static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
563  {
564  return cp1->source_xy == cp2->source_xy &&
565  cp1->days_in_transit == cp2->days_in_transit &&
566  cp1->source_type == cp2->source_type &&
567  cp1->source_id == cp2->source_id;
568  }
569 };
570 
571 #endif /* CARGOPACKET_H */