summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordP <dp@dpointer.org>2020-05-12 01:36:28 +0300
committerCharles Pigott <charlespigott@googlemail.com>2020-05-13 08:43:01 +0100
commit7bd52970a1e83cb88069e73e26479eb71bd17726 (patch)
tree88e6fca4b38b16333dd6f37c7fde50fd4464596d /src
parent2d5869fc79a1f1f347ab31665148c806d54afcd9 (diff)
downloadopenttd-7bd52970a1e83cb88069e73e26479eb71bd17726.tar.xz
Codechange: Refactor FindStationsAroundTiles to avoid code duplication
Diffstat (limited to 'src')
-rw-r--r--src/industry_cmd.cpp18
-rw-r--r--src/station.cpp9
-rw-r--r--src/station_base.h36
-rw-r--r--src/station_cmd.cpp63
-rw-r--r--src/station_func.h2
-rw-r--r--src/station_gui.cpp2
-rw-r--r--src/town_cmd.cpp6
7 files changed, 61 insertions, 75 deletions
diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp
index dfc43500f..39fc0d6f1 100644
--- a/src/industry_cmd.cpp
+++ b/src/industry_cmd.cpp
@@ -1697,20 +1697,10 @@ static void PopulateStationsNearby(Industry *ind)
return;
}
- /* Get our list of nearby stations. */
- FindStationsAroundTiles(ind->location, &ind->stations_near, false);
-
- /* Test if industry can accept cargo */
- uint cargo_index;
- for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
- if (ind->accepts_cargo[cargo_index] != CT_INVALID) break;
- }
- if (cargo_index >= lengthof(ind->accepts_cargo)) return;
-
- /* Cargo is accepted, add industry to nearby stations nearby industry list. */
- for (Station *st : ind->stations_near) {
- st->industries_near.insert(ind);
- }
+ ForAllStationsAroundTiles(ind->location, [ind](Station *st) {
+ ind->stations_near.insert(st);
+ st->AddIndustryToDeliver(ind);
+ });
}
/**
diff --git a/src/station.cpp b/src/station.cpp
index 61c53bc56..ec332e0bb 100644
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -359,12 +359,11 @@ Rect Station::GetCatchmentRect() const
/**
* Add nearby industry to station's industries_near list if it accepts cargo.
* @param ind Industry
- * @param st Station
*/
-static void AddIndustryToDeliver(Industry *ind, Station *st)
+void Station::AddIndustryToDeliver(Industry *ind)
{
/* Don't check further if this industry is already in the list */
- if (st->industries_near.find(ind) != st->industries_near.end()) return;
+ if (this->industries_near.find(ind) != this->industries_near.end()) return;
/* Include only industries that can accept cargo */
uint cargo_index;
@@ -373,7 +372,7 @@ static void AddIndustryToDeliver(Industry *ind, Station *st)
}
if (cargo_index >= lengthof(ind->accepts_cargo)) return;
- st->industries_near.insert(ind);
+ this->industries_near.insert(ind);
}
/**
@@ -464,7 +463,7 @@ void Station::RecomputeCatchment()
i->stations_near.insert(this);
/* Add if we can deliver to this industry as well */
- AddIndustryToDeliver(i, this);
+ this->AddIndustryToDeliver(i);
}
}
}
diff --git a/src/station_base.h b/src/station_base.h
index 0c33a58ed..3be7d4437 100644
--- a/src/station_base.h
+++ b/src/station_base.h
@@ -503,6 +503,7 @@ public:
uint GetCatchmentRadius() const;
Rect GetCatchmentRect() const;
bool CatchmentCoversTown(TownID t) const;
+ void AddIndustryToDeliver(Industry *ind);
void RemoveFromAllNearbyLists();
inline bool TileIsInCatchment(TileIndex tile) const
@@ -557,4 +558,39 @@ public:
void RebuildStationKdtree();
+/**
+ * Call a function on all stations that have any part of the requested area within their catchment.
+ * @param area The tile area to check
+ */
+template<typename Func>
+void ForAllStationsAroundTiles(const TileArea &ta, Func func)
+{
+ /* Not using, or don't have a nearby stations list, so we need to scan. */
+ std::set<StationID> seen_stations;
+
+ /* Scan an area around the building covering the maximum possible station
+ * to find the possible nearby stations. */
+ uint max_c = _settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED;
+ TileArea ta_ext = TileArea(ta).Expand(max_c);
+ TILE_AREA_LOOP(tile, ta_ext) {
+ if (IsTileType(tile, MP_STATION)) seen_stations.insert(GetStationIndex(tile));
+ }
+
+ for (StationID stationid : seen_stations) {
+ Station *st = Station::GetIfValid(stationid);
+ if (st == nullptr) continue; /* Waypoint */
+
+ /* Check if station is attached to an industry */
+ if (!_settings_game.station.serve_neutral_industries && st->industry != nullptr) continue;
+
+ /* Test if the tile is within the station's catchment */
+ TILE_AREA_LOOP(tile, ta) {
+ if (st->TileIsInCatchment(tile)) {
+ func(st);
+ break;
+ }
+ }
+ }
+}
+
#endif /* STATION_BASE_H */
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index b88383884..7bf2c43df 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -36,6 +36,7 @@
#include "animated_tile_func.h"
#include "elrail_func.h"
#include "station_base.h"
+#include "station_func.h"
#include "station_kdtree.h"
#include "roadstop_base.h"
#include "newgrf_railtype.h"
@@ -3966,69 +3967,27 @@ static void AddNearbyStationsByCatchment(TileIndex tile, StationList *stations,
}
/**
- * Find all stations around a rectangular producer (industry, house, headquarter, ...)
- *
- * @param location The location/area of the producer
- * @param[out] stations The list to store the stations in
- * @param use_nearby Use nearby station list of industry/town associated with location.tile
- */
-void FindStationsAroundTiles(const TileArea &location, StationList * const stations, bool use_nearby)
-{
- if (use_nearby) {
- /* Industries and towns maintain a list of nearby stations */
- if (IsTileType(location.tile, MP_INDUSTRY)) {
- /* Industry nearby stations are already filtered by catchment. */
- *stations = Industry::GetByTile(location.tile)->stations_near;
- return;
- } else if (IsTileType(location.tile, MP_HOUSE)) {
- /* Town nearby stations need to be filtered per tile. */
- assert(location.w == 1 && location.h == 1);
- AddNearbyStationsByCatchment(location.tile, stations, Town::GetByTile(location.tile)->stations_near);
- return;
- }
- }
-
- /* Not using, or don't have a nearby stations list, so we need to scan. */
- std::set<StationID> seen_stations;
-
- /* Scan an area around the building covering the maximum possible station
- * to find the possible nearby stations. */
- uint max_c = _settings_game.station.modified_catchment ? MAX_CATCHMENT : CA_UNMODIFIED;
- TileArea ta = TileArea(location).Expand(max_c);
- TILE_AREA_LOOP(tile, ta) {
- if (IsTileType(tile, MP_STATION)) seen_stations.insert(GetStationIndex(tile));
- }
-
- for (StationID stationid : seen_stations) {
- Station *st = Station::GetIfValid(stationid);
- if (st == nullptr) continue; /* Waypoint */
-
- /* Check if station is attached to an industry */
- if (!_settings_game.station.serve_neutral_industries && st->industry != nullptr) continue;
-
- /* Test if the tile is within the station's catchment */
- TILE_AREA_LOOP(tile, location) {
- if (st->TileIsInCatchment(tile)) {
- stations->insert(st);
- break;
- }
- }
- }
-}
-
-/**
* Run a tile loop to find stations around a tile, on demand. Cache the result for further requests
* @return pointer to a StationList containing all stations found
*/
const StationList *StationFinder::GetStations()
{
if (this->tile != INVALID_TILE) {
- FindStationsAroundTiles(*this, &this->stations);
+ if (IsTileType(this->tile, MP_HOUSE)) {
+ /* Town nearby stations need to be filtered per tile. */
+ assert(this->w == 1 && this->h == 1);
+ AddNearbyStationsByCatchment(this->tile, &this->stations, Town::GetByTile(this->tile)->stations_near);
+ } else {
+ ForAllStationsAroundTiles(*this, [this](Station *st) {
+ this->stations.insert(st);
+ });
+ }
this->tile = INVALID_TILE;
}
return &this->stations;
}
+
static bool CanMoveGoodsToStation(const Station *st, CargoID type)
{
/* Is the station reserved exclusively for somebody else? */
diff --git a/src/station_func.h b/src/station_func.h
index f9959089e..dc8942841 100644
--- a/src/station_func.h
+++ b/src/station_func.h
@@ -22,8 +22,6 @@
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
-void FindStationsAroundTiles(const TileArea &location, StationList *stations, bool use_nearby = true);
-
void ShowStationViewWindow(StationID station);
void UpdateAllStationVirtCoords();
void ClearAllStationCachedNames();
diff --git a/src/station_gui.cpp b/src/station_gui.cpp
index 764d34748..ef2873f22 100644
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -102,7 +102,7 @@ static void FindStationsAroundSelection()
Station *adjacent = nullptr;
- /* Direct loop instead of FindStationsAroundTiles as we are not interested in catchment area */
+ /* Direct loop instead of ForAllStationsAroundTiles as we are not interested in catchment area */
TILE_AREA_LOOP(tile, ta) {
if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) {
Station *st = Station::GetByTile(tile);
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index 0a582eee7..44c396cba 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -2249,7 +2249,11 @@ static void MakeTownHouse(TileIndex t, Town *town, byte counter, byte stage, Hou
if (size & BUILDING_2_TILES_X) ClearMakeHouseTile(t + TileDiffXY(1, 0), town, counter, stage, ++type, random_bits);
if (size & BUILDING_HAS_4_TILES) ClearMakeHouseTile(t + TileDiffXY(1, 1), town, counter, stage, ++type, random_bits);
- if (!_generating_world) FindStationsAroundTiles(TileArea(t, (size & BUILDING_2_TILES_X) ? 2 : 1, (size & BUILDING_2_TILES_Y) ? 2 : 1), &town->stations_near, false);
+ if (!_generating_world) {
+ ForAllStationsAroundTiles(TileArea(t, (size & BUILDING_2_TILES_X) ? 2 : 1, (size & BUILDING_2_TILES_Y) ? 2 : 1), [town](Station *st) {
+ town->stations_near.insert(st);
+ });
+ }
}