INodeDefManager *nodemgr = m_gamedef->ndef();
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
//TimeTaker timer("transformLiquids()");
u32 loopcount = 0;
loop_max *= m_transforming_liquid_loop_count_multiplier;
#endif
- while(m_transforming_liquid.size() != 0)
+ while (m_transforming_liquid.size() != 0)
{
// This should be done here so that it is done when continue is used
- if(loopcount >= initial_size || loopcount >= loop_max)
+ if (loopcount >= initial_size || loopcount >= loop_max)
break;
loopcount++;
*/
s8 liquid_level = -1;
content_t liquid_kind = CONTENT_IGNORE;
- LiquidType liquid_type = nodemgr->get(n0).liquid_type;
+ content_t floodable_node = CONTENT_AIR;
+ ContentFeatures cf = nodemgr->get(n0);
+ LiquidType liquid_type = cf.liquid_type;
switch (liquid_type) {
case LIQUID_SOURCE:
liquid_level = LIQUID_LEVEL_SOURCE;
- liquid_kind = nodemgr->getId(nodemgr->get(n0).liquid_alternative_flowing);
+ liquid_kind = nodemgr->getId(cf.liquid_alternative_flowing);
break;
case LIQUID_FLOWING:
liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
liquid_kind = n0.getContent();
break;
case LIQUID_NONE:
- // if this is an air node, it *could* be transformed into a liquid. otherwise,
- // continue with the next node.
- if (n0.getContent() != CONTENT_AIR)
+ // if this node is 'floodable', it *could* be transformed
+ // into a liquid, otherwise, continue with the next node.
+ if (!cf.floodable)
continue;
+ floodable_node = n0.getContent();
liquid_kind = CONTENT_AIR;
break;
}
}
v3s16 npos = p0 + dirs[i];
NodeNeighbor nb(getNodeNoEx(npos), nt, npos);
+ ContentFeatures cfnb = nodemgr->get(nb.n);
switch (nodemgr->get(nb.n.getContent()).liquid_type) {
case LIQUID_NONE:
- if (nb.n.getContent() == CONTENT_AIR) {
+ if (cfnb.floodable) {
airs[num_airs++] = nb;
// if the current node is a water source the neighbor
// should be enqueded for transformation regardless of whether the
if (nb.t != NEIGHBOR_UPPER && liquid_type != LIQUID_NONE)
m_transforming_liquid.push_back(npos);
// if the current node happens to be a flowing node, it will start to flow down here.
- if (nb.t == NEIGHBOR_LOWER) {
+ if (nb.t == NEIGHBOR_LOWER)
flowing_down = true;
- }
} else {
neutrals[num_neutrals++] = nb;
+ // If neutral below is ignore prevent water spreading outwards
+ if (nb.t == NEIGHBOR_LOWER &&
+ nb.n.getContent() == CONTENT_IGNORE)
+ flowing_down = true;
}
break;
case LIQUID_SOURCE:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if (liquid_kind == CONTENT_AIR)
- liquid_kind = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing);
- if (nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing) != liquid_kind) {
+ liquid_kind = nodemgr->getId(cfnb.liquid_alternative_flowing);
+ if (nodemgr->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
neutrals[num_neutrals++] = nb;
} else {
// Do not count bottom source, it will screw things up
case LIQUID_FLOWING:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if (liquid_kind == CONTENT_AIR)
- liquid_kind = nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing);
- if (nodemgr->getId(nodemgr->get(nb.n).liquid_alternative_flowing) != liquid_kind) {
+ liquid_kind = nodemgr->getId(cfnb.liquid_alternative_flowing);
+ if (nodemgr->getId(cfnb.liquid_alternative_flowing) != liquid_kind) {
neutrals[num_neutrals++] = nb;
} else {
flows[num_flows++] = nb;
s8 max_node_level = -1;
u8 range = nodemgr->get(liquid_kind).liquid_range;
- if (range > LIQUID_LEVEL_MAX+1)
- range = LIQUID_LEVEL_MAX+1;
+ if (range > LIQUID_LEVEL_MAX + 1)
+ range = LIQUID_LEVEL_MAX + 1;
if ((num_sources >= 2 && nodemgr->get(liquid_kind).liquid_renewable) || liquid_type == LIQUID_SOURCE) {
// liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
new_node_content = nodemgr->getId(nodemgr->get(liquid_kind).liquid_alternative_source);
} else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) {
// liquid_kind is set properly, see above
- new_node_content = liquid_kind;
max_node_level = new_node_level = LIQUID_LEVEL_MAX;
- if (new_node_level < (LIQUID_LEVEL_MAX+1-range))
- new_node_content = CONTENT_AIR;
+ if (new_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
+ new_node_content = liquid_kind;
+ else
+ new_node_content = floodable_node;
} else {
// no surrounding sources, so get the maximum level that can flow into this node
for (u16 i = 0; i < num_flows; i++) {
max_node_level = LIQUID_LEVEL_MAX;
if (nb_liquid_level + WATER_DROP_BOOST < LIQUID_LEVEL_MAX)
max_node_level = nb_liquid_level + WATER_DROP_BOOST;
- } else if (nb_liquid_level > max_node_level)
+ } else if (nb_liquid_level > max_node_level) {
max_node_level = nb_liquid_level;
+ }
break;
case NEIGHBOR_LOWER:
break;
case NEIGHBOR_SAME_LEVEL:
if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
- nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level) {
+ nb_liquid_level > 0 && nb_liquid_level - 1 > max_node_level)
max_node_level = nb_liquid_level - 1;
- }
break;
}
}
new_node_level = liquid_level + 1;
if (new_node_level != max_node_level)
must_reflow.push_back(p0);
- } else
+ } else {
new_node_level = max_node_level;
+ }
- if (max_node_level >= (LIQUID_LEVEL_MAX+1-range))
+ if (max_node_level >= (LIQUID_LEVEL_MAX + 1 - range))
new_node_content = liquid_kind;
else
- new_node_content = CONTENT_AIR;
+ new_node_content = floodable_node;
}
/*
check if anything has changed. if not, just continue with the next node.
*/
- if (new_node_content == n0.getContent() && (nodemgr->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
- ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
- ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
- == flowing_down)))
+ if (new_node_content == n0.getContent() &&
+ (nodemgr->get(n0.getContent()).liquid_type != LIQUID_FLOWING ||
+ ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
+ ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
+ == flowing_down)))
continue;
// Find out whether there is a suspect for this action
std::string suspect;
- if(m_gamedef->rollback()) {
+ if (m_gamedef->rollback())
suspect = m_gamedef->rollback()->getSuspect(p0, 83, 1);
- }
- if(m_gamedef->rollback() && !suspect.empty()){
+ if (m_gamedef->rollback() && !suspect.empty()) {
// Blame suspect
RollbackScopeActor rollback_scope(m_gamedef->rollback(), suspect, true);
// Get old node for rollback
v3s16 blockpos = getNodeBlockPos(p0);
MapBlock *block = getBlockNoCreateNoEx(blockpos);
- if(block != NULL) {
+ if (block != NULL) {
modified_blocks[blockpos] = block;
// If new or old node emits light, MapBlock requires lighting update
- if(nodemgr->get(n0).light_source != 0 ||
+ if (nodemgr->get(n0).light_source != 0 ||
nodemgr->get(n00).light_source != 0)
lighting_modified_blocks[block->getPos()] = block;
}
m_emerge(emerge),
m_map_metadata_changed(true)
{
- verbosestream<<__FUNCTION_NAME<<std::endl;
+ verbosestream<<FUNCTION_NAME<<std::endl;
/*
Try to load map; if not found, create a new one.
ServerMap::~ServerMap()
{
- verbosestream<<__FUNCTION_NAME<<std::endl;
+ verbosestream<<FUNCTION_NAME<<std::endl;
try
{
ServerMapSector *ServerMap::createSector(v2s16 p2d)
{
DSTACKF("%s: p2d=(%d,%d)",
- __FUNCTION_NAME,
+ FUNCTION_NAME,
p2d.X, p2d.Y);
/*
std::map<v3s16, MapBlock*> &modified_blocks
)
{
- DSTACKF("%s: p=(%d,%d,%d)", __FUNCTION_NAME, p.X, p.Y, p.Z);
+ DSTACKF("%s: p=(%d,%d,%d)", FUNCTION_NAME, p.X, p.Y, p.Z);
/*infostream<<"generateBlock(): "
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
*/
if(blockpos_over_limit(p))
{
- infostream<<__FUNCTION_NAME<<": Block position over limit"<<std::endl;
+ infostream<<FUNCTION_NAME<<": Block position over limit"<<std::endl;
throw InvalidPositionException("generateBlock(): pos. over limit");
}
MapBlock * ServerMap::createBlock(v3s16 p)
{
DSTACKF("%s: p=(%d,%d,%d)",
- __FUNCTION_NAME, p.X, p.Y, p.Z);
+ FUNCTION_NAME, p.X, p.Y, p.Z);
/*
Do not create over-limit
MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
{
DSTACKF("%s: p=(%d,%d,%d), create_blank=%d",
- __FUNCTION_NAME,
+ FUNCTION_NAME,
p.X, p.Y, p.Z, create_blank);
{
void ServerMap::save(ModifiedState save_level)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
if(m_map_saving_enabled == false) {
warningstream<<"Not saving map, saving disabled."<<std::endl;
return;
void ServerMap::saveMapMeta()
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
createDirs(m_savedir);
void ServerMap::loadMapMeta()
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
Settings conf;
std::string fullpath = m_savedir + DIR_DELIM + "map_meta.txt";
void ServerMap::saveSectorMeta(ServerMapSector *sector)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
// Format used for writing
u8 version = SER_FMT_VER_HIGHEST_WRITE;
// Get destination
MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
// Get destination
v2s16 p2d = getSectorPos(sectordir);
bool ServerMap::loadSectorMeta(v2s16 p2d)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
// The directory layout we're going to load from.
// 1 - original sectors/xxxxzzzz/
#if 0
bool ServerMap::loadSectorFull(v2s16 p2d)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
MapSector *sector = NULL;
void ServerMap::loadBlock(std::string sectordir, std::string blockfile,
MapSector *sector, bool save_after_load)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
std::string fullpath = sectordir + DIR_DELIM + blockfile;
try {
void ServerMap::loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
try {
std::istringstream is(*blob, std::ios_base::binary);
MapBlock* ServerMap::loadBlock(v3s16 blockpos)
{
- DSTACK(__FUNCTION_NAME);
+ DSTACK(FUNCTION_NAME);
v2s16 p2d(blockpos.X, blockpos.Z);