cargopacket.cpp
Go to the documentation of this file.00001
00002
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "station.h"
00008 #include "cargopacket.h"
00009 #include "saveload.h"
00010
00011
00012 DEFINE_OLD_POOL_GENERIC(CargoPacket, CargoPacket)
00013
00014 void InitializeCargoPackets()
00015 {
00016
00017 _CargoPacket_pool.CleanPool();
00018 _CargoPacket_pool.AddBlockToPool();
00019 }
00020
00021 CargoPacket::CargoPacket(StationID source, uint16 count)
00022 {
00023 if (source != INVALID_STATION) assert(count != 0);
00024
00025 this->source = source;
00026 this->source_xy = (source != INVALID_STATION) ? GetStation(source)->xy : 0;
00027 this->loaded_at_xy = this->source_xy;
00028
00029 this->count = count;
00030 this->days_in_transit = 0;
00031 this->feeder_share = 0;
00032 this->paid_for = false;
00033 }
00034
00035 CargoPacket::~CargoPacket()
00036 {
00037 this->count = 0;
00038 }
00039
00040 bool CargoPacket::SameSource(const CargoPacket *cp) const
00041 {
00042 return this->source_xy == cp->source_xy && this->days_in_transit == cp->days_in_transit && this->paid_for == cp->paid_for;
00043 }
00044
00045 static const SaveLoad _cargopacket_desc[] = {
00046 SLE_VAR(CargoPacket, source, SLE_UINT16),
00047 SLE_VAR(CargoPacket, source_xy, SLE_UINT32),
00048 SLE_VAR(CargoPacket, loaded_at_xy, SLE_UINT32),
00049 SLE_VAR(CargoPacket, count, SLE_UINT16),
00050 SLE_VAR(CargoPacket, days_in_transit, SLE_UINT8),
00051 SLE_VAR(CargoPacket, feeder_share, SLE_INT64),
00052 SLE_VAR(CargoPacket, paid_for, SLE_BOOL),
00053
00054 SLE_END()
00055 };
00056
00057 static void Save_CAPA()
00058 {
00059 CargoPacket *cp;
00060
00061 FOR_ALL_CARGOPACKETS(cp) {
00062 SlSetArrayIndex(cp->index);
00063 SlObject(cp, _cargopacket_desc);
00064 }
00065 }
00066
00067 static void Load_CAPA()
00068 {
00069 int index;
00070
00071 while ((index = SlIterateArray()) != -1) {
00072 CargoPacket *cp = new (index) CargoPacket();
00073 SlObject(cp, _cargopacket_desc);
00074 }
00075 }
00076
00077 extern const ChunkHandler _cargopacket_chunk_handlers[] = {
00078 { 'CAPA', Save_CAPA, Load_CAPA, CH_ARRAY | CH_LAST},
00079 };
00080
00081
00082
00083
00084
00085
00086
00087 CargoList::~CargoList()
00088 {
00089 while (!packets.empty()) {
00090 delete packets.front();
00091 packets.pop_front();
00092 }
00093 }
00094
00095 const CargoList::List *CargoList::Packets() const
00096 {
00097 return &packets;
00098 }
00099
00100 void CargoList::AgeCargo()
00101 {
00102 if (empty) return;
00103
00104 uint dit = 0;
00105 for (List::const_iterator it = packets.begin(); it != packets.end(); it++) {
00106 if ((*it)->days_in_transit != 0xFF) (*it)->days_in_transit++;
00107 dit += (*it)->days_in_transit * (*it)->count;
00108 }
00109 days_in_transit = dit / count;
00110 }
00111
00112 bool CargoList::Empty() const
00113 {
00114 return empty;
00115 }
00116
00117 uint CargoList::Count() const
00118 {
00119 return count;
00120 }
00121
00122 bool CargoList::UnpaidCargo() const
00123 {
00124 return unpaid_cargo;
00125 }
00126
00127 Money CargoList::FeederShare() const
00128 {
00129 return feeder_share;
00130 }
00131
00132 StationID CargoList::Source() const
00133 {
00134 return source;
00135 }
00136
00137 uint CargoList::DaysInTransit() const
00138 {
00139 return days_in_transit;
00140 }
00141
00142 void CargoList::Append(CargoPacket *cp)
00143 {
00144 assert(cp != NULL);
00145 assert(cp->IsValid());
00146
00147 for (List::iterator it = packets.begin(); it != packets.end(); it++) {
00148 if ((*it)->SameSource(cp) && (*it)->count + cp->count <= 65535) {
00149 (*it)->count += cp->count;
00150 (*it)->feeder_share += cp->feeder_share;
00151 delete cp;
00152
00153 InvalidateCache();
00154 return;
00155 }
00156 }
00157
00158
00159 packets.push_back(cp);
00160 InvalidateCache();
00161 }
00162
00163
00164 void CargoList::Truncate(uint count)
00165 {
00166 for (List::iterator it = packets.begin(); it != packets.end(); it++) {
00167 uint local_count = (*it)->count;
00168 if (local_count <= count) {
00169 count -= local_count;
00170 continue;
00171 }
00172
00173 (*it)->count = count;
00174 count = 0;
00175 }
00176
00177 while (!packets.empty()) {
00178 CargoPacket *cp = packets.back();
00179 if (cp->count != 0) break;
00180 delete cp;
00181 packets.pop_back();
00182 }
00183
00184 InvalidateCache();
00185 }
00186
00187 bool CargoList::MoveTo(CargoList *dest, uint count, CargoList::MoveToAction mta, uint data)
00188 {
00189 assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
00190 CargoList tmp;
00191
00192 while (!packets.empty() && count > 0) {
00193 CargoPacket *cp = *packets.begin();
00194 if (cp->count <= count) {
00195
00196 packets.remove(cp);
00197 switch (mta) {
00198 case MTA_FINAL_DELIVERY:
00199 if (cp->source == data) {
00200 tmp.Append(cp);
00201 } else {
00202 count -= cp->count;
00203 delete cp;
00204 }
00205 break;
00206 case MTA_CARGO_LOAD:
00207 cp->loaded_at_xy = data;
00208
00209 cp->paid_for = false;
00210
00211 case MTA_OTHER:
00212 count -= cp->count;
00213 dest->packets.push_back(cp);
00214 break;
00215 }
00216 } else {
00217
00218 if (mta != MTA_FINAL_DELIVERY) {
00219 CargoPacket *cp_new = new CargoPacket();
00220
00221 Money fs = cp->feeder_share * count / static_cast<uint>(cp->count);
00222 cp->feeder_share -= fs;
00223
00224 cp_new->source = cp->source;
00225 cp_new->source_xy = cp->source_xy;
00226 cp_new->loaded_at_xy = (mta == MTA_CARGO_LOAD) ? data : cp->loaded_at_xy;
00227
00228 cp_new->days_in_transit = cp->days_in_transit;
00229 cp_new->feeder_share = fs;
00230
00231 cp_new->paid_for = (mta == MTA_CARGO_LOAD) ? false : cp->paid_for;
00232
00233 cp_new->count = count;
00234 dest->packets.push_back(cp_new);
00235 }
00236 cp->count -= count;
00237
00238 count = 0;
00239 }
00240 }
00241
00242 bool remaining = !packets.empty();
00243
00244 if (mta == MTA_FINAL_DELIVERY && !tmp.Empty()) {
00245
00246 tmp.MoveTo(this, MAX_UVALUE(uint));
00247 tmp.packets.clear();
00248 }
00249
00250 if (dest != NULL) dest->InvalidateCache();
00251 InvalidateCache();
00252
00253 return remaining;
00254 }
00255
00256 void CargoList::InvalidateCache()
00257 {
00258 empty = packets.empty();
00259 count = 0;
00260 unpaid_cargo = false;
00261 feeder_share = 0;
00262 source = INVALID_STATION;
00263 days_in_transit = 0;
00264
00265 if (empty) return;
00266
00267 uint dit = 0;
00268 for (List::const_iterator it = packets.begin(); it != packets.end(); it++) {
00269 count += (*it)->count;
00270 unpaid_cargo |= !(*it)->paid_for;
00271 dit += (*it)->days_in_transit * (*it)->count;
00272 feeder_share += (*it)->feeder_share;
00273 }
00274 days_in_transit = dit / count;
00275 source = (*packets.begin())->source;
00276 }