mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Refactor FindStationsAroundTiles to avoid code duplication
parent
2d5869fc79
commit
7bd52970a1
|
@ -1697,20 +1697,10 @@ static void PopulateStationsNearby(Industry *ind)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get our list of nearby stations. */
|
ForAllStationsAroundTiles(ind->location, [ind](Station *st) {
|
||||||
FindStationsAroundTiles(ind->location, &ind->stations_near, false);
|
ind->stations_near.insert(st);
|
||||||
|
st->AddIndustryToDeliver(ind);
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -359,12 +359,11 @@ Rect Station::GetCatchmentRect() const
|
||||||
/**
|
/**
|
||||||
* Add nearby industry to station's industries_near list if it accepts cargo.
|
* Add nearby industry to station's industries_near list if it accepts cargo.
|
||||||
* @param ind Industry
|
* @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 */
|
/* 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 */
|
/* Include only industries that can accept cargo */
|
||||||
uint cargo_index;
|
uint cargo_index;
|
||||||
|
@ -373,7 +372,7 @@ static void AddIndustryToDeliver(Industry *ind, Station *st)
|
||||||
}
|
}
|
||||||
if (cargo_index >= lengthof(ind->accepts_cargo)) return;
|
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);
|
i->stations_near.insert(this);
|
||||||
|
|
||||||
/* Add if we can deliver to this industry as well */
|
/* Add if we can deliver to this industry as well */
|
||||||
AddIndustryToDeliver(i, this);
|
this->AddIndustryToDeliver(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,6 +503,7 @@ public:
|
||||||
uint GetCatchmentRadius() const;
|
uint GetCatchmentRadius() const;
|
||||||
Rect GetCatchmentRect() const;
|
Rect GetCatchmentRect() const;
|
||||||
bool CatchmentCoversTown(TownID t) const;
|
bool CatchmentCoversTown(TownID t) const;
|
||||||
|
void AddIndustryToDeliver(Industry *ind);
|
||||||
void RemoveFromAllNearbyLists();
|
void RemoveFromAllNearbyLists();
|
||||||
|
|
||||||
inline bool TileIsInCatchment(TileIndex tile) const
|
inline bool TileIsInCatchment(TileIndex tile) const
|
||||||
|
@ -557,4 +558,39 @@ public:
|
||||||
|
|
||||||
void RebuildStationKdtree();
|
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 */
|
#endif /* STATION_BASE_H */
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "animated_tile_func.h"
|
#include "animated_tile_func.h"
|
||||||
#include "elrail_func.h"
|
#include "elrail_func.h"
|
||||||
#include "station_base.h"
|
#include "station_base.h"
|
||||||
|
#include "station_func.h"
|
||||||
#include "station_kdtree.h"
|
#include "station_kdtree.h"
|
||||||
#include "roadstop_base.h"
|
#include "roadstop_base.h"
|
||||||
#include "newgrf_railtype.h"
|
#include "newgrf_railtype.h"
|
||||||
|
@ -3965,57 +3966,6 @@ 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
|
* 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
|
* @return pointer to a StationList containing all stations found
|
||||||
|
@ -4023,12 +3973,21 @@ void FindStationsAroundTiles(const TileArea &location, StationList * const stati
|
||||||
const StationList *StationFinder::GetStations()
|
const StationList *StationFinder::GetStations()
|
||||||
{
|
{
|
||||||
if (this->tile != INVALID_TILE) {
|
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;
|
this->tile = INVALID_TILE;
|
||||||
}
|
}
|
||||||
return &this->stations;
|
return &this->stations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool CanMoveGoodsToStation(const Station *st, CargoID type)
|
static bool CanMoveGoodsToStation(const Station *st, CargoID type)
|
||||||
{
|
{
|
||||||
/* Is the station reserved exclusively for somebody else? */
|
/* Is the station reserved exclusively for somebody else? */
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
|
|
||||||
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius);
|
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 ShowStationViewWindow(StationID station);
|
||||||
void UpdateAllStationVirtCoords();
|
void UpdateAllStationVirtCoords();
|
||||||
void ClearAllStationCachedNames();
|
void ClearAllStationCachedNames();
|
||||||
|
|
|
@ -102,7 +102,7 @@ static void FindStationsAroundSelection()
|
||||||
|
|
||||||
Station *adjacent = nullptr;
|
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) {
|
TILE_AREA_LOOP(tile, ta) {
|
||||||
if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) {
|
if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) {
|
||||||
Station *st = Station::GetByTile(tile);
|
Station *st = Station::GetByTile(tile);
|
||||||
|
|
|
@ -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_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 (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);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue