00001
00002
00003
00004
00005
00006
00007
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;
00036 class 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 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