# cargopacket.h

Go to the documentation of this file.

    00001 /* $Id: cargopacket.h 26327 2014-02-09 21:10:25Z fonsinchen $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    00008  */
    00009
    00012 #ifndef CARGOPACKET_H
    00013 #define CARGOPACKET_H
    00014
    00015 #include "core/pool_type.hpp"
    00016 #include "economy_type.h"
    00017 #include "station_type.h"
    00018 #include "order_type.h"
    00019 #include "cargo_type.h"
    00020 #include "vehicle_type.h"
    00021 #include "core/multimap.hpp"
    00022 #include <list>
    00023
    00025 typedef uint32 CargoPacketID;
    00026 struct CargoPacket;
    00027
    00029 typedef Pool<CargoPacket, CargoPacketID, 1024, 0xFFF000, PT_NORMAL, true, false> CargoPacketPool;
    00031 extern CargoPacketPool _cargopacket_pool;
    00032
    00033 struct GoodsEntry; // forward-declare for Stage() and RerouteStalePackets()
    00034
    00035 template <class Tinst, class Tcont> class CargoList;
    00036 class StationCargoList; // forward-declare, so we can use it in VehicleCargoList.
    00037 extern const struct SaveLoad *GetCargoPacketDesc();
    00038
    00039 typedef uint32 TileOrStationID;
    00040
    00044 struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> {
    00045 private:
    00046   Money feeder_share;
    00047   uint16 count;
    00048   byte days_in_transit;
    00049   SourceTypeByte source_type;
    00050   SourceID source_id;
    00051   StationID source;
    00052   TileIndex source_xy;
    00053   union {
    00054     TileOrStationID loaded_at_xy;
    00055     TileOrStationID next_station;
    00056   };
    00057
    00059   template <class Tinst, class Tcont> friend class CargoList;
    00060   friend class VehicleCargoList;
    00061   friend class StationCargoList;
    00063   friend const struct SaveLoad *GetCargoPacketDesc();
    00064 public:
    00066   static const uint16 MAX_COUNT = UINT16_MAX;
    00067
    00068   CargoPacket();
    00069   CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id);
    00070   CargoPacket(uint16 count, byte days_in_transit, StationID source, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share = 0, SourceType source_type = ST_INDUSTRY, SourceID source_id = INVALID_SOURCE);
    00071
    00073   ~CargoPacket() { }
    00074
    00075   CargoPacket *Split(uint new_size);
    00076   void Merge(CargoPacket *cp);
    00077   void Reduce(uint count);
    00078
    00083   void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
    00084
    00089   void SetNextStation(StationID next_station) { this->next_station = next_station; }
    00090
    00095   void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
    00096
    00101   inline uint16 Count() const
    00102   {
    00103     return this->count;
    00104   }
    00105
    00111   inline Money FeederShare() const
    00112   {
    00113     return this->feeder_share;
    00114   }
    00115
    00122   inline Money FeederShare(uint part) const
    00123   {
    00124     return this->feeder_share * part / static_cast<uint>(this->count);
    00125   }
    00126
    00133   inline byte DaysInTransit() const
    00134   {
    00135     return this->days_in_transit;
    00136   }
    00137
    00142   inline SourceType SourceSubsidyType() const
    00143   {
    00144     return this->source_type;
    00145   }
    00146
    00151   inline SourceID SourceSubsidyID() const
    00152   {
    00153     return this->source_id;
    00154   }
    00155
    00160   inline SourceID SourceStation() const
    00161   {
    00162     return this->source;
    00163   }
    00164
    00169   inline TileIndex SourceStationXY() const
    00170   {
    00171     return this->source_xy;
    00172   }
    00173
    00178   inline TileIndex LoadedAtXY() const
    00179   {
    00180     return this->loaded_at_xy;
    00181   }
    00182
    00187   inline StationID NextStation() const
    00188   {
    00189     return this->next_station;
    00190   }
    00191
    00192   static void InvalidateAllFrom(SourceType src_type, SourceID src);
    00193   static void InvalidateAllFrom(StationID sid);
    00194   static void AfterLoad();
    00195 };
    00196
    00202 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
    00203
    00208 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
    00209
    00214 template <class Tinst, class Tcont>
    00215 class CargoList {
    00216 public:
    00218   typedef typename Tcont::iterator Iterator;
    00220   typedef typename Tcont::reverse_iterator ReverseIterator;
    00222   typedef typename Tcont::const_iterator ConstIterator;
    00224   typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
    00225
    00227   enum MoveToAction {
    00228     MTA_BEGIN = 0,
    00229     MTA_TRANSFER = 0,
    00230     MTA_DELIVER,
    00231     MTA_KEEP,
    00232     MTA_LOAD,
    00233     MTA_END,
    00234     NUM_MOVE_TO_ACTION = MTA_END
    00235   };
    00236
    00237 protected:
    00238   uint count;
    00239   uint cargo_days_in_transit;
    00240
    00241   Tcont packets;
    00242
    00243   void AddToCache(const CargoPacket *cp);
    00244
    00245   void RemoveFromCache(const CargoPacket *cp, uint count);
    00246
    00247   static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
    00248
    00249 public:
    00251   CargoList() {}
    00252
    00253   ~CargoList();
    00254
    00255   void OnCleanPool();
    00256
    00261   inline const Tcont *Packets() const
    00262   {
    00263     return &this->packets;
    00264   }
    00265
    00270   inline uint DaysInTransit() const
    00271   {
    00272     return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
    00273   }
    00274
    00275   void InvalidateCache();
    00276 };
    00277
    00278 typedef std::list<CargoPacket *> CargoPacketList;
    00279
    00283 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
    00284 protected:
    00286   typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
    00287
    00288   Money feeder_share;
    00289   uint action_counts[NUM_MOVE_TO_ACTION];
    00290
    00291   template<class Taction>
    00292   void ShiftCargo(Taction action);
    00293
    00294   template<class Taction>
    00295   void PopCargo(Taction action);
    00296
    00300   inline void AssertCountConsistency() const
    00301   {
    00302     assert(this->action_counts[MTA_KEEP] +
    00303         this->action_counts[MTA_DELIVER] +
    00304         this->action_counts[MTA_TRANSFER] +
    00305         this->action_counts[MTA_LOAD] == this->count);
    00306   }
    00307
    00308   void AddToCache(const CargoPacket *cp);
    00309   void RemoveFromCache(const CargoPacket *cp, uint count);
    00310
    00311   void AddToMeta(const CargoPacket *cp, MoveToAction action);
    00312   void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
    00313
    00314   static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
    00315       StationID current_station, bool accepted, StationIDStack next_station);
    00316
    00317 public:
    00319   friend class StationCargoList;
    00321   friend class CargoList<VehicleCargoList, CargoPacketList>;
    00323   friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
    00324
    00325   friend class CargoShift;
    00326   friend class CargoTransfer;
    00327   friend class CargoDelivery;
    00328   template<class Tsource>
    00329   friend class CargoRemoval;
    00330   friend class CargoReturn;
    00331   friend class VehicleCargoReroute;
    00332
    00337   inline StationID Source() const
    00338   {
    00339     return this->count == 0 ? INVALID_STATION : this->packets.front()->source;
    00340   }
    00341
    00346   inline Money FeederShare() const
    00347   {
    00348     return this->feeder_share;
    00349   }
    00350
    00356   inline uint ActionCount(MoveToAction action) const
    00357   {
    00358     return this->action_counts[action];
    00359   }
    00360
    00366   inline uint StoredCount() const
    00367   {
    00368     return this->count - this->action_counts[MTA_LOAD];
    00369   }
    00370
    00375   inline uint TotalCount() const
    00376   {
    00377     return this->count;
    00378   }
    00379
    00384   inline uint ReservedCount() const
    00385   {
    00386     return this->action_counts[MTA_LOAD];
    00387   }
    00388
    00393   inline uint UnloadCount() const
    00394   {
    00395     return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
    00396   }
    00397
    00402   inline uint RemainingCount() const
    00403   {
    00404     return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
    00405   }
    00406
    00407   void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
    00408
    00409   void AgeCargo();
    00410
    00411   void InvalidateCache();
    00412
    00413   void SetTransferLoadPlace(TileIndex xy);
    00414
    00415   bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
    00416
    00422   inline void KeepAll()
    00423   {
    00424     this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
    00425     this->action_counts[MTA_KEEP] = this->count;
    00426   }
    00427
    00428   /* Methods for moving cargo around. First parameter is always maximum
    00429    * amount of cargo to be moved. Second parameter is destination (if
    00430    * applicable), return value is amount of cargo actually moved. */
    00431
    00432   template<MoveToAction Tfrom, MoveToAction Tto>
    00433   uint Reassign(uint max_move, TileOrStationID update = INVALID_TILE);
    00434   uint Return(uint max_move, StationCargoList *dest, StationID next_station);
    00435   uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
    00436   uint Shift(uint max_move, VehicleCargoList *dest);
    00437   uint Truncate(uint max_move = UINT_MAX);
    00438   uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
    00439
    00447   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
    00448   {
    00449     return cp1->source_xy    == cp2->source_xy &&
    00450         cp1->days_in_transit == cp2->days_in_transit &&
    00451         cp1->source_type     == cp2->source_type &&
    00452         cp1->source_id       == cp2->source_id &&
    00453         cp1->loaded_at_xy    == cp2->loaded_at_xy;
    00454   }
    00455 };
    00456
    00457 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
    00458 typedef std::map<StationID, uint> StationCargoAmountMap;
    00459
    00463 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
    00464 protected:
    00466   typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
    00467
    00468   uint reserved_count;
    00469
    00470 public:
    00472   friend class CargoList<StationCargoList, StationCargoPacketMap>;
    00474   friend const struct SaveLoad *GetGoodsDesc();
    00475
    00476   friend class CargoLoad;
    00477   friend class CargoTransfer;
    00478   template<class Tsource>
    00479   friend class CargoRemoval;
    00480   friend class CargoReservation;
    00481   friend class CargoReturn;
    00482   friend class StationCargoReroute;
    00483
    00484   static void InvalidateAllFrom(SourceType src_type, SourceID src);
    00485
    00486   template<class Taction>
    00487   bool ShiftCargo(Taction &action, StationID next);
    00488
    00489   template<class Taction>
    00490   uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid);
    00491
    00492   void Append(CargoPacket *cp, StationID next);
    00493
    00499   inline bool HasCargoFor(StationIDStack next) const
    00500   {
    00501     while (!next.IsEmpty()) {
    00502       if (this->packets.find(next.Pop()) != this->packets.end()) return true;
    00503     }
    00504     /* Packets for INVALID_STTION can go anywhere. */
    00505     return this->packets.find(INVALID_STATION) != this->packets.end();
    00506   }
    00507
    00512   inline StationID Source() const
    00513   {
    00514     return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->source;
    00515   }
    00516
    00522   inline uint AvailableCount() const
    00523   {
    00524     return this->count;
    00525   }
    00526
    00531   inline uint ReservedCount() const
    00532   {
    00533     return this->reserved_count;
    00534   }
    00535
    00541   inline uint TotalCount() const
    00542   {
    00543     return this->count + this->reserved_count;
    00544   }
    00545
    00546   /* Methods for moving cargo around. First parameter is always maximum
    00547    * amount of cargo to be moved. Second parameter is destination (if
    00548    * applicable), return value is amount of cargo actually moved. */
    00549
    00550   uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
    00551   uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
    00552   uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
    00553   uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
    00554
    00562   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
    00563   {
    00564     return cp1->source_xy    == cp2->source_xy &&
    00565         cp1->days_in_transit == cp2->days_in_transit &&
    00566         cp1->source_type     == cp2->source_type &&
    00567         cp1->source_id       == cp2->source_id;
    00568   }
    00569 };
    00570
    00571 #endif /* CARGOPACKET_H */