Skip to content

Commit

Permalink
Codechange: Use vehicle tile hash to build depot vehicle list. (#12186)
Browse files Browse the repository at this point in the history
This avoids iterating the entire vehicle pool.
  • Loading branch information
PeterN authored Feb 27, 2024
1 parent a61311f commit 59420d5
Showing 1 changed file with 36 additions and 26 deletions.
62 changes: 36 additions & 26 deletions src/vehiclelist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "stdafx.h"
#include "train.h"
#include "vehicle_func.h"
#include "vehiclelist.h"
#include "vehiclelist_func.h"
#include "group.h"
Expand Down Expand Up @@ -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
Expand All @@ -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. */
Expand Down

0 comments on commit 59420d5

Please sign in to comment.