00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "core/pool_func.hpp"
00014 #include "economy_base.h"
00015
00016
00017 CargoPacketPool _cargopacket_pool("CargoPacket");
00018 INSTANTIATE_POOL_METHODS(CargoPacket)
00019
00020
00023 void InitializeCargoPackets()
00024 {
00025 _cargopacket_pool.CleanPool();
00026 }
00027
00031 CargoPacket::CargoPacket()
00032 {
00033 this->source_type = ST_INDUSTRY;
00034 this->source_id = INVALID_SOURCE;
00035 }
00036
00048 CargoPacket::CargoPacket(StationID source, TileIndex source_xy, uint16 count, SourceType source_type, SourceID source_id) :
00049 feeder_share(0),
00050 count(count),
00051 days_in_transit(0),
00052 source_id(source_id),
00053 source(source),
00054 source_xy(source_xy),
00055 loaded_at_xy(0)
00056 {
00057 assert(count != 0);
00058 this->source_type = source_type;
00059 }
00060
00075 CargoPacket::CargoPacket(uint16 count, byte days_in_transit, StationID source, TileIndex source_xy, TileIndex loaded_at_xy, Money feeder_share, SourceType source_type, SourceID source_id) :
00076 feeder_share(feeder_share),
00077 count(count),
00078 days_in_transit(days_in_transit),
00079 source_id(source_id),
00080 source(source),
00081 source_xy(source_xy),
00082 loaded_at_xy(loaded_at_xy)
00083 {
00084 assert(count != 0);
00085 this->source_type = source_type;
00086 }
00087
00093 FORCEINLINE CargoPacket *CargoPacket::Split(uint new_size)
00094 {
00095 if (!CargoPacket::CanAllocateItem()) return NULL;
00096
00097 Money fs = this->feeder_share * new_size / static_cast<uint>(this->count);
00098 CargoPacket *cp_new = new CargoPacket(new_size, this->days_in_transit, this->source, this->source_xy, this->loaded_at_xy, fs, this->source_type, this->source_id);
00099 this->feeder_share -= fs;
00100 this->count -= new_size;
00101 return cp_new;
00102 }
00103
00108 FORCEINLINE void CargoPacket::Merge(CargoPacket *cp)
00109 {
00110 this->count += cp->count;
00111 this->feeder_share += cp->feeder_share;
00112 delete cp;
00113 }
00114
00120 void CargoPacket::InvalidateAllFrom(SourceType src_type, SourceID src)
00121 {
00122 CargoPacket *cp;
00123 FOR_ALL_CARGOPACKETS(cp) {
00124 if (cp->source_type == src_type && cp->source_id == src) cp->source_id = INVALID_SOURCE;
00125 }
00126 }
00127
00132 void CargoPacket::InvalidateAllFrom(StationID sid)
00133 {
00134 CargoPacket *cp;
00135 FOR_ALL_CARGOPACKETS(cp) {
00136 if (cp->source == sid) cp->source = INVALID_STATION;
00137 }
00138 }
00139
00140
00141
00142
00143
00144
00145
00149 template <class Tinst>
00150 CargoList<Tinst>::~CargoList()
00151 {
00152 for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
00153 delete *it;
00154 }
00155 }
00156
00162 template <class Tinst>
00163 void CargoList<Tinst>::RemoveFromCache(const CargoPacket *cp)
00164 {
00165 this->count -= cp->count;
00166 this->cargo_days_in_transit -= cp->days_in_transit * cp->count;
00167 }
00168
00174 template <class Tinst>
00175 void CargoList<Tinst>::AddToCache(const CargoPacket *cp)
00176 {
00177 this->count += cp->count;
00178 this->cargo_days_in_transit += cp->days_in_transit * cp->count;
00179 }
00180
00189 template <class Tinst>
00190 void CargoList<Tinst>::Append(CargoPacket *cp)
00191 {
00192 assert(cp != NULL);
00193 static_cast<Tinst *>(this)->AddToCache(cp);
00194
00195 for (List::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
00196 CargoPacket *icp = *it;
00197 if (Tinst::AreMergable(icp, cp) && icp->count + cp->count <= CargoPacket::MAX_COUNT) {
00198 icp->Merge(cp);
00199 return;
00200 }
00201 }
00202
00203
00204 this->packets.push_back(cp);
00205 }
00206
00212 template <class Tinst>
00213 void CargoList<Tinst>::Truncate(uint max_remaining)
00214 {
00215 for (Iterator it(packets.begin()); it != packets.end(); ) {
00216 CargoPacket *cp = *it;
00217 if (max_remaining == 0) {
00218
00219 it = this->packets.erase(it);
00220 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00221 delete cp;
00222 continue;
00223 }
00224
00225 uint local_count = cp->count;
00226 if (local_count > max_remaining) {
00227 uint diff = local_count - max_remaining;
00228 this->count -= diff;
00229 this->cargo_days_in_transit -= cp->days_in_transit * diff;
00230 cp->count = max_remaining;
00231 max_remaining = 0;
00232 } else {
00233 max_remaining -= local_count;
00234 }
00235 ++it;
00236 }
00237 }
00238
00260 template <class Tinst>
00261 template <class Tother_inst>
00262 bool CargoList<Tinst>::MoveTo(Tother_inst *dest, uint max_move, MoveToAction mta, CargoPayment *payment, uint data)
00263 {
00264 assert(mta == MTA_FINAL_DELIVERY || dest != NULL);
00265 assert(mta == MTA_UNLOAD || mta == MTA_CARGO_LOAD || payment != NULL);
00266
00267 Iterator it(this->packets.begin());
00268 while (it != this->packets.end() && max_move > 0) {
00269 CargoPacket *cp = *it;
00270 if (cp->source == data && mta == MTA_FINAL_DELIVERY) {
00271
00272 ++it;
00273 continue;
00274 }
00275
00276 if (cp->count <= max_move) {
00277
00278 max_move -= cp->count;
00279 it = this->packets.erase(it);
00280 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00281 switch (mta) {
00282 case MTA_FINAL_DELIVERY:
00283 payment->PayFinalDelivery(cp, cp->count);
00284 delete cp;
00285 continue;
00286
00287 case MTA_CARGO_LOAD:
00288 cp->loaded_at_xy = data;
00289 break;
00290
00291 case MTA_TRANSFER:
00292 cp->feeder_share += payment->PayTransfer(cp, cp->count);
00293 break;
00294
00295 case MTA_UNLOAD:
00296 break;
00297 }
00298 dest->Append(cp);
00299 continue;
00300 }
00301
00302
00303 if (mta == MTA_FINAL_DELIVERY) {
00304
00305 payment->PayFinalDelivery(cp, max_move);
00306
00307
00308 uint left = cp->count - max_move;
00309 cp->count = max_move;
00310 static_cast<Tinst *>(this)->RemoveFromCache(cp);
00311
00312
00313
00314 cp->feeder_share = 0;
00315 cp->count = left;
00316 } else {
00317
00318 CargoPacket *cp_new = cp->Split(max_move);
00319
00320
00321 if (cp_new == NULL) return false;
00322
00323 static_cast<Tinst *>(this)->RemoveFromCache(cp_new);
00324
00325 if (mta == MTA_TRANSFER) {
00326
00327 cp_new->feeder_share += payment->PayTransfer(cp_new, max_move);
00328 } else if (mta == MTA_CARGO_LOAD) {
00329 cp_new->loaded_at_xy = data;
00330 }
00331
00332 dest->Append(cp_new);
00333 }
00334
00335 max_move = 0;
00336 }
00337
00338 return it != packets.end();
00339 }
00340
00342 template <class Tinst>
00343 void CargoList<Tinst>::InvalidateCache()
00344 {
00345 this->count = 0;
00346 this->cargo_days_in_transit = 0;
00347
00348 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00349 static_cast<Tinst *>(this)->AddToCache(*it);
00350 }
00351 }
00352
00358 void VehicleCargoList::RemoveFromCache(const CargoPacket *cp)
00359 {
00360 this->feeder_share -= cp->feeder_share;
00361 this->Parent::RemoveFromCache(cp);
00362 }
00363
00369 void VehicleCargoList::AddToCache(const CargoPacket *cp)
00370 {
00371 this->feeder_share += cp->feeder_share;
00372 this->Parent::AddToCache(cp);
00373 }
00374
00378 void VehicleCargoList::AgeCargo()
00379 {
00380 for (ConstIterator it(this->packets.begin()); it != this->packets.end(); it++) {
00381 CargoPacket *cp = *it;
00382
00383 if (cp->days_in_transit == 0xFF) continue;
00384
00385 cp->days_in_transit++;
00386 this->cargo_days_in_transit += cp->count;
00387 }
00388 }
00389
00391 void VehicleCargoList::InvalidateCache()
00392 {
00393 this->feeder_share = 0;
00394 this->Parent::InvalidateCache();
00395 }
00396
00397
00398
00399
00400 template class CargoList<VehicleCargoList>;
00401 template class CargoList<StationCargoList>;
00402
00404 template bool CargoList<VehicleCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00406 template bool CargoList<VehicleCargoList>::MoveTo(StationCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);
00408 template bool CargoList<StationCargoList>::MoveTo(VehicleCargoList *, uint max_move, MoveToAction mta, CargoPayment *payment, uint data);