Refactor MapCache: make it parse everything that is known re tiles & mats.

develop
Alexander Gavrilov 2012-04-19 19:17:07 +04:00
parent f655a0986d
commit 4b87f1bcac
8 changed files with 601 additions and 144 deletions

@ -31,12 +31,17 @@ distribution.
#include <stdint.h> #include <stdint.h>
#include <cstring> #include <cstring>
#include "df/map_block.h" #include "df/map_block.h"
#include "df/tile_bitmask.h"
#include "df/block_square_event_mineralst.h" #include "df/block_square_event_mineralst.h"
#include "df/construction.h" #include "df/construction.h"
#include "df/item.h" #include "df/item.h"
using namespace DFHack; using namespace DFHack;
namespace df {
struct world_region_details;
}
namespace MapExtras namespace MapExtras
{ {
@ -50,6 +55,38 @@ inline bool is_valid_tile_coord(df::coord2d p) {
return (p.x & ~15) == 0 && (p.y & ~15) == 0; return (p.x & ~15) == 0 && (p.y & ~15) == 0;
} }
class Block;
class BlockInfo
{
Block *mblock;
MapCache *parent;
df::map_block *block;
public:
t_blockmaterials veinmats;
t_blockmaterials basemats;
t_blockmaterials grass;
std::map<df::coord,df::plant*> plants;
df::feature_init *global_feature;
df::feature_init *local_feature;
BlockInfo()
: mblock(NULL), parent(NULL), block(NULL),
global_feature(NULL), local_feature(NULL) {}
void prepare(Block *mblock);
t_matpair getBaseMaterial(df::tiletype tt, df::coord2d pos);
static void SquashVeins(df::map_block *mb, t_blockmaterials & materials);
static void SquashFrozenLiquids (df::map_block *mb, tiletypes40d & frozen);
static void SquashRocks (df::map_block *mb, t_blockmaterials & materials,
std::vector< std::vector <int16_t> > * layerassign);
static void SquashGrass(df::map_block *mb, t_blockmaterials &materials);
};
class DFHACK_EXPORT Block class DFHACK_EXPORT Block
{ {
public: public:
@ -62,39 +99,81 @@ public:
//Arbitrary tag field for flood fills etc. //Arbitrary tag field for flood fills etc.
int16_t &tag(df::coord2d p) { int16_t &tag(df::coord2d p) {
if (!tags) init_tags();
return index_tile<int16_t&>(tags, p); return index_tile<int16_t&>(tags, p);
} }
// Base layer
df::tiletype baseTiletypeAt(df::coord2d p)
{
if (!tiles) init_tiles();
return index_tile<df::tiletype>(tiles->base_tiles,p);
}
t_matpair baseMaterialAt(df::coord2d p)
{
if (!basemats) init_tiles(true);
return t_matpair(
index_tile<int16_t>(basemats->mattype,p),
index_tile<int16_t>(basemats->matindex,p)
);
}
bool isVeinAt(df::coord2d p)
{
using namespace df::enums::tiletype_material;
auto tm = tileMaterial(baseTiletypeAt(p));
return tm == MINERAL;
}
bool isLayerAt(df::coord2d p)
{
using namespace df::enums::tiletype_material;
auto tm = tileMaterial(baseTiletypeAt(p));
return tm == STONE || tm == SOIL;
}
int16_t veinMaterialAt(df::coord2d p) int16_t veinMaterialAt(df::coord2d p)
{ {
return index_tile<int16_t>(veinmats,p); return isVeinAt(p) ? baseMaterialAt(p).mat_index : -1;
} }
int16_t baseMaterialAt(df::coord2d p) int16_t layerMaterialAt(df::coord2d p)
{ {
return index_tile<int16_t>(basemats,p); if (!basemats) init_tiles(true);
return index_tile<int16_t>(basemats->layermat,p);
} }
df::tiletype BaseTileTypeAt(df::coord2d p) // Static layer (base + constructions)
df::tiletype staticTiletypeAt(df::coord2d p)
{ {
auto tt = index_tile<df::tiletype>(contiles,p); if (!tiles) init_tiles();
if (tt != tiletype::Void) return tt; if (tiles->con_info)
tt = index_tile<df::tiletype>(icetiles,p); return index_tile<df::tiletype>(tiles->con_info->tiles,p);
if (tt != tiletype::Void) return tt; return baseTiletypeAt(p);
return index_tile<df::tiletype>(rawtiles,p);
} }
df::tiletype TileTypeAt(df::coord2d p) t_matpair staticMaterialAt(df::coord2d p)
{ {
return index_tile<df::tiletype>(rawtiles,p); if (!basemats) init_tiles(true);
if (tiles->con_info)
return t_matpair(
index_tile<int16_t>(tiles->con_info->mattype,p),
index_tile<int16_t>(tiles->con_info->matindex,p)
);
return baseMaterialAt(p);
} }
bool setTiletypeAt(df::coord2d p, df::tiletype tiletype) bool hasConstructionAt(df::coord2d p)
{ {
if(!valid) return false; if (!tiles) init_tiles();
dirty_tiletypes = true; return tiles->con_info &&
//printf("setting block %d/%d/%d , %d %d\n",x,y,z, p.x, p.y); tiles->con_info->constructed.getassignment(p);
index_tile<df::tiletype&>(rawtiles,p) = tiletype;
return true;
} }
df::tiletype tiletypeAt(df::coord2d p)
{
if (!block) return tiletype::Void;
if (tiles)
return index_tile<df::tiletype>(tiles->raw_tiles,p);
return index_tile<df::tiletype>(block->tiletype,p);
}
bool setTiletypeAt(df::coord2d, df::tiletype tt, bool force = false);
uint16_t temperature1At(df::coord2d p) uint16_t temperature1At(df::coord2d p)
{ {
return index_tile<uint16_t>(temp1,p); return index_tile<uint16_t>(temp1,p);
@ -179,29 +258,29 @@ public:
bool is_valid() { return valid; } bool is_valid() { return valid; }
df::map_block *getRaw() { return block; } df::map_block *getRaw() { return block; }
MapCache *getParent() { return parent; }
private: private:
friend class MapCache; friend class MapCache;
MapCache *parent; MapCache *parent;
df::map_block *block; df::map_block *block;
static void SquashVeins(df::map_block *mb, t_blockmaterials & materials);
static void SquashFrozenLiquids (df::map_block *mb, tiletypes40d & frozen);
static void SquashConstructions (df::map_block *mb, tiletypes40d & constructions);
static void SquashRocks (df::map_block *mb, t_blockmaterials & materials,
std::vector< std::vector <int16_t> > * layerassign);
bool valid; bool valid;
bool dirty_designations:1; bool dirty_designations:1;
bool dirty_tiletypes:1; bool dirty_tiles:1;
bool dirty_temperatures:1; bool dirty_temperatures:1;
bool dirty_blockflags:1; bool dirty_blockflags:1;
bool dirty_occupancies:1; bool dirty_occupancies:1;
DFCoord bcoord; DFCoord bcoord;
int16_t tags[16][16]; // Custom tags for floodfill
typedef int16_t T_tags[16];
T_tags *tags;
void init_tags();
// On-ground item count info
typedef int T_item_counts[16]; typedef int T_item_counts[16];
T_item_counts *item_counts; T_item_counts *item_counts;
void init_item_counts(); void init_item_counts();
@ -209,30 +288,53 @@ private:
bool addItemOnGround(df::item *item); bool addItemOnGround(df::item *item);
bool removeItemOnGround(df::item *item); bool removeItemOnGround(df::item *item);
tiletypes40d rawtiles; struct ConInfo {
df::tile_bitmask constructed;
df::tiletype tiles[16][16];
t_blockmaterials mattype;
t_blockmaterials matindex;
};
struct TileInfo {
df::tile_bitmask frozen;
df::tile_bitmask dirty_raw;
df::tiletype raw_tiles[16][16];
ConInfo *con_info;
df::tile_bitmask dirty_base;
df::tiletype base_tiles[16][16];
TileInfo();
~TileInfo();
void init_coninfo();
};
struct BasematInfo {
df::tile_bitmask dirty;
t_blockmaterials mattype;
t_blockmaterials matindex;
t_blockmaterials layermat;
BasematInfo();
};
TileInfo *tiles;
BasematInfo *basemats;
void init_tiles(bool basemat = false);
void ParseTiles(TileInfo *tiles);
void ParseBasemats(TileInfo *tiles, BasematInfo *bmats);
designations40d designation; designations40d designation;
occupancies40d occupancy; occupancies40d occupancy;
t_blockflags blockflags; t_blockflags blockflags;
t_blockmaterials veinmats;
t_blockmaterials basemats;
t_temperatures temp1; t_temperatures temp1;
t_temperatures temp2; t_temperatures temp2;
tiletypes40d contiles; // what's underneath constructions
tiletypes40d icetiles; // what's underneath ice
}; };
class DFHACK_EXPORT MapCache class DFHACK_EXPORT MapCache
{ {
public: public:
MapCache() MapCache();
{
valid = 0;
Maps::getSize(x_bmax, y_bmax, z_max);
x_tmax = x_bmax*16; y_tmax = y_bmax*16;
validgeo = Maps::ReadGeology(&layer_mats, &geoidx);
valid = true;
};
~MapCache() ~MapCache()
{ {
trash(); trash();
@ -251,19 +353,60 @@ class DFHACK_EXPORT MapCache
df::tiletype baseTiletypeAt (DFCoord tilecoord) df::tiletype baseTiletypeAt (DFCoord tilecoord)
{ {
Block * b= BlockAtTile(tilecoord); Block *b = BlockAtTile(tilecoord);
return b ? b->BaseTileTypeAt(tilecoord) : tiletype::Void; return b ? b->baseTiletypeAt(tilecoord) : tiletype::Void;
}
t_matpair baseMaterialAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b ? b->baseMaterialAt(tilecoord) : t_matpair();
}
int16_t veinMaterialAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b ? b->veinMaterialAt(tilecoord) : -1;
}
int16_t layerMaterialAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b ? b->layerMaterialAt(tilecoord) : -1;
}
bool isVeinAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b && b->isVeinAt(tilecoord);
} }
bool isLayerAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b && b->isLayerAt(tilecoord);
}
df::tiletype staticTiletypeAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b ? b->staticTiletypeAt(tilecoord) : tiletype::Void;
}
t_matpair staticMaterialAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b ? b->staticMaterialAt(tilecoord) : t_matpair();
}
bool hasConstructionAt (DFCoord tilecoord)
{
Block *b = BlockAtTile(tilecoord);
return b && b->hasConstructionAt(tilecoord);
}
df::tiletype tiletypeAt (DFCoord tilecoord) df::tiletype tiletypeAt (DFCoord tilecoord)
{ {
Block * b= BlockAtTile(tilecoord); Block *b = BlockAtTile(tilecoord);
return b ? b->TileTypeAt(tilecoord) : tiletype::Void; return b ? b->tiletypeAt(tilecoord) : tiletype::Void;
} }
bool setTiletypeAt(DFCoord tilecoord, df::tiletype tiletype) bool setTiletypeAt (DFCoord tilecoord, df::tiletype tt, bool force = false)
{ {
if (Block * b= BlockAtTile(tilecoord)) Block *b = BlockAtTile(tilecoord);
return b->setTiletypeAt(tilecoord, tiletype); return b && b->setTiletypeAt(tilecoord, tt, force);
return false;
} }
uint16_t temperature1At (DFCoord tilecoord) uint16_t temperature1At (DFCoord tilecoord)
@ -290,17 +433,6 @@ class DFHACK_EXPORT MapCache
return false; return false;
} }
int16_t veinMaterialAt (DFCoord tilecoord)
{
Block * b= BlockAtTile(tilecoord);
return b ? b->veinMaterialAt(tilecoord) : -1;
}
int16_t baseMaterialAt (DFCoord tilecoord)
{
Block * b= BlockAtTile(tilecoord);
return b ? b->baseMaterialAt(tilecoord) : -1;
}
int16_t tagAt(DFCoord tilecoord) int16_t tagAt(DFCoord tilecoord)
{ {
Block * b= BlockAtTile(tilecoord); Block * b= BlockAtTile(tilecoord);
@ -311,6 +443,7 @@ class DFHACK_EXPORT MapCache
Block * b= BlockAtTile(tilecoord); Block * b= BlockAtTile(tilecoord);
if (b) b->tag(tilecoord) = val; if (b) b->tag(tilecoord) = val;
} }
void resetTags();
df::tile_designation designationAt (DFCoord tilecoord) df::tile_designation designationAt (DFCoord tilecoord)
{ {
@ -378,6 +511,7 @@ class DFHACK_EXPORT MapCache
private: private:
friend class Block; friend class Block;
friend class BlockInfo;
bool valid; bool valid;
bool validgeo; bool validgeo;
@ -388,6 +522,7 @@ private:
uint32_t z_max; uint32_t z_max;
std::vector<df::coord2d> geoidx; std::vector<df::coord2d> geoidx;
std::vector< std::vector <int16_t> > layer_mats; std::vector< std::vector <int16_t> > layer_mats;
std::map<df::coord2d, df::world_region_details*> region_details;
std::map<DFCoord, Block *> blocks; std::map<DFCoord, Block *> blocks;
}; };
} }

