Codechange: Use vehicle tile hash to build depot vehicle list. (#12186)

This avoids iterating the entire vehicle pool.
pull/661/head
Peter Nelson 3 months ago committed by GitHub
parent a61311fcb0
commit 59420d57ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -9,6 +9,7 @@
#include "stdafx.h"
#include "train.h"
#include "vehicle_func.h"
#include "vehiclelist.h"
#include "vehiclelist_func.h"
#include "group.h"
@ -59,6 +60,39 @@ bool VehicleListIdentifier::UnpackIfValid(uint32_t data)
return result;
}
/** Data for building a depot vehicle list. */
struct BuildDepotVehicleListData
{
VehicleList *engines; ///< Pointer to list to add vehicles to.
VehicleList *wagons; ///< Pointer to list to add wagons to (can be nullptr).
VehicleType type; ///< Type of vehicle.
bool individual_wagons; ///< If true add every wagon to \a wagons which is not attached to an engine. If false only add the first wagon of every row.
};
/**
* Add vehicles to a depot vehicle list.
* @param v The found vehicle.
* @param data The depot vehicle list data.
* @return Always nullptr.
*/
static Vehicle *BuildDepotVehicleListProc(Vehicle *v, void *data)
{
auto bdvld = static_cast<BuildDepotVehicleListData *>(data);
if (v->type != bdvld->type || !v->IsInDepot()) return nullptr;
if (bdvld->type == VEH_TRAIN) {
const Train *t = Train::From(v);
if (t->IsArticulatedPart() || t->IsRearDualheaded()) return nullptr;
if (bdvld->wagons != nullptr && t->First()->IsFreeWagon()) {
if (bdvld->individual_wagons || t->IsFreeWagon()) bdvld->wagons->push_back(t);
return nullptr;
}
}
if (v->IsPrimaryVehicle()) bdvld->engines->push_back(v);
return nullptr;
};
/**
* Generate a list of vehicles inside a depot.
* @param type Type of vehicle
@ -72,32 +106,8 @@ void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine
engines->clear();
if (wagons != nullptr && wagons != engines) wagons->clear();
for (const Vehicle *v : Vehicle::Iterate()) {
/* General tests for all vehicle types */
if (v->type != type) continue;
if (v->tile != tile) continue;
switch (type) {
case VEH_TRAIN: {
const Train *t = Train::From(v);
if (t->IsArticulatedPart() || t->IsRearDualheaded()) continue;
if (!t->IsInDepot()) continue;
if (wagons != nullptr && t->First()->IsFreeWagon()) {
if (individual_wagons || t->IsFreeWagon()) wagons->push_back(t);
continue;
}
if (!t->IsPrimaryVehicle()) continue;
break;
}
default:
if (!v->IsPrimaryVehicle()) continue;
if (!v->IsInDepot()) continue;
break;
}
engines->push_back(v);
}
BuildDepotVehicleListData bdvld{engines, wagons, type, individual_wagons};
FindVehicleOnPos(tile, &bdvld, BuildDepotVehicleListProc);
/* Ensure the lists are not wasting too much space. If the lists are fresh
* (i.e. built within a command) then this will actually do nothing. */

Loading…
Cancel
Save