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
00039 typedef uint32 TileOrStationID;
00040
00044 struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> {
00045 private:
00046 Money feeder_share;
00047 uint16 count;
00048 byte days_in_transit;
00049 SourceTypeByte source_type;
00050 SourceID source_id;
00051 StationID source;
00052 TileIndex source_xy;
00053 union {
00054 TileOrStationID loaded_at_xy;
00055 TileOrStationID next_station;
00056 };
00057
00059 template <class Tinst, class Tcont> friend class CargoList;
00060 friend class VehicleCargoList;
00061 friend class StationCargoList;
00063 friend const struct SaveLoad *GetCargoPacketDesc();
00064 public:
00066 static const uint16 MAX_COUNT = UINT16_MAX;
00067
00068 CargoPacket();
00069 CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id);
00070 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);
00071
00073 ~CargoPacket() { }
00074
00075 CargoPacket *Split(uint new_size);
00076 void Merge(CargoPacket *cp);
00077 void Reduce(uint count);
00078
00083 void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
00084
00089 void SetNextStation(StationID next_station) { this->next_station = next_station; }
00090
00095 void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
00096
00101 inline uint16 Count() const
00102 {
00103 return this->count;
00104 }
00105
00111 inline Money FeederShare() const
00112 {
00113 return this->feeder_share;
00114 }
00115
00122 inline Money FeederShare(uint part) const
00123 {
00124 return this->feeder_share * part / static_cast<uint>(this->count);
00125 }
00126
00133 inline byte DaysInTransit() const
00134 {
00135 return this->days_in_transit;
00136 }
00137
00142 inline SourceType SourceSubsidyType() const
00143 {
00144 return this->source_type;
00145 }
00146
00151 inline SourceID SourceSubsidyID() const
00152 {
00153 return this->source_id;
00154 }
00155
00160 inline StationID SourceStation() const
00161 {
00162 return this->source;
00163 }
00164
00169 inline TileIndex SourceStationXY() const
00170 {
00171 return this->source_xy;
00172 }
00173
00178 inline TileIndex LoadedAtXY() const
00179 {
00180 return this->loaded_at_xy;
00181 }
00182
00187 inline StationID NextStation() const
00188 {
00189 return this->next_station;
00190 }
00191
00192 static void InvalidateAllFrom(SourceType src_type, SourceID src);
00193 static void InvalidateAllFrom(StationID sid);
00194 static void AfterLoad();
00195 };
00196
00202 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
00203
00208 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
00209
00214 template <class Tinst, class Tcont>
00215 class CargoList {
00216 public:
00218 typedef typename Tcont::iterator Iterator;
00220 typedef typename Tcont::reverse_iterator ReverseIterator;
00222 typedef typename Tcont::const_iterator ConstIterator;
00224 typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
00225
00227 enum MoveToAction {
00228 MTA_BEGIN = 0,
00229 MTA_TRANSFER = 0,
00230 MTA_DELIVER,
00231 MTA_KEEP,
00232 MTA_LOAD,
00233 MTA_END,
00234 NUM_MOVE_TO_ACTION = MTA_END
00235 };
00236
00237 protected:
00238 uint count;
00239 uint cargo_days_in_transit;
00240
00241 Tcont packets;
00242
00243 void AddToCache(const CargoPacket *cp);
00244
00245 void RemoveFromCache(const CargoPacket *cp, uint count);
00246
00247 static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
00248
00249 public:
00251 CargoList() {}
00252
00253 ~CargoList();
00254
00255 void OnCleanPool();
00256
00261 inline const Tcont *Packets() const
00262 {
00263 return &this->packets;
00264 }
00265
00270 inline uint DaysInTransit() const
00271 {
00272 return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
00273 }
00274
00275 void InvalidateCache();
00276 };
00277
00278 typedef std::list<CargoPacket *> CargoPacketList;
00279
00283 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
00284 protected:
00286 typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
00287
00288 Money feeder_share;
00289 uint action_counts[NUM_MOVE_TO_ACTION];
00290
00291 template<class Taction>
00292 void ShiftCargo(Taction action);
00293
00294 template<class Taction>
00295 void PopCargo(Taction action);
00296
00300 inline void AssertCountConsistency() const
00301 {
00302 assert(this->action_counts[MTA_KEEP] +
00303 this->action_counts[MTA_DELIVER] +
00304 this->action_counts[MTA_TRANSFER] +
00305 this->action_counts[MTA_LOAD] == this->count);
00306 }
00307
00308 void AddToCache(const CargoPacket *cp);
00309 void RemoveFromCache(const CargoPacket *cp, uint count);
00310
00311 void AddToMeta(const CargoPacket *cp, MoveToAction action);
00312 void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
00313
00314 static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
00315 StationID current_station, bool accepted, StationIDStack next_station);
00316
00317 public:
00319 friend class StationCargoList;
00321 friend class CargoList<VehicleCargoList, CargoPacketList>;
00323 friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
00324
00325 friend class CargoShift;
00326 friend class CargoTransfer;
00327 friend class CargoDelivery;
00328 template<class Tsource>
00329 friend class CargoRemoval;
00330 friend class CargoReturn;
00331 friend class VehicleCargoReroute;
00332
00337 inline StationID Source() const
00338 {
00339 return this->count == 0 ? INVALID_STATION : this->packets.front()->source;
00340 }
00341
00346 inline Money FeederShare() const
00347 {
00348 return this->feeder_share;
00349 }
00350
00356 inline uint ActionCount(MoveToAction action) const
00357 {
00358 return this->action_counts[action];
00359 }
00360
00366 inline uint StoredCount() const
00367 {
00368 return this->count - this->action_counts[MTA_LOAD];
00369 }
00370
00375 inline uint TotalCount() const
00376 {
00377 return this->count;
00378 }
00379
00384 inline uint ReservedCount() const
00385 {
00386 return this->action_counts[MTA_LOAD];
00387 }
00388
00393 inline uint UnloadCount() const
00394 {
00395 return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
00396 }
00397
00402 inline uint RemainingCount() const
00403 {
00404 return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
00405 }
00406
00407 void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
00408
00409 void AgeCargo();
00410
00411 void InvalidateCache();
00412
00413 void SetTransferLoadPlace(TileIndex xy);
00414
00415 bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
00416
00422 inline void KeepAll()
00423 {
00424 this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
00425 this->action_counts[MTA_KEEP] = this->count;
00426 }
00427
00428
00429
00430
00431
00432 template<MoveToAction Tfrom, MoveToAction Tto>
00433 uint Reassign(uint max_move, TileOrStationID update = INVALID_TILE);
00434 uint Return(uint max_move, StationCargoList *dest, StationID next_station);
00435 uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
00436 uint Shift(uint max_move, VehicleCargoList *dest);
00437 uint Truncate(uint max_move = UINT_MAX);
00438 uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
00439
00447 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00448 {
00449 return cp1->source_xy == cp2->source_xy &&
00450 cp1->days_in_transit == cp2->days_in_transit &&
00451 cp1->source_type == cp2->source_type &&
00452 cp1->source_id == cp2->source_id &&
00453 cp1->loaded_at_xy == cp2->loaded_at_xy;
00454 }
00455 };
00456
00457 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
00458 typedef std::map<StationID, uint> StationCargoAmountMap;
00459
00463 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
00464 protected:
00466 typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
00467
00468 uint reserved_count;
00469
00470 public:
00472 friend class CargoList<StationCargoList, StationCargoPacketMap>;
00474 friend const struct SaveLoad *GetGoodsDesc();
00475
00476 friend class CargoLoad;
00477 friend class CargoTransfer;
00478 template<class Tsource>
00479 friend class CargoRemoval;
00480 friend class CargoReservation;
00481 friend class CargoReturn;
00482 friend class StationCargoReroute;
00483
00484 static void InvalidateAllFrom(SourceType src_type, SourceID src);
00485
00486 template<class Taction>
00487 bool ShiftCargo(Taction &action, StationID next);
00488
00489 template<class Taction>
00490 uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid);
00491
00492 void Append(CargoPacket *cp, StationID next);
00493
00499 inline bool HasCargoFor(StationIDStack next) const
00500 {
00501 while (!next.IsEmpty()) {
00502 if (this->packets.find(next.Pop()) != this->packets.end()) return true;
00503 }
00504
00505 return this->packets.find(INVALID_STATION) != this->packets.end();
00506 }
00507
00512 inline StationID Source() const
00513 {
00514 return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->source;
00515 }
00516
00522 inline uint AvailableCount() const
00523 {
00524 return this->count;
00525 }
00526
00531 inline uint ReservedCount() const
00532 {
00533 return this->reserved_count;
00534 }
00535
00541 inline uint TotalCount() const
00542 {
00543 return this->count + this->reserved_count;
00544 }
00545
00546
00547
00548
00549
00550 uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
00551 uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
00552 uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
00553 uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
00554
00562 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00563 {
00564 return cp1->source_xy == cp2->source_xy &&
00565 cp1->days_in_transit == cp2->days_in_transit &&
00566 cp1->source_type == cp2->source_type &&
00567 cp1->source_id == cp2->source_id;
00568 }
00569 };
00570
00571 #endif