X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmap.cpp;h=4b0d2e2d8e846d8e5ee664ece1e245a8e4b4faaa;hb=5da6896d51ae3ee5140dc1041eff44a616751231;hp=8f612aeacb153e5164c125a86acd223d9ff71e2f;hpb=674be38fc262aab78ed75141c70e5c02830ca80d;p=dragonfireclient.git diff --git a/src/map.cpp b/src/map.cpp index 8f612aeac..4b0d2e2d8 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -37,7 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "environment.h" #include "emerge.h" #include "mapgen_v6.h" -#include "biome.h" +#include "mg_biome.h" #include "config.h" #include "server.h" #include "database.h" @@ -186,26 +186,42 @@ bool Map::isValidPosition(v3s16 p) } // Returns a CONTENT_IGNORE node if not found -MapNode Map::getNodeNoEx(v3s16 p) +MapNode Map::getNodeNoEx(v3s16 p, bool *is_valid_position) { v3s16 blockpos = getNodeBlockPos(p); MapBlock *block = getBlockNoCreateNoEx(blockpos); - if(block == NULL) + if (block == NULL) { + if (is_valid_position != NULL) + *is_valid_position = false; return MapNode(CONTENT_IGNORE); + } + v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; - return block->getNodeNoCheck(relpos); + bool is_valid_p; + MapNode node = block->getNodeNoCheck(relpos, &is_valid_p); + if (is_valid_position != NULL) + *is_valid_position = is_valid_p; + return node; } +#if 0 +// Deprecated // throws InvalidPositionException if not found +// TODO: Now this is deprecated, getNodeNoEx should be renamed MapNode Map::getNode(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); MapBlock *block = getBlockNoCreateNoEx(blockpos); - if(block == NULL) + if (block == NULL) throw InvalidPositionException(); v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; - return block->getNodeNoCheck(relpos); + bool is_valid_position; + MapNode node = block->getNodeNoCheck(relpos, &is_valid_position); + if (!is_valid_position) + throw InvalidPositionException(); + return node; } +#endif // throws InvalidPositionException if not found void Map::setNode(v3s16 p, MapNode & n) @@ -215,9 +231,10 @@ void Map::setNode(v3s16 p, MapNode & n) v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; // Never allow placing CONTENT_IGNORE, it fucks up stuff if(n.getContent() == CONTENT_IGNORE){ + bool temp_bool; errorstream<<"Map::setNode(): Not allowing to place CONTENT_IGNORE" <<" while trying to replace \"" - <ndef()->get(block->getNodeNoCheck(relpos)).name + <ndef()->get(block->getNodeNoCheck(relpos, &temp_bool)).name <<"\" at "<getNode(relpos); + // Calculate relative position in block + v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE; + // Get node straight from the block + bool is_valid_position; + MapNode n2 = block->getNode(relpos, &is_valid_position); + if (!is_valid_position) + continue; - bool changed = false; + bool changed = false; - //TODO: Optimize output by optimizing light_sources? + //TODO: Optimize output by optimizing light_sources? + /* + If the neighbor is dimmer than what was specified + as oldlight (the light of the previous node) + */ + if(n2.getLight(bank, nodemgr) < oldlight) + { /* - If the neighbor is dimmer than what was specified - as oldlight (the light of the previous node) + And the neighbor is transparent and it has some light */ - if(n2.getLight(bank, nodemgr) < oldlight) + if(nodemgr->get(n2).light_propagates + && n2.getLight(bank, nodemgr) != 0) { /* - And the neighbor is transparent and it has some light + Set light to 0 and add to queue */ - if(nodemgr->get(n2).light_propagates - && n2.getLight(bank, nodemgr) != 0) - { - /* - Set light to 0 and add to queue - */ - - u8 current_light = n2.getLight(bank, nodemgr); - n2.setLight(bank, 0, nodemgr); - block->setNode(relpos, n2); - - unlighted_nodes[n2pos] = current_light; - changed = true; - - /* - Remove from light_sources if it is there - NOTE: This doesn't happen nearly at all - */ - /*if(light_sources.find(n2pos)) - { - infostream<<"Removed from light_sources"<setNode(relpos, n2); - // Add to modified_blocks - if(changed == true && block_checked_in_modified == false) - { - // If the block is not found in modified_blocks, add. - if(modified_blocks.find(blockpos) == modified_blocks.end()) + unlighted_nodes[n2pos] = current_light; + changed = true; + + /* + Remove from light_sources if it is there + NOTE: This doesn't happen nearly at all + */ + /*if(light_sources.find(n2pos)) { - modified_blocks[blockpos] = block; - } - block_checked_in_modified = true; + infostream<<"Removed from light_sources"<getNode(relpos); + bool is_valid_position; + MapNode n = block->getNode(relpos, &is_valid_position); - u8 oldlight = n.getLight(bank, nodemgr); + u8 oldlight = is_valid_position ? n.getLight(bank, nodemgr) : 0; u8 newlight = diminish_light(oldlight); // Loop through 6 neighbors @@ -499,67 +511,61 @@ void Map::spreadLight(enum LightBank bank, // Get the block where the node is located v3s16 blockpos = getNodeBlockPos(n2pos); - try - { - // Only fetch a new block if the block position has changed - try{ - if(block == NULL || blockpos != blockpos_last){ - block = getBlockNoCreate(blockpos); - blockpos_last = blockpos; + // Only fetch a new block if the block position has changed + try { + if(block == NULL || blockpos != blockpos_last){ + block = getBlockNoCreate(blockpos); + blockpos_last = blockpos; - block_checked_in_modified = false; - blockchangecount++; - } - } - catch(InvalidPositionException &e) - { - continue; + block_checked_in_modified = false; + blockchangecount++; } + } + catch(InvalidPositionException &e) { + continue; + } - // Calculate relative position in block - v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE; - // Get node straight from the block - MapNode n2 = block->getNode(relpos); + // Calculate relative position in block + v3s16 relpos = n2pos - blockpos * MAP_BLOCKSIZE; + // Get node straight from the block + MapNode n2 = block->getNode(relpos, &is_valid_position); + if (!is_valid_position) + continue; - bool changed = false; - /* - If the neighbor is brighter than the current node, - add to list (it will light up this node on its turn) - */ - if(n2.getLight(bank, nodemgr) > undiminish_light(oldlight)) + bool changed = false; + /* + If the neighbor is brighter than the current node, + add to list (it will light up this node on its turn) + */ + if(n2.getLight(bank, nodemgr) > undiminish_light(oldlight)) + { + lighted_nodes.insert(n2pos); + changed = true; + } + /* + If the neighbor is dimmer than how much light this node + would spread on it, add to list + */ + if(n2.getLight(bank, nodemgr) < newlight) + { + if(nodemgr->get(n2).light_propagates) { + n2.setLight(bank, newlight, nodemgr); + block->setNode(relpos, n2); lighted_nodes.insert(n2pos); changed = true; } - /* - If the neighbor is dimmer than how much light this node - would spread on it, add to list - */ - if(n2.getLight(bank, nodemgr) < newlight) - { - if(nodemgr->get(n2).light_propagates) - { - n2.setLight(bank, newlight, nodemgr); - block->setNode(relpos, n2); - lighted_nodes.insert(n2pos); - changed = true; - } - } + } - // Add to modified_blocks - if(changed == true && block_checked_in_modified == false) + // Add to modified_blocks + if(changed == true && block_checked_in_modified == false) + { + // If the block is not found in modified_blocks, add. + if(modified_blocks.find(blockpos) == modified_blocks.end()) { - // If the block is not found in modified_blocks, add. - if(modified_blocks.find(blockpos) == modified_blocks.end()) - { - modified_blocks[blockpos] = block; - } - block_checked_in_modified = true; + modified_blocks[blockpos] = block; } - } - catch(InvalidPositionException &e) - { - continue; + block_checked_in_modified = true; } } } @@ -607,13 +613,11 @@ v3s16 Map::getBrightestNeighbour(enum LightBank bank, v3s16 p) // Get the position of the neighbor node v3s16 n2pos = p + dirs[i]; MapNode n2; - try{ - n2 = getNode(n2pos); - } - catch(InvalidPositionException &e) - { + bool is_valid_position; + n2 = getNodeNoEx(n2pos, &is_valid_position); + if (!is_valid_position) continue; - } + if(n2.getLight(bank, nodemgr) > brightest_light || found_something == false){ brightest_light = n2.getLight(bank, nodemgr); brightest_pos = n2pos; @@ -656,7 +660,10 @@ s16 Map::propagateSunlight(v3s16 start, } v3s16 relpos = pos - blockpos*MAP_BLOCKSIZE; - MapNode n = block->getNode(relpos); + bool is_valid_position; + MapNode n = block->getNode(relpos, &is_valid_position); + if (!is_valid_position) + break; if(nodemgr->get(n).sunlight_propagates) { @@ -723,39 +730,37 @@ void Map::updateLighting(enum LightBank bank, for(s16 x=0; xgetNode(p); - u8 oldlight = n.getLight(bank, nodemgr); - n.setLight(bank, 0, nodemgr); - block->setNode(p, n); - - // If node sources light, add to list - u8 source = nodemgr->get(n).light_source; - if(source != 0) - light_sources.insert(p + posnodes); - - // Collect borders for unlighting - if((x==0 || x == MAP_BLOCKSIZE-1 - || y==0 || y == MAP_BLOCKSIZE-1 - || z==0 || z == MAP_BLOCKSIZE-1) - && oldlight != 0) - { - v3s16 p_map = p + posnodes; - unlight_from[p_map] = oldlight; - } - } - catch(InvalidPositionException &e) - { - /* - This would happen when dealing with a - dummy block. + v3s16 p(x,y,z); + bool is_valid_position; + MapNode n = block->getNode(p, &is_valid_position); + if (!is_valid_position) { + /* This would happen when dealing with a + dummy block. */ - //assert(0); infostream<<"updateLighting(): InvalidPositionException" <setNode(p, n); + + // If node sources light, add to list + u8 source = nodemgr->get(n).light_source; + if(source != 0) + light_sources.insert(p + posnodes); + + // Collect borders for unlighting + if((x==0 || x == MAP_BLOCKSIZE-1 + || y==0 || y == MAP_BLOCKSIZE-1 + || z==0 || z == MAP_BLOCKSIZE-1) + && oldlight != 0) + { + v3s16 p_map = p + posnodes; + unlight_from[p_map] = oldlight; } + + } if(bank == LIGHTBANK_DAY) @@ -965,15 +970,12 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, Otherwise there probably is. */ - try{ - MapNode topnode = getNode(toppos); - if(topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) - node_under_sunlight = false; - } - catch(InvalidPositionException &e) - { - } + bool is_valid_position; + MapNode topnode = getNodeNoEx(toppos, &is_valid_position); + + if(is_valid_position && topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) + node_under_sunlight = false; /* Remove all light that has come out of this node @@ -988,7 +990,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, { enum LightBank bank = banks[i]; - u8 lightwas = getNode(p).getLight(bank, ndef); + u8 lightwas = getNodeNoEx(p).getLight(bank, ndef); // Add the block of the added node to modified_blocks v3s16 blockpos = getNodeBlockPos(p); @@ -1045,13 +1047,10 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, v3s16 n2pos(p.X, y, p.Z); MapNode n2; - try{ - n2 = getNode(n2pos); - } - catch(InvalidPositionException &e) - { + + n2 = getNodeNoEx(n2pos, &is_valid_position); + if (!is_valid_position) break; - } if(n2.getLight(LIGHTBANK_DAY, ndef) == LIGHT_SUN) { @@ -1100,7 +1099,6 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, /* Add neighboring liquid nodes and the node itself if it is liquid (=water node was added) to transform queue. - note: todo: for liquid_finite enough to add only self node */ v3s16 dirs[7] = { v3s16(0,0,0), // self @@ -1113,20 +1111,14 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, }; for(u16 i=0; i<7; i++) { - try - { - v3s16 p2 = p + dirs[i]; - MapNode n2 = getNode(p2); - if(ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR) + MapNode n2 = getNodeNoEx(p2, &is_valid_position); + if(is_valid_position + && (ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)) { m_transforming_liquid.push_back(p2); } - - }catch(InvalidPositionException &e) - { - } } } @@ -1157,15 +1149,11 @@ void Map::removeNodeAndUpdate(v3s16 p, If there is a node at top and it doesn't have sunlight, there will be no sunlight going down. */ - try{ - MapNode topnode = getNode(toppos); + bool is_valid_position; + MapNode topnode = getNodeNoEx(toppos, &is_valid_position); - if(topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) - node_under_sunlight = false; - } - catch(InvalidPositionException &e) - { - } + if(is_valid_position && topnode.getLight(LIGHTBANK_DAY, ndef) != LIGHT_SUN) + node_under_sunlight = false; std::set light_sources; @@ -1182,7 +1170,7 @@ void Map::removeNodeAndUpdate(v3s16 p, Unlight neighbors (in case the node is a light source) */ unLightNeighbors(bank, p, - getNode(p).getLight(bank, ndef), + getNodeNoEx(p).getLight(bank, ndef), light_sources, modified_blocks); } @@ -1242,13 +1230,11 @@ void Map::removeNodeAndUpdate(v3s16 p, { // Set the lighting of this node to 0 // TODO: Is this needed? Lighting is cleared up there already. - try{ - MapNode n = getNode(p); + MapNode n = getNodeNoEx(p, &is_valid_position); + if (is_valid_position) { n.setLight(LIGHTBANK_DAY, 0, ndef); setNode(p, n); - } - catch(InvalidPositionException &e) - { + } else { assert(0); } } @@ -1292,7 +1278,6 @@ void Map::removeNodeAndUpdate(v3s16 p, /* Add neighboring liquid nodes and this node to transform queue. (it's vital for the node itself to get updated last.) - note: todo: for liquid_finite enough to add only self node */ v3s16 dirs[7] = { v3s16(0,0,1), // back @@ -1305,20 +1290,15 @@ void Map::removeNodeAndUpdate(v3s16 p, }; for(u16 i=0; i<7; i++) { - try - { - v3s16 p2 = p + dirs[i]; - MapNode n2 = getNode(p2); - if(ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR) + bool is_position_valid; + MapNode n2 = getNodeNoEx(p2, &is_position_valid); + if (is_position_valid + && (ndef->get(n2).isLiquid() || n2.getContent() == CONTENT_AIR)) { m_transforming_liquid.push_back(p2); } - - }catch(InvalidPositionException &e) - { - } } } @@ -1475,11 +1455,11 @@ void Map::timerUpdate(float dtime, float unload_timeout, v3s16 p = block->getPos(); // Save if modified - if(block->getModified() != MOD_STATE_CLEAN - && save_before_unloading) + if (block->getModified() != MOD_STATE_CLEAN && save_before_unloading) { modprofiler.add(block->getModifiedReason(), 1); - saveBlock(block); + if (!saveBlock(block)) + continue; saved_blocks_count++; } @@ -1619,7 +1599,6 @@ struct NodeNeighbor { NeighborType t; v3s16 p; bool l; //can liquid - bool i; //infinity }; void Map::transforming_liquid_add(v3s16 p) { @@ -1630,383 +1609,8 @@ s32 Map::transforming_liquid_size() { return m_transforming_liquid.size(); } -const v3s16 g_7dirs[7] = -{ - // +right, +top, +back - v3s16( 0,-1, 0), // bottom - v3s16( 0, 0, 0), // self - v3s16( 0, 0, 1), // back - v3s16( 0, 0,-1), // front - v3s16( 1, 0, 0), // right - v3s16(-1, 0, 0), // left - v3s16( 0, 1, 0) // top -}; - -#define D_BOTTOM 0 -#define D_TOP 6 -#define D_SELF 1 - -void Map::transformLiquidsFinite(std::map & modified_blocks) -{ - INodeDefManager *nodemgr = m_gamedef->ndef(); - - DSTACK(__FUNCTION_NAME); - //TimeTaker timer("transformLiquids()"); - - u32 loopcount = 0; - u32 initial_size = m_transforming_liquid.size(); - - u8 relax = g_settings->getS16("liquid_relax"); - bool fast_flood = g_settings->getS16("liquid_fast_flood"); - int water_level = g_settings->getS16("water_level"); - - // list of nodes that due to viscosity have not reached their max level height - UniqueQueue must_reflow, must_reflow_second; - - // List of MapBlocks that will require a lighting update (due to lava) - std::map lighting_modified_blocks; - - u16 loop_max = g_settings->getU16("liquid_loop_max"); - - //if (m_transforming_liquid.size() > 0) errorstream << "Liquid queue size="< 0) - { - // This should be done here so that it is done when continue is used - if (loopcount >= initial_size || loopcount >= loop_max) - break; - loopcount++; - /* - Get a queued transforming liquid node - */ - v3s16 p0 = m_transforming_liquid.pop_front(); - u16 total_level = 0; - // surrounding flowing liquid nodes - NodeNeighbor neighbors[7]; - // current level of every block - s8 liquid_levels[7] = {-1, -1, -1, -1, -1, -1, -1}; - // target levels - s8 liquid_levels_want[7] = {-1, -1, -1, -1, -1, -1, -1}; - s8 can_liquid_same_level = 0; - content_t liquid_kind = CONTENT_IGNORE; - content_t liquid_kind_flowing = CONTENT_IGNORE; - /* - Collect information about the environment - */ - const v3s16 *dirs = g_7dirs; - for (u16 i = 0; i < 7; i++) { - NeighborType nt = NEIGHBOR_SAME_LEVEL; - switch (i) { - case D_TOP: - nt = NEIGHBOR_UPPER; - break; - case D_BOTTOM: - nt = NEIGHBOR_LOWER; - break; - } - v3s16 npos = p0 + dirs[i]; - - neighbors[i].n = getNodeNoEx(npos); - neighbors[i].t = nt; - neighbors[i].p = npos; - neighbors[i].l = 0; - neighbors[i].i = 0; - NodeNeighbor & nb = neighbors[i]; - - switch (nodemgr->get(nb.n.getContent()).liquid_type) { - case LIQUID_NONE: - if (nb.n.getContent() == CONTENT_AIR) { - liquid_levels[i] = 0; - nb.l = 1; - } - break; - case LIQUID_SOURCE: - // if this node is not (yet) of a liquid type, - // choose the first liquid type we encounter - if (liquid_kind_flowing == CONTENT_IGNORE) - liquid_kind_flowing = nodemgr->getId( - nodemgr->get(nb.n).liquid_alternative_flowing); - if (liquid_kind == CONTENT_IGNORE) - liquid_kind = nb.n.getContent(); - if (nb.n.getContent() == liquid_kind) { - liquid_levels[i] = nb.n.getLevel(nodemgr); //LIQUID_LEVEL_SOURCE; - nb.l = 1; - nb.i = (nb.n.param2 & LIQUID_INFINITY_MASK); - } - break; - case LIQUID_FLOWING: - // if this node is not (yet) of a liquid type, - // choose the first liquid type we encounter - if (liquid_kind_flowing == CONTENT_IGNORE) - liquid_kind_flowing = nb.n.getContent(); - if (liquid_kind == CONTENT_IGNORE) - liquid_kind = nodemgr->getId( - nodemgr->get(nb.n).liquid_alternative_source); - if (nb.n.getContent() == liquid_kind_flowing) { - liquid_levels[i] = nb.n.getLevel(nodemgr); //(nb.n.param2 & LIQUID_LEVEL_MASK); - nb.l = 1; - } - break; - } - - if (nb.l && nb.t == NEIGHBOR_SAME_LEVEL) - ++can_liquid_same_level; - if (liquid_levels[i] > 0) - total_level += liquid_levels[i]; - - /* - infostream << "get node i=" <<(int)i<<" " << PP(npos) << " c=" - << nb.n.getContent() <<" p0="<< (int)nb.n.param0 <<" p1=" - << (int)nb.n.param1 <<" p2="<< (int)nb.n.param2 << " lt=" - << nodemgr->get(nb.n.getContent()).liquid_type - //<< " lk=" << liquid_kind << " lkf=" << liquid_kind_flowing - << " l="<< nb.l << " inf="<< nb.i << " nlevel=" << (int)liquid_levels[i] - << " tlevel=" << (int)total_level << " cansame=" - << (int)can_liquid_same_level << std::endl; - */ - } - - if (liquid_kind == CONTENT_IGNORE || - !neighbors[D_SELF].l || - total_level <= 0) - continue; - - // fill bottom block - if (neighbors[D_BOTTOM].l) { - liquid_levels_want[D_BOTTOM] = total_level > LIQUID_LEVEL_SOURCE ? - LIQUID_LEVEL_SOURCE : total_level; - total_level -= liquid_levels_want[D_BOTTOM]; - } - - //relax up - if (relax && ((p0.Y == water_level) || (fast_flood && p0.Y <= water_level)) && liquid_levels[D_TOP] == 0 && - liquid_levels[D_BOTTOM] == LIQUID_LEVEL_SOURCE && - total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level- - (can_liquid_same_level - relax) && - can_liquid_same_level >= relax + 1) { - total_level = LIQUID_LEVEL_SOURCE * can_liquid_same_level; - } - - // prevent lakes in air above unloaded blocks - if (liquid_levels[D_TOP] == 0 && (p0.Y > water_level) && neighbors[D_BOTTOM].n.getContent() == CONTENT_IGNORE && !(loopcount % 3)) { - --total_level; - } - - // calculate self level 5 blocks - u8 want_level = - total_level >= LIQUID_LEVEL_SOURCE * can_liquid_same_level - ? LIQUID_LEVEL_SOURCE - : total_level / can_liquid_same_level; - total_level -= want_level * can_liquid_same_level; - - //relax down - if (relax && p0.Y == water_level + 1 && liquid_levels[D_TOP] == 0 && - liquid_levels[D_BOTTOM] == LIQUID_LEVEL_SOURCE && want_level == 0 && - total_level <= (can_liquid_same_level - relax) && - can_liquid_same_level >= relax + 1) { - total_level = 0; - } - - for (u16 ii = D_SELF; ii < D_TOP; ++ii) { // fill only same level - if (!neighbors[ii].l) - continue; - liquid_levels_want[ii] = want_level; - if (liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE && total_level > 0) { - if (loopcount % 3 || liquid_levels[ii] <= 0){ - if (liquid_levels[ii] > liquid_levels_want[ii]) { - ++liquid_levels_want[ii]; - --total_level; - } - } else if (neighbors[ii].l > 0){ - ++liquid_levels_want[ii]; - --total_level; - } - } - } - - for (u16 ii = 0; ii < 7; ++ii) { - if (total_level < 1) break; - if (liquid_levels_want[ii] >= 0 && - liquid_levels_want[ii] < LIQUID_LEVEL_SOURCE) { - ++liquid_levels_want[ii]; - --total_level; - } - } - - // fill top block if can - if (neighbors[D_TOP].l) { - liquid_levels_want[D_TOP] = total_level > LIQUID_LEVEL_SOURCE ? - LIQUID_LEVEL_SOURCE : total_level; - total_level -= liquid_levels_want[D_TOP]; - } - - for (u16 ii = 0; ii < 7; ii++) // infinity and cave flood optimization - if ( neighbors[ii].i || - (liquid_levels_want[ii] >= 0 && - (fast_flood && p0.Y < water_level && - (initial_size >= 1000 - && ii != D_TOP - && want_level >= LIQUID_LEVEL_SOURCE/4 - && can_liquid_same_level >= 5 - && liquid_levels[D_TOP] >= LIQUID_LEVEL_SOURCE)))) - liquid_levels_want[ii] = LIQUID_LEVEL_SOURCE; - - /* - if (total_level > 0) //|| flowed != volume) - infostream <<" AFTER level=" << (int)total_level - //<< " flowed="<ndef(); DSTACK(__FUNCTION_NAME); @@ -2385,26 +1989,6 @@ void Map::removeNodeTimer(v3s16 p) block->m_node_timers.remove(p_rel); } -s16 Map::getHeat(v3s16 p) -{ - MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p)); - if(block != NULL) { - return block->heat; - } - //errorstream << "No heat for " << p.X<<"," << p.Z << std::endl; - return 0; -} - -s16 Map::getHumidity(v3s16 p) -{ - MapBlock *block = getBlockNoCreateNoEx(getNodeBlockPos(p)); - if(block != NULL) { - return block->humidity; - } - //errorstream << "No humidity for " << p.X<<"," << p.Z << std::endl; - return 0; -} - /* ServerMap */ @@ -2653,7 +2237,7 @@ bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) //TimeTaker timer("initBlockMake() initialEmerge"); data->vmanip->initialEmerge(bigarea_blocks_min, bigarea_blocks_max, false); } - + // Ensure none of the blocks to be generated were marked as containing CONTENT_IGNORE /* for (s16 z = blockpos_min.Z; z <= blockpos_max.Z; z++) { for (s16 y = blockpos_min.Y; y <= blockpos_max.Y; y++) { @@ -2673,7 +2257,7 @@ bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) return true; } -MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, +void ServerMap::finishBlockMake(BlockMakeData *data, std::map &changed_blocks) { v3s16 blockpos_min = data->blockpos_min; @@ -2767,7 +2351,9 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, y<=blockpos_max.Y+extra_borders.Y; y++) { v3s16 p(x, y, z); - getBlockNoCreateNoEx(p)->setLightingExpired(false); + MapBlock * block = getBlockNoCreateNoEx(p); + if (block != NULL) + block->setLightingExpired(false); } #if 0 @@ -2783,7 +2369,8 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, i != changed_blocks.end(); ++i) { MapBlock *block = i->second; - assert(block); + if (!block) + continue; /* Update day/night difference cache of the MapBlocks */ @@ -2804,7 +2391,8 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, { v3s16 p(x, y, z); MapBlock *block = getBlockNoCreateNoEx(p); - assert(block); + if (!block) + continue; block->setGenerated(true); } @@ -2817,31 +2405,8 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, /*infostream<<"finishBlockMake() done for ("<getEnv(); - for(s16 x=blockpos_min.X-extra_borders.X; - x<=blockpos_max.X+extra_borders.X; x++) - for(s16 z=blockpos_min.Z-extra_borders.Z; - z<=blockpos_max.Z+extra_borders.Z; z++) - for(s16 y=blockpos_min.Y-extra_borders.Y; - y<=blockpos_max.Y+extra_borders.Y; y++) - { - v3s16 p(x, y, z); - MapBlock *block = getBlockNoCreateNoEx(p); - block->heat_last_update = 0; - block->humidity_last_update = 0; - if (senv->m_use_weather) { - updateBlockHeat(senv, p * MAP_BLOCKSIZE, block); - updateBlockHumidity(senv, p * MAP_BLOCKSIZE, block); - } else { - block->heat = HEAT_UNDEFINED; - block->humidity = HUMIDITY_UNDEFINED; - } - } - + + #if 0 if(enable_mapgen_debug_info) { @@ -2865,10 +2430,7 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, } #endif - MapBlock *block = getBlockNoCreateNoEx(blockpos_requested); - assert(block); - - return block; + getBlockNoCreateNoEx(blockpos_requested); } ServerMapSector * ServerMap::createSector(v2s16 p2d) @@ -3175,19 +2737,28 @@ MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d) } void ServerMap::prepareBlock(MapBlock *block) { - ServerEnvironment *senv = &((Server *)m_gamedef)->getEnv(); - - // Calculate weather conditions - block->heat_last_update = 0; - block->humidity_last_update = 0; - if (senv->m_use_weather) { - v3s16 p = block->getPos() * MAP_BLOCKSIZE; - updateBlockHeat(senv, p, block); - updateBlockHumidity(senv, p, block); - } else { - block->heat = HEAT_UNDEFINED; - block->humidity = HUMIDITY_UNDEFINED; - } +} + +// N.B. This requires no synchronization, since data will not be modified unless +// the VoxelManipulator being updated belongs to the same thread. +void ServerMap::updateVManip(v3s16 pos) +{ + Mapgen *mg = m_emerge->getCurrentMapgen(); + if (!mg) + return; + + ManualMapVoxelManipulator *vm = mg->vm; + if (!vm) + return; + + if (!vm->m_area.contains(pos)) + return; + + s32 idx = vm->m_area.index(pos); + vm->m_data[idx] = getNodeNoEx(pos); + vm->m_flags[idx] &= ~VOXELFLAG_NO_DATA; + + vm->m_is_dirty = true; } s16 ServerMap::findGroundLevel(v2s16 p2d) @@ -3476,37 +3047,25 @@ void ServerMap::loadMapMeta() { DSTACK(__FUNCTION_NAME); - /*infostream<<"ServerMap::loadMapMeta(): Loading map metadata" - <loadParamsFromSettings(¶ms); - verbosestream<<"ServerMap::loadMapMeta(): seed=" - << m_emerge->params.seed<serialize(o, version, true); + + std::string data = o.str(); + bool ret = db->saveBlock(p3d, data); + if(ret) { + // We just wrote it to the disk so clear modified flag + block->resetModified(); + } + return ret; } -void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load) +void ServerMap::loadBlock(std::string sectordir, std::string blockfile, + MapSector *sector, bool save_after_load) { DSTACK(__FUNCTION_NAME); std::string fullpath = sectordir+DIR_DELIM+blockfile; - try{ + try { std::ifstream is(fullpath.c_str(), std::ios_base::binary); if(is.good() == false) @@ -3850,10 +3443,13 @@ MapBlock* ServerMap::loadBlock(v3s16 blockpos) v2s16 p2d(blockpos.X, blockpos.Z); - MapBlock *ret; + std::string ret; ret = dbase->loadBlock(blockpos); - if (ret) return (ret); + if (ret != "") { + loadBlock(&ret, blockpos, createSector(p2d), false); + return getBlockNoCreateNoEx(blockpos); + } // Not found in database, try the files // The directory layout we're going to load from. @@ -3917,209 +3513,11 @@ void ServerMap::PrintInfo(std::ostream &out) out<<"ServerMap: "; } -s16 ServerMap::updateBlockHeat(ServerEnvironment *env, v3s16 p, MapBlock *block) -{ - u32 gametime = env->getGameTime(); - - if (block) { - if (gametime - block->heat_last_update < 10) - return block->heat; - } else { - block = getBlockNoCreateNoEx(getNodeBlockPos(p)); - } - - f32 heat = m_emerge->biomedef->calcBlockHeat(p, getSeed(), - env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed()); - - if(block) { - block->heat = heat; - block->heat_last_update = gametime; - } - return heat; -} - -s16 ServerMap::updateBlockHumidity(ServerEnvironment *env, v3s16 p, MapBlock *block) -{ - u32 gametime = env->getGameTime(); - - if (block) { - if (gametime - block->humidity_last_update < 10) - return block->humidity; - } else { - block = getBlockNoCreateNoEx(getNodeBlockPos(p)); - } - - f32 humidity = m_emerge->biomedef->calcBlockHumidity(p, getSeed(), - env->getTimeOfDayF(), gametime * env->getTimeOfDaySpeed()); - - if(block) { - block->humidity = humidity; - block->humidity_last_update = gametime; - } - return humidity; -} - -/* - MapVoxelManipulator -*/ - -MapVoxelManipulator::MapVoxelManipulator(Map *map) -{ - m_map = map; -} - -MapVoxelManipulator::~MapVoxelManipulator() -{ - /*infostream<<"MapVoxelManipulator: blocks: "<::iterator n; - n = m_loaded_blocks.find(p); - if(n != m_loaded_blocks.end()) - continue; - - bool block_data_inexistent = false; - try - { - TimeTaker timer1("emerge load", &emerge_load_time); - - /*infostream<<"Loading block (caller_id="<getBlockNoCreate(p); - if(block->isDummy()) - block_data_inexistent = true; - else - block->copyTo(*this); - } - catch(InvalidPositionException &e) - { - block_data_inexistent = true; - } - - if(block_data_inexistent) - { - flags |= VMANIP_BLOCK_DATA_INEXIST; - - VoxelArea a(p*MAP_BLOCKSIZE, (p+1)*MAP_BLOCKSIZE-v3s16(1,1,1)); - // Fill with VOXELFLAG_INEXISTENT - for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++) - for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++) - { - s32 i = m_area.index(a.MinEdge.X,y,z); - memset(&m_flags[i], VOXELFLAG_INEXISTENT, MAP_BLOCKSIZE); - } - } - /*else if (block->getNode(0, 0, 0).getContent() == CONTENT_IGNORE) - { - // Mark that block was loaded as blank - flags |= VMANIP_BLOCK_CONTAINS_CIGNORE; - }*/ - - m_loaded_blocks[p] = flags; - } - - //infostream<<"emerge done"< & modified_blocks) -{ - if(m_area.getExtent() == v3s16(0,0,0)) - return; - - //TimeTaker timer1("blitBack"); - - /*infostream<<"blitBack(): m_loaded_blocks.size()=" - <getBlockNoCreate(blockpos); - blockpos_last = blockpos; - block_checked_in_modified = false; - } - - // Calculate relative position in block - v3s16 relpos = p - blockpos * MAP_BLOCKSIZE; - - // Don't continue if nothing has changed here - if(block->getNode(relpos) == n) - continue; - - //m_map->setNode(m_area.MinEdge + p, n); - block->setNode(relpos, n); - - /* - Make sure block is in modified_blocks - */ - if(block_checked_in_modified == false) - { - modified_blocks[blockpos] = block; - block_checked_in_modified = true; - } - } - catch(InvalidPositionException &e) - { - } - } -} - ManualMapVoxelManipulator::ManualMapVoxelManipulator(Map *map): - MapVoxelManipulator(map), - m_create_area(false) + VoxelManipulator(), + m_is_dirty(false), + m_create_area(false), + m_map(map) { } @@ -4127,12 +3525,6 @@ ManualMapVoxelManipulator::~ManualMapVoxelManipulator() { } -void ManualMapVoxelManipulator::emerge(VoxelArea a, s32 caller_id) -{ - // Just create the area so that it can be pointed to - VoxelManipulator::emerge(a, caller_id); -} - void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max, bool load_if_inexistent) { @@ -4186,7 +3578,7 @@ void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min, if(block_data_inexistent) { - + if (load_if_inexistent) { ServerMap *svrmap = (ServerMap *)m_map; block = svrmap->emergeBlock(p, false); @@ -4196,17 +3588,17 @@ void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min, block->copyTo(*this); } else { flags |= VMANIP_BLOCK_DATA_INEXIST; - + /* Mark area inexistent */ VoxelArea a(p*MAP_BLOCKSIZE, (p+1)*MAP_BLOCKSIZE-v3s16(1,1,1)); - // Fill with VOXELFLAG_INEXISTENT + // Fill with VOXELFLAG_NO_DATA for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++) for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++) { s32 i = m_area.index(a.MinEdge.X,y,z); - memset(&m_flags[i], VOXELFLAG_INEXISTENT, MAP_BLOCKSIZE); + memset(&m_flags[i], VOXELFLAG_NO_DATA, MAP_BLOCKSIZE); } } } @@ -4218,10 +3610,13 @@ void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min, m_loaded_blocks[p] = flags; } + + m_is_dirty = false; } void ManualMapVoxelManipulator::blitBackAll( - std::map * modified_blocks) + std::map *modified_blocks, + bool overwrite_generated) { if(m_area.getExtent() == v3s16(0,0,0)) return; @@ -4236,10 +3631,9 @@ void ManualMapVoxelManipulator::blitBackAll( v3s16 p = i->first; MapBlock *block = m_map->getBlockNoCreateNoEx(p); bool existed = !(i->second & VMANIP_BLOCK_DATA_INEXIST); - if(existed == false) - { + if ((existed == false) || (block == NULL) || + (overwrite_generated == false && block->isGenerated() == true)) continue; - } block->copyFrom(*this);