# 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 "cargotype.h"
    00021 #include "vehicle_type.h"
    00022 #include "core/multimap.hpp"
    00023 #include <list>
    00024
    00026 typedef uint32 CargoPacketID;
    00027 struct CargoPacket;
    00028
    00030 typedef Pool<CargoPacket, CargoPacketID, 1024, 0xFFF000, PT_NORMAL, true, false> CargoPacketPool;
    00032 extern CargoPacketPool _cargopacket_pool;
    00033
    00034 template <class Tinst, class Tcont> class CargoList;
    00035 class StationCargoList; // forward-declare, so we can use it in VehicleCargoList::Unreserve
    00036 class VehicleCargoList; // forward-declare, so we can use it in CargoList::MovePacket
    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   TileIndex loaded_at_xy;
    00052
    00054   template <class Tinst, class Tcont> friend class CargoList;
    00055   friend class VehicleCargoList;
    00056   friend class StationCargoList;
    00058   friend const struct SaveLoad *GetCargoPacketDesc();
    00059 public:
    00061   static const uint16 MAX_COUNT = UINT16_MAX;
    00062
    00063   CargoPacket();
    00064   CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id);
    00065   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);
    00066
    00068   ~CargoPacket() { }
    00069
    00070   CargoPacket *Split(uint new_size);
    00071   void Merge(CargoPacket *cp);
    00072
    00077   inline uint16 Count() const
    00078   {
    00079     return this->count;
    00080   }
    00081
    00087   inline Money FeederShare() const
    00088   {
    00089     return this->feeder_share;
    00090   }
    00091
    00098   inline byte DaysInTransit() const
    00099   {
    00100     return this->days_in_transit;
    00101   }
    00102
    00107   inline SourceType SourceSubsidyType() const
    00108   {
    00109     return this->source_type;
    00110   }
    00111
    00116   inline SourceID SourceSubsidyID() const
    00117   {
    00118     return this->source_id;
    00119   }
    00120
    00125   inline SourceID SourceStation() const
    00126   {
    00127     return this->source;
    00128   }
    00129
    00134   inline TileIndex SourceStationXY() const
    00135   {
    00136     return this->source_xy;
    00137   }
    00138
    00143   inline TileIndex LoadedAtXY() const
    00144   {
    00145     return this->loaded_at_xy;
    00146   }
    00147
    00148   static void InvalidateAllFrom(SourceType src_type, SourceID src);
    00149   static void InvalidateAllFrom(StationID sid);
    00150   static void AfterLoad();
    00151 };
    00152
    00158 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
    00159
    00164 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
    00165
    00167 enum UnloadType {
    00168   UL_KEEP     = 0,
    00169   UL_DELIVER  = 1 << 0,
    00170   UL_TRANSFER = 1 << 1,
    00171   UL_ACCEPTED = 1 << 2,
    00172 };
    00173
    00178 template <class Tinst, class Tcont>
    00179 class CargoList {
    00180 public:
    00182   typedef typename Tcont::iterator Iterator;
    00184   typedef typename Tcont::const_iterator ConstIterator;
    00186   typedef typename Tcont::reverse_iterator ReverseIterator;
    00188   typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
    00189
    00190 protected:
    00191   uint count;
    00192   uint cargo_days_in_transit;
    00193
    00194   Tcont packets;
    00195
    00196   void AddToCache(const CargoPacket *cp);
    00197
    00198   void RemoveFromCache(const CargoPacket *cp);
    00199
    00200   CargoPacket *RemovePacket(Iterator &it, uint cap, TileIndex load_place = INVALID_TILE);
    00201
    00202   uint MovePacket(StationCargoList *dest, StationID next, Iterator &it, uint cap);
    00203
    00204   uint MovePacket(VehicleCargoList *dest, Iterator &it, uint cap, TileIndex load_place = INVALID_TILE, bool reserved = false);
    00205
    00206 public:
    00208   CargoList() {}
    00209
    00210   ~CargoList();
    00211
    00212   void OnCleanPool();
    00213
    00218   inline const Tcont *Packets() const
    00219   {
    00220     return &this->packets;
    00221   }
    00222
    00227   inline bool Empty() const
    00228   {
    00229     return this->count == 0;
    00230   }
    00231
    00236   inline uint Count() const
    00237   {
    00238     return this->count;
    00239   }
    00240
    00245   inline uint DaysInTransit() const
    00246   {
    00247     return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
    00248   }
    00249
    00250   void Truncate(uint max_remaining);
    00251
    00252   void InvalidateCache();
    00253 };
    00254
    00255 typedef std::list<CargoPacket *> CargoPacketList;
    00256
    00260 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
    00261 protected:
    00262   uint TransferPacket(Iterator &c, uint remaining_unload, StationCargoList *dest, CargoPayment *payment, StationID next);
    00263   uint DeliverPacket(Iterator &c, uint remaining_unload, CargoPayment *payment);
    00264   uint KeepPacket(Iterator &c);
    00265
    00267   typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
    00268
    00269   CargoPacketList reserved;
    00270   Money feeder_share;
    00271   uint reserved_count;
    00272
    00273   void AddToCache(const CargoPacket *cp);
    00274   void RemoveFromCache(const CargoPacket *cp);
    00275
    00276 public:
    00278   friend class StationCargoList;
    00280   friend class CargoList<VehicleCargoList, CargoPacketList>;
    00282   friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
    00283
    00284   ~VehicleCargoList();
    00285
    00286   void OnCleanPool();
    00287
    00292   inline Money FeederShare() const
    00293   {
    00294     return this->feeder_share;
    00295   }
    00296
    00297   void Append(CargoPacket *cp, bool update_cache = true);
    00298
    00304   inline uint OnboardCount() const
    00305   {
    00306     return this->count - this->reserved_count;
    00307   }
    00308
    00313   inline uint ReservedCount() const
    00314   {
    00315     return this->reserved_count;
    00316   }
    00317
    00322   inline const CargoPacketList *Reserved() const
    00323   {
    00324     return &this->reserved;
    00325   }
    00326
    00334   inline StationID Source() const
    00335   {
    00336     if (this->Empty()) {
    00337       return INVALID_STATION;
    00338     } else if (this->packets.empty()) {
    00339       return this->reserved.front()->source;
    00340     } else {
    00341       return this->packets.front()->source;
    00342     }
    00343   }
    00344
    00345   void Reserve(CargoPacket *cp);
    00346
    00347   void Unreserve(StationID next, StationCargoList *dest);
    00348
    00349   uint LoadReserved(uint count);
    00350
    00351   void SwapReserved();
    00352
    00353   void AgeCargo();
    00354
    00355   void InvalidateCache();
    00356
    00357   uint MoveTo(VehicleCargoList *dest, uint cap);
    00358
    00366   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
    00367   {
    00368     return cp1->source_xy    == cp2->source_xy &&
    00369         cp1->days_in_transit == cp2->days_in_transit &&
    00370         cp1->source_type     == cp2->source_type &&
    00371         cp1->source_id       == cp2->source_id &&
    00372         cp1->loaded_at_xy    == cp2->loaded_at_xy;
    00373   }
    00374 };
    00375
    00376 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
    00377 typedef std::map<StationID, uint> StationCargoAmountMap;
    00378
    00382 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
    00383 public:
    00385   friend class CargoList<StationCargoList, StationCargoPacketMap>;
    00387   friend const struct SaveLoad *GetGoodsDesc();
    00388
    00389   StationCargoList() : station(NULL), cargo(INVALID_CARGO) {}
    00390
    00398   static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
    00399   {
    00400     return cp1->source_xy    == cp2->source_xy &&
    00401         cp1->days_in_transit == cp2->days_in_transit &&
    00402         cp1->source_type     == cp2->source_type &&
    00403         cp1->source_id       == cp2->source_id;
    00404   }
    00405
    00406   uint TakeFrom(VehicleCargoList *source, uint max_unload, OrderUnloadFlags flags, StationID next_station, bool has_stopped, CargoPayment *payment);
    00407
    00408   uint MoveTo(VehicleCargoList *dest, uint cap, StationID next_station, bool reserve = false);
    00409
    00410   void Append(StationID next, CargoPacket *cp);
    00411
    00412   void RerouteStalePackets(StationID to);
    00413
    00414   void CountAndTruncate(uint max_remaining, StationCargoAmountMap &cargo_per_source);
    00415
    00420   inline StationID Source() const
    00421   {
    00422     return this->Empty() ? INVALID_STATION : this->packets.begin()->second.front()->source;
    00423   }
    00424
    00425   void AssignTo(Station *station, CargoID cargo);
    00426
    00427   static void InvalidateAllFrom(SourceType src_type, SourceID src);
    00428
    00429 protected:
    00430   Station *station;
    00431   CargoID cargo;
    00432
    00433   byte GetUnloadFlags(OrderUnloadFlags order_flags);
    00434
    00435   UnloadType WillUnloadOld(byte flags, StationID source);
    00436   UnloadType WillUnloadCargoDist(byte flags, StationID next_station, StationID via, StationID source);
    00437
    00438   uint MovePackets(VehicleCargoList *dest, uint cap, Iterator begin, Iterator end, bool reserve);
    00439 };
    00440
    00441 #endif /* CARGOPACKET_H */