diff --git a/src/economy_func.h b/src/economy_func.h index 38505d4504..e4a77fb6a9 100644 --- a/src/economy_func.h +++ b/src/economy_func.h @@ -21,6 +21,7 @@ #include "industry_type.h" #include "company_type.h" #include "station_type.h" +#include "station_func.h" void ResetPriceBaseMultipliers(); void SetPriceBaseMultiplier(Price price, int factor); @@ -35,7 +36,7 @@ int UpdateCompanyRatingAndValue(Company *c, bool update); void StartupIndustryDailyChanges(bool init_counter); Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type); -uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount, SourceType source_type, SourceID source_id); +uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations); void PrepareUnload(Vehicle *front_v); void LoadUnloadStation(Station *st); diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 7080ac4a8e..5e0ad84db1 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -507,6 +507,8 @@ static void TransportIndustryGoods(TileIndex tile) const IndustrySpec *indspec = GetIndustrySpec(i->type); bool moved_cargo = false; + StationFinder stations(i->xy, i->width, i->height); + for (uint j = 0; j < lengthof(i->produced_cargo_waiting); j++) { uint cw = min(i->produced_cargo_waiting[j], 255); if (cw > indspec->minimal_cargo && i->produced_cargo[j] != CT_INVALID) { @@ -517,7 +519,7 @@ static void TransportIndustryGoods(TileIndex tile) i->this_month_production[j] += cw; - uint am = MoveGoodsToStation(i->xy, i->width, i->height, i->produced_cargo[j], cw, ST_INDUSTRY, i->index); + uint am = MoveGoodsToStation(i->produced_cargo[j], cw, ST_INDUSTRY, i->index, stations.GetStations()); i->this_month_transported[j] += am; moved_cargo |= (am != 0); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 601322cf52..d17d0dc499 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3009,7 +3009,20 @@ void FindStationsAroundTiles(TileIndex tile, int w_prod, int h_prod, StationList } } -uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount, SourceType source_type, SourceID source_id) +/** + * 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->tile, this->x_extent, this->y_extent, &this->stations); + this->tile = INVALID_TILE; + } + return &this->stations; +} + +uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations) { /* Return if nothing to do. Also the rounding below fails for 0. */ if (amount == 0) return 0; @@ -3019,9 +3032,7 @@ uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount, uint best_rating1 = 0; // rating of st1 uint best_rating2 = 0; // rating of st2 - StationList all_stations; - FindStationsAroundTiles(tile, w, h, &all_stations); - for (Station **st_iter = all_stations.Begin(); st_iter != all_stations.End(); ++st_iter) { + for (Station * const *st_iter = all_stations->Begin(); st_iter != all_stations->End(); ++st_iter) { Station *st = *st_iter; /* Is the station reserved exclusively for somebody else? */ diff --git a/src/station_func.h b/src/station_func.h index 0f87d19382..22a7cf79a4 100644 --- a/src/station_func.h +++ b/src/station_func.h @@ -19,11 +19,9 @@ #include "tile_type.h" #include "cargo_type.h" #include "vehicle_type.h" -#include "core/smallvec_type.hpp" void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius); -typedef SmallVector StationList; void FindStationsAroundTiles(TileIndex tile, int w_prod, int h_prod, StationList *stations); void ShowStationViewWindow(StationID station); diff --git a/src/station_type.h b/src/station_type.h index 5f827fffc0..2784f123bf 100644 --- a/src/station_type.h +++ b/src/station_type.h @@ -13,6 +13,7 @@ #define STATION_TYPE_H #include "core/enum_type.hpp" +#include "core/smallvec_type.hpp" #include "tile_type.h" typedef uint16 StationID; @@ -115,4 +116,27 @@ struct TileArea { uint8 h; ///< The height of the area }; +/** List of stations */ +typedef SmallVector StationList; + +/** + * Structure contains cached list of stations nearby. The list + * is created upon first call to GetStations() + */ +class StationFinder { + StationList stations; ///< List of stations nearby + TileIndex tile; ///< Northern tile of producer, INVALID_TILE when # stations is valid + int x_extent; ///< Width of producer + int y_extent; ///< Height of producer +public: + /** + * Constructs StationFinder + * @param t northern tile + * @param dx width of producer + * @param dy height of producer + */ + StationFinder(TileIndex t, int dx, int dy) : tile(t), x_extent(dx), y_extent(dy) {} + const StationList *GetStations(); +}; + #endif /* STATION_TYPE_H */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 0d2b45b71c..30c4806b1d 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -465,6 +465,8 @@ static void TileLoop_Town(TileIndex tile) Town *t = Town::GetByTile(tile); uint32 r = Random(); + StationFinder stations(tile, 1, 1); + if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) { for (uint i = 0; i < 256; i++) { uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, r, house_id, t, tile); @@ -477,7 +479,7 @@ static void TileLoop_Town(TileIndex tile) uint amt = GB(callback, 0, 8); if (amt == 0) continue; - uint moved = MoveGoodsToStation(tile, 1, 1, cargo, amt, ST_TOWN, t->index); + uint moved = MoveGoodsToStation(cargo, amt, ST_TOWN, t->index, stations.GetStations()); const CargoSpec *cs = CargoSpec::Get(cargo); switch (cs->town_effect) { @@ -501,7 +503,7 @@ static void TileLoop_Town(TileIndex tile) if (_economy.fluct <= 0) amt = (amt + 1) >> 1; t->new_max_pass += amt; - t->new_act_pass += MoveGoodsToStation(tile, 1, 1, CT_PASSENGERS, amt, ST_TOWN, t->index); + t->new_act_pass += MoveGoodsToStation(CT_PASSENGERS, amt, ST_TOWN, t->index, stations.GetStations()); } if (GB(r, 8, 8) < hs->mail_generation) { @@ -509,7 +511,7 @@ static void TileLoop_Town(TileIndex tile) if (_economy.fluct <= 0) amt = (amt + 1) >> 1; t->new_max_mail += amt; - t->new_act_mail += MoveGoodsToStation(tile, 1, 1, CT_MAIL, amt, ST_TOWN, t->index); + t->new_act_mail += MoveGoodsToStation(CT_MAIL, amt, ST_TOWN, t->index, stations.GetStations()); } } diff --git a/src/unmovable_cmd.cpp b/src/unmovable_cmd.cpp index 93ac089981..931d2d7c96 100644 --- a/src/unmovable_cmd.cpp +++ b/src/unmovable_cmd.cpp @@ -344,12 +344,14 @@ static void TileLoop_Unmovable(TileIndex tile) uint level = GetCompanyHQSize(tile) + 1; assert(level < 6); + StationFinder stations(tile, 2, 2); + uint r = Random(); /* Top town buildings generate 250, so the top HQ type makes 256. */ if (GB(r, 0, 8) < (256 / 4 / (6 - level))) { uint amt = GB(r, 0, 8) / 8 / 4 + 1; if (_economy.fluct <= 0) amt = (amt + 1) >> 1; - MoveGoodsToStation(tile, 2, 2, CT_PASSENGERS, amt, ST_HEADQUARTERS, GetTileOwner(tile)); + MoveGoodsToStation(CT_PASSENGERS, amt, ST_HEADQUARTERS, GetTileOwner(tile), stations.GetStations()); } /* Top town building generates 90, HQ can make up to 196. The @@ -358,7 +360,7 @@ static void TileLoop_Unmovable(TileIndex tile) if (GB(r, 8, 8) < (196 / 4 / (6 - level))) { uint amt = GB(r, 8, 8) / 8 / 4 + 1; if (_economy.fluct <= 0) amt = (amt + 1) >> 1; - MoveGoodsToStation(tile, 2, 2, CT_MAIL, amt, ST_HEADQUARTERS, GetTileOwner(tile)); + MoveGoodsToStation(CT_MAIL, amt, ST_HEADQUARTERS, GetTileOwner(tile), stations.GetStations()); } }