Use hash table index for NewGRFClass::GetByGrf

This commit is contained in:
Jonathan G Rennison 2024-08-23 16:48:10 +01:00
parent 5f94f1e27e
commit 3994f329e3
3 changed files with 29 additions and 7 deletions

View File

@ -11763,6 +11763,11 @@ static void AfterLoadGRFs()
/* Deallocate temporary loading data */
_gted.clear();
_grm_sprites.clear();
ObjectClass::PrepareIndices();
StationClass::PrepareIndices();
AirportClass::PrepareIndices();
RoadStopClass::PrepareIndices();
}
/**

View File

@ -11,6 +11,7 @@
#define NEWGRF_CLASS_H
#include "strings_type.h"
#include "3rdparty/robin_hood/robin_hood.h"
#include <vector>
@ -39,6 +40,12 @@ private:
* @note This may be reallocated during initialization so pointers may be invalidated.
*/
static inline std::vector<NewGRFClass<Tspec, Tindex, Tmax>> classes;
static inline robin_hood::unordered_flat_map<uint64_t, const Tspec *> grf_index;
static inline uint64_t GrfHashKey(uint32_t grfid, uint16_t local_id)
{
return (static_cast<uint64_t>(local_id) << 32) | grfid;
}
/** Initialise the defaults. */
static void InsertDefaults();
@ -86,6 +93,7 @@ public:
static bool HasUIClass();
static NewGRFClass *Get(Tindex class_index);
static void PrepareIndices();
static const Tspec *GetByGrf(uint32_t grfid, uint16_t local_id);
};

View File

@ -19,6 +19,8 @@ void NewGRFClass<Tspec, Tindex, Tmax>::Reset()
NewGRFClass::classes.clear();
NewGRFClass::classes.shrink_to_fit();
NewGRFClass::grf_index.clear();
NewGRFClass::InsertDefaults();
}
@ -131,6 +133,18 @@ const Tspec *NewGRFClass<Tspec, Tindex, Tmax>::GetSpec(uint index) const
return index < this->GetSpecCount() ? this->spec[index] : nullptr;
}
template <typename Tspec, typename Tindex, Tindex Tmax>
void NewGRFClass<Tspec, Tindex, Tmax>::PrepareIndices()
{
for (const auto &cls : NewGRFClass::classes) {
for (const auto &spec : cls.spec) {
if (spec == nullptr) continue;
uint32_t grfid = spec->grf_prop.grffile == nullptr ? 0 : spec->grf_prop.grffile->grfid;
NewGRFClass::grf_index[NewGRFClass::GrfHashKey(grfid, spec->grf_prop.local_id)] = spec;
}
}
}
/**
* Retrieve a spec by GRF location.
* @param grfid GRF ID of spec.
@ -141,13 +155,8 @@ const Tspec *NewGRFClass<Tspec, Tindex, Tmax>::GetSpec(uint index) const
template <typename Tspec, typename Tindex, Tindex Tmax>
const Tspec *NewGRFClass<Tspec, Tindex, Tmax>::GetByGrf(uint32_t grfid, uint16_t local_id)
{
for (const auto &cls : NewGRFClass::classes) {
for (const auto &spec : cls.spec) {
if (spec == nullptr) continue;
if (spec->grf_prop.local_id != local_id) continue;
if ((spec->grf_prop.grffile == nullptr ? 0 : spec->grf_prop.grffile->grfid) == grfid) return spec;
}
}
auto iter = NewGRFClass::grf_index.find(NewGRFClass::GrfHashKey(grfid, local_id));
if (iter != NewGRFClass::grf_index.end()) return iter->second;
return nullptr;
}