# HG changeset patch # User Peter Nelson # Date 2024-02-27 17:19:17 # Node ID 78a91e5251d1475f269ecbfa1d1084980a545852 # Parent ebda70ff18b6da50c8711b3d979429bba3ceff55 Codechange: Use vehicle tile hash to build depot vehicle list. (#12186) This avoids iterating the entire vehicle pool. diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp --- a/src/vehiclelist.cpp +++ b/src/vehiclelist.cpp @@ -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::UnpackIfVali 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(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 t 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. */