|
1 /* $Id$ */ |
|
2 |
|
3 /** @file cargotype.h */ |
|
4 |
|
5 #ifndef CARGOPACKET_H |
|
6 #define CARGOPACKET_H |
|
7 |
|
8 #include <list> |
|
9 |
|
10 /** |
|
11 * Container for cargo from the same location and time |
|
12 */ |
|
13 struct CargoPacket { |
|
14 bool touched; |
|
15 |
|
16 typedef uint32 ID; ///< Type for cargopacket identifiers |
|
17 |
|
18 ID index; ///< The unique index of this packet |
|
19 |
|
20 StationID source; ///< The station where the cargo came from first |
|
21 TileIndex source_xy; ///< The origin of the cargo (first station in feeder chain) |
|
22 TileIndex loaded_at_xy; ///< Location where this cargo has been loaded into the vehicle |
|
23 |
|
24 uint16 count; ///< The amount of cargo in this packet |
|
25 byte days_in_transit; ///< Amount of days this packet has been in transit |
|
26 Money feeder_share; ///< Value of feeder pickup to be paid for on delivery of cargo |
|
27 bool paid_for; ///< Have we been paid for this cargo packet? |
|
28 |
|
29 /** |
|
30 * Creates a new cargo packet |
|
31 * @param source the source of the packet |
|
32 * @param count the number of cargo entities to put in this packet |
|
33 * @pre count != 0 || source == INVALID_STATION |
|
34 */ |
|
35 CargoPacket(StationID source = INVALID_STATION, uint16 count = 0); |
|
36 |
|
37 /** Destroy the packet */ |
|
38 ~CargoPacket(); |
|
39 |
|
40 |
|
41 /** |
|
42 * Is this a valid cargo packet ? |
|
43 * @return true if and only it is valid |
|
44 */ |
|
45 bool IsValid() const { return this->count != 0; } |
|
46 |
|
47 /** |
|
48 * Checks whether the cargo packet is from (exactly) the same source |
|
49 * in time and location. |
|
50 * @param cp the cargo packet to compare to |
|
51 * @return true if and only if days_in_transit and source_xy are equal |
|
52 */ |
|
53 bool SameSource(CargoPacket *cp); |
|
54 |
|
55 |
|
56 /* normal new/delete operators. Used when building/removing station */ |
|
57 void* operator new (size_t size); |
|
58 void operator delete(void *p); |
|
59 |
|
60 /* new/delete operators accepting station index. Used when loading station from savegame. */ |
|
61 void* operator new (size_t size, CargoPacket::ID cp_idx); |
|
62 void operator delete(void *p, CargoPacket::ID cp_idx); |
|
63 |
|
64 private: |
|
65 /** |
|
66 * Allocate the raw memory for this cargo packet |
|
67 * @return the allocated memory |
|
68 */ |
|
69 static CargoPacket *AllocateRaw(); |
|
70 }; |
|
71 |
|
72 /** We want to use a pool */ |
|
73 DECLARE_OLD_POOL(CargoPacket, CargoPacket, 10, 1000) |
|
74 |
|
75 /** |
|
76 * Iterate over all _valid_ cargo packets from the given start |
|
77 * @param cp the variable used as "iterator" |
|
78 * @param start the cargo packet ID of the first packet to iterate over |
|
79 */ |
|
80 #define FOR_ALL_CARGOPACKETS_FROM(cp, start) for (cp = GetCargoPacket(start); cp != NULL; cp = (cp->index + 1U < GetCargoPacketPoolSize()) ? GetCargoPacket(cp->index + 1U) : NULL) if (cp->IsValid()) |
|
81 |
|
82 /** |
|
83 * Iterate over all _valid_ cargo packets from the begin of the pool |
|
84 * @param cp the variable used as "iterator" |
|
85 */ |
|
86 #define FOR_ALL_CARGOPACKETS(cp) FOR_ALL_CARGOPACKETS_FROM(cp, 0) |
|
87 |
|
88 /** |
|
89 * Simple collection class for a list of cargo packets |
|
90 */ |
|
91 class CargoList { |
|
92 public: |
|
93 /** List of cargo packets */ |
|
94 typedef std::list<CargoPacket *> List; |
|
95 |
|
96 /** Kind of actions that could be done with packets on move */ |
|
97 enum MoveToAction { |
|
98 MTA_FINAL_DELIVERY, ///< "Deliver" the packet to the final destination, i.e. destroy the packet |
|
99 MTA_CARGO_LOAD, ///< Load the packet onto a vehicle, i.e. set the last loaded station ID |
|
100 MTA_OTHER ///< "Just" move the packet to another cargo list |
|
101 }; |
|
102 |
|
103 private: |
|
104 List packets; ///< The cargo packets in this list |
|
105 |
|
106 bool empty; ///< Cache for whether this list is empty or not |
|
107 uint count; ///< Cache for the number of cargo entities |
|
108 bool unpaid_cargo; ///< Cache for the unpaid cargo |
|
109 Money feeder_share; ///< Cache for the feeder share |
|
110 StationID source; ///< Cache for the source of the packet |
|
111 uint days_in_transit; ///< Cache for the number of days in transit |
|
112 |
|
113 public: |
|
114 /** |
|
115 * Needed for an ugly hack: |
|
116 * - vehicles and stations need to store cargo lists, so they use CargoList as container |
|
117 * - this internals of the container should be protected, e.g. private (or protected) by C++ |
|
118 * - for saving/loading we need to pass pointer to objects |
|
119 * -> so *if* the pointer to the cargo list is the same as the pointer to the packet list |
|
120 * encapsulated in the CargoList, we can just pass the CargoList as "offset". |
|
121 * Normally we would then just add the offset of the packets variable within the cargo list |
|
122 * but that is not possible because the variable is private. Furthermore we are not sure |
|
123 * that this works on all platforms, we need to check whether the offset is actually 0. |
|
124 * This cannot be done compile time, because the variable is private. So we need to write |
|
125 * a function that does actually check the offset runtime and call it somewhere where it |
|
126 * is always called but it should not be called often. |
|
127 */ |
|
128 static void AssertOnWrongPacketOffset(); |
|
129 |
|
130 /** Create the cargo list */ |
|
131 CargoList() { this->InvalidateCache(); } |
|
132 /** And destroy it ("frees" all cargo packets) */ |
|
133 ~CargoList(); |
|
134 |
|
135 /** |
|
136 * Returns a pointer to the cargo packet list (so you can iterate over it etc). |
|
137 * @return pointer to the packet list |
|
138 */ |
|
139 const CargoList::List *Packets() const; |
|
140 |
|
141 /** |
|
142 * Ages the all cargo in this list |
|
143 */ |
|
144 void AgeCargo(); |
|
145 |
|
146 /** |
|
147 * Checks whether this list is empty |
|
148 * @return true if and only if the list is empty |
|
149 */ |
|
150 bool Empty() const; |
|
151 |
|
152 /** |
|
153 * Returns the number of cargo entities in this list |
|
154 * @return the before mentioned number |
|
155 */ |
|
156 uint Count() const; |
|
157 |
|
158 /** |
|
159 * Is there some cargo that has not been paid for? |
|
160 * @return true if and only if there is such a cargo |
|
161 */ |
|
162 bool UnpaidCargo() const; |
|
163 |
|
164 /** |
|
165 * Returns total sum of the feeder share for all packets |
|
166 * @return the before mentioned number |
|
167 */ |
|
168 Money FeederShare() const; |
|
169 |
|
170 /** |
|
171 * Returns source of the first cargo packet in this list |
|
172 * @return the before mentioned source |
|
173 */ |
|
174 StationID Source() const; |
|
175 |
|
176 /** |
|
177 * Returns average number of days in transit for a cargo entity |
|
178 * @return the before mentioned number |
|
179 */ |
|
180 uint DaysInTransit() const; |
|
181 |
|
182 |
|
183 /** |
|
184 * Appends the given cargo packet |
|
185 * @warning After appending this packet may not exist anymore! |
|
186 * @note Do not use the cargo packet anymore after it has been appended to this CargoList! |
|
187 * @param cp the cargo packet to add |
|
188 * @pre cp != NULL |
|
189 */ |
|
190 void Append(CargoPacket *cp); |
|
191 |
|
192 /** |
|
193 * Truncates the cargo in this list to the given amount. It leaves the |
|
194 * first count cargo entities and removes the rest. |
|
195 * @param count the maximum amount of entities to be in the list after the command |
|
196 */ |
|
197 void Truncate(uint count); |
|
198 |
|
199 /** |
|
200 * Moves the given amount of cargo to another list. |
|
201 * Depending on the value of mta the side effects of this function differ: |
|
202 * - MTA_FINAL_DELIVERY: destroys the packets that do not originate from a specific station |
|
203 * - MTA_CARGO_LOAD: sets the loaded_at_xy value of the moved packets |
|
204 * - MTA_OTHER: just move without side effects |
|
205 * @param dest the destination to move the cargo to |
|
206 * @param count the amount of cargo entities to move |
|
207 * @param mta how to handle the moving (side effects) |
|
208 * @param data Depending on mta the data of this variable differs: |
|
209 * - MTA_FINAL_DELIVERY - station ID of packet's origin not to remove |
|
210 * - MTA_CARGO_LOAD - station's tile index of load |
|
211 * - MTA_OTHER - unused |
|
212 * @param mta == MTA_FINAL_DELIVERY || dest != NULL |
|
213 * @return true if there are still packets that might be moved from this cargo list |
|
214 */ |
|
215 bool MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta = MTA_OTHER, uint data = 0); |
|
216 |
|
217 /** Invalidates the cached data and rebuild it */ |
|
218 void InvalidateCache(); |
|
219 }; |
|
220 |
|
221 #endif /* CARGOPACKET_H */ |