@ -60,6 +60,14 @@ namespace df
namespace DFHack namespace DFHack
{ {
struct t_matpair {
int16_t mat_type;
int32_t mat_index;
t_matpair(int16_t type = -1, int32_t index = -1)
: mat_type(type), mat_index(index) {}
};
struct DFHACK_EXPORT MaterialInfo { struct DFHACK_EXPORT MaterialInfo {
static const int NUM_BUILTIN = 19; static const int NUM_BUILTIN = 19;
static const int GROUP_SIZE = 200; static const int GROUP_SIZE = 200;
@ -91,6 +99,7 @@ namespace DFHack
public: public:
MaterialInfo(int16_t type = -1, int32_t index = -1) { decode(type, index); } MaterialInfo(int16_t type = -1, int32_t index = -1) { decode(type, index); }
MaterialInfo(const t_matpair &mp) { decode(mp.mat_type, mp.mat_index); }
template<class T> MaterialInfo(T *ptr) { decode(ptr); } template<class T> MaterialInfo(T *ptr) { decode(ptr); }
bool isValid() const { return material != NULL; } bool isValid() const { return material != NULL; }
@ -107,6 +116,7 @@ namespace DFHack
bool decode(int16_t type, int32_t index = -1); bool decode(int16_t type, int32_t index = -1);
bool decode(df::item *item); bool decode(df::item *item);
bool decode(const df::material_vec_ref &vr, int idx); bool decode(const df::material_vec_ref &vr, int idx);
bool decode(const t_matpair &mp) { return decode(mp.mat_type, mp.mat_index); }
template<class T> bool decode(T *ptr) { template<class T> bool decode(T *ptr) {
// Assume and exploit a certain naming convention // Assume and exploit a certain naming convention

@ -51,6 +51,9 @@ using namespace std;
#include "df/burrow.h" #include "df/burrow.h"
#include "df/block_burrow.h" #include "df/block_burrow.h"
#include "df/block_burrow_link.h" #include "df/block_burrow_link.h"
#include "df/world_region_details.h"
#include "df/builtin_mats.h"
#include "df/block_square_event_grassst.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums; using namespace df::enums;
@ -158,7 +161,7 @@ df::world_data::T_region_map *Maps::getRegionBiome(df::coord2d rgn_pos)
df::feature_init *Maps::getGlobalInitFeature(int32_t index) df::feature_init *Maps::getGlobalInitFeature(int32_t index)
{ {
auto data = world->world_data; auto data = world->world_data;
if (!data) if (!data || index < 0)
return NULL; return NULL;
auto rgn = vector_get(data->underground_regions, index); auto rgn = vector_get(data->underground_regions, index);
@ -186,7 +189,7 @@ bool Maps::GetGlobalFeature(t_feature &feature, int32_t index)
df::feature_init *Maps::getLocalInitFeature(df::coord2d rgn_pos, int32_t index) df::feature_init *Maps::getLocalInitFeature(df::coord2d rgn_pos, int32_t index)
{ {
auto data = world->world_data; auto data = world->world_data;
if (!data) if (!data || index < 0)
return NULL; return NULL;
if (rgn_pos.x < 0 || rgn_pos.x >= data->world_width || if (rgn_pos.x < 0 || rgn_pos.x >= data->world_width ||
@ -353,7 +356,7 @@ bool Maps::ReadGeology(vector<vector<int16_t> > *layer_mats, vector<df::coord2d>
int bioRX = world->map.region_x / 16 + ((i % 3) - 1); int bioRX = world->map.region_x / 16 + ((i % 3) - 1);
int bioRY = world->map.region_y / 16 + ((i / 3) - 1); int bioRY = world->map.region_y / 16 + ((i / 3) - 1);
df::coord2d rgn_pos(clip_range(bioRX,0,world_width-1),clip_range(bioRX,0,world_height-1)); df::coord2d rgn_pos(clip_range(bioRX,0,world_width-1),clip_range(bioRY,0,world_height-1));
(*geoidx)[i] = rgn_pos; (*geoidx)[i] = rgn_pos;
@ -389,7 +392,7 @@ bool Maps::ReadGeology(vector<vector<int16_t> > *layer_mats, vector<df::coord2d>
MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent) MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
{ {
dirty_designations = false; dirty_designations = false;
dirty_tiletypes = false; dirty_tiles = false;
dirty_temperatures = false; dirty_temperatures = false;
dirty_blockflags = false; dirty_blockflags = false;
dirty_occupancies = false; dirty_occupancies = false;
@ -397,12 +400,12 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
bcoord = _bcoord; bcoord = _bcoord;
block = Maps::getBlock(bcoord); block = Maps::getBlock(bcoord);
item_counts = NULL; item_counts = NULL;
tags = NULL;
memset(tags,0,sizeof(tags)); tiles = NULL;
basemats = NULL;
if(block) if(block)
{ {
COPY(rawtiles, block->tiletype);
COPY(designation, block->designation); COPY(designation, block->designation);
COPY(occupancy, block->occupancy); COPY(occupancy, block->occupancy);
blockflags = block->flags; blockflags = block->flags;
@ -410,33 +413,189 @@ MapExtras::Block::Block(MapCache *parent, DFCoord _bcoord) : parent(parent)
COPY(temp1, block->temperature_1); COPY(temp1, block->temperature_1);
COPY(temp2, block->temperature_2); COPY(temp2, block->temperature_2);
SquashVeins(block,veinmats);
SquashConstructions(block, contiles);
SquashFrozenLiquids(block, icetiles);
if(parent->validgeo)
SquashRocks(block,basemats,&parent->layer_mats);
else
memset(basemats,-1,sizeof(basemats));
valid = true; valid = true;
} }
else else
{ {
blockflags.whole = 0; blockflags.whole = 0;
memset(rawtiles,0,sizeof(rawtiles));
memset(designation,0,sizeof(designation)); memset(designation,0,sizeof(designation));
memset(occupancy,0,sizeof(occupancy)); memset(occupancy,0,sizeof(occupancy));
memset(temp1,0,sizeof(temp1)); memset(temp1,0,sizeof(temp1));
memset(temp2,0,sizeof(temp2)); memset(temp2,0,sizeof(temp2));
memset(veinmats,-1,sizeof(veinmats));
memset(contiles,0,sizeof(contiles));
memset(icetiles,0,sizeof(icetiles));
memset(basemats,-1,sizeof(basemats));
} }
} }
MapExtras::Block::~Block() MapExtras::Block::~Block()
{ {
delete[] item_counts; delete[] item_counts;
delete[] tags;
delete tiles;
delete basemats;
}
void MapExtras::Block::init_tags()
{
if (!tags)
tags = new T_tags[16];
memset(tags,0,sizeof(T_tags)*16);
}
void MapExtras::Block::init_tiles(bool basemat)
{
if (!tiles)
{
tiles = new TileInfo();
if (block)
ParseTiles(tiles);
}
if (basemat && !basemats)
{
basemats = new BasematInfo();
if (block)
ParseBasemats(tiles, basemats);
}
}
MapExtras::Block::TileInfo::TileInfo()
{
frozen.clear();
dirty_raw.clear();
memset(raw_tiles,0,sizeof(raw_tiles));
con_info = NULL;
dirty_base.clear();
memset(base_tiles,0,sizeof(base_tiles));
}
MapExtras::Block::TileInfo::~TileInfo()
{
delete con_info;
}
void MapExtras::Block::TileInfo::init_coninfo()
{
if (con_info)
return;
con_info = new ConInfo();
con_info->constructed.clear();
COPY(con_info->tiles, base_tiles);
memset(con_info->mattype, -1, sizeof(con_info->mattype));
memset(con_info->matindex, -1, sizeof(con_info->matindex));
}
MapExtras::Block::BasematInfo::BasematInfo()
{
dirty.clear();
memset(mattype,0,sizeof(mattype));
memset(matindex,-1,sizeof(matindex));
memset(layermat,-1,sizeof(layermat));
}
bool MapExtras::Block::setTiletypeAt(df::coord2d pos, df::tiletype tt, bool force)
{
if (!block)
return false;
if (!basemats)
init_tiles(true);
pos = pos & 15;
dirty_tiles = true;
tiles->raw_tiles[pos.x][pos.y] = tt;
tiles->dirty_raw.setassignment(pos, true);
return true;
}
void MapExtras::Block::ParseTiles(TileInfo *tiles)
{
tiletypes40d icetiles;
BlockInfo::SquashFrozenLiquids(block, icetiles);
COPY(tiles->raw_tiles, block->tiletype);
for (int x = 0; x < 16; x++)
{
for (int y = 0; y < 16; y++)
{
using namespace df::enums::tiletype_material;
df::tiletype tt = tiles->raw_tiles[x][y];
df::coord coord = block->map_pos + df::coord(x,y,0);
// Frozen liquid comes topmost
if (tileMaterial(tt) == FROZEN_LIQUID)
{
tiles->frozen.setassignment(x,y,true);
if (icetiles[x][y] != tiletype::Void)
{
tt = icetiles[x][y];
}
}
// The next layer may be construction
bool is_con = false;
if (tileMaterial(tt) == CONSTRUCTION)
{
df::construction *con = df::construction::find(coord);
if (con)
{
if (!tiles->con_info)
tiles->init_coninfo();
is_con = true;
tiles->con_info->constructed.setassignment(x,y,true);
tiles->con_info->tiles[x][y] = tt;
tiles->con_info->mattype[x][y] = con->mat_type;
tiles->con_info->matindex[x][y] = con->mat_index;
tt = con->original_tile;
}
}
// Finally, base material
tiles->base_tiles[x][y] = tt;
// Copy base info back to construction layer
if (tiles->con_info && !is_con)
tiles->con_info->tiles[x][y] = tt;
}
}
}
void MapExtras::Block::ParseBasemats(TileInfo *tiles, BasematInfo *bmats)
{
BlockInfo info;
info.prepare(this);
COPY(bmats->layermat, info.basemats);
for (int x = 0; x < 16; x++)
{
for (int y = 0; y < 16; y++)
{
using namespace df::enums::tiletype_material;
auto tt = tiles->base_tiles[x][y];
auto mat = info.getBaseMaterial(tt, df::coord2d(x,y));
bmats->mattype[x][y] = mat.mat_type;
bmats->matindex[x][y] = mat.mat_index;
// Copy base info back to construction layer
if (tiles->con_info && !tiles->con_info->constructed.getassignment(x,y))
{
tiles->con_info->mattype[x][y] = mat.mat_type;
tiles->con_info->matindex[x][y] = mat.mat_index;
}
}
}
} }
bool MapExtras::Block::Write () bool MapExtras::Block::Write ()
@ -454,10 +613,21 @@ bool MapExtras::Block::Write ()
block->flags.bits.designated = true; block->flags.bits.designated = true;
dirty_designations = false; dirty_designations = false;
} }
if(dirty_tiletypes) if(dirty_tiles && tiles)
{ {
COPY(block->tiletype, rawtiles); dirty_tiles = false;
dirty_tiletypes = false;
for (int x = 0; x < 16; x++)
{
for (int y = 0; y < 16; y++)
{
if (tiles->dirty_raw.getassignment(x,y))
block->tiletype[x][y] = tiles->raw_tiles[x][y];
}
}
delete tiles; tiles = NULL;
delete basemats; basemats = NULL;
} }
if(dirty_temperatures) if(dirty_temperatures)
{ {
@ -473,65 +643,145 @@ bool MapExtras::Block::Write ()
return true; return true;
} }
void MapExtras::Block::SquashVeins(df::map_block *mb, t_blockmaterials & materials) void MapExtras::BlockInfo::prepare(Block *mblock)
{ {
memset(materials,-1,sizeof(materials)); this->mblock = mblock;
std::vector <df::block_square_event_mineralst *> veins;
Maps::SortBlockEvents(mb,&veins); block = mblock->getRaw();
for (uint32_t x = 0;x<16;x++) for (uint32_t y = 0; y< 16;y++) parent = mblock->getParent();
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++)
{ {
df::tiletype tt = mb->tiletype[x][y]; auto pp = block->plants[i];
if (tileMaterial(tt) == tiletype_material::MINERAL) plants[pp->pos] = pp;
}
global_feature = Maps::getGlobalInitFeature(block->global_feature);
local_feature = Maps::getLocalInitFeature(block->region_pos, block->local_feature);
}
t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos)
{
using namespace df::enums::tiletype_material;
t_matpair rv(0,-1);
int x = pos.x, y = pos.y;
switch (tileMaterial(tt)) {
case CONSTRUCTION: // just a fallback
case SOIL:
case STONE:
rv.mat_index = basemats[x][y];
break;
case MINERAL:
rv.mat_index = veinmats[x][y];
break;
case LAVA_STONE:
if (auto details = parent->region_details[mblock->biomeRegionAt(pos)])
rv.mat_index = details->lava_stone;
break;
case PLANT:
rv.mat_type = MaterialInfo::PLANT_BASE;
if (auto plant = plants[block->map_pos + df::coord(x,y,0)])
{ {
for (size_t i = 0; i < veins.size(); i++) if (auto raw = df::plant_raw::find(plant->material))
{ {
if (veins[i]->getassignment(x,y)) rv.mat_type = raw->material_defs.type_basic_mat;
materials[x][y] = veins[i]->inorganic_mat; rv.mat_index = raw->material_defs.idx_basic_mat;
} }
} }
break;
case GRASS_LIGHT:
case GRASS_DARK:
case GRASS_DRY:
case GRASS_DEAD:
rv.mat_type = MaterialInfo::PLANT_BASE;
if (auto raw = df::plant_raw::find(grass[x][y]))
{
rv.mat_type = raw->material_defs.type_basic_mat;
rv.mat_index = raw->material_defs.idx_basic_mat;
}
break;
case FEATURE:
{
auto dsgn = block->designation[x][y];
if (dsgn.bits.feature_local && local_feature)
local_feature->getMaterial(&rv.mat_type, &rv.mat_index);
else if (dsgn.bits.feature_global && global_feature)
global_feature->getMaterial(&rv.mat_type, &rv.mat_index);
break;
} }
case FROZEN_LIQUID:
case POOL:
case BROOK:
case RIVER:
rv.mat_type = builtin_mats::WATER;
break;
case ASHES:
case FIRE:
case CAMPFIRE:
rv.mat_type = builtin_mats::ASH;
break;
default:
rv.mat_type = -1;
}
return rv;
} }
void MapExtras::Block::SquashFrozenLiquids(df::map_block *mb, tiletypes40d & frozen) void MapExtras::BlockInfo::SquashVeins(df::map_block *mb, t_blockmaterials & materials)
{ {
std::vector <df::block_square_event_frozen_liquidst *> ices; std::vector <df::block_square_event_mineralst *> veins;
Maps::SortBlockEvents(mb,NULL,&ices); Maps::SortBlockEvents(mb,&veins);
for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++) memset(materials,-1,sizeof(materials));
for (uint32_t x = 0;x<16;x++) for (uint32_t y = 0; y< 16;y++)
{ {
df::tiletype tt = mb->tiletype[x][y]; for (size_t i = 0; i < veins.size(); i++)
frozen[x][y] = tiletype::Void;
if (tileMaterial(tt) == tiletype_material::FROZEN_LIQUID)
{ {
for (size_t i = 0; i < ices.size(); i++) if (veins[i]->getassignment(x,y))
{ materials[x][y] = veins[i]->inorganic_mat;
df::tiletype tt2 = ices[i]->tiles[x][y];
if (tt2 != tiletype::Void)
{
frozen[x][y] = tt2;
break;
}
}
} }
} }
} }
void MapExtras::Block::SquashConstructions (df::map_block *mb, tiletypes40d & constructions) void MapExtras::BlockInfo::SquashFrozenLiquids(df::map_block *mb, tiletypes40d & frozen)
{ {
std::vector <df::block_square_event_frozen_liquidst *> ices;
Maps::SortBlockEvents(mb,NULL,&ices);
memset(frozen,0,sizeof(frozen));
for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++) for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++)
{ {
df::tiletype tt = mb->tiletype[x][y]; for (size_t i = 0; i < ices.size(); i++)
constructions[x][y] = tiletype::Void;
if (tileMaterial(tt) == tiletype_material::CONSTRUCTION)
{ {
DFCoord coord = mb->map_pos + df::coord(x,y,0); df::tiletype tt2 = ices[i]->tiles[x][y];
df::construction *con = df::construction::find(coord); if (tt2 != tiletype::Void)
if (con) {
constructions[x][y] = con->original_tile; frozen[x][y] = tt2;
break;
}
} }
} }
} }
void MapExtras::Block::SquashRocks (df::map_block *mb, t_blockmaterials & materials, void MapExtras::BlockInfo::SquashRocks (df::map_block *mb, t_blockmaterials & materials,
std::vector< std::vector <int16_t> > * layerassign) std::vector< std::vector <int16_t> > * layerassign)
{ {
// get the layer materials // get the layer materials
@ -547,6 +797,25 @@ void MapExtras::Block::SquashRocks (df::map_block *mb, t_blockmaterials & materi
} }
} }
void MapExtras::BlockInfo::SquashGrass(df::map_block *mb, t_blockmaterials &materials)
{
std::vector<df::block_square_event_grassst*> grasses;
Maps::SortBlockEvents(mb, NULL, NULL, NULL, &grasses);
memset(materials,-1,sizeof(materials));
for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++)
{
int amount = 0;
for (size_t i = 0; i < grasses.size(); i++)
{
if (grasses[i]->amount[x][y] >= amount)
{
amount = grasses[i]->amount[x][y];
materials[x][y] = grasses[i]->plant_index;
}
}
}
}
df::coord2d MapExtras::Block::biomeRegionAt(df::coord2d p) df::coord2d MapExtras::Block::biomeRegionAt(df::coord2d p)
{ {
if (!block) if (!block)
@ -662,6 +931,24 @@ bool MapExtras::Block::removeItemOnGround(df::item *item)
return true; return true;
} }
MapExtras::MapCache::MapCache()
{
valid = 0;
Maps::getSize(x_bmax, y_bmax, z_max);
x_tmax = x_bmax*16; y_tmax = y_bmax*16;
validgeo = Maps::ReadGeology(&layer_mats, &geoidx);
valid = true;
if (auto data = df::global::world->world_data)
{
for (size_t i = 0; i < data->region_details.size(); i++)
{
auto info = data->region_details[i];
region_details[info->pos] = info;
}
}
}
MapExtras::Block *MapExtras::MapCache::BlockAt(DFCoord blockcoord) MapExtras::Block *MapExtras::MapCache::BlockAt(DFCoord blockcoord)
{ {
if(!valid) if(!valid)
@ -685,6 +972,15 @@ MapExtras::Block *MapExtras::MapCache::BlockAt(DFCoord blockcoord)
} }
} }
void MapExtras::MapCache::resetTags()
{
for (auto it = blocks.begin(); it != blocks.end(); ++it)
{
delete[] it->second->tags;
it->second->tags = NULL;
}
}
df::burrow *Maps::findBurrowByName(std::string name) df::burrow *Maps::findBurrowByName(std::string name)
{ {
auto &vec = df::burrow::get_vector(); auto &vec = df::burrow::get_vector();

@ -1 +1 @@
Subproject commit a1e342afe5a5e1e07672cd8b6553953bc251a05d Subproject commit 25c2a3dad964abbcceb5abd41558b71fb113e83b

@ -1196,7 +1196,7 @@ command_result digl (color_ostream &out, vector <string> & parameters)
df::tile_designation des = MCache->designationAt(xy); df::tile_designation des = MCache->designationAt(xy);
df::tiletype tt = MCache->tiletypeAt(xy); df::tiletype tt = MCache->tiletypeAt(xy);
int16_t veinmat = MCache->veinMaterialAt(xy); int16_t veinmat = MCache->veinMaterialAt(xy);
int16_t basemat = MCache->baseMaterialAt(xy); int16_t basemat = MCache->layerMaterialAt(xy);
if( veinmat != -1 ) if( veinmat != -1 )
{ {
con.printerr("This is a vein. Use vdig instead!\n"); con.printerr("This is a vein. Use vdig instead!\n");
@ -1215,7 +1215,7 @@ command_result digl (color_ostream &out, vector <string> & parameters)
if (MCache->tagAt(current)) if (MCache->tagAt(current))
continue; continue;
int16_t vmat2 = MCache->veinMaterialAt(current); int16_t vmat2 = MCache->veinMaterialAt(current);
int16_t bmat2 = MCache->baseMaterialAt(current); int16_t bmat2 = MCache->layerMaterialAt(current);
tt = MCache->tiletypeAt(current); tt = MCache->tiletypeAt(current);
if(!DFHack::isWallTerrain(tt)) if(!DFHack::isWallTerrain(tt))
@ -1282,7 +1282,7 @@ command_result digl (color_ostream &out, vector <string> & parameters)
//below = 1; //below = 1;
des_minus = MCache->designationAt(current-1); des_minus = MCache->designationAt(current-1);
vmat_minus = MCache->veinMaterialAt(current-1); vmat_minus = MCache->veinMaterialAt(current-1);
bmat_minus = MCache->baseMaterialAt(current-1); bmat_minus = MCache->layerMaterialAt(current-1);
tt_minus = MCache->tiletypeAt(current-1); tt_minus = MCache->tiletypeAt(current-1);
if ( tileMaterial(tt_minus)==tiletype_material::STONE if ( tileMaterial(tt_minus)==tiletype_material::STONE
|| tileMaterial(tt_minus)==tiletype_material::SOIL) || tileMaterial(tt_minus)==tiletype_material::SOIL)
@ -1293,7 +1293,7 @@ command_result digl (color_ostream &out, vector <string> & parameters)
//above = 1; //above = 1;
des_plus = MCache->designationAt(current+1); des_plus = MCache->designationAt(current+1);
vmat_plus = MCache->veinMaterialAt(current+1); vmat_plus = MCache->veinMaterialAt(current+1);
bmat_plus = MCache->baseMaterialAt(current+1); bmat_plus = MCache->layerMaterialAt(current+1);
tt_plus = MCache->tiletypeAt(current+1); tt_plus = MCache->tiletypeAt(current+1);
if ( tileMaterial(tt_plus)==tiletype_material::STONE if ( tileMaterial(tt_plus)==tiletype_material::STONE
|| tileMaterial(tt_plus)==tiletype_material::SOIL) || tileMaterial(tt_plus)==tiletype_material::SOIL)

@ -193,7 +193,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
prototile->set_flow_size(des.bits.flow_size); prototile->set_flow_size(des.bits.flow_size);
} }
df::tiletype type = b->TileTypeAt(coord); df::tiletype type = b->tiletypeAt(coord);
prototile->set_type((dfproto::Tile::TileType)tileShape(type)); prototile->set_type((dfproto::Tile::TileType)tileShape(type));
prototile->set_tile_material((dfproto::Tile::TileMaterialType)tileMaterial(type)); prototile->set_tile_material((dfproto::Tile::TileMaterialType)tileMaterial(type));
@ -204,7 +204,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
case tiletype_material::SOIL: case tiletype_material::SOIL:
case tiletype_material::STONE: case tiletype_material::STONE:
prototile->set_material_type(0); prototile->set_material_type(0);
prototile->set_material_index(b->baseMaterialAt(coord)); prototile->set_material_index(b->layerMaterialAt(coord));
break; break;
case tiletype_material::MINERAL: case tiletype_material::MINERAL:
prototile->set_material_type(0); prototile->set_material_type(0);

@ -103,6 +103,30 @@ command_result df_cprobe (color_ostream &out, vector <string> & parameters)
return CR_OK; return CR_OK;
} }
void describeTile(color_ostream &out, df::tiletype tiletype)
{
out.print("%d", tiletype);
if(tileName(tiletype))
out.print(" = %s",tileName(tiletype));
out.print("\n");
df::tiletype_shape shape = tileShape(tiletype);
df::tiletype_material material = tileMaterial(tiletype);
df::tiletype_special special = tileSpecial(tiletype);
df::tiletype_variant variant = tileVariant(tiletype);
out.print("%-10s: %4d %s\n","Class" ,shape,
ENUM_KEY_STR(tiletype_shape, shape).c_str());
out.print("%-10s: %4d %s\n","Material" ,
material, ENUM_KEY_STR(tiletype_material, material).c_str());
out.print("%-10s: %4d %s\n","Special" ,
special, ENUM_KEY_STR(tiletype_special, special).c_str());
out.print("%-10s: %4d %s\n" ,"Variant" ,
variant, ENUM_KEY_STR(tiletype_variant, variant).c_str());
out.print("%-10s: %s\n" ,"Direction",
tileDirection(tiletype).getStr());
out.print("\n");
}
command_result df_probe (color_ostream &out, vector <string> & parameters) command_result df_probe (color_ostream &out, vector <string> & parameters)
{ {
//bool showBlock, showDesig, showOccup, showTile, showMisc; //bool showBlock, showDesig, showOccup, showTile, showMisc;
@ -186,26 +210,12 @@ command_result df_probe (color_ostream &out, vector <string> & parameters)
*/ */
// tiletype // tiletype
out.print("tiletype: %d", tiletype); out.print("tiletype: ");
if(tileName(tiletype)) describeTile(out, tiletype);
out.print(" = %s",tileName(tiletype)); out.print("static: ");
out.print("\n"); describeTile(out, mc.staticTiletypeAt(cursor));
out.print("base: ");
df::tiletype_shape shape = tileShape(tiletype); describeTile(out, mc.baseTiletypeAt(cursor));
df::tiletype_material material = tileMaterial(tiletype);
df::tiletype_special special = tileSpecial(tiletype);
df::tiletype_variant variant = tileVariant(tiletype);
out.print("%-10s: %4d %s\n","Class" ,shape,
ENUM_KEY_STR(tiletype_shape, shape).c_str());
out.print("%-10s: %4d %s\n","Material" ,
material, ENUM_KEY_STR(tiletype_material, material).c_str());
out.print("%-10s: %4d %s\n","Special" ,
special, ENUM_KEY_STR(tiletype_special, special).c_str());
out.print("%-10s: %4d %s\n" ,"Variant" ,
variant, ENUM_KEY_STR(tiletype_variant, variant).c_str());
out.print("%-10s: %s\n" ,"Direction",
tileDirection(tiletype).getStr());
out.print("\n");
out.print("temperature1: %d U\n",mc.temperature1At(cursor)); out.print("temperature1: %d U\n",mc.temperature1At(cursor));
out.print("temperature2: %d U\n",mc.temperature2At(cursor)); out.print("temperature2: %d U\n",mc.temperature2At(cursor));
@ -214,7 +224,7 @@ command_result df_probe (color_ostream &out, vector <string> & parameters)
out << "biome: " << des.bits.biome << std::endl; out << "biome: " << des.bits.biome << std::endl;
out << "geolayer: " << des.bits.geolayer_index out << "geolayer: " << des.bits.geolayer_index
<< std::endl; << std::endl;
int16_t base_rock = mc.baseMaterialAt(cursor); int16_t base_rock = mc.layerMaterialAt(cursor);
if(base_rock != -1) if(base_rock != -1)
{ {
out << "Layer material: " << dec << base_rock; out << "Layer material: " << dec << base_rock;
@ -238,6 +248,12 @@ command_result df_probe (color_ostream &out, vector <string> & parameters)
else else
out << endl; out << endl;
} }
MaterialInfo minfo(mc.baseMaterialAt(cursor));
if (minfo.isValid())
out << "Base material: " << minfo.getToken() << " / " << minfo.toString() << endl;
minfo.decode(mc.staticMaterialAt(cursor));
if (minfo.isValid())
out << "Static material: " << minfo.getToken() << " / " << minfo.toString() << endl;
// liquids // liquids
if(des.bits.flow_size) if(des.bits.flow_size)
{ {

@ -474,7 +474,7 @@ command_result prospector (color_ostream &con, vector <string> & parameters)
liquidWater.add(global_z); liquidWater.add(global_z);
} }
df::tiletype type = b->TileTypeAt(coord); df::tiletype type = b->tiletypeAt(coord);
df::tiletype_shape tileshape = tileShape(type); df::tiletype_shape tileshape = tileShape(type);
df::tiletype_material tilemat = tileMaterial(type); df::tiletype_material tilemat = tileMaterial(type);
@ -506,7 +506,7 @@ command_result prospector (color_ostream &con, vector <string> & parameters)
{ {
case tiletype_material::SOIL: case tiletype_material::SOIL:
case tiletype_material::STONE: case tiletype_material::STONE:
layerMats[b->baseMaterialAt(coord)].add(global_z); layerMats[b->layerMaterialAt(coord)].add(global_z);
break; break;
case tiletype_material::MINERAL: case tiletype_material::MINERAL:
veinMats[b->veinMaterialAt(coord)].add(global_z); veinMats[b->veinMaterialAt(coord)].add(global_z);