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 AddFeederShare(Money new_share) { this->feeder_share += new_share; }
00090
00095 inline uint16 Count() const
00096 {
00097 return this->count;
00098 }
00099
00105 inline Money FeederShare() const
00106 {
00107 return this->feeder_share;
00108 }
00109
00116 inline Money FeederShare(uint part) const
00117 {
00118 return this->feeder_share * part / static_cast<uint>(this->count);
00119 }
00120
00127 inline byte DaysInTransit() const
00128 {
00129 return this->days_in_transit;
00130 }
00131
00136 inline SourceType SourceSubsidyType() const
00137 {
00138 return this->source_type;
00139 }
00140
00145 inline SourceID SourceSubsidyID() const
00146 {
00147 return this->source_id;
00148 }
00149
00154 inline SourceID SourceStation() const
00155 {
00156 return this->source;
00157 }
00158
00163 inline TileIndex SourceStationXY() const
00164 {
00165 return this->source_xy;
00166 }
00167
00172 inline TileIndex LoadedAtXY() const
00173 {
00174 return this->loaded_at_xy;
00175 }
00176
00181 inline StationID NextStation() const
00182 {
00183 return this->next_station;
00184 }
00185
00186 static void InvalidateAllFrom(SourceType src_type, SourceID src);
00187 static void InvalidateAllFrom(StationID sid);
00188 static void AfterLoad();
00189 };
00190
00196 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
00197
00202 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
00203
00208 template <class Tinst, class Tcont>
00209 class CargoList {
00210 public:
00212 typedef typename Tcont::iterator Iterator;
00214 typedef typename Tcont::reverse_iterator ReverseIterator;
00216 typedef typename Tcont::const_iterator ConstIterator;
00218 typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
00219
00221 enum MoveToAction {
00222 MTA_BEGIN = 0,
00223 MTA_TRANSFER = 0,
00224 MTA_DELIVER,
00225 MTA_KEEP,
00226 MTA_LOAD,
00227 MTA_END,
00228 NUM_MOVE_TO_ACTION = MTA_END
00229 };
00230
00231 protected:
00232 uint count;
00233 uint cargo_days_in_transit;
00234
00235 Tcont packets;
00236
00237 void AddToCache(const CargoPacket *cp);
00238
00239 void RemoveFromCache(const CargoPacket *cp, uint count);
00240
00241 static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
00242
00243 public:
00245 CargoList() {}
00246
00247 ~CargoList();
00248
00249 void OnCleanPool();
00250
00255 inline const Tcont *Packets() const
00256 {
00257 return &this->packets;
00258 }
00259
00264 inline uint DaysInTransit() const
00265 {
00266 return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
00267 }
00268
00269 void InvalidateCache();
00270 };
00271
00272 typedef std::list<CargoPacket *> CargoPacketList;
00273
00277 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
00278 protected:
00280 typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
00281
00282 Money feeder_share;
00283 uint action_counts[NUM_MOVE_TO_ACTION];
00284
00285 template<class Taction>
00286 void ShiftCargo(Taction action);
00287
00288 template<class Taction>
00289 void PopCargo(Taction action);
00290
00294 inline void AssertCountConsistency() const
00295 {
00296 assert(this->action_counts[MTA_KEEP] +
00297 this->action_counts[MTA_DELIVER] +
00298 this->action_counts[MTA_TRANSFER] +
00299 this->action_counts[MTA_LOAD] == this->count);
00300 }
00301
00302 void AddToCache(const CargoPacket *cp);
00303 void RemoveFromCache(const CargoPacket *cp, uint count);
00304
00305 void AddToMeta(const CargoPacket *cp, MoveToAction action);
00306 void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
00307
00308 public:
00310 friend class StationCargoList;
00312 friend class CargoList<VehicleCargoList, CargoPacketList>;
00314 friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
00315
00316 friend class CargoShift;
00317 friend class CargoTransfer;
00318 friend class CargoDelivery;
00319 template<class Tsource>
00320 friend class CargoRemoval;
00321 friend class CargoReturn;
00322
00327 inline StationID Source() const
00328 {
00329 return this->count == 0 ? INVALID_STATION : this->packets.front()->source;
00330 }
00331
00336 inline Money FeederShare() const
00337 {
00338 return this->feeder_share;
00339 }
00340
00346 inline uint ActionCount(MoveToAction action) const
00347 {
00348 return this->action_counts[action];
00349 }
00350
00356 inline uint StoredCount() const
00357 {
00358 return this->count - this->action_counts[MTA_LOAD];
00359 }
00360
00365 inline uint TotalCount() const
00366 {
00367 return this->count;
00368 }
00369
00374 inline uint ReservedCount() const
00375 {
00376 return this->action_counts[MTA_LOAD];
00377 }
00378
00383 inline uint UnloadCount() const
00384 {
00385 return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
00386 }
00387
00392 inline uint RemainingCount() const
00393 {
00394 return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
00395 }
00396
00397 void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
00398
00399 void AgeCargo();
00400
00401 void InvalidateCache();
00402
00403 void SetTransferLoadPlace(TileIndex xy);
00404
00405 bool Stage(bool accepted, StationID current_station, StationID next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
00406
00412 inline void KeepAll()
00413 {
00414 this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
00415 this->action_counts[MTA_KEEP] = this->count;
00416 }
00417
00418
00419
00420
00421
00422 uint Reassign(uint max_move, MoveToAction from, MoveToAction to);
00423 uint Return(uint max_move, StationCargoList *dest, StationID next_station);
00424 uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
00425 uint Shift(uint max_move, VehicleCargoList *dest);
00426 uint Truncate(uint max_move = UINT_MAX);
00427
00435 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00436 {
00437 return cp1->source_xy == cp2->source_xy &&
00438 cp1->days_in_transit == cp2->days_in_transit &&
00439 cp1->source_type == cp2->source_type &&
00440 cp1->source_id == cp2->source_id &&
00441 cp1->loaded_at_xy == cp2->loaded_at_xy;
00442 }
00443 };
00444
00445 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
00446 typedef std::map<StationID, uint> StationCargoAmountMap;
00447
00451 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
00452 protected:
00454 typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
00455
00456 uint reserved_count;
00457
00458 public:
00460 friend class CargoList<StationCargoList, StationCargoPacketMap>;
00462 friend const struct SaveLoad *GetGoodsDesc();
00463
00464 friend class CargoLoad;
00465 friend class CargoTransfer;
00466 template<class Tsource>
00467 friend class CargoRemoval;
00468 friend class CargoReservation;
00469 friend class CargoReturn;
00470 friend class CargoReroute;
00471
00472 static void InvalidateAllFrom(SourceType src_type, SourceID src);
00473
00474 template<class Taction>
00475 bool ShiftCargo(Taction &action, StationID next);
00476
00477 template<class Taction>
00478 uint ShiftCargo(Taction action, StationID next, bool include_invalid);
00479
00480 void Append(CargoPacket *cp, StationID next);
00481
00487 inline bool HasCargoFor(StationID next) const
00488 {
00489 return this->packets.find(next) != this->packets.end();
00490 }
00491
00496 inline StationID Source() const
00497 {
00498 return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->source;
00499 }
00500
00506 inline uint AvailableCount() const
00507 {
00508 return this->count;
00509 }
00510
00515 inline uint ReservedCount() const
00516 {
00517 return this->reserved_count;
00518 }
00519
00525 inline uint TotalCount() const
00526 {
00527 return this->count + this->reserved_count;
00528 }
00529
00530
00531
00532
00533
00534 uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
00535 uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next);
00536 uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
00537 uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
00538
00546 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
00547 {
00548 return cp1->source_xy == cp2->source_xy &&
00549 cp1->days_in_transit == cp2->days_in_transit &&
00550 cp1->source_type == cp2->source_type &&
00551 cp1->source_id == cp2->source_id;
00552 }
00553 };
00554
00555 #endif