This commit is contained in:
Kuhnovic 2024-04-26 23:01:34 +01:00 committed by GitHub
commit 41fd78fb0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 26 additions and 29 deletions

View File

@ -51,7 +51,6 @@ class WaterRegion
private:
std::array<TWaterRegionTraversabilityBits, DIAGDIR_END> edge_traversability_bits{};
bool has_cross_region_aqueducts = false;
bool initialized = false;
TWaterRegionPatchLabel number_of_patches = 0; // 0 = no water, 1 = one single patch of water, etc...
const OrthogonalTileArea tile_area;
std::unique_ptr<TWaterRegionPatchLabelArray> tile_patch_labels; ///< Tile patch labels, this may be nullptr in the following trivial cases: region is invalid, region is only land (0 patches), region is only water (1 patch)
@ -76,14 +75,6 @@ public:
OrthogonalTileIterator begin() const { return this->tile_area.begin(); }
OrthogonalTileIterator end() const { return this->tile_area.end(); }
bool IsInitialized() const { return this->initialized; }
void Invalidate()
{
if (!IsInitialized()) Debug(map, 3, "Invalidated water region ({},{})", GetWaterRegionX(this->tile_area.tile), GetWaterRegionY(this->tile_area.tile));
this->initialized = false;
}
/**
* Returns a set of bits indicating whether an edge tile on a particular side is traversable or not. These
* values can be used to determine whether a ship can enter/leave the region through a particular edge tile.
@ -182,7 +173,6 @@ public:
}
this->number_of_patches = highest_assigned_label;
this->initialized = true;
if (this->number_of_patches == 0 || (this->number_of_patches == 1 &&
std::all_of(this->tile_patch_labels->begin(), this->tile_patch_labels->end(), [](TWaterRegionPatchLabel label) { return label == 1; }))) {
@ -191,14 +181,6 @@ public:
}
}
/**
* Updates the patch labels and other data, but only if the region is not yet initialized.
*/
inline void UpdateIfNotInitialized()
{
if (!this->initialized) ForceUpdate();
}
void PrintDebugInfo()
{
Debug(map, 9, "Water region {},{} labels and edge traversability = ...", GetWaterRegionX(tile_area.tile), GetWaterRegionY(tile_area.tile));
@ -228,6 +210,7 @@ public:
};
std::vector<WaterRegion> _water_regions;
std::vector<bool> _is_water_region_valid;
TileIndex GetTileIndexFromLocalCoordinate(int region_x, int region_y, int local_x, int local_y)
{
@ -250,16 +233,18 @@ TileIndex GetEdgeTileCoordinate(int region_x, int region_y, DiagDirection side,
WaterRegion &GetUpdatedWaterRegion(uint16_t region_x, uint16_t region_y)
{
WaterRegion &result = _water_regions[GetWaterRegionIndex(region_x, region_y)];
result.UpdateIfNotInitialized();
return result;
const int index = GetWaterRegionIndex(region_x, region_y);
auto &water_region = _water_regions[index];
if (!_is_water_region_valid[index]) {
water_region.ForceUpdate();
_is_water_region_valid[index] = true;
}
return water_region;
}
WaterRegion &GetUpdatedWaterRegion(TileIndex tile)
{
WaterRegion &result = _water_regions[GetWaterRegionIndex(tile)];
result.UpdateIfNotInitialized();
return result;
return GetUpdatedWaterRegion(GetWaterRegionX(tile), GetWaterRegionY(tile));
}
/**
@ -316,15 +301,21 @@ WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
void InvalidateWaterRegion(TileIndex tile)
{
if (!IsValidTile(tile)) return;
const int water_region_index = GetWaterRegionIndex(tile);
_water_regions[water_region_index].Invalidate();
auto invalidateRegion = [](TileIndex tile) {
const int water_region_index = GetWaterRegionIndex(tile);
if (!_is_water_region_valid[water_region_index]) Debug(map, 3, "Invalidated water region ({},{})", GetWaterRegionX(tile), GetWaterRegionY(tile));
_is_water_region_valid[water_region_index] = false;
};
invalidateRegion(tile);
/* When updating the water region we look into the first tile of adjacent water regions to determine edge
* traversability. This means that if we invalidate any region edge tiles we might also change the traversability
* of the adjacent region. This code ensures the adjacent regions also get invalidated in such a case. */
for (DiagDirection side = DIAGDIR_BEGIN; side < DIAGDIR_END; side++) {
const int adjacent_region_index = GetWaterRegionIndex(TileAddByDiagDir(tile, side));
if (adjacent_region_index != water_region_index) _water_regions[adjacent_region_index].Invalidate();
const TileIndex adjacent_tile = TileAddByDiagDir(tile, side);
if (GetWaterRegionIndex(adjacent_tile) != GetWaterRegionIndex(tile)) invalidateRegion(adjacent_tile);
}
}
@ -409,8 +400,12 @@ void VisitWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_pat
*/
void AllocateWaterRegions()
{
const int number_of_regions = static_cast<size_t>(GetWaterRegionMapSizeX()) * GetWaterRegionMapSizeY();
_water_regions.clear();
_water_regions.reserve(static_cast<size_t>(GetWaterRegionMapSizeX()) * GetWaterRegionMapSizeY());
_water_regions.reserve(number_of_regions);
_is_water_region_valid.resize(number_of_regions, false);
Debug(map, 2, "Allocating {} x {} water regions", GetWaterRegionMapSizeX(), GetWaterRegionMapSizeY());
@ -419,6 +414,8 @@ void AllocateWaterRegions()
_water_regions.emplace_back(region_x, region_y);
}
}
assert(_is_water_region_valid.size() == _water_regions.size());
}
void PrintWaterRegionDebugInfo(TileIndex tile)