OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

cargopacket.h
Go to the documentation of this file.
1 /* $Id: cargopacket.h 26660 2014-06-21 19:52:52Z fonsinchen $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
9
12 #ifndef CARGOPACKET_H
13 #define CARGOPACKET_H
14
15 #include "core/pool_type.hpp"
16 #include "economy_type.h"
17 #include "station_type.h"
18 #include "order_type.h"
19 #include "cargo_type.h"
20 #include "vehicle_type.h"
21 #include "core/multimap.hpp"
22 #include <list>
23
25 typedef uint32 CargoPacketID;
26 struct CargoPacket;
27
29 typedef Pool<CargoPacket, CargoPacketID, 1024, 0xFFF000, PT_NORMAL, true, false> CargoPacketPool;
31 extern CargoPacketPool _cargopacket_pool;
32
33 struct GoodsEntry; // forward-declare for Stage() and RerouteStalePackets()
34
35 template <class Tinst, class Tcont> class CargoList;
36 class StationCargoList; // forward-declare, so we can use it in VehicleCargoList.
37 extern const struct SaveLoad *GetCargoPacketDesc();
38
39 typedef uint32 TileOrStationID;
40
44 struct CargoPacket : CargoPacketPool::PoolItem<&_cargopacket_pool> {
45 private:
46 Money feeder_share;
47 uint16 count;
48 byte days_in_transit;
49 SourceTypeByte source_type;
50 SourceID source_id;
51 StationID source;
52 TileIndex source_xy;
53 union {
54 TileOrStationID loaded_at_xy;
55 TileOrStationID next_station;
56 };
57
59 template <class Tinst, class Tcont> friend class CargoList;
60 friend class VehicleCargoList;
61 friend class StationCargoList;
63 friend const struct SaveLoad *GetCargoPacketDesc();
64 public:
66 static const uint16 MAX_COUNT = UINT16_MAX;
67
68 CargoPacket();
69 CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id);
70 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);
71
73 ~CargoPacket() { }
74
75 CargoPacket *Split(uint new_size);
76 void Merge(CargoPacket *cp);
77 void Reduce(uint count);
78
83 void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; }
84
89 void SetNextStation(StationID next_station) { this->next_station = next_station; }
90
95 void AddFeederShare(Money new_share) { this->feeder_share += new_share; }
96
101 inline uint16 Count() const
102 {
103 return this->count;
104 }
105
111 inline Money FeederShare() const
112 {
113 return this->feeder_share;
114 }
115
122 inline Money FeederShare(uint part) const
123 {
124 return this->feeder_share * part / static_cast<uint>(this->count);
125 }
126
133 inline byte DaysInTransit() const
134 {
135 return this->days_in_transit;
136 }
137
142 inline SourceType SourceSubsidyType() const
143 {
144 return this->source_type;
145 }
146
151 inline SourceID SourceSubsidyID() const
152 {
153 return this->source_id;
154 }
155
160 inline StationID SourceStation() const
161 {
162 return this->source;
163 }
164
169 inline TileIndex SourceStationXY() const
170 {
171 return this->source_xy;
172 }
173
178 inline TileIndex LoadedAtXY() const
179 {
180 return this->loaded_at_xy;
181 }
182
187 inline StationID NextStation() const
188 {
189 return this->next_station;
190 }
191
192 static void InvalidateAllFrom(SourceType src_type, SourceID src);
193 static void InvalidateAllFrom(StationID sid);
194 static void AfterLoad();
195 };
196
202 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
203
208 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
209
214 template <class Tinst, class Tcont>
215 class CargoList {
216 public:
218 typedef typename Tcont::iterator Iterator;
220 typedef typename Tcont::reverse_iterator ReverseIterator;
222 typedef typename Tcont::const_iterator ConstIterator;
224 typedef typename Tcont::const_reverse_iterator ConstReverseIterator;
225
227 enum MoveToAction {
228 MTA_BEGIN = 0,
229 MTA_TRANSFER = 0,
230 MTA_DELIVER,
231 MTA_KEEP,
232 MTA_LOAD,
233 MTA_END,
234 NUM_MOVE_TO_ACTION = MTA_END
235 };
236
237 protected:
238 uint count;
239 uint cargo_days_in_transit;
240
241 Tcont packets;
242
243 void AddToCache(const CargoPacket *cp);
244
245 void RemoveFromCache(const CargoPacket *cp, uint count);
246
247 static bool TryMerge(CargoPacket *cp, CargoPacket *icp);
248
249 public:
251 CargoList() {}
252
253 ~CargoList();
254
255 void OnCleanPool();
256
261 inline const Tcont *Packets() const
262 {
263 return &this->packets;
264 }
265
270 inline uint DaysInTransit() const
271 {
272 return this->count == 0 ? 0 : this->cargo_days_in_transit / this->count;
273 }
274
275 void InvalidateCache();
276 };
277
278 typedef std::list<CargoPacket *> CargoPacketList;
279
283 class VehicleCargoList : public CargoList<VehicleCargoList, CargoPacketList> {
284 protected:
286 typedef CargoList<VehicleCargoList, CargoPacketList> Parent;
287
288 Money feeder_share;
289 uint action_counts[NUM_MOVE_TO_ACTION];
290
291 template<class Taction>
292 void ShiftCargo(Taction action);
293
294 template<class Taction>
295 void PopCargo(Taction action);
296
300 inline void AssertCountConsistency() const
301 {
302 assert(this->action_counts[MTA_KEEP] +
303 this->action_counts[MTA_DELIVER] +
304 this->action_counts[MTA_TRANSFER] +
305 this->action_counts[MTA_LOAD] == this->count);
306 }
307
308 void AddToCache(const CargoPacket *cp);
309 void RemoveFromCache(const CargoPacket *cp, uint count);
310
311 void AddToMeta(const CargoPacket *cp, MoveToAction action);
312 void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count);
313
314 static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next,
315 StationID current_station, bool accepted, StationIDStack next_station);
316
317 public:
319 friend class StationCargoList;
321 friend class CargoList<VehicleCargoList, CargoPacketList>;
323 friend const struct SaveLoad *GetVehicleDescription(VehicleType vt);
324
325 friend class CargoShift;
326 friend class CargoTransfer;
327 friend class CargoDelivery;
328 template<class Tsource>
329 friend class CargoRemoval;
330 friend class CargoReturn;
331 friend class VehicleCargoReroute;
332
337 inline StationID Source() const
338 {
339 return this->count == 0 ? INVALID_STATION : this->packets.front()->source;
340 }
341
346 inline Money FeederShare() const
347 {
348 return this->feeder_share;
349 }
350
356 inline uint ActionCount(MoveToAction action) const
357 {
358 return this->action_counts[action];
359 }
360
366 inline uint StoredCount() const
367 {
368 return this->count - this->action_counts[MTA_LOAD];
369 }
370
375 inline uint TotalCount() const
376 {
377 return this->count;
378 }
379
384 inline uint ReservedCount() const
385 {
386 return this->action_counts[MTA_LOAD];
387 }
388
393 inline uint UnloadCount() const
394 {
395 return this->action_counts[MTA_TRANSFER] + this->action_counts[MTA_DELIVER];
396 }
397
402 inline uint RemainingCount() const
403 {
404 return this->action_counts[MTA_KEEP] + this->action_counts[MTA_LOAD];
405 }
406
407 void Append(CargoPacket *cp, MoveToAction action = MTA_KEEP);
408
409 void AgeCargo();
410
411 void InvalidateCache();
412
413 void SetTransferLoadPlace(TileIndex xy);
414
415 bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment);
416
422 inline void KeepAll()
423 {
424 this->action_counts[MTA_DELIVER] = this->action_counts[MTA_TRANSFER] = this->action_counts[MTA_LOAD] = 0;
425 this->action_counts[MTA_KEEP] = this->count;
426 }
427
428 /* Methods for moving cargo around. First parameter is always maximum
429 * amount of cargo to be moved. Second parameter is destination (if
430 * applicable), return value is amount of cargo actually moved. */
431
432 template<MoveToAction Tfrom, MoveToAction Tto>
433 uint Reassign(uint max_move, TileOrStationID update = INVALID_TILE);
434 uint Return(uint max_move, StationCargoList *dest, StationID next_station);
435 uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
436 uint Shift(uint max_move, VehicleCargoList *dest);
437 uint Truncate(uint max_move = UINT_MAX);
438 uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
439
447 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
448 {
449 return cp1->source_xy == cp2->source_xy &&
450 cp1->days_in_transit == cp2->days_in_transit &&
451 cp1->source_type == cp2->source_type &&
452 cp1->source_id == cp2->source_id &&
453 cp1->loaded_at_xy == cp2->loaded_at_xy;
454 }
455 };
456
457 typedef MultiMap<StationID, CargoPacket *> StationCargoPacketMap;
458 typedef std::map<StationID, uint> StationCargoAmountMap;
459
463 class StationCargoList : public CargoList<StationCargoList, StationCargoPacketMap> {
464 protected:
466 typedef CargoList<StationCargoList, StationCargoPacketMap> Parent;
467
468 uint reserved_count;
469
470 public:
472 friend class CargoList<StationCargoList, StationCargoPacketMap>;
474 friend const struct SaveLoad *GetGoodsDesc();
475
476 friend class CargoLoad;
477 friend class CargoTransfer;
478 template<class Tsource>
479 friend class CargoRemoval;
480 friend class CargoReservation;
481 friend class CargoReturn;
482 friend class StationCargoReroute;
483
484 static void InvalidateAllFrom(SourceType src_type, SourceID src);
485
486 template<class Taction>
487 bool ShiftCargo(Taction &action, StationID next);
488
489 template<class Taction>
490 uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid);
491
492 void Append(CargoPacket *cp, StationID next);
493
499 inline bool HasCargoFor(StationIDStack next) const
500 {
501 while (!next.IsEmpty()) {
502 if (this->packets.find(next.Pop()) != this->packets.end()) return true;
503 }
504 /* Packets for INVALID_STTION can go anywhere. */
505 return this->packets.find(INVALID_STATION) != this->packets.end();
506 }
507
512 inline StationID Source() const
513 {
514 return this->count == 0 ? INVALID_STATION : this->packets.begin()->second.front()->source;
515 }
516
522 inline uint AvailableCount() const
523 {
524 return this->count;
525 }
526
531 inline uint ReservedCount() const
532 {
533 return this->reserved_count;
534 }
535
541 inline uint TotalCount() const
542 {
543 return this->count + this->reserved_count;
544 }
545
546 /* Methods for moving cargo around. First parameter is always maximum
547 * amount of cargo to be moved. Second parameter is destination (if
548 * applicable), return value is amount of cargo actually moved. */
549
550 uint Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
551 uint Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationIDStack next);
552 uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = NULL);
553 uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge);
554
562 static bool AreMergable(const CargoPacket *cp1, const CargoPacket *cp2)
563 {
564 return cp1->source_xy == cp2->source_xy &&
565 cp1->days_in_transit == cp2->days_in_transit &&
566 cp1->source_type == cp2->source_type &&
567 cp1->source_id == cp2->source_id;
568 }
569 };
570
571 #endif /* CARGOPACKET_H */