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 FORCEINLINE uint16 Count() const
00078 {
00079 return this->count;
00080 }
00081
00087 FORCEINLINE Money FeederShare() const
00088 {
00089 return this->feeder_share;
00090 }
00091
00098 FORCEINLINE byte DaysInTransit() const
00099 {
00100 return this->days_in_transit;
00101 }
00102
00107 FORCEINLINE SourceType SourceSubsidyType() const
00108 {
00109 return this->source_type;
00110 }
00111
00116 FORCEINLINE SourceID SourceSubsidyID() const
00117 {
00118 return this->source_id;
00119 }
00120
00125 FORCEINLINE SourceID SourceStation() const
00126 {
00127 return this->source;
00128 }
00129
00134 FORCEINLINE TileIndex SourceStationXY() const
00135 {
00136 return this->source_xy;
00137 }
00138
00143 FORCEINLINE 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 FORCEINLINE const Tcont *Packets() const
00219 {
00220 return &this->packets;
00221 }
00222
00227 FORCEINLINE bool Empty() const
00228 {
00229 return this->count == 0;
00230 }
00231
00236 FORCEINLINE uint Count() const
00237 {
00238 return this->count;
00239 }
00240
00245 FORCEINLINE uint DaysInTransit() const
00246 {
00247 return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
00248 }
00249
00250 void Append(CargoPacket *cp, bool update_cache = true);
00251 void Truncate(uint max_remaining);
00252
00253 void InvalidateCache();
00254 };
00255
00256 typedef std::list<CargoPacket *> CargoPacketList;
00257
00261 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
00262 protected:
00263
00264 uint TransferPacket(Iterator &c, uint remaining_unload, StationCargoList *dest, CargoPayment *payment, StationID next);
00265 uint DeliverPacket(Iterator &c, uint remaining_unload, CargoPayment *payment);
00266 uint KeepPacket(Iterator &c);
00267
00269 typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
00270
00271 CargoPacketList reserved;
00272 Money feeder_share;
00273 uint reserved_count;
00274
00275 void AddToCache(const CargoPacket *cp);
00276 void RemoveFromCache(const CargoPacket *cp);
00277
00278 public:
00280 friend class StationCargoList;
00282 friend class CargoList<VehicleCargoList, CargoPacketList>;
00284 friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
00285
00286 ~VehicleCargoList();
00287
00288 void OnCleanPool();
00289
00294 FORCEINLINE Money FeederShare() const
00295 {
00296 return this->feeder_share;
00297 }
00298
00299 void Append(CargoPacket *cp, bool update_cache = true);
00300
00306 FORCEINLINE uint OnboardCount() const
00307 {
00308 return this->count - this->reserved_count;
00309 }
00310
00315 FORCEINLINE uint ReservedCount() const
00316 {
00317 return this->reserved_count;
00318 }
00319
00324 FORCEINLINE const CargoPacketList *Reserved() const
00325 {
00326 return &this->reserved;
00327 }
00328
00336 FORCEINLINE StationID Source() const
00337 {
00338 if (this->Empty()) {
00339 return INVALID_STATION;
00340 } else if (this->packets.empty()) {
00341 return this->reserved.front()->source;
00342 } else {
00343 return this->packets.front()->source;
00344 }
00345 }
00346
00347 void Reserve(CargoPacket *cp);
00348
00349 void Unreserve(StationID next, StationCargoList *dest);
00350
00351 uint LoadReserved(uint count);
00352
00353 void SwapReserved();
00354
00355 void AgeCargo();
00356
00357 void InvalidateCache();
00358
00359 uint MoveTo(VehicleCargoList *dest, uint cap);
00360
00368 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00369 {
00370 return cp1->source_xy == cp2->source_xy &&
00371 cp1->days_in_transit == cp2->days_in_transit &&
00372 cp1->source_type == cp2->source_type &&
00373 cp1->source_id == cp2->source_id &&
00374 cp1->loaded_at_xy == cp2->loaded_at_xy;
00375 }
00376 };
00377
00378 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
00379 typedef std::map<StationID, uint> StationCargoAmountMap;
00380
00384 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
00385 public:
00387 friend class CargoList<StationCargoList, StationCargoPacketMap>;
00389 friend const struct SaveLoad *GetGoodsDesc();
00390
00391 StationCargoList() : station(NULL), cargo(INVALID_CARGO) {}
00392
00400 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00401 {
00402 return cp1->source_xy == cp2->source_xy &&
00403 cp1->days_in_transit == cp2->days_in_transit &&
00404 cp1->source_type == cp2->source_type &&
00405 cp1->source_id == cp2->source_id;
00406 }
00407
00408 uint TakeFrom(VehicleCargoList *source, uint max_unload, OrderUnloadFlags flags, StationID next_station, bool has_stopped, CargoPayment *payment);
00409
00410 uint MoveTo(VehicleCargoList *dest, uint cap, StationID next_station, bool reserve = false);
00411
00412 void Append(StationID next, CargoPacket *cp);
00413
00414 void RerouteStalePackets(StationID to);
00415
00416 void CountAndTruncate(uint max_remaining, StationCargoAmountMap &cargo_per_source);
00417
00422 FORCEINLINE StationID Source() const
00423 {
00424 return this->Empty() ? INVALID_STATION : this->packets.begin()->second.front()->source;
00425 }
00426
00427 void AssignTo(Station *station, CargoID cargo);
00428
00429 static void InvalidateAllFrom(SourceType src_type, SourceID src);
00430
00431 protected:
00432 Station *station;
00433 CargoID cargo;
00434
00435 byte GetUnloadFlags(OrderUnloadFlags order_flags);
00436
00437 UnloadType WillUnloadOld(byte flags, StationID source);
00438 UnloadType WillUnloadCargoDist(byte flags, StationID next_station, StationID via, StationID source);
00439
00440 uint MovePackets(VehicleCargoList *dest, uint cap, Iterator begin, Iterator end, bool reserve);
00441 };
00442
00443 #endif