Make biome information more explicit in MapCache.

develop
Alexander Gavrilov 2013-10-03 17:54:28 +04:00
parent ea36233dff
commit 9442e8ea1f
2 changed files with 102 additions and 57 deletions

@ -49,6 +49,19 @@ class DFHACK_EXPORT MapCache;
class Block;
struct BiomeInfo {
// Determined by the 4-bit index in the designation bitfield
static const unsigned MAX_LAYERS = 16;
df::coord2d pos;
int default_soil, default_stone, lava_stone;
int geo_index;
df::region_map_entry *biome;
df::world_geo_biome *geobiome;
df::world_region_details *details;
int16_t layer_stone[MAX_LAYERS];
};
class BlockInfo
{
Block *mblock;
@ -56,8 +69,12 @@ class BlockInfo
df::map_block *block;
public:
enum GroundType {
G_UNKNOWN = 0, G_STONE, G_SOIL
};
static GroundType getGroundType(int material);
t_blockmaterials veinmats;
t_blockmaterials basemats;
t_blockmaterials grass;
std::map<df::coord,df::plant*> plants;
@ -132,12 +149,15 @@ public:
{
return isVeinAt(p) ? baseMaterialAt(p).mat_index : -1;
}
int16_t layerMaterialAt(df::coord2d p)
{
if (!basemats) init_tiles(true);
return index_tile<int16_t>(basemats->layermat,p);
/// Geological layer soil or stone material at pos
int16_t layerMaterialAt(df::coord2d p) {
return biomeInfoAt(p).layer_stone[layerIndexAt(p)];
}
/// Biome-specific lava stone at pos
int16_t lavaStoneAt(df::coord2d p) { return biomeInfoAt(p).lava_stone; }
// Static layer (base + constructions)
df::tiletype staticTiletypeAt(df::coord2d p)
{
@ -237,8 +257,14 @@ public:
bool Write();
bool isDirty();
int biomeIndexAt(df::coord2d p);
int layerIndexAt(df::coord2d p) {
return index_tile<df::tile_designation&>(designation,p).bits.geolayer_index;
}
df::coord2d biomeRegionAt(df::coord2d p);
int16_t GeoIndexAt(df::coord2d p);
const BiomeInfo &biomeInfoAt(df::coord2d p);
int16_t GeoIndexAt(df::coord2d p) { return biomeInfoAt(p).geo_index; }
bool GetGlobalFeature(t_feature *out);
bool GetLocalFeature(t_feature *out);
@ -259,8 +285,6 @@ private:
void init();
int biomeIndexAt(df::coord2d p);
bool valid;
bool dirty_designations:1;
bool dirty_tiles:1;
@ -511,10 +535,17 @@ class DFHACK_EXPORT MapCache
uint32_t maxTileY() { return y_tmax; }
uint32_t maxZ() { return z_max; }
size_t getBiomeCount() { return biomes.size(); }
const BiomeInfo &getBiomeByIndex(unsigned idx) {
return (idx < biomes.size()) ? biomes[idx] : biome_stub;
}
private:
friend class Block;
friend class BlockInfo;
static const BiomeInfo biome_stub;
bool valid;
bool validgeo;
uint32_t x_bmax;
@ -522,10 +553,7 @@ private:
uint32_t x_tmax;
uint32_t y_tmax;
uint32_t z_max;
std::vector<df::coord2d> geoidx;
std::vector<int> default_soil;
std::vector<int> default_stone;
std::vector< std::vector <int16_t> > layer_mats;
std::vector<BiomeInfo> biomes;
std::map<df::coord2d, df::world_region_details*> region_details;
std::map<DFCoord, Block *> blocks;
};

@ -65,11 +65,20 @@ using namespace std;
#include "df/building_type.h"
using namespace DFHack;
using namespace MapExtras;
using namespace df::enums;
using df::global::world;
extern bool GetLocalFeature(t_feature &feature, df::coord2d rgn_pos, int32_t index);
const BiomeInfo MapCache::biome_stub = {
df::coord2d(),
-1, -1, -1, -1,
NULL, NULL, NULL,
{ -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1 }
};
#define COPY(a,b) memcpy(&a,&b,sizeof(a))
MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
@ -356,11 +365,6 @@ void MapExtras::BlockInfo::prepare(Block *mblock)
SquashVeins(block,veinmats);
SquashGrass(block, grass);
if (parent->validgeo)
SquashRocks(block,basemats,&parent->layer_mats);
else
memset(basemats,-1,sizeof(basemats));
for (size_t i = 0; i < block->plants.size(); i++)
{
auto pp = block->plants[i];
@ -371,6 +375,18 @@ void MapExtras::BlockInfo::prepare(Block *mblock)
local_feature = Maps::getLocalInitFeature(block->region_pos, block->local_feature);
}
BlockInfo::GroundType MapExtras::BlockInfo::getGroundType(int material)
{
auto raw = df::inorganic_raw::find(material);
if (!raw)
return G_UNKNOWN;
if (raw->flags.is_set(inorganic_flags::SOIL_ANY))
return G_SOIL;
return G_STONE;
}
t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos)
{
using namespace df::enums::tiletype_material;
@ -387,15 +403,12 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
case DRIFTWOOD:
case SOIL:
{
rv.mat_index = basemats[x][y];
auto &biome = mblock->biomeInfoAt(pos);
rv.mat_index = biome.layer_stone[mblock->layerIndexAt(pos)];
if (auto raw = df::inorganic_raw::find(rv.mat_index))
if (getGroundType(rv.mat_index) == G_STONE)
{
if (raw->flags.is_set(inorganic_flags::SOIL_ANY))
break;
int biome = mblock->biomeIndexAt(pos);
int idx = vector_get(parent->default_soil, biome, -1);
int idx = biome.default_soil;
if (idx >= 0)
rv.mat_index = idx;
}
@ -405,15 +418,12 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
case STONE:
{
rv.mat_index = basemats[x][y];
auto &biome = mblock->biomeInfoAt(pos);
rv.mat_index = biome.layer_stone[mblock->layerIndexAt(pos)];
if (auto raw = df::inorganic_raw::find(rv.mat_index))
if (getGroundType(rv.mat_index) == G_SOIL)
{
if (!raw->flags.is_set(inorganic_flags::SOIL_ANY))
break;
int biome = mblock->biomeIndexAt(pos);
int idx = vector_get(parent->default_stone, biome, -1);
int idx = biome.default_stone;
if (idx >= 0)
rv.mat_index = idx;
}
@ -426,8 +436,7 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
break;
case LAVA_STONE:
if (auto details = parent->region_details[mblock->biomeRegionAt(pos)])
rv.mat_index = details->lava_stone;
rv.mat_index = mblock->biomeInfoAt(pos).lava_stone;
break;
case PLANT:
@ -479,7 +488,7 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
case POOL:
case BROOK:
case RIVER:
rv.mat_index = basemats[x][y];
rv.mat_index = mblock->layerMaterialAt(pos);
break;
case ASHES:
@ -571,11 +580,16 @@ int MapExtras::Block::biomeIndexAt(df::coord2d p)
if (idx >= 9)
return -1;
idx = block->region_offset[idx];
if (idx >= parent->geoidx.size())
if (idx >= parent->biomes.size())
return -1;
return idx;
}
const BiomeInfo &Block::biomeInfoAt(df::coord2d p)
{
return parent->getBiomeByIndex(biomeIndexAt(p));
}
df::coord2d MapExtras::Block::biomeRegionAt(df::coord2d p)
{
if (!block)
@ -585,20 +599,7 @@ df::coord2d MapExtras::Block::biomeRegionAt(df::coord2d p)
if (idx < 0)
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;
return parent->biomes[idx].pos;
}
bool MapExtras::Block::GetGlobalFeature(t_feature *out)
@ -707,6 +708,8 @@ MapExtras::MapCache::MapCache()
valid = 0;
Maps::getSize(x_bmax, y_bmax, z_max);
x_tmax = x_bmax*16; y_tmax = y_bmax*16;
std::vector<df::coord2d> geoidx;
std::vector<std::vector<int16_t> > layer_mats;
validgeo = Maps::ReadGeology(&layer_mats, &geoidx);
valid = true;
@ -719,25 +722,39 @@ MapExtras::MapCache::MapCache()
}
}
default_soil.resize(layer_mats.size());
default_stone.resize(layer_mats.size());
biomes.resize(layer_mats.size());
for (size_t i = 0; i < layer_mats.size(); i++)
{
default_soil[i] = -1;
default_stone[i] = -1;
biomes[i].pos = geoidx[i];
biomes[i].biome = Maps::getRegionBiome(geoidx[i]);
biomes[i].details = region_details[geoidx[i]];
biomes[i].geo_index = biomes[i].biome ? biomes[i].biome->geo_index : -1;
biomes[i].geobiome = df::world_geo_biome::find(biomes[i].geo_index);
biomes[i].lava_stone = -1;
biomes[i].default_soil = -1;
biomes[i].default_stone = -1;
for (size_t j = 0; j < layer_mats[i].size(); j++)
if (biomes[i].details)
biomes[i].lava_stone = biomes[i].details->lava_stone;
memset(biomes[i].layer_stone, -1, sizeof(biomes[i].layer_stone));
for (size_t j = 0; j < std::min(BiomeInfo::MAX_LAYERS,layer_mats[i].size()); j++)
{
biomes[i].layer_stone[j] = layer_mats[i][j];
auto raw = df::inorganic_raw::find(layer_mats[i][j]);
if (!raw)
continue;
bool is_soil = raw->flags.is_set(inorganic_flags::SOIL_ANY);
if (is_soil)
default_soil[i] = layer_mats[i][j];
else if (default_stone[i] == -1)
default_stone[i] = layer_mats[i][j];
biomes[i].default_soil = layer_mats[i][j];
else if (biomes[i].default_stone == -1)
biomes[i].default_stone = layer_mats[i][j];
}
}
}