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/>.
10 /** @file cargopacket.h Base class for cargo packets. */
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 "saveload/saveload_data.h"
25 /** Unique identifier for a single cargo packet. */
26 typedef uint32 CargoPacketID
;
29 struct GoodsEntry
; // forward-declare for Stage() and RerouteStalePackets()
31 template <class Tinst
, class Tcont
> class CargoList
;
32 class StationCargoList
; // forward-declare, so we can use it in VehicleCargoList.
33 extern const struct SaveLoad
*GetCargoPacketDesc();
35 typedef uint32 TileOrStationID
;
38 * Container for cargo from the same location and time.
40 struct CargoPacket
: PooledItem
<CargoPacket
, CargoPacketID
, 1024, 0xFFF000, PT_NORMAL
, true, false> {
42 Money feeder_share
; ///< Value of feeder pickup to be paid for on delivery of cargo.
43 uint16 count
; ///< The amount of cargo in this packet.
44 byte days_in_transit
; ///< Amount of days this packet has been in transit.
45 CargoSource source
; ///< Source of cargo.
46 StationID source_st
; ///< The station where the cargo came from first.
47 TileIndex source_xy
; ///< The origin of the cargo (first station in feeder chain).
49 TileOrStationID loaded_at_xy
; ///< Location where this cargo has been loaded into the vehicle.
50 TileOrStationID next_station
; ///< Station where the cargo wants to go next.
53 /** The CargoList caches, thus needs to know about it. */
54 template <class Tinst
, class Tcont
> friend class CargoList
;
55 friend class VehicleCargoList
;
56 friend class StationCargoList
;
57 /** We want this to be saved, right? */
58 friend const struct SaveLoad
*GetCargoPacketDesc();
60 /** Maximum number of items in a single cargo packet. */
61 static const uint16 MAX_COUNT
= UINT16_MAX
;
64 CargoPacket (const struct Station
*st
, uint16 count
, SourceType source_type
, SourceID source_id
);
65 CargoPacket (uint16 count
, byte days_in_transit
, StationID source_st
, TileIndex source_xy
, TileIndex loaded_at_xy
, Money feeder_share
= 0);
66 CargoPacket (const CargoPacket
&cp
, uint16 count
, Money share
);
68 /** Destroy the packet. */
71 CargoPacket
*Split(uint new_size
);
72 void Merge(CargoPacket
*cp
);
73 void Reduce(uint count
);
76 * Try to merge another packet into this one, if the total count allows it.
77 * @param cp Packet to merge.
78 * @return Whether merging was possible (and done).
80 bool TryMerge (CargoPacket
*cp
)
82 if (this->count
+ cp
->count
> MAX_COUNT
) return false;
88 * Sets the tile where the packet was loaded last.
89 * @param load_place Tile where the packet was loaded last.
91 void SetLoadPlace(TileIndex load_place
) { this->loaded_at_xy
= load_place
; }
94 * Sets the station where the packet is supposed to go next.
95 * @param next_station Next station the packet should go to.
97 void SetNextStation(StationID next_station
) { this->next_station
= next_station
; }
100 * Adds some feeder share to the packet.
101 * @param new_share Feeder share to be added.
103 void AddFeederShare(Money new_share
) { this->feeder_share
+= new_share
; }
106 * Gets the number of 'items' in this packet.
107 * @return Item count.
109 inline uint16
Count() const
115 * Gets the amount of money already paid to earlier vehicles in
117 * @return Feeder share.
119 inline Money
FeederShare() const
121 return this->feeder_share
;
125 * Gets part of the amount of money already paid to earlier vehicles in
127 * @param part Amount of cargo to get the share for.
128 * @return Feeder share for the given amount of cargo.
130 inline Money
FeederShare(uint part
) const
132 return this->feeder_share
* part
/ static_cast<uint
>(this->count
);
136 * Gets the number of days this cargo has been in transit.
137 * This number isn't really in days, but in 2.5 days (CARGO_AGING_TICKS = 185 ticks) and
138 * it is capped at 255.
139 * @return Length this cargo has been in transit.
141 inline byte
DaysInTransit() const
143 return this->days_in_transit
;
147 * Gets the source of the cargo.
148 * @return Source of the cargo.
150 inline const CargoSource
&Source() const
156 * Gets the ID of the station where the cargo was loaded for the first time.
159 inline StationID
SourceStation() const
161 return this->source_st
;
165 * Gets the coordinates of the cargo's source station.
166 * @return Source station's coordinates.
168 inline TileIndex
SourceStationXY() const
170 return this->source_xy
;
174 * Gets the coordinates of the cargo's last loading station.
175 * @return Last loading station's coordinates.
177 inline TileIndex
LoadedAtXY() const
179 return this->loaded_at_xy
;
183 * Gets the ID of station the cargo wants to go next.
184 * @return Next station for this packets.
186 inline StationID
NextStation() const
188 return this->next_station
;
191 static void InvalidateAllFrom(SourceType src_type
, SourceID src
);
192 static void InvalidateAllFrom(StationID sid
);
193 static void AfterLoad(const SavegameTypeVersion
*stv
);
197 * Iterate over all _valid_ cargo packets from the given start.
198 * @param var Variable used as "iterator".
199 * @param start Cargo packet ID of the first packet to iterate over.
201 #define FOR_ALL_CARGOPACKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(CargoPacket, cargopacket_index, var, start)
204 * Iterate over all _valid_ cargo packets from the begin of the pool.
205 * @param var Variable used as "iterator".
207 #define FOR_ALL_CARGOPACKETS(var) FOR_ALL_CARGOPACKETS_FROM(var, 0)
210 * Simple collection class for a list of cargo packets.
211 * @tparam Tinst Actual instantiation of this cargo list.
213 template <class Tinst
, class Tcont
>
216 /** The iterator for our container. */
217 typedef typename
Tcont::iterator Iterator
;
218 /** The reverse iterator for our container. */
219 typedef typename
Tcont::reverse_iterator ReverseIterator
;
220 /** The const iterator for our container. */
221 typedef typename
Tcont::const_iterator ConstIterator
;
222 /** The const reverse iterator for our container. */
223 typedef typename
Tcont::const_reverse_iterator ConstReverseIterator
;
225 /** Kind of actions that could be done with packets on move. */
228 MTA_TRANSFER
= 0, ///< Transfer the cargo to the station.
229 MTA_DELIVER
, ///< Deliver the cargo to some town or industry.
230 MTA_KEEP
, ///< Keep the cargo in the vehicle.
231 MTA_LOAD
, ///< Load the cargo from the station.
233 NUM_MOVE_TO_ACTION
= MTA_END
237 uint count
; ///< Cache for the number of cargo entities.
238 uint cargo_days_in_transit
; ///< Cache for the sum of number of days in transit of each entity; comparable to man-hours.
240 Tcont packets
; ///< The cargo packets in this list.
242 void AddToCache(const CargoPacket
*cp
);
244 void RemoveFromCache(const CargoPacket
*cp
, uint count
);
247 /** Create the cargo list. */
248 CargoList() : count(0), cargo_days_in_transit(0), packets()
257 * Returns a pointer to the cargo packet list (so you can iterate over it etc).
258 * @return Pointer to the packet list.
260 inline const Tcont
*Packets() const
262 return &this->packets
;
266 * Returns average number of days in transit for a cargo entity.
267 * @return The before mentioned number.
269 inline uint
DaysInTransit() const
271 return this->count
== 0 ? 0 : this->cargo_days_in_transit
/ this->count
;
274 void InvalidateCache();
277 typedef std::list
<CargoPacket
*> CargoPacketList
;
280 * CargoList that is used for vehicles.
282 class VehicleCargoList
: public CargoList
<VehicleCargoList
, CargoPacketList
> {
284 /** The (direct) parent of this class. */
285 typedef CargoList
<VehicleCargoList
, CargoPacketList
> Parent
;
287 Money feeder_share
; ///< Cache for the feeder share.
288 uint action_counts
[NUM_MOVE_TO_ACTION
]; ///< Counts of cargo to be transfered, delivered, kept and loaded.
291 * Assert that the designation counts add up.
293 inline void AssertCountConsistency() const
295 assert(this->action_counts
[MTA_KEEP
] +
296 this->action_counts
[MTA_DELIVER
] +
297 this->action_counts
[MTA_TRANSFER
] +
298 this->action_counts
[MTA_LOAD
] == this->count
);
301 void AddToCache(const CargoPacket
*cp
);
302 void RemoveFromCache(const CargoPacket
*cp
, uint count
);
304 void AddToMeta(const CargoPacket
*cp
, MoveToAction action
);
305 void RemoveFromMeta(const CargoPacket
*cp
, MoveToAction action
, uint count
);
307 static MoveToAction
ChooseAction(const CargoPacket
*cp
, StationID cargo_next
,
308 StationID current_station
, bool accepted
,
309 const StationIDStack
&next_station
);
312 VehicleCargoList() : feeder_share(0)
314 memset (this->action_counts
, 0, sizeof(this->action_counts
));
317 /** The station cargo list needs to control the unloading. */
318 friend class StationCargoList
;
319 /** The super class ought to know what it's doing. */
320 friend class CargoList
<VehicleCargoList
, CargoPacketList
>;
321 /** The vehicles have a cargo list (and we want that saved). */
322 friend const struct SaveLoad
*GetVehicleDescription(VehicleType vt
);
325 * Returns source of the first cargo packet in this list.
326 * @return The before mentioned source.
328 inline StationID
Source() const
330 return this->count
== 0 ? INVALID_STATION
: this->packets
.front()->SourceStation();
334 * Returns total sum of the feeder share for all packets.
335 * @return The before mentioned number.
337 inline Money
FeederShare() const
339 return this->feeder_share
;
343 * Returns the amount of cargo designated for a given purpose.
344 * @param action Action the cargo is designated for.
345 * @return Amount of cargo designated for the given action.
347 inline uint
ActionCount(MoveToAction action
) const
349 return this->action_counts
[action
];
353 * Returns sum of cargo on board the vehicle (ie not only
355 * @return Cargo on board the vehicle.
357 inline uint
StoredCount() const
359 return this->count
- this->action_counts
[MTA_LOAD
];
363 * Returns sum of cargo, including reserved cargo.
364 * @return Sum of cargo.
366 inline uint
TotalCount() const
372 * Returns sum of reserved cargo.
373 * @return Sum of reserved cargo.
375 inline uint
ReservedCount() const
377 return this->action_counts
[MTA_LOAD
];
381 * Returns sum of cargo to be moved out of the vehicle at the current station.
382 * @return Cargo to be moved.
384 inline uint
UnloadCount() const
386 return this->action_counts
[MTA_TRANSFER
] + this->action_counts
[MTA_DELIVER
];
390 * Returns the sum of cargo to be kept in the vehicle at the current station.
391 * @return Cargo to be kept or loaded.
393 inline uint
RemainingCount() const
395 return this->action_counts
[MTA_KEEP
] + this->action_counts
[MTA_LOAD
];
398 void Append(CargoPacket
*cp
, MoveToAction action
= MTA_KEEP
);
402 void InvalidateCache();
404 void SetTransferLoadPlace(TileIndex xy
);
406 bool Stage (bool accepted
, StationID current_station
,
407 const StationIDStack
&next_station
, uint8 order_flags
,
408 const GoodsEntry
*ge
, CargoPayment
*payment
);
411 * Marks all cargo in the vehicle as to be kept. This is mostly useful for
412 * loading old savegames. When loading is aborted the reserved cargo has
413 * to be returned first.
415 inline void KeepAll()
417 this->action_counts
[MTA_DELIVER
] = this->action_counts
[MTA_TRANSFER
] = this->action_counts
[MTA_LOAD
] = 0;
418 this->action_counts
[MTA_KEEP
] = this->count
;
422 * Marks cargo previously set to load or deliver as to be kept.
423 * @param from Previous designation of cargo (MTA_LOAD or MTA_DELIVER).
424 * @param max_move Maximum amount of cargo to reassign.
426 void Keep (MoveToAction from
, uint max_move
= UINT_MAX
)
428 assert (from
== MTA_DELIVER
|| from
== MTA_LOAD
);
429 max_move
= min (this->action_counts
[from
], max_move
);
430 this->action_counts
[from
] -= max_move
;
431 this->action_counts
[MTA_KEEP
] += max_move
;
434 /* Methods for moving cargo around. First parameter is always maximum
435 * amount of cargo to be moved. Second parameter is destination (if
436 * applicable), return value is amount of cargo actually moved. */
438 void Transfer (void);
439 uint
Return (StationCargoList
*dest
, uint max_move
= UINT_MAX
);
440 uint
Unload(uint max_move
, StationCargoList
*dest
, CargoPayment
*payment
);
441 uint
Shift(uint max_move
, VehicleCargoList
*dest
);
442 uint
Truncate(uint max_move
= UINT_MAX
);
443 void Reroute (StationID avoid
, StationID avoid2
, const GoodsEntry
*ge
);
444 void Reattach (VehicleCargoList
*dest
, uint max_move
= UINT_MAX
);
447 typedef MultiMap
<StationID
, CargoPacket
*> StationCargoPacketMap
;
448 typedef std::map
<StationID
, uint
> StationCargoAmountMap
;
451 * CargoList that is used for stations.
453 class StationCargoList
: public CargoList
<StationCargoList
, StationCargoPacketMap
> {
455 /** The (direct) parent of this class. */
456 typedef CargoList
<StationCargoList
, StationCargoPacketMap
> Parent
;
458 uint reserved_count
; ///< Amount of cargo being reserved for loading.
461 /** The super class ought to know what it's doing. */
462 friend class CargoList
<StationCargoList
, StationCargoPacketMap
>;
463 /** The stations, via GoodsEntry, have a CargoList. */
464 friend const struct SaveLoad
*GetGoodsDesc();
466 friend class VehicleCargoList
;
468 uint
ShiftCargo (VehicleCargoList
*dest
, uint max_move
,
469 TileIndex load_place
, const StationIDStack
&next
, bool load
);
471 void Append(CargoPacket
*cp
, StationID next
);
474 * Check for cargo headed for a specific station.
475 * @param next Station the cargo is headed for.
476 * @return If there is any cargo for that station.
478 inline bool HasCargoFor (const StationIDStack
&next
) const
480 for (StationIDStack::const_iterator
iter (next
.begin()); iter
!= next
.end(); iter
++) {
481 if (this->packets
.find (*iter
) != this->packets
.end()) return true;
483 /* Packets for INVALID_STTION can go anywhere. */
484 return this->packets
.find(INVALID_STATION
) != this->packets
.end();
488 * Returns source of the first cargo packet in this list.
489 * @return The before mentioned source.
491 inline StationID
Source() const
493 return this->count
== 0 ? INVALID_STATION
: this->packets
.begin()->second
.front()->SourceStation();
497 * Returns sum of cargo still available for loading at the sation.
498 * (i.e. not counting cargo which is already reserved for loading)
499 * @return Cargo on board the vehicle.
501 inline uint
AvailableCount() const
507 * Returns sum of cargo reserved for loading onto vehicles.
508 * @return Cargo reserved for loading.
510 inline uint
ReservedCount() const
512 return this->reserved_count
;
516 * Returns total count of cargo at the station, including
517 * cargo which is already reserved for loading.
518 * @return Total cargo count.
520 inline uint
TotalCount() const
522 return this->count
+ this->reserved_count
;
525 /* Methods for moving cargo around. First parameter is always maximum
526 * amount of cargo to be moved. Second parameter is destination (if
527 * applicable), return value is amount of cargo actually moved. */
530 * Reserves cargo for loading onto the vehicle.
531 * @param max_move Maximum amount of cargo to reserve.
532 * @param dest VehicleCargoList to reserve for.
533 * @param load_place Tile index of the current station.
534 * @param next Next station(s) the loading vehicle will visit.
535 * @return Amount of cargo actually reserved.
537 uint
Reserve (uint max_move
, VehicleCargoList
*dest
,
538 TileIndex load_place
, const StationIDStack
&next
)
540 return this->ShiftCargo (dest
, max_move
, load_place
, next
, false);
543 uint
Load (uint max_move
, VehicleCargoList
*dest
, TileIndex load_place
, const StationIDStack
&next
);
544 uint
Truncate(uint max_move
= UINT_MAX
, StationCargoAmountMap
*cargo_per_source
= NULL
);
545 void Reroute (StationID avoid
, StationID avoid2
, const GoodsEntry
*ge
);
548 #endif /* CARGOPACKET_H */