# cargopacket.h

Go to the documentation of this file.

    00001 /* $Id$ */
    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
    00042 struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> {
    00043 private:
    00044   Money feeder_share;
    00045   uint16 count;
    00046   byte days_in_transit;
    00047   SourceTypeByte source_type;
    00048   SourceID source_id;
    00049   StationID source;
    00050   TileIndex source_xy;
    00051   union {
    00052     TileIndex loaded_at_xy;
    00053     StationID next_station;
    00054   };
    00055
    00057   template <class Tinst, class Tcont> friend class CargoList;
    00058   friend class VehicleCargoList;
    00059   friend class StationCargoList;
    00061   friend const struct SaveLoad *GetCargoPacketDesc();
    00062 public:
    00064   static const uint16 MAX_COUNT = UINT16_MAX;
    00065
    00066   CargoPacket();
    00067   CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id);
    00068   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);
    00069
    00071   ~CargoPacket() { }
    00072
    00073   CargoPacket *Split(uint new_size);
    00074   void Merge(CargoPacket *cp);
    00075   void Reduce(uint count);
    00076
    00081   void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
    00082
    00087   void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
    00088
    00093   inline uint16 Count() const
    00094   {
    00095     return this->count;
    00096   }
    00097
    00103   inline Money FeederShare() const
    00104   {
    00105     return this->feeder_share;
    00106   }
    00107
    00114   inline Money FeederShare(uint part) const
    00115   {
    00116     return this->feeder_share * part / static_cast<uint>(this->count);
    00117   }
    00118
    00125   inline byte DaysInTransit() const
    00126   {
    00127     return this->days_in_transit;
    00128   }
    00129
    00134   inline SourceType SourceSubsidyType() const
    00135   {
    00136     return this->source_type;
    00137   }
    00138
    00143   inline SourceID SourceSubsidyID() const
    00144   {
    00145     return this->source_id;
    00146   }
    00147
    00152   inline SourceID SourceStation() const
    00153   {
    00154     return this->source;
    00155   }
    00156
    00161   inline TileIndex SourceStationXY() const
    00162   {
    00163     return this->source_xy;
    00164   }
    00165
    00170   inline TileIndex LoadedAtXY() const
    00171   {
    00172     return this->loaded_at_xy;
    00173   }
    00174
    00179   inline StationID NextStation() const
    00180   {
    00181     return this->next_station;
    00182   }
    00183
    00184   static void InvalidateAllFrom(SourceType src_type, SourceID src);
    00185   static void InvalidateAllFrom(StationID sid);
    00186   static void AfterLoad();
    00187 };
    00188
    00194 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
    00195
    00200 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
    00201
    00206 template <class Tinst, class Tcont>
    00207 class CargoList {
    00208 public:
    00210   typedef typename Tcont::iterator Iterator;
    00212   typedef typename Tcont::reverse_iterator ReverseIterator;
    00214   typedef typename Tcont::const_iterator ConstIterator;
    00216   typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
    00217
    00219   enum MoveToAction {
    00220     MTA_BEGIN = 0,
    00221     MTA_TRANSFER = 0,
    00222     MTA_DELIVER,
    00223     MTA_KEEP,
    00224     MTA_LOAD,
    00225     MTA_END,
    00226     NUM_MOVE_TO_ACTION = MTA_END
    00227   };
    00228
    00229 protected:
    00230   uint count;
    00231   uint cargo_days_in_transit;
    00232
    00233   Tcont packets;
    00234
    00235   void AddToCache(const CargoPacket *cp);
    00236
    00237   void RemoveFromCache(const CargoPacket *cp, uint count);
    00238
    00239   static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
    00240
    00241 public:
    00243   CargoList() {}
    00244
    00245   ~CargoList();
    00246
    00247   void OnCleanPool();
    00248
    00253   inline const Tcont *Packets() const
    00254   {
    00255     return &this->packets;
    00256   }
    00257
    00262   inline bool Empty() const
    00263   {
    00264     return this->count == 0;
    00265   }
    00266
    00271   inline uint Count() const
    00272   {
    00273     return this->count;
    00274   }
    00275
    00280   inline uint DaysInTransit() const
    00281   {
    00282     return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
    00283   }
    00284
    00285   void InvalidateCache();
    00286 };
    00287
    00288 typedef std::list<CargoPacket *> CargoPacketList;
    00289
    00293 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
    00294 protected:
    00296   typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
    00297
    00298   Money feeder_share;
    00299   uint action_counts[NUM_MOVE_TO_ACTION];
    00300
    00301   template<class Taction>
    00302   void ShiftCargo(Taction action);
    00303
    00304   template<class Taction>
    00305   void PopCargo(Taction action);
    00306
    00310   inline void AssertCountConsistency() const
    00311   {
    00312     assert(this->action_counts[MTA_KEEP] +
    00313         this->action_counts[MTA_DELIVER] +
    00314         this->action_counts[MTA_TRANSFER] +
    00315         this->action_counts[MTA_LOAD] == this->count);
    00316   }
    00317
    00318   void AddToCache(const CargoPacket *cp);
    00319   void RemoveFromCache(const CargoPacket *cp, uint count);
    00320
    00321   void AddToMeta(const CargoPacket *cp, MoveToAction action);
    00322   void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
    00323
    00324 public:
    00326   friend class StationCargoList;
    00328   friend class CargoList<VehicleCargoList, CargoPacketList>;
    00330   friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
    00331
    00332   friend class CargoShift;
    00333   friend class CargoTransfer;
    00334   friend class CargoDelivery;
    00335   template<class Tsource>
    00336   friend class CargoRemoval;
    00337   friend class CargoReturn;
    00338
    00343   inline StationID Source() const
    00344   {
    00345     return this->Empty() ? INVALID_STATION : this->packets.front()->source;
    00346   }
    00347
    00352   inline Money FeederShare() const
    00353   {
    00354     return this->feeder_share;
    00355   }
    00356
    00362   inline uint ActionCount(MoveToAction action) const
    00363   {
    00364     return this->action_counts[action];
    00365   }
    00366
    00372   inline uint OnboardCount() const
    00373   {
    00374     return this->count - this->action_counts[MTA_LOAD];
    00375   }
    00376
    00381   inline uint UnloadCount() const
    00382   {
    00383     return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
    00384   }
    00385
    00390   inline uint RemainingCount() const
    00391   {
    00392     return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
    00393   }
    00394
    00395   void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
    00396
    00397   void AgeCargo();
    00398
    00399   void InvalidateCache();
    00400
    00401   void SetTransferLoadPlace(TileIndex xy);
    00402
    00403   bool Stage(bool accepted, StationID current_station, StationID next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
    00404
    00410   inline void KeepAll()
    00411   {
    00412     this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
    00413     this->action_counts[MTA_KEEP] = this->count;
    00414   }
    00415
    00416   /* Methods for moving cargo around. First parameter is always maximum
    00417    * amount of cargo to be moved. Second parameter is destination (if
    00418    * applicable), return value is amount of cargo actually moved. */
    00419
    00420   uint Reassign(uint max_move, MoveToAction from, MoveToAction to);
    00421   uint Return(uint max_move, StationCargoList *dest, StationID next_station);
    00422   uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
    00423   uint Shift(uint max_move, VehicleCargoList *dest);
    00424   uint Truncate(uint max_move = UINT_MAX);
    00425
    00433   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
    00434   {
    00435     return cp1->source_xy    == cp2->source_xy &&
    00436         cp1->days_in_transit == cp2->days_in_transit &&
    00437         cp1->source_type     == cp2->source_type &&
    00438         cp1->source_id       == cp2->source_id &&
    00439         cp1->loaded_at_xy    == cp2->loaded_at_xy;
    00440   }
    00441 };
    00442
    00443 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
    00444 typedef std::map<StationID, uint> StationCargoAmountMap;
    00445
    00449 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
    00450 protected:
    00452   typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
    00453
    00454   uint reserved_count;
    00455
    00456 public:
    00458   friend class CargoList<StationCargoList, StationCargoPacketMap>;
    00460   friend const struct SaveLoad *GetGoodsDesc();
    00461
    00462   friend class CargoLoad;
    00463   friend class CargoTransfer;
    00464   template<class Tsource>
    00465   friend class CargoRemoval;
    00466   friend class CargoReservation;
    00467   friend class CargoReturn;
    00468   friend class CargoReroute;
    00469
    00470   static void InvalidateAllFrom(SourceType src_type, SourceID src);
    00471
    00472   template<class Taction>
    00473   bool ShiftCargo(Taction &action, StationID next);
    00474
    00475   template<class Taction>
    00476   uint ShiftCargo(Taction action, StationID next, bool include_invalid);
    00477
    00478   void Append(CargoPacket *cp, StationID next);
    00479
    00485   inline bool HasCargoFor(StationID next) const
    00486   {
    00487     return this->packets.find(next) != this->packets.end();
    00488   }
    00489
    00494   inline StationID Source() const
    00495   {
    00496     return this->Empty() ? INVALID_STATION : this->packets.begin()->second.front()->source;
    00497   }
    00498
    00503   inline uint ReservedCount() const
    00504   {
    00505     return this->reserved_count;
    00506   }
    00507
    00513   inline uint TotalCount() const
    00514   {
    00515     return this->count + this->reserved_count;
    00516   }
    00517
    00518   /* Methods for moving cargo around. First parameter is always maximum
    00519    * amount of cargo to be moved. Second parameter is destination (if
    00520    * applicable), return value is amount of cargo actually moved. */
    00521
    00522   uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
    00523   uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
    00524   uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
    00525   uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
    00526
    00534   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
    00535   {
    00536     return cp1->source_xy    == cp2->source_xy &&
    00537         cp1->days_in_transit == cp2->days_in_transit &&
    00538         cp1->source_type     == cp2->source_type &&
    00539         cp1->source_id       == cp2->source_id;
    00540   }
    00541 };
    00542
    00543 #endif /* CARGOPACKET_H */