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: private:
std::array<TWaterRegionTraversabilityBits, DIAGDIR_END> edge_traversability_bits{}; std::array<TWaterRegionTraversabilityBits, DIAGDIR_END> edge_traversability_bits{};
bool has_cross_region_aqueducts = false; bool has_cross_region_aqueducts = false;
bool initialized = false;
TWaterRegionPatchLabel number_of_patches = 0; // 0 = no water, 1 = one single patch of water, etc... TWaterRegionPatchLabel number_of_patches = 0; // 0 = no water, 1 = one single patch of water, etc...
const OrthogonalTileArea tile_area; 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) 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 begin() const { return this->tile_area.begin(); }
OrthogonalTileIterator end() const { return this->tile_area.end(); } 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 * 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. * 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->number_of_patches = highest_assigned_label;
this->initialized = true;
if (this->number_of_patches == 0 || (this->number_of_patches == 1 && 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; }))) { 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() void PrintDebugInfo()
{ {
Debug(map, 9, "Water region {},{} labels and edge traversability = ...", GetWaterRegionX(tile_area.tile), GetWaterRegionY(tile_area.tile)); 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<WaterRegion> _water_regions;
std::vector<bool> _is_water_region_valid;
TileIndex GetTileIndexFromLocalCoordinate(int region_x, int region_y, int local_x, int local_y) 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 &GetUpdatedWaterRegion(uint16_t region_x, uint16_t region_y)
{ {
WaterRegion &result = _water_regions[GetWaterRegionIndex(region_x, region_y)]; const int index = GetWaterRegionIndex(region_x, region_y);
result.UpdateIfNotInitialized(); auto &water_region = _water_regions[index];
return result; if (!_is_water_region_valid[index]) {
water_region.ForceUpdate();
_is_water_region_valid[index] = true;
}
return water_region;
} }
WaterRegion &GetUpdatedWaterRegion(TileIndex tile) WaterRegion &GetUpdatedWaterRegion(TileIndex tile)
{ {
WaterRegion &result = _water_regions[GetWaterRegionIndex(tile)]; return GetUpdatedWaterRegion(GetWaterRegionX(tile), GetWaterRegionY(tile));
result.UpdateIfNotInitialized();
return result;
} }
/** /**
@ -316,15 +301,21 @@ WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
void InvalidateWaterRegion(TileIndex tile) void InvalidateWaterRegion(TileIndex tile)
{ {
if (!IsValidTile(tile)) return; 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 /* 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 * 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. */ * 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++) { for (DiagDirection side = DIAGDIR_BEGIN; side < DIAGDIR_END; side++) {
const int adjacent_region_index = GetWaterRegionIndex(TileAddByDiagDir(tile, side)); const TileIndex adjacent_tile = TileAddByDiagDir(tile, side);
if (adjacent_region_index != water_region_index) _water_regions[adjacent_region_index].Invalidate(); if (GetWaterRegionIndex(adjacent_tile) != GetWaterRegionIndex(tile)) invalidateRegion(adjacent_tile);
} }
} }
@ -409,8 +400,12 @@ void VisitWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_pat
*/ */
void AllocateWaterRegions() void AllocateWaterRegions()
{ {
const int number_of_regions = static_cast<size_t>(GetWaterRegionMapSizeX()) * GetWaterRegionMapSizeY();
_water_regions.clear(); _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()); Debug(map, 2, "Allocating {} x {} water regions", GetWaterRegionMapSizeX(), GetWaterRegionMapSizeY());
@ -419,6 +414,8 @@ void AllocateWaterRegions()
_water_regions.emplace_back(region_x, region_y); _water_regions.emplace_back(region_x, region_y);
} }
} }
assert(_is_water_region_valid.size() == _water_regions.size());
} }
void PrintWaterRegionDebugInfo(TileIndex tile) void PrintWaterRegionDebugInfo(TileIndex tile)