diff --git a/src/industry.h b/src/industry.h index cd29dcff7f..6dd1cf792a 100644 --- a/src/industry.h +++ b/src/industry.h @@ -243,28 +243,6 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> { static Industry *GetRandom(); static void PostDestructor(size_t index); - /** - * Increment the count of industries for this type. - * @param type IndustryType to increment - * @pre type < NUM_INDUSTRYTYPES - */ - static inline void IncIndustryTypeCount(IndustryType type) - { - assert(type < NUM_INDUSTRYTYPES); - counts[type]++; - } - - /** - * Decrement the count of industries for this type. - * @param type IndustryType to decrement - * @pre type < NUM_INDUSTRYTYPES - */ - static inline void DecIndustryTypeCount(IndustryType type) - { - assert(type < NUM_INDUSTRYTYPES); - counts[type]--; - } - /** * Get the count of industries for this type. * @param type IndustryType to query @@ -273,13 +251,7 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> { static inline uint16_t GetIndustryTypeCount(IndustryType type) { assert(type < NUM_INDUSTRYTYPES); - return counts[type]; - } - - /** Resets industry counts. */ - static inline void ResetIndustryCounts() - { - memset(&counts, 0, sizeof(counts)); + return static_cast(std::size(industries[type])); } inline const std::string &GetCachedName() const @@ -288,11 +260,10 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> { return this->cached_name; } + static std::array, NUM_INDUSTRYTYPES> industries; ///< List of industries of each type. + private: void FillCachedName() const; - -protected: - static uint16_t counts[NUM_INDUSTRYTYPES]; ///< Number of industries per type ingame }; void ClearAllIndustryCachedNames(); diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 0c8d02fda5..2c8dd8bf69 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -63,7 +63,7 @@ void BuildOilRig(TileIndex tile); static uint8_t _industry_sound_ctr; static TileIndex _industry_sound_tile; -uint16_t Industry::counts[NUM_INDUSTRYTYPES]; +std::array, NUM_INDUSTRYTYPES> Industry::industries; IndustrySpec _industry_specs[NUM_INDUSTRYTYPES]; IndustryTileSpec _industry_tile_specs[NUM_INDUSTRYTILES]; @@ -189,7 +189,9 @@ Industry::~Industry() /* Clear the persistent storage. */ delete this->psa; - DecIndustryTypeCount(this->type); + auto &industries = Industry::industries[type]; + auto it = std::ranges::lower_bound(industries, this->index); + industries.erase(it); DeleteIndustryNews(this->index); CloseWindowById(WC_INDUSTRY_VIEW, this->index); @@ -1434,8 +1436,8 @@ static CommandCost FindTownForIndustry(TileIndex tile, IndustryType type, Town * if (_settings_game.economy.multiple_industry_per_town) return CommandCost(); - for (const Industry *i : Industry::Iterate()) { - if (i->type == type && i->town == *t) { + for (const IndustryID &industry : Industry::industries[type]) { + if (Industry::Get(industry)->town == *t) { *t = nullptr; return_cmd_error(STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN); } @@ -1693,35 +1695,13 @@ static CommandCost CheckIfFarEnoughFromConflictingIndustry(TileIndex tile, Indus { const IndustrySpec *indspec = GetIndustrySpec(type); - /* On a large map with many industries, it may be faster to check an area. */ - static const int dmax = 14; - if (Industry::GetNumItems() > static_cast(dmax * dmax * 2)) { - const Industry *i = nullptr; - TileArea tile_area = TileArea(tile, 1, 1).Expand(dmax); - for (TileIndex atile : tile_area) { - if (GetTileType(atile) == MP_INDUSTRY) { - const Industry *i2 = Industry::GetByTile(atile); - if (i == i2) continue; - i = i2; - if (DistanceMax(tile, i->location.tile) > (uint)dmax) continue; - if (i->type == indspec->conflicting[0] || - i->type == indspec->conflicting[1] || - i->type == indspec->conflicting[2]) { - return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE); - } - } - } - return CommandCost(); - } + for (IndustryType conflicting_type : indspec->conflicting) { + if (conflicting_type == IT_INVALID) continue; - for (const Industry *i : Industry::Iterate()) { - /* Within 14 tiles from another industry is considered close */ - if (DistanceMax(tile, i->location.tile) > 14) continue; + for (const IndustryID &industry : Industry::industries[conflicting_type]) { + /* Within 14 tiles from another industry is considered close */ + if (DistanceMax(tile, Industry::Get(industry)->location.tile) > 14) continue; - /* check if there are any conflicting industry types around */ - if (i->type == indspec->conflicting[0] || - i->type == indspec->conflicting[1] || - i->type == indspec->conflicting[2]) { return_cmd_error(STR_ERROR_INDUSTRY_TOO_CLOSE); } } @@ -1787,7 +1767,10 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, i->location = TileArea(tile, 1, 1); i->type = type; - Industry::IncIndustryTypeCount(type); + + auto &industries = Industry::industries[type]; + auto it = std::ranges::lower_bound(industries, i->index); + it = industries.emplace(it, i->index); for (size_t index = 0; index < std::size(indspec->produced_cargo); ++index) { if (!IsValidCargoID(indspec->produced_cargo[index])) break; @@ -2413,8 +2396,10 @@ static void PlaceInitialIndustry(IndustryType type, bool try_hard) */ static uint GetCurrentTotalNumberOfIndustries() { - int total = 0; - for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) total += Industry::GetIndustryTypeCount(it); + uint total = 0; + for (const auto &industries : Industry::industries) { + total += static_cast(std::size(industries)); + } return total; } @@ -3090,7 +3075,7 @@ static IntervalTimer _economy_industries_monthly({TimerGameEco void InitializeIndustries() { - Industry::ResetIndustryCounts(); + Industry::industries = {}; _industry_sound_tile = 0; _industry_builder.Reset(); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 41ab0218cc..221c224922 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -92,10 +92,11 @@ uint32_t GetIndustryIDAtOffset(TileIndex tile, const Industry *i, uint32_t cur_g static uint32_t GetClosestIndustry(TileIndex tile, IndustryType type, const Industry *current) { uint32_t best_dist = UINT32_MAX; - for (const Industry *i : Industry::Iterate()) { - if (i->type != type || i == current) continue; - best_dist = std::min(best_dist, DistanceManhattan(tile, i->location.tile)); + for (const IndustryID &industry : Industry::industries[type]) { + if (industry == current->index) continue; + + best_dist = std::min(best_dist, DistanceManhattan(tile, Industry::Get(industry)->location.tile)); } return best_dist; @@ -145,8 +146,11 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t param_setID, uint8_ } else { /* Count only those who match the same industry type and layout filter * Unfortunately, we have to do it manually */ - for (const Industry *i : Industry::Iterate()) { - if (i->type == ind_index && i != current && (i->selected_layout == layout_filter || layout_filter == 0) && (!town_filter || i->town == current->town)) { + for (const IndustryID &industry : Industry::industries[ind_index]) { + if (industry == current->index) continue; + + const Industry *i = Industry::Get(industry); + if ((layout_filter == 0 || i->selected_layout == layout_filter) && (!town_filter || i->town == current->town)) { closest_dist = std::min(closest_dist, DistanceManhattan(current->location.tile, i->location.tile)); count++; } @@ -278,9 +282,12 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint8_t param_setID, uint8_ } /* Distance of nearest industry of given type */ - case 0x64: + case 0x64: { if (this->tile == INVALID_TILE) break; - return GetClosestIndustry(this->tile, MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid), this->industry); + IndustryType type = MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid); + if (type >= NUM_INDUSTRYTYPES) return UINT32_MAX; + return GetClosestIndustry(this->tile, type, this->industry); + } /* Get town zone and Manhattan distance of closest town */ case 0x65: { if (this->tile == INVALID_TILE) break; diff --git a/src/saveload/industry_sl.cpp b/src/saveload/industry_sl.cpp index bb1682227a..5d843ec349 100644 --- a/src/saveload/industry_sl.cpp +++ b/src/saveload/industry_sl.cpp @@ -211,7 +211,6 @@ struct INDYChunkHandler : ChunkHandler { SlIndustryAccepted::ResetOldStructure(); SlIndustryProduced::ResetOldStructure(); - Industry::ResetIndustryCounts(); while ((index = SlIterateArray()) != -1) { Industry *i = new (index) Industry(); @@ -229,7 +228,7 @@ struct INDYChunkHandler : ChunkHandler { } else if (IsSavegameVersionBefore(SLV_INDUSTRY_CARGO_REORGANISE)) { LoadMoveAcceptsProduced(i, INDUSTRY_NUM_INPUTS, INDUSTRY_NUM_OUTPUTS); } - Industry::IncIndustryTypeCount(i->type); + Industry::industries[i->type].push_back(i->index); // Assume savegame indices are sorted. } } diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index ea9c97c212..436c309b3a 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -874,7 +874,7 @@ static bool LoadOldIndustry(LoadgameState *ls, int num) i->random_colour = RemapTTOColour(i->random_colour); } - Industry::IncIndustryTypeCount(i->type); + Industry::industries[i->type].push_back(i->index); // Assume savegame indices are sorted. } else { delete i; }