Implement SOIL/STONE substitution logic, and add compat in mapexport.

develop
Alexander Gavrilov 2012-04-19 23:02:30 +04:00
parent 4b87f1bcac
commit 0b32d374db
3 changed files with 123 additions and 7 deletions

@ -262,10 +262,13 @@ public:
private: private:
friend class MapCache; friend class MapCache;
friend class BlockInfo;
MapCache *parent; MapCache *parent;
df::map_block *block; df::map_block *block;
int biomeIndexAt(df::coord2d p);
bool valid; bool valid;
bool dirty_designations:1; bool dirty_designations:1;
bool dirty_tiles:1; bool dirty_tiles:1;
@ -521,6 +524,8 @@ private:
uint32_t y_tmax; uint32_t y_tmax;
uint32_t z_max; uint32_t z_max;
std::vector<df::coord2d> geoidx; 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< std::vector <int16_t> > layer_mats;
std::map<df::coord2d, df::world_region_details*> region_details; std::map<df::coord2d, df::world_region_details*> region_details;
std::map<DFCoord, Block *> blocks; std::map<DFCoord, Block *> blocks;

@ -676,11 +676,42 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
int x = pos.x, y = pos.y; int x = pos.x, y = pos.y;
switch (tileMaterial(tt)) { switch (tileMaterial(tt)) {
case CONSTRUCTION: // just a fallback case DRIFTWOOD:
case SOIL: case SOIL:
{
rv.mat_index = basemats[x][y];
if (auto raw = df::inorganic_raw::find(rv.mat_index))
{
if (raw->flags.is_set(inorganic_flags::SOIL_ANY))
break;
int biome = mblock->biomeIndexAt(pos);
int idx = vector_get(parent->default_soil, biome, -1);
if (idx >= 0)
rv.mat_index = idx;
}
break;
}
case STONE: case STONE:
{
rv.mat_index = basemats[x][y]; rv.mat_index = basemats[x][y];
if (auto raw = df::inorganic_raw::find(rv.mat_index))
{
if (!raw->flags.is_set(inorganic_flags::SOIL_ANY))
break;
int biome = mblock->biomeIndexAt(pos);
int idx = vector_get(parent->default_stone, biome, -1);
if (idx >= 0)
rv.mat_index = idx;
}
break; break;
}
case MINERAL: case MINERAL:
rv.mat_index = veinmats[x][y]; rv.mat_index = veinmats[x][y];
@ -727,11 +758,17 @@ t_matpair MapExtras::BlockInfo::getBaseMaterial(df::tiletype tt, df::coord2d pos
break; break;
} }
case CONSTRUCTION: // just a fallback
break;
case FROZEN_LIQUID: case FROZEN_LIQUID:
rv.mat_type = builtin_mats::WATER;
break;
case POOL: case POOL:
case BROOK: case BROOK:
case RIVER: case RIVER:
rv.mat_type = builtin_mats::WATER; rv.mat_index = basemats[x][y];
break; break;
case ASHES: case ASHES:
@ -816,18 +853,30 @@ void MapExtras::BlockInfo::SquashGrass(df::map_block *mb, t_blockmaterials &mate
} }
} }
df::coord2d MapExtras::Block::biomeRegionAt(df::coord2d p) int MapExtras::Block::biomeIndexAt(df::coord2d p)
{ {
if (!block) if (!block)
return df::coord2d(-30000,-30000); return -1;
auto des = index_tile<df::tile_designation>(designation,p); auto des = index_tile<df::tile_designation>(designation,p);
uint8_t idx = des.bits.biome; uint8_t idx = des.bits.biome;
if (idx >= 9) if (idx >= 9)
return block->region_pos; return -1;
idx = block->region_offset[idx]; idx = block->region_offset[idx];
if (idx >= parent->geoidx.size()) if (idx >= parent->geoidx.size())
return -1;
return idx;
}
df::coord2d MapExtras::Block::biomeRegionAt(df::coord2d p)
{
if (!block)
return df::coord2d(-30000,-30000);
int idx = biomeIndexAt(p);
if (idx < 0)
return block->region_pos; return block->region_pos;
return parent->geoidx[idx]; return parent->geoidx[idx];
} }
@ -947,6 +996,28 @@ MapExtras::MapCache::MapCache()
region_details[info->pos] = info; region_details[info->pos] = info;
} }
} }
default_soil.resize(layer_mats.size());
default_stone.resize(layer_mats.size());
for (size_t i = 0; i < layer_mats.size(); i++)
{
default_soil[i] = -1;
default_stone[i] = -1;
for (size_t j = 0; j < layer_mats[i].size(); 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];
}
}
} }
MapExtras::Block *MapExtras::MapCache::BlockAt(DFCoord blockcoord) MapExtras::Block *MapExtras::MapCache::BlockAt(DFCoord blockcoord)

@ -2,7 +2,7 @@
#include "Console.h" #include "Console.h"
#include "Export.h" #include "Export.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "modules/MapCache.h" #include "modules/MapCache.h"f
using namespace DFHack; using namespace DFHack;
#include <fstream> #include <fstream>
@ -39,6 +39,46 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
return CR_OK; return CR_OK;
} }
static dfproto::Tile::TileMaterialType toProto(df::tiletype_material mat)
{
/*
* This is surely ugly, but casting enums without officially
* defined numerical values to protobuf enums is against the
* way protobufs are supposed to be used, because it defeats
* the backward compatible nature of the protocols.
*/
switch (mat)
{
#define CONVERT(name) case tiletype_material::name: return dfproto::Tile::name;
CONVERT(AIR)
case tiletype_material::PLANT:
CONVERT(SOIL)
CONVERT(STONE)
CONVERT(FEATURE)
CONVERT(LAVA_STONE)
CONVERT(MINERAL)
CONVERT(FROZEN_LIQUID)
CONVERT(CONSTRUCTION)
CONVERT(GRASS_LIGHT)
CONVERT(GRASS_DARK)
CONVERT(GRASS_DRY)
CONVERT(GRASS_DEAD)
CONVERT(HFS)
CONVERT(CAMPFIRE)
CONVERT(FIRE)
CONVERT(ASHES)
case tiletype_material::MAGMA:
return dfproto::Tile::MAGMA_TYPE;
CONVERT(DRIFTWOOD)
CONVERT(POOL)
CONVERT(BROOK)
CONVERT(RIVER)
#undef CONVERT
default:
return dfproto::Tile::AIR;
}
}
command_result mapexport (color_ostream &out, std::vector <std::string> & parameters) command_result mapexport (color_ostream &out, std::vector <std::string> & parameters)
{ {
bool showHidden = false; bool showHidden = false;
@ -195,7 +235,7 @@ command_result mapexport (color_ostream &out, std::vector <std::string> & parame
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(toProto(tileMaterial(type)));
df::coord map_pos = df::coord(b_x*16+x,b_y*16+y,z); df::coord map_pos = df::coord(b_x*16+x,b_y*16+y,z);