@ -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 invalidate_region = [ ] ( 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 ;
} ;
invalidate_region ( 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 ) ) invalidate_region ( adjacent_tile ) ;
}
}
}
}
@ -409,8 +400,12 @@ void VisitWaterRegionPatchNeighbors(const WaterRegionPatchDesc &water_region_pat
*/
*/
void AllocateWaterRegions ( )
void AllocateWaterRegions ( )
{
{
const int number_of_regions = 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 )