Mapgen v6: Various mudflow code improvements and bugfixes (#8805)

Calculate 'i' inside 'y' loop to avoid 'i' and 'y' becoming
out of step due to the uses of 'continue'.
Simplify calculation of 'p2d' when coordinates are inverted.
Remove some unnecessary and unreliable 'index out of
voxelmanip' checks.
Move calculation of '&em' out of loops.
For 'Loop further down until not air' code, use y coordinate
to detect being out of voxelmanip, instead of checking index
which did not detect that.
Add and improve comments.
Indent the 'for (;; y--) {' loop.
Improve format and fix codestyle issues.
This commit is contained in:
Paramat 2019-08-24 20:06:31 +01:00 committed by GitHub
parent fbc8724d59
commit b53a60c8d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -538,7 +538,7 @@ void MapgenV6::makeChunk(BlockMakeData *data)
updateHeightmap(node_min, node_max); updateHeightmap(node_min, node_max);
const s16 max_spread_amount = MAP_BLOCKSIZE; const s16 max_spread_amount = MAP_BLOCKSIZE;
// Limit dirt flow area by 1 because mud is flown into neighbors. // Limit dirt flow area by 1 because mud is flowed into neighbors
s16 mudflow_minpos = -max_spread_amount + 1; s16 mudflow_minpos = -max_spread_amount + 1;
s16 mudflow_maxpos = central_area_size.X + max_spread_amount - 2; s16 mudflow_maxpos = central_area_size.X + max_spread_amount - 2;
@ -773,6 +773,14 @@ void MapgenV6::addMud()
void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos) void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos)
{ {
const v3s16 &em = vm->m_area.getExtent();
static const v3s16 dirs4[4] = {
v3s16(0, 0, 1), // Back
v3s16(1, 0, 0), // Right
v3s16(0, 0, -1), // Front
v3s16(-1, 0, 0), // Left
};
// Iterate twice // Iterate twice
for (s16 k = 0; k < 2; k++) { for (s16 k = 0; k < 2; k++) {
for (s16 z = mudflow_minpos; z <= mudflow_maxpos; z++) for (s16 z = mudflow_minpos; z <= mudflow_maxpos; z++)
@ -781,120 +789,97 @@ void MapgenV6::flowMud(s16 &mudflow_minpos, s16 &mudflow_maxpos)
v2s16 p2d; v2s16 p2d;
// Invert coordinates on second iteration to process columns in // Invert coordinates on second iteration to process columns in
// opposite order, to avoid a directional bias. // opposite order, to avoid a directional bias.
if (k == 1) { if (k == 1)
p2d = v2s16(node_min.X, node_min.Z) + v2s16( p2d = v2s16(node_max.X, node_max.Z) - v2s16(x, z);
mudflow_maxpos - (x - mudflow_minpos), else
mudflow_maxpos - (z - mudflow_minpos));
} else {
p2d = v2s16(node_min.X, node_min.Z) + v2s16(x, z); p2d = v2s16(node_min.X, node_min.Z) + v2s16(x, z);
}
const v3s16 &em = vm->m_area.getExtent();
u32 i = vm->m_area.index(p2d.X, node_max.Y, p2d.Y);
s16 y = node_max.Y; s16 y = node_max.Y;
while (y >= node_min.Y) { while (y >= node_min.Y) {
for (;; y--) {
u32 i = vm->m_area.index(p2d.X, y, p2d.Y);
MapNode *n = nullptr;
for (;; y--) { // Find next mud node in mapchunk column
MapNode *n = NULL; for (; y >= node_min.Y; y--) {
// Find mud n = &vm->m_data[i];
for (; y >= node_min.Y; y--) { if (n->getContent() == c_dirt ||
n = &vm->m_data[i]; n->getContent() == c_dirt_with_grass ||
if (n->getContent() == c_dirt || n->getContent() == c_gravel)
n->getContent() == c_dirt_with_grass || break;
n->getContent() == c_gravel)
VoxelArea::add_y(em, i, -1);
}
if (y < node_min.Y)
// No mud found in mapchunk column, process the next column
break; break;
VoxelArea::add_y(em, i, -1); if (n->getContent() == c_dirt || n->getContent() == c_dirt_with_grass) {
} // Convert dirt_with_grass to dirt
n->setContent(c_dirt);
// Stop if out of area // Don't flow mud if the stuff under it is not mud,
//if(vmanip.m_area.contains(i) == false) // to leave at least 1 node of mud.
if (y < node_min.Y)
break;
if (n->getContent() == c_dirt ||
n->getContent() == c_dirt_with_grass) {
// Make it exactly mud
n->setContent(c_dirt);
// Don't flow it if the stuff under it is not mud
{
u32 i2 = i; u32 i2 = i;
VoxelArea::add_y(em, i2, -1); VoxelArea::add_y(em, i2, -1);
// Cancel if out of area
if (!vm->m_area.contains(i2))
continue;
MapNode *n2 = &vm->m_data[i2]; MapNode *n2 = &vm->m_data[i2];
if (n2->getContent() != c_dirt && if (n2->getContent() != c_dirt &&
n2->getContent() != c_dirt_with_grass) n2->getContent() != c_dirt_with_grass)
// Find next mud node in column
continue; continue;
} }
}
static const v3s16 dirs4[4] = { // Check if node above is walkable. If so, cancel
v3s16(0, 0, 1), // back // flowing as if node above keeps it in place.
v3s16(1, 0, 0), // right u32 i3 = i;
v3s16(0, 0, -1), // front VoxelArea::add_y(em, i3, 1);
v3s16(-1, 0, 0), // left MapNode *n3 = &vm->m_data[i3];
};
// Check that upper is walkable. Cancel
// dropping if upper keeps it in place.
u32 i3 = i;
VoxelArea::add_y(em, i3, 1);
MapNode *n3 = NULL;
if (vm->m_area.contains(i3)) {
n3 = &vm->m_data[i3];
if (ndef->get(*n3).walkable) if (ndef->get(*n3).walkable)
// Find next mud node in column
continue; continue;
}
// Drop mud on side // Drop mud on one side
for (const v3s16 &dirp : dirs4) { for (const v3s16 &dirp : dirs4) {
u32 i2 = i; u32 i2 = i;
// Move to side // Move to side
VoxelArea::add_p(em, i2, dirp); VoxelArea::add_p(em, i2, dirp);
// Fail if out of area // Check that side is air
if (!vm->m_area.contains(i2)) MapNode *n2 = &vm->m_data[i2];
continue; if (ndef->get(*n2).walkable)
// Check that side is air continue;
MapNode *n2 = &vm->m_data[i2];
if (ndef->get(*n2).walkable) // Check that under side is air
continue;
// Check that under side is air
VoxelArea::add_y(em, i2, -1);
if (!vm->m_area.contains(i2))
continue;
n2 = &vm->m_data[i2];
if (ndef->get(*n2).walkable)
continue;
// Loop further down until not air
bool dropped_to_unknown = false;
do {
VoxelArea::add_y(em, i2, -1); VoxelArea::add_y(em, i2, -1);
n2 = &vm->m_data[i2]; n2 = &vm->m_data[i2];
// if out of known area if (ndef->get(*n2).walkable)
if (!vm->m_area.contains(i2) || continue;
n2->getContent() == CONTENT_IGNORE) {
dropped_to_unknown = true; // Loop further down until not air
break; s16 y2 = y - 1; // y of i2
bool dropped_to_unknown = false;
do {
y2--;
VoxelArea::add_y(em, i2, -1);
n2 = &vm->m_data[i2];
// If out of area or in ungenerated world
if (y2 < full_node_min.Y || n2->getContent() == CONTENT_IGNORE) {
dropped_to_unknown = true;
break;
}
} while (!ndef->get(*n2).walkable);
if (!dropped_to_unknown) {
// Move up one so that we're in air
VoxelArea::add_y(em, i2, 1);
// Move mud to new place, and if outside mapchunk remove
// any decorations above removed or placed mud.
moveMud(i, i2, i3, p2d, em);
} }
} while (!ndef->get(*n2).walkable); // Done, find next mud node in column
// Loop one up so that we're in air break;
VoxelArea::add_y(em, i2, 1); }
// Move mud to new place. Outside mapchunk remove
// any decorations above removed or placed mud.
if (!dropped_to_unknown)
moveMud(i, i2, i3, p2d, em);
// Done
break;
} }
} }
}
} }
} }
} }