diff --git a/library/include/modules/MapCache.h b/library/include/modules/MapCache.h index f2aebc23d..8eac514be 100644 --- a/library/include/modules/MapCache.h +++ b/library/include/modules/MapCache.h @@ -170,6 +170,7 @@ public: bool Write(); + df::coord2d biomeRegionAt(df::coord2d p); int16_t GeoIndexAt(df::coord2d p); bool GetGlobalFeature(t_feature *out); @@ -385,7 +386,7 @@ private: uint32_t x_tmax; uint32_t y_tmax; uint32_t z_max; - std::vector geoidx; + std::vector geoidx; std::vector< std::vector > layer_mats; std::map blocks; }; diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h index 492512ca9..91b8ae7c2 100644 --- a/library/include/modules/Maps.h +++ b/library/include/modules/Maps.h @@ -49,6 +49,7 @@ distribution. #include "df/tile_liquid.h" #include "df/tile_dig_designation.h" #include "df/tile_traffic.h" +#include "df/world_data.h" /** * \defgroup grp_maps Maps module and its types @@ -188,7 +189,7 @@ void DfMap::applyGeoMatgloss(Block * b) * @endcode */ extern DFHACK_EXPORT bool ReadGeology(std::vector > *layer_mats, - std::vector *geoidx); + std::vector *geoidx); /** * Get pointers to features of a block */ @@ -198,11 +199,22 @@ extern DFHACK_EXPORT bool ReadFeatures(uint32_t x, uint32_t y, uint32_t z, t_fea */ extern DFHACK_EXPORT bool ReadFeatures(df::map_block * block,t_feature * local, t_feature * global); + +/** + * Get a pointer to a specific global feature directly. + */ +DFHACK_EXPORT df::feature_init *getGlobalInitFeature(int32_t index); +/** + * Get a pointer to a specific local feature directly. rgn_coord is in the world region grid. + */ +DFHACK_EXPORT df::feature_init *getLocalInitFeature(df::coord2d rgn_coord, int32_t index); + /** * Read a specific global or local feature directly */ extern DFHACK_EXPORT bool GetGlobalFeature(t_feature &feature, int32_t index); -extern DFHACK_EXPORT bool GetLocalFeature(t_feature &feature, df::coord2d coord, int32_t index); +//extern DFHACK_EXPORT bool GetLocalFeature(t_feature &feature, df::coord2d rgn_coord, int32_t index); + /* * BLOCK DATA @@ -217,13 +229,12 @@ extern DFHACK_EXPORT void getPosition(int32_t& x, int32_t& y, int32_t& z); * Get the map block or NULL if block is not valid */ extern DFHACK_EXPORT df::map_block * getBlock (int32_t blockx, int32_t blocky, int32_t blockz); -extern DFHACK_EXPORT df::map_block * getBlockAbs (int32_t x, int32_t y, int32_t z); +extern DFHACK_EXPORT df::map_block * getTileBlock (int32_t x, int32_t y, int32_t z); inline df::map_block * getBlock (df::coord pos) { return getBlock(pos.x, pos.y, pos.z); } -inline df::map_block * getBlockAbs (df::coord pos) { return getBlockAbs(pos.x, pos.y, pos.z); } +inline df::map_block * getTileBlock (df::coord pos) { return getTileBlock(pos.x, pos.y, pos.z); } -/// copy region offsets of a block - used for determining layer stone matgloss -extern DFHACK_EXPORT bool ReadRegionOffsets(uint32_t blockx, uint32_t blocky, uint32_t blockz, biome_indices40d *buffer); +DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos); /// sorts the block event vector into multiple vectors by type /// mineral veins, what's under ice, blood smears and mud @@ -238,9 +249,6 @@ extern DFHACK_EXPORT bool SortBlockEvents(df::map_block *block, /// remove a block event from the block by address extern DFHACK_EXPORT bool RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, df::block_square_event * which ); -/// read all plants in this block -extern DFHACK_EXPORT bool ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector*& plants); - } } #endif diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp index 848454468..4d653b4fa 100644 --- a/library/modules/Maps.cpp +++ b/library/modules/Maps.cpp @@ -127,7 +127,7 @@ df::map_block *Maps::getBlock (int32_t blockx, int32_t blocky, int32_t blockz) return world->map.block_index[blockx][blocky][blockz]; } -df::map_block *Maps::getBlockAbs (int32_t x, int32_t y, int32_t z) +df::map_block *Maps::getTileBlock (int32_t x, int32_t y, int32_t z) { if (!IsValid()) return NULL; @@ -138,31 +138,40 @@ df::map_block *Maps::getBlockAbs (int32_t x, int32_t y, int32_t z) return world->map.block_index[x >> 4][y >> 4][z]; } -/* - * Region Offsets - used for layer geology - */ -bool Maps::ReadRegionOffsets (uint32_t x, uint32_t y, uint32_t z, biome_indices40d *buffer) +df::world_data::T_region_map *Maps::getRegionBiome(df::coord2d rgn_pos) { - df::map_block *block = getBlock(x,y,z); - if (block) - { - memcpy(buffer, block->region_offset,sizeof(biome_indices40d)); - return true; - } - return false; + auto data = world->world_data; + if (!data) + return NULL; + + if (rgn_pos.x < 0 || rgn_pos.x >= data->world_width || + rgn_pos.y < 0 || rgn_pos.y >= data->world_height) + return NULL; + + return &data->region_map[rgn_pos.x][rgn_pos.y]; +} + +df::feature_init *Maps::getGlobalInitFeature(int32_t index) +{ + auto data = world->world_data; + if (!data) + return NULL; + + auto rgn = vector_get(data->underground_regions, index); + if (!rgn) + return NULL; + + return rgn->feature_init; } bool Maps::GetGlobalFeature(t_feature &feature, int32_t index) { feature.type = (df::feature_type)-1; - if (!world->world_data) - return false; - if ((index < 0) || (index >= world->world_data->underground_regions.size())) + auto f = Maps::getGlobalInitFeature(index); + if (!f) return false; - df::feature_init *f = world->world_data->underground_regions[index]->feature_init; - feature.discovered = false; feature.origin = f; feature.type = f->getType(); @@ -170,35 +179,38 @@ bool Maps::GetGlobalFeature(t_feature &feature, int32_t index) return true; } -bool Maps::GetLocalFeature(t_feature &feature, df::coord2d coord, int32_t index) +df::feature_init *Maps::getLocalInitFeature(df::coord2d rgn_pos, int32_t index) { - feature.type = (df::feature_type)-1; - if (!world->world_data) - return false; - - // regionX and regionY are in embark squares! - // we convert to full region tiles - // this also works in adventure mode - // region X coord - whole regions - uint32_t region_x = ( (coord.x / 3) + world->map.region_x ) / 16; - // region Y coord - whole regions - uint32_t region_y = ( (coord.y / 3) + world->map.region_y ) / 16; + auto data = world->world_data; + if (!data) + return NULL; - uint32_t bigregion_x = region_x / 16; - uint32_t bigregion_y = region_y / 16; + if (rgn_pos.x < 0 || rgn_pos.x >= data->world_width || + rgn_pos.y < 0 || rgn_pos.y >= data->world_height) + return NULL; - uint32_t sub_x = region_x % 16; - uint32_t sub_y = region_y % 16; // megaregions = 16x16 squares of regions = 256x256 squares of embark squares + df::coord2d bigregion = rgn_pos / 16; // bigregion is 16x16 regions. for each bigregion in X dimension: - if (!world->world_data->unk_204[bigregion_x][bigregion_y].features) - return false; + auto fptr = data->unk_204[bigregion.x][bigregion.y].features; + if (!fptr) + return NULL; + + df::coord2d sub = rgn_pos & 15; + + vector &features = fptr->feature_init[sub.x][sub.y]; + + return vector_get(features, index); +} + +static bool GetLocalFeature(t_feature &feature, df::coord2d rgn_pos, int32_t index) +{ + feature.type = (df::feature_type)-1; - vector &features = world->world_data->unk_204[bigregion_x][bigregion_y].features->feature_init[sub_x][sub_y]; - if ((index < 0) || (index >= features.size())) + auto f = Maps::getLocalInitFeature(rgn_pos, index); + if (!f) return false; - df::feature_init *f = features[index]; feature.discovered = false; feature.origin = f; @@ -228,7 +240,7 @@ bool Maps::ReadFeatures(df::map_block * block, t_feature * local, t_feature * gl if (local) { if (block->local_feature != -1) - result &= GetLocalFeature(*local, block->map_pos/16, block->local_feature); + result &= GetLocalFeature(*local, block->region_pos, block->local_feature); else local->type = (df::feature_type)-1; } @@ -310,7 +322,7 @@ bool Maps::RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, df::block_square /* * Layer geology */ -bool Maps::ReadGeology(vector > *layer_mats, vector *geoidx) +bool Maps::ReadGeology(vector > *layer_mats, vector *geoidx) { if (!world->world_data) return false; @@ -321,9 +333,12 @@ bool Maps::ReadGeology(vector > *layer_mats, vector *ge for (int i = 0; i < eBiomeCount; i++) { (*layer_mats)[i].clear(); - (*geoidx)[i] = -1; + (*geoidx)[i] = df::coord2d(-30000,-30000); } + int world_width = world->world_data->world_width; + int world_height = world->world_data->world_height; + // iterate over 8 surrounding regions + local region for (int i = eNorthWest; i < eBiomeCount; i++) { @@ -332,16 +347,18 @@ bool Maps::ReadGeology(vector > *layer_mats, vector *ge // regionX/16 is in 16x16 embark square regions // i provides -1 .. +1 offset from the current region int bioRX = world->map.region_x / 16 + ((i % 3) - 1); - if (bioRX < 0) bioRX = 0; - if (bioRX >= world->world_data->world_width) bioRX = world->world_data->world_width - 1; int bioRY = world->map.region_y / 16 + ((i / 3) - 1); - if (bioRY < 0) bioRY = 0; - if (bioRY >= world->world_data->world_height) bioRY = world->world_data->world_height - 1; - // get index into geoblock vector - int16_t geoindex = world->world_data->region_map[bioRX][bioRY].geo_index; + df::coord2d rgn_pos(clip_range(bioRX,0,world_width-1),clip_range(bioRX,0,world_height-1)); + + (*geoidx)[i] = rgn_pos; + + auto biome = getRegionBiome(rgn_pos); + if (!biome) + continue; - (*geoidx)[i] = geoindex; + // get index into geoblock vector + int16_t geoindex = biome->geo_index; /// geology blocks have a vector of layer descriptors // get the vector with pointer to layers @@ -363,16 +380,6 @@ bool Maps::ReadGeology(vector > *layer_mats, vector *ge return true; } -bool Maps::ReadVegetation(uint32_t x, uint32_t y, uint32_t z, std::vector*& plants) -{ - df::map_block *block = getBlock(x,y,z); - if (!block) - return false; - - plants = &block->plants; - return true; -} - #define COPY(a,b) memcpy(&a,&b,sizeof(a)) MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent) @@ -536,18 +543,34 @@ void MapExtras::Block::SquashRocks (df::map_block *mb, t_blockmaterials & materi } } -int16_t MapExtras::Block::GeoIndexAt(df::coord2d p) +df::coord2d MapExtras::Block::biomeRegionAt(df::coord2d p) { + if (!block) + return df::coord2d(-30000,-30000); + auto des = index_tile(designation,p); uint8_t idx = des.bits.biome; if (idx >= 9) - return -1; + return block->region_pos; idx = block->region_offset[idx]; if (idx >= parent->geoidx.size()) - return -1; + return block->region_pos; return parent->geoidx[idx]; } +int16_t MapExtras::Block::GeoIndexAt(df::coord2d p) +{ + df::coord2d biome = biomeRegionAt(p); + if (!biome.isValid()) + return -1; + + auto pinfo = Maps::getRegionBiome(biome); + if (!pinfo) + return -1; + + return pinfo->geo_index; +} + bool MapExtras::Block::GetGlobalFeature(t_feature *out) { out->type = (df::feature_type)-1; @@ -561,7 +584,7 @@ bool MapExtras::Block::GetLocalFeature(t_feature *out) out->type = (df::feature_type)-1; if (!valid || block->local_feature < 0) return false; - return Maps::GetLocalFeature(*out, block->map_pos/16, block->local_feature); + return ::GetLocalFeature(*out, block->region_pos, block->local_feature); } void MapExtras::Block::init_item_counts() diff --git a/plugins/advtools.cpp b/plugins/advtools.cpp index ffb428fd8..69841849a 100644 --- a/plugins/advtools.cpp +++ b/plugins/advtools.cpp @@ -780,7 +780,7 @@ command_result adv_tools (color_ostream &out, std::vector & parame if (!num) continue; - df::map_block *block = Maps::getBlockAbs(item->pos); + df::map_block *block = Maps::getTileBlock(item->pos); if (!block) continue; diff --git a/plugins/changevein.cpp b/plugins/changevein.cpp index 133d7ef4a..1d08cfeaf 100644 --- a/plugins/changevein.cpp +++ b/plugins/changevein.cpp @@ -50,7 +50,7 @@ command_result df_changevein (color_ostream &out, vector & parameters) return CR_FAILURE; } - df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z); + df::map_block *block = Maps::getTileBlock(cursor->x, cursor->y, cursor->z); if (!block) { out.printerr("Invalid tile selected.\n"); diff --git a/plugins/cleaners.cpp b/plugins/cleaners.cpp index ea5edc991..30befab2f 100644 --- a/plugins/cleaners.cpp +++ b/plugins/cleaners.cpp @@ -127,7 +127,7 @@ command_result spotclean (color_ostream &out, vector & parameters) out.printerr("Map is not available.\n"); return CR_FAILURE; } - df::map_block *block = Maps::getBlockAbs(cursor->x, cursor->y, cursor->z); + df::map_block *block = Maps::getTileBlock(cursor->x, cursor->y, cursor->z); if (block == NULL) { out.printerr("Invalid map block selected!\n"); diff --git a/plugins/deramp.cpp b/plugins/deramp.cpp index c872f33dd..e5d0331d9 100644 --- a/plugins/deramp.cpp +++ b/plugins/deramp.cpp @@ -38,7 +38,7 @@ command_result df_deramp (color_ostream &out, vector & parameters) for (int i = 0; i < blocks_total; i++) { df::map_block *block = world->map.map_blocks[i]; - df::map_block *above = Maps::getBlockAbs(block->map_pos.x, block->map_pos.y, block->map_pos.z + 1); + df::map_block *above = Maps::getTileBlock(block->map_pos + df::coord(0,0,1)); for (int x = 0; x < 16; x++) { diff --git a/plugins/fixveins.cpp b/plugins/fixveins.cpp index 474201a81..f02f61673 100644 --- a/plugins/fixveins.cpp +++ b/plugins/fixveins.cpp @@ -65,8 +65,7 @@ command_result df_fixveins (color_ostream &out, vector & parameters) has_mineral[k] |= mineral->tile_bitmask[k]; } t_feature local, global; - Maps::GetGlobalFeature(global, block->global_feature); - Maps::GetLocalFeature(local, df::coord2d(block->map_pos.x / 16, block->map_pos.y / 16), block->local_feature); + Maps::ReadFeatures(block, &local, &global); for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) diff --git a/plugins/mapexport/mapexport.cpp b/plugins/mapexport/mapexport.cpp index 805261c21..e0a7e5e69 100644 --- a/plugins/mapexport/mapexport.cpp +++ b/plugins/mapexport/mapexport.cpp @@ -241,9 +241,9 @@ command_result mapexport (color_ostream &out, std::vector & parame } } - PlantList *plants; - if (Maps::ReadVegetation(b_x, b_y, z, plants)) + if (b->getRaw()) { + PlantList *plants = &b->getRaw()->plants; for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++) { const df::plant & plant = *(*it); diff --git a/plugins/plants.cpp b/plugins/plants.cpp index 09220c653..5ab09868f 100644 --- a/plugins/plants.cpp +++ b/plugins/plants.cpp @@ -125,8 +125,9 @@ static command_result immolations (color_ostream &out, do_what what, bool shrubs int32_t x,y,z; if(Gui::getCursorCoords(x,y,z)) { - vector * alltrees; - if(Maps::ReadVegetation(x/16,y/16,z,alltrees)) + auto block = Maps::getTileBlock(x,y,z); + vector *alltrees = block ? &block->plants : NULL; + if(alltrees) { bool didit = false; for(size_t i = 0 ; i < alltrees->size(); i++) @@ -206,8 +207,9 @@ command_result df_grow (color_ostream &out, vector & parameters) int32_t x,y,z; if(Gui::getCursorCoords(x,y,z)) { - vector * alltrees; - if(Maps::ReadVegetation(x/16,y/16,z,alltrees)) + auto block = Maps::getTileBlock(x,y,z); + vector *alltrees = block ? &block->plants : NULL; + if(alltrees) { for(size_t i = 0 ; i < alltrees->size(); i++) { diff --git a/plugins/prospector.cpp b/plugins/prospector.cpp index 80ce365cc..c90a66c5a 100644 --- a/plugins/prospector.cpp +++ b/plugins/prospector.cpp @@ -544,8 +544,9 @@ command_result prospector (color_ostream &con, vector & parameters) // and we can check visibility more easily here if (showPlants) { - PlantList * plants; - if (Maps::ReadVegetation(b_x, b_y, z, plants)) + auto block = Maps::getBlock(b_x,b_y,z); + vector *plants = block ? &block->plants : NULL; + if(plants) { for (PlantList::const_iterator it = plants->begin(); it != plants->end(); it++) { diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp index 39a2ed9cd..513eededb 100644 --- a/plugins/reveal.cpp +++ b/plugins/reveal.cpp @@ -290,7 +290,7 @@ command_result unreveal(color_ostream &out, vector & params) for(size_t i = 0; i < hidesaved.size();i++) { hideblock & hb = hidesaved[i]; - df::map_block * b = Maps::getBlockAbs(hb.c.x,hb.c.y,hb.c.z); + df::map_block * b = Maps::getTileBlock(hb.c.x,hb.c.y,hb.c.z); for (uint32_t x = 0; x < 16;x++) for (uint32_t y = 0; y < 16;y++) { b->designation[x][y].bits.hidden = hb.hiddens[x][y]; diff --git a/plugins/tubefill.cpp b/plugins/tubefill.cpp index 0dd045343..0d20136de 100644 --- a/plugins/tubefill.cpp +++ b/plugins/tubefill.cpp @@ -59,12 +59,9 @@ command_result tubefill(color_ostream &out, std::vector & params) for (size_t i = 0; i < world->map.map_blocks.size(); i++) { df::map_block *block = world->map.map_blocks[i]; - df::map_block *above = Maps::getBlockAbs(block->map_pos.x, block->map_pos.y, block->map_pos.z + 1); - if (block->local_feature == -1) - continue; + df::map_block *above = Maps::getTileBlock(block->map_pos + df::coord(0,0,1)); DFHack::t_feature feature; - DFCoord coord(block->map_pos.x >> 4, block->map_pos.y >> 4, block->map_pos.z); - if (!Maps::GetLocalFeature(feature, coord, block->local_feature)) + if (!Maps::ReadFeatures(block, &feature, NULL)) continue; if (feature.type != feature_type::deep_special_tube) continue;