Skip to content

Commit

Permalink
Fix 3dveins crashing because of trees and malformed biome data.
Browse files Browse the repository at this point in the history
The sky in the latest versions has uninitialized biome data, which
made the plugin crash on invalid vector index access. Also, trees
on ground may still have wrong geolayer inside them like obsidian.
  • Loading branch information
angavrilov committed Sep 5, 2014
1 parent cf06dc3 commit a45438d
Showing 1 changed file with 57 additions and 4 deletions.
61 changes: 57 additions & 4 deletions plugins/3dveins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,55 @@ GeoLayer *VeinGenerator::mapLayer(Block *pb, df::coord2d tile)
return biome->layers[lidx];
}

static bool isTransientMaterial(df::tiletype tile)
{
using namespace df::enums::tiletype_material;

switch (tileMaterial(tile))
{
case AIR:
case LAVA_STONE:
case PLANT:
case ROOT:
case TREE:
case MUSHROOM:
return true;

default:
return false;
}
}

static bool isSkyBlock(Block *b)
{
for (int x = 0; x < 16; x++)
{
for (int y = 0; y < 16; y++)
{
df::coord2d tile(x,y);
auto dsgn = b->DesignationAt(tile);
auto ttype = b->baseTiletypeAt(tile);

if (dsgn.bits.subterranean || !dsgn.bits.light || !isTransientMaterial(ttype))
return false;
}
}

return true;
}

static int findTopBlock(MapCache &map, int x, int y)
{
for (int z = map.maxZ(); z >= 0; z--)
{
Block *b = map.BlockAt(df::coord(x,y,z));
if (b && b->is_valid() && !isSkyBlock(b))
return z;
}

return -1;
}

bool VeinGenerator::scan_tiles()
{
for (int x = 0; x < size.x; x++)
Expand All @@ -669,8 +718,10 @@ bool VeinGenerator::scan_tiles()
{
df::coord2d column(x,y);

int top = findTopBlock(map, x, y);

// First find where layers start and end
for (int z = map.maxZ(); z >= 0; z--)
for (int z = top; z >= 0; z--)
{
Block *b = map.BlockAt(df::coord(x,y,z));
if (!b || !b->is_valid())
Expand All @@ -684,7 +735,7 @@ bool VeinGenerator::scan_tiles()
return false;

// Collect tile data
for (int z = map.maxZ(); z >= 0; z--)
for (int z = top; z >= 0; z--)
{
Block *b = map.BlockAt(df::coord(x,y,z));
if (!b || !b->is_valid())
Expand Down Expand Up @@ -725,7 +776,7 @@ bool VeinGenerator::scan_layer_depth(Block *b, df::coord2d column, int z)
auto &bottom = col_info.bottom_layer[x][y];

auto ttype = b->baseTiletypeAt(tile);
bool obsidian = (tileMaterial(ttype) == tiletype_material::LAVA_STONE);
bool obsidian = isTransientMaterial(ttype);

if (top_solid < 0 && !obsidian && isWallTerrain(ttype))
top_solid = z;
Expand Down Expand Up @@ -974,7 +1025,9 @@ void VeinGenerator::write_tiles()
{
df::coord2d column(x,y);

for (int z = map.maxZ(); z >= 0; z--)
int top = findTopBlock(map, x, y);

for (int z = top; z >= 0; z--)
{
Block *b = map.BlockAt(df::coord(x,y,z));
if (!b || !b->is_valid())
Expand Down

0 comments on commit a45438d

Please sign in to comment.