VarAction2: Move IndustryLocationDistanceCache inside IndustriesScopeResolver
Use in all cases, not just CBID_INDUSTRY_LOCATION
This commit is contained in:
@@ -88,40 +88,21 @@ uint32 GetIndustryIDAtOffset(TileIndex tile, const Industry *i, uint32 cur_grfid
|
|||||||
return 0xFF << 8 | indtsp->grf_prop.subst_id; // so just give it the substitute
|
return 0xFF << 8 | indtsp->grf_prop.subst_id; // so just give it the substitute
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IndustryLocationDistanceCache {
|
uint32 IndustriesScopeResolver::GetClosestIndustry(IndustryType type) const
|
||||||
uint16 distances[NUM_INDUSTRYTYPES];
|
|
||||||
bool initialised = false;
|
|
||||||
|
|
||||||
static IndustryLocationDistanceCache *instance;
|
|
||||||
};
|
|
||||||
IndustryLocationDistanceCache *IndustryLocationDistanceCache::instance = nullptr;
|
|
||||||
|
|
||||||
static uint32 GetClosestIndustry(TileIndex tile, IndustryType type, const Industry *current)
|
|
||||||
{
|
{
|
||||||
if (type >= NUM_INDUSTRYTYPES) return UINT32_MAX;
|
if (type >= NUM_INDUSTRYTYPES) return UINT32_MAX;
|
||||||
if (IndustryLocationDistanceCache::instance != nullptr) {
|
|
||||||
IndustryLocationDistanceCache *cache = IndustryLocationDistanceCache::instance;
|
if (this->location_distance_cache == nullptr) {
|
||||||
if (!cache->initialised) {
|
this->location_distance_cache = std::make_unique<IndustryLocationDistanceCache>();
|
||||||
MemSetT(cache->distances, 0xFF, NUM_INDUSTRYTYPES);
|
MemSetT(this->location_distance_cache->distances, 0xFF, NUM_INDUSTRYTYPES);
|
||||||
for (const Industry *i : Industry::Iterate()) {
|
for (const Industry *i : Industry::Iterate()) {
|
||||||
if (i == current || i->type >= NUM_INDUSTRYTYPES) continue;
|
if (i == this->industry || i->type >= NUM_INDUSTRYTYPES) continue;
|
||||||
|
|
||||||
uint dist = DistanceManhattan(tile, i->location.tile);
|
uint dist = DistanceManhattan(this->tile, i->location.tile);
|
||||||
if (dist < (uint)cache->distances[i->type]) cache->distances[i->type] = (uint16)dist;
|
if (dist < (uint)this->location_distance_cache->distances[i->type]) this->location_distance_cache->distances[i->type] = (uint16)dist;
|
||||||
}
|
}
|
||||||
cache->initialised = true;
|
|
||||||
}
|
}
|
||||||
return cache->distances[type];
|
return this->location_distance_cache->distances[type];
|
||||||
}
|
|
||||||
|
|
||||||
uint32 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
return best_dist;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,10 +112,9 @@ static uint32 GetClosestIndustry(TileIndex tile, IndustryType type, const Indust
|
|||||||
* @param param_setID parameter given to the callback, which is the set id, or the local id, in our terminology
|
* @param param_setID parameter given to the callback, which is the set id, or the local id, in our terminology
|
||||||
* @param layout_filter on what layout do we filter?
|
* @param layout_filter on what layout do we filter?
|
||||||
* @param town_filter Do we filter on the same town as the current industry?
|
* @param town_filter Do we filter on the same town as the current industry?
|
||||||
* @param current Industry for which the inquiry is made
|
|
||||||
* @return the formatted answer to the callback : rr(reserved) cc(count) dddd(manhattan distance of closest sister)
|
* @return the formatted answer to the callback : rr(reserved) cc(count) dddd(manhattan distance of closest sister)
|
||||||
*/
|
*/
|
||||||
static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout_filter, bool town_filter, const Industry *current, uint32 mask)
|
uint32 IndustriesScopeResolver::GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout_filter, bool town_filter, uint32 mask) const
|
||||||
{
|
{
|
||||||
uint32 GrfID = GetRegister(0x100); ///< Get the GRFID of the definition to look for in register 100h
|
uint32 GrfID = GetRegister(0x100); ///< Get the GRFID of the definition to look for in register 100h
|
||||||
IndustryType ind_index;
|
IndustryType ind_index;
|
||||||
@@ -148,7 +128,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFFFFFFF: // current grf
|
case 0xFFFFFFFF: // current grf
|
||||||
GrfID = GetIndustrySpec(current->type)->grf_prop.grffile->grfid;
|
GrfID = GetIndustrySpec(this->industry->type)->grf_prop.grffile->grfid;
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
|
|
||||||
default: // use the grfid specified in register 100h
|
default: // use the grfid specified in register 100h
|
||||||
@@ -163,14 +143,14 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
|
|||||||
if (layout_filter == 0 && !town_filter) {
|
if (layout_filter == 0 && !town_filter) {
|
||||||
/* If the filter is 0, it could be because none was specified as well as being really a 0.
|
/* If the filter is 0, it could be because none was specified as well as being really a 0.
|
||||||
* In either case, just do the regular var67 */
|
* In either case, just do the regular var67 */
|
||||||
if (mask & 0xFFFF) closest_dist = GetClosestIndustry(current->location.tile, ind_index, current);
|
if (mask & 0xFFFF) closest_dist = this->GetClosestIndustry(ind_index);
|
||||||
if (mask & 0xFF0000) count = ClampTo<byte>(Industry::GetIndustryTypeCount(ind_index));
|
if (mask & 0xFF0000) count = ClampTo<byte>(Industry::GetIndustryTypeCount(ind_index));
|
||||||
} else {
|
} else {
|
||||||
/* Count only those who match the same industry type and layout filter
|
/* Count only those who match the same industry type and layout filter
|
||||||
* Unfortunately, we have to do it manually */
|
* Unfortunately, we have to do it manually */
|
||||||
for (const Industry *i : Industry::Iterate()) {
|
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)) {
|
if (i->type == ind_index && i != this->industry && (i->selected_layout == layout_filter || layout_filter == 0) && (!town_filter || i->town == this->industry->town)) {
|
||||||
closest_dist = std::min(closest_dist, DistanceManhattan(current->location.tile, i->location.tile));
|
closest_dist = std::min(closest_dist, DistanceManhattan(this->tile, i->location.tile));
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,7 +289,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
|
|||||||
/* Distance of nearest industry of given type */
|
/* Distance of nearest industry of given type */
|
||||||
case 0x64:
|
case 0x64:
|
||||||
if (this->tile == INVALID_TILE) break;
|
if (this->tile == INVALID_TILE) break;
|
||||||
return GetClosestIndustry(this->tile, MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid), this->industry);
|
return this->GetClosestIndustry(MapNewGRFIndustryType(parameter, indspec->grf_prop.grffile->grfid));
|
||||||
/* Get town zone and Manhattan distance of closest town */
|
/* Get town zone and Manhattan distance of closest town */
|
||||||
case 0x65: {
|
case 0x65: {
|
||||||
if (this->tile == INVALID_TILE) break;
|
if (this->tile == INVALID_TILE) break;
|
||||||
@@ -334,7 +314,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
|
|||||||
layout_filter = GB(reg, 0, 8);
|
layout_filter = GB(reg, 0, 8);
|
||||||
town_filter = HasBit(reg, 8);
|
town_filter = HasBit(reg, 8);
|
||||||
}
|
}
|
||||||
return GetCountAndDistanceOfClosestInstance(parameter, layout_filter, town_filter, this->industry, extra->mask);
|
return this->GetCountAndDistanceOfClosestInstance(parameter, layout_filter, town_filter, extra->mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x69:
|
case 0x69:
|
||||||
@@ -580,14 +560,9 @@ CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, siz
|
|||||||
ind.founder = founder;
|
ind.founder = founder;
|
||||||
ind.psa = nullptr;
|
ind.psa = nullptr;
|
||||||
|
|
||||||
IndustryLocationDistanceCache distance_cache;
|
|
||||||
IndustryLocationDistanceCache::instance = &distance_cache;
|
|
||||||
|
|
||||||
IndustriesResolverObject object(tile, &ind, type, seed, CBID_INDUSTRY_LOCATION, 0, creation_type);
|
IndustriesResolverObject object(tile, &ind, type, seed, CBID_INDUSTRY_LOCATION, 0, creation_type);
|
||||||
uint16 result = object.ResolveCallback();
|
uint16 result = object.ResolveCallback();
|
||||||
|
|
||||||
IndustryLocationDistanceCache::instance = nullptr;
|
|
||||||
|
|
||||||
/* Unlike the "normal" cases, not having a valid result means we allow
|
/* Unlike the "normal" cases, not having a valid result means we allow
|
||||||
* the building of the industry, as that's how it's done in TTDP. */
|
* the building of the industry, as that's how it's done in TTDP. */
|
||||||
if (result == CALLBACK_FAILED) return CommandCost();
|
if (result == CALLBACK_FAILED) return CommandCost();
|
||||||
|
@@ -12,12 +12,18 @@
|
|||||||
|
|
||||||
#include "newgrf_town.h"
|
#include "newgrf_town.h"
|
||||||
|
|
||||||
|
struct IndustryLocationDistanceCache {
|
||||||
|
uint16 distances[NUM_INDUSTRYTYPES];
|
||||||
|
};
|
||||||
|
|
||||||
/** Resolver for industry scopes. */
|
/** Resolver for industry scopes. */
|
||||||
struct IndustriesScopeResolver : public ScopeResolver {
|
struct IndustriesScopeResolver : public ScopeResolver {
|
||||||
TileIndex tile; ///< Tile owned by the industry.
|
TileIndex tile; ///< Tile owned by the industry.
|
||||||
|
uint32 random_bits; ///< Random bits of the new industry.
|
||||||
Industry *industry; ///< %Industry being resolved.
|
Industry *industry; ///< %Industry being resolved.
|
||||||
IndustryType type; ///< Type of the industry.
|
IndustryType type; ///< Type of the industry.
|
||||||
uint32 random_bits; ///< Random bits of the new industry.
|
|
||||||
|
mutable std::unique_ptr<IndustryLocationDistanceCache> location_distance_cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scope resolver for industries.
|
* Scope resolver for industries.
|
||||||
@@ -28,7 +34,7 @@ struct IndustriesScopeResolver : public ScopeResolver {
|
|||||||
* @param random_bits Random bits of the new industry.
|
* @param random_bits Random bits of the new industry.
|
||||||
*/
|
*/
|
||||||
IndustriesScopeResolver(ResolverObject &ro, TileIndex tile, Industry *industry, IndustryType type, uint32 random_bits = 0)
|
IndustriesScopeResolver(ResolverObject &ro, TileIndex tile, Industry *industry, IndustryType type, uint32 random_bits = 0)
|
||||||
: ScopeResolver(ro), tile(tile), industry(industry), type(type), random_bits(random_bits)
|
: ScopeResolver(ro), tile(tile), random_bits(random_bits), industry(industry), type(type)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +42,9 @@ struct IndustriesScopeResolver : public ScopeResolver {
|
|||||||
uint32 GetVariable(uint16 variable, uint32 parameter, GetVariableExtra *extra) const override;
|
uint32 GetVariable(uint16 variable, uint32 parameter, GetVariableExtra *extra) const override;
|
||||||
uint32 GetTriggers() const override;
|
uint32 GetTriggers() const override;
|
||||||
void StorePSA(uint pos, int32 value) override;
|
void StorePSA(uint pos, int32 value) override;
|
||||||
|
|
||||||
|
uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout_filter, bool town_filter, uint32 mask) const;
|
||||||
|
uint32 GetClosestIndustry(IndustryType type) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Resolver for industries. */
|
/** Resolver for industries. */
|
||||||
|
Reference in New Issue
Block a user