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