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 "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;
00034
00035 template <class Tinst, class Tcont> class CargoList;
00036 class StationCargoList;
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
00417
00418
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
00519
00520
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, 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