X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmap.cpp;h=fda4d461dbe43480e674970849ba555b86ef39dc;hb=6929206bc29960b0fab8c0a0a65a48992cfff398;hp=4be094326f182e47243699107f704cbfa96876ef;hpb=d31f07bd4b83f858cce589faac56922e12ba670f;p=oweals%2Fminetest.git diff --git a/src/map.cpp b/src/map.cpp index 4be094326..fda4d461d 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "voxel.h" #include "porting.h" -#include "mapgen.h" +#include "serialization.h" #include "nodemetadata.h" #include "settings.h" #include "log.h" @@ -32,9 +32,23 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "nodedef.h" #include "gamedef.h" #include "util/directiontables.h" +#include "util/mathconstants.h" #include "rollback_interface.h" +#include "environment.h" #include "emerge.h" #include "mapgen_v6.h" +#include "biome.h" +#include "config.h" +#include "server.h" +#include "database.h" +#include "database-dummy.h" +#include "database-sqlite3.h" +#if USE_LEVELDB +#include "database-leveldb.h" +#endif +#if USE_REDIS +#include "database-redis.h" +#endif #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -64,8 +78,6 @@ Map::Map(std::ostream &dout, IGameDef *gamedef): m_gamedef(gamedef), m_sector_cache(NULL) { - /*m_sector_mutex.Init(); - assert(m_sector_mutex.IsInitialized());*/ } Map::~Map() @@ -73,34 +85,30 @@ Map::~Map() /* Free all MapSectors */ - core::map::Iterator i = m_sectors.getIterator(); - for(; i.atEnd() == false; i++) + for(std::map::iterator i = m_sectors.begin(); + i != m_sectors.end(); ++i) { - MapSector *sector = i.getNode()->getValue(); - delete sector; + delete i->second; } } void Map::addEventReceiver(MapEventReceiver *event_receiver) { - m_event_receivers.insert(event_receiver, false); + m_event_receivers.insert(event_receiver); } void Map::removeEventReceiver(MapEventReceiver *event_receiver) { - if(m_event_receivers.find(event_receiver) == NULL) - return; - m_event_receivers.remove(event_receiver); + m_event_receivers.erase(event_receiver); } void Map::dispatchEvent(MapEditEvent *event) { - for(core::map::Iterator - i = m_event_receivers.getIterator(); - i.atEnd()==false; i++) + for(std::set::iterator + i = m_event_receivers.begin(); + i != m_event_receivers.end(); ++i) { - MapEventReceiver* event_receiver = i.getNode()->getKey(); - event_receiver->onMapEditEvent(event); + (*i)->onMapEditEvent(event); } } @@ -111,12 +119,12 @@ MapSector * Map::getSectorNoGenerateNoExNoLock(v2s16 p) return sector; } - core::map::Node *n = m_sectors.find(p); + std::map::iterator n = m_sectors.find(p); - if(n == NULL) + if(n == m_sectors.end()) return NULL; - MapSector *sector = n->getValue(); + MapSector *sector = n->second; // Cache the last result m_sector_cache_p = p; @@ -236,9 +244,9 @@ void Map::setNode(v3s16 p, MapNode & n) values of from_nodes are lighting values. */ void Map::unspreadLight(enum LightBank bank, - core::map & from_nodes, - core::map & light_sources, - core::map & modified_blocks) + std::map & from_nodes, + std::set & light_sources, + std::map & modified_blocks) { INodeDefManager *nodemgr = m_gamedef->ndef(); @@ -256,9 +264,7 @@ void Map::unspreadLight(enum LightBank bank, u32 blockchangecount = 0; - core::map unlighted_nodes; - core::map::Iterator j; - j = from_nodes.getIterator(); + std::map unlighted_nodes; /* Initialize block cache @@ -268,9 +274,10 @@ void Map::unspreadLight(enum LightBank bank, // Cache this a bit, too bool block_checked_in_modified = false; - for(; j.atEnd() == false; j++) + for(std::map::iterator j = from_nodes.begin(); + j != from_nodes.end(); ++j) { - v3s16 pos = j.getNode()->getKey(); + v3s16 pos = j->first; v3s16 blockpos = getNodeBlockPos(pos); // Only fetch a new block if the block position has changed @@ -292,12 +299,12 @@ void Map::unspreadLight(enum LightBank bank, continue; // Calculate relative position in block - v3s16 relpos = pos - blockpos_last * MAP_BLOCKSIZE; + //v3s16 relpos = pos - blockpos_last * MAP_BLOCKSIZE; // Get node straight from the block - MapNode n = block->getNode(relpos); + //MapNode n = block->getNode(relpos); - u8 oldlight = j.getNode()->getValue(); + u8 oldlight = j->second; // Loop through 6 neighbors for(u16 i=0; i<6; i++) @@ -354,7 +361,7 @@ void Map::unspreadLight(enum LightBank bank, n2.setLight(bank, 0, nodemgr); block->setNode(relpos, n2); - unlighted_nodes.insert(n2pos, current_light); + unlighted_nodes[n2pos] = current_light; changed = true; /* @@ -373,16 +380,16 @@ void Map::unspreadLight(enum LightBank bank, light_sources.remove(n2pos);*/ } else{ - light_sources.insert(n2pos, true); + light_sources.insert(n2pos); } // 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) == NULL) + if(modified_blocks.find(blockpos) == modified_blocks.end()) { - modified_blocks.insert(blockpos, block); + modified_blocks[blockpos] = block; } block_checked_in_modified = true; } @@ -408,11 +415,11 @@ void Map::unspreadLight(enum LightBank bank, */ void Map::unLightNeighbors(enum LightBank bank, v3s16 pos, u8 lightwas, - core::map & light_sources, - core::map & modified_blocks) + std::set & light_sources, + std::map & modified_blocks) { - core::map from_nodes; - from_nodes.insert(pos, lightwas); + std::map from_nodes; + from_nodes[pos] = lightwas; unspreadLight(bank, from_nodes, light_sources, modified_blocks); } @@ -422,8 +429,8 @@ void Map::unLightNeighbors(enum LightBank bank, goes on recursively. */ void Map::spreadLight(enum LightBank bank, - core::map & from_nodes, - core::map & modified_blocks) + std::set & from_nodes, + std::map & modified_blocks) { INodeDefManager *nodemgr = m_gamedef->ndef(); @@ -441,9 +448,7 @@ void Map::spreadLight(enum LightBank bank, u32 blockchangecount = 0; - core::map lighted_nodes; - core::map::Iterator j; - j = from_nodes.getIterator(); + std::set lighted_nodes; /* Initialize block cache @@ -453,12 +458,10 @@ void Map::spreadLight(enum LightBank bank, // Cache this a bit, too bool block_checked_in_modified = false; - for(; j.atEnd() == false; j++) - //for(; j != from_nodes.end(); j++) + for(std::set::iterator j = from_nodes.begin(); + j != from_nodes.end(); ++j) { - v3s16 pos = j.getNode()->getKey(); - //v3s16 pos = *j; - //infostream<<"pos=("< undiminish_light(oldlight)) { - lighted_nodes.insert(n2pos, true); - //lighted_nodes.push_back(n2pos); + lighted_nodes.insert(n2pos); changed = true; } /* @@ -539,8 +541,7 @@ void Map::spreadLight(enum LightBank bank, { n2.setLight(bank, newlight, nodemgr); block->setNode(relpos, n2); - lighted_nodes.insert(n2pos, true); - //lighted_nodes.push_back(n2pos); + lighted_nodes.insert(n2pos); changed = true; } } @@ -549,9 +550,9 @@ void Map::spreadLight(enum LightBank bank, if(changed == true && block_checked_in_modified == false) { // If the block is not found in modified_blocks, add. - if(modified_blocks.find(blockpos) == NULL) + if(modified_blocks.find(blockpos) == modified_blocks.end()) { - modified_blocks.insert(blockpos, block); + modified_blocks[blockpos] = block; } block_checked_in_modified = true; } @@ -577,10 +578,10 @@ void Map::spreadLight(enum LightBank bank, */ void Map::lightNeighbors(enum LightBank bank, v3s16 pos, - core::map & modified_blocks) + std::map & modified_blocks) { - core::map from_nodes; - from_nodes.insert(pos, true); + std::set from_nodes; + from_nodes.insert(pos); spreadLight(bank, from_nodes, modified_blocks); } @@ -635,7 +636,7 @@ v3s16 Map::getBrightestNeighbour(enum LightBank bank, v3s16 p) Mud is turned into grass in where the sunlight stops. */ s16 Map::propagateSunlight(v3s16 start, - core::map & modified_blocks) + std::map & modified_blocks) { INodeDefManager *nodemgr = m_gamedef->ndef(); @@ -662,7 +663,7 @@ s16 Map::propagateSunlight(v3s16 start, n.setLight(LIGHTBANK_DAY, LIGHT_SUN, nodemgr); block->setNode(relpos, n); - modified_blocks.insert(blockpos, block); + modified_blocks[blockpos] = block; } else { @@ -674,8 +675,8 @@ s16 Map::propagateSunlight(v3s16 start, } void Map::updateLighting(enum LightBank bank, - core::map & a_blocks, - core::map & modified_blocks) + std::map & a_blocks, + std::map & modified_blocks) { INodeDefManager *nodemgr = m_gamedef->ndef(); @@ -688,22 +689,21 @@ void Map::updateLighting(enum LightBank bank, //bool debug=true; //u32 count_was = modified_blocks.size(); - core::map blocks_to_update; + std::map blocks_to_update; - core::map light_sources; + std::set light_sources; - core::map unlight_from; + std::map unlight_from; int num_bottom_invalid = 0; { //TimeTaker t("first stuff"); - core::map::Iterator i; - i = a_blocks.getIterator(); - for(; i.atEnd() == false; i++) + for(std::map::iterator i = a_blocks.begin(); + i != a_blocks.end(); ++i) { - MapBlock *block = i.getNode()->getValue(); + MapBlock *block = i->second; for(;;) { @@ -713,9 +713,8 @@ void Map::updateLighting(enum LightBank bank, v3s16 pos = block->getPos(); v3s16 posnodes = block->getPosRelative(); - modified_blocks.insert(pos, block); - - blocks_to_update.insert(pos, block); + modified_blocks[pos] = block; + blocks_to_update[pos] = block; /* Clear all light from block @@ -735,7 +734,7 @@ void Map::updateLighting(enum LightBank bank, // If node sources light, add to list u8 source = nodemgr->get(n).light_source; if(source != 0) - light_sources[p + posnodes] = true; + light_sources.insert(p + posnodes); // Collect borders for unlighting if((x==0 || x == MAP_BLOCKSIZE-1 @@ -744,7 +743,7 @@ void Map::updateLighting(enum LightBank bank, && oldlight != 0) { v3s16 p_map = p + posnodes; - unlight_from.insert(p_map, oldlight); + unlight_from[p_map] = oldlight; } } catch(InvalidPositionException &e) @@ -912,8 +911,8 @@ void Map::updateLighting(enum LightBank bank, //m_dout<<"Done ("< & a_blocks, - core::map & modified_blocks) +void Map::updateLighting(std::map & a_blocks, + std::map & modified_blocks) { updateLighting(LIGHTBANK_DAY, a_blocks, modified_blocks); updateLighting(LIGHTBANK_NIGHT, a_blocks, modified_blocks); @@ -921,11 +920,11 @@ void Map::updateLighting(core::map & a_blocks, /* Update information about whether day and night light differ */ - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { - MapBlock *block = i.getNode()->getValue(); + MapBlock *block = i->second; block->expireDayNightDiff(); } } @@ -933,7 +932,8 @@ void Map::updateLighting(core::map & a_blocks, /* */ void Map::addNodeAndUpdate(v3s16 p, MapNode n, - core::map &modified_blocks) + std::map &modified_blocks, + bool remove_metadata) { INodeDefManager *ndef = m_gamedef->ndef(); @@ -949,10 +949,10 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, */ v3s16 toppos = p + v3s16(0,1,0); - v3s16 bottompos = p + v3s16(0,-1,0); + //v3s16 bottompos = p + v3s16(0,-1,0); bool node_under_sunlight = true; - core::map light_sources; + std::set light_sources; /* Collect old node for rollback @@ -994,7 +994,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, v3s16 blockpos = getNodeBlockPos(p); MapBlock * block = getBlockNoCreate(blockpos); assert(block != NULL); - modified_blocks.insert(blockpos, block); + modified_blocks[blockpos] = block; assert(isValidPosition(p)); @@ -1020,8 +1020,9 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, /* Remove node metadata */ - - removeNodeMetadata(p); + if (remove_metadata) { + removeNodeMetadata(p); + } /* Set the node on the map @@ -1078,12 +1079,11 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, /* Update information about whether day and night light differ */ - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { - MapBlock *block = i.getNode()->getValue(); - block->expireDayNightDiff(); + i->second->expireDayNightDiff(); } /* @@ -1132,7 +1132,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, /* */ void Map::removeNodeAndUpdate(v3s16 p, - core::map &modified_blocks) + std::map &modified_blocks) { INodeDefManager *ndef = m_gamedef->ndef(); @@ -1166,7 +1166,7 @@ void Map::removeNodeAndUpdate(v3s16 p, { } - core::map light_sources; + std::set light_sources; enum LightBank banks[] = { @@ -1214,7 +1214,7 @@ void Map::removeNodeAndUpdate(v3s16 p, v3s16 blockpos = getNodeBlockPos(p); MapBlock * block = getBlockNoCreate(blockpos); assert(block != NULL); - modified_blocks.insert(blockpos, block); + modified_blocks[blockpos] = block; /* If the removed node was under sunlight, propagate the @@ -1259,7 +1259,7 @@ void Map::removeNodeAndUpdate(v3s16 p, // Get the brightest neighbour node and propagate light from it v3s16 n2p = getBrightestNeighbour(bank, p); try{ - MapNode n2 = getNode(n2p); + //MapNode n2 = getNode(n2p); lightNeighbors(bank, n2p, modified_blocks); } catch(InvalidPositionException &e) @@ -1270,12 +1270,11 @@ void Map::removeNodeAndUpdate(v3s16 p, /* Update information about whether day and night light differ */ - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd() == false; i++) + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { - MapBlock *block = i.getNode()->getValue(); - block->expireDayNightDiff(); + i->second->expireDayNightDiff(); } /* @@ -1321,24 +1320,24 @@ void Map::removeNodeAndUpdate(v3s16 p, } } -bool Map::addNodeWithEvent(v3s16 p, MapNode n) +bool Map::addNodeWithEvent(v3s16 p, MapNode n, bool remove_metadata) { MapEditEvent event; - event.type = MEET_ADDNODE; + event.type = remove_metadata ? MEET_ADDNODE : MEET_SWAPNODE; event.p = p; event.n = n; bool succeeded = true; try{ - core::map modified_blocks; - addNodeAndUpdate(p, n, modified_blocks); + std::map modified_blocks; + addNodeAndUpdate(p, n, modified_blocks, remove_metadata); // Copy modified_blocks to event - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd()==false; i++) + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { - event.modified_blocks.insert(i.getNode()->getKey(), false); + event.modified_blocks.insert(i->first); } } catch(InvalidPositionException &e){ @@ -1358,15 +1357,15 @@ bool Map::removeNodeWithEvent(v3s16 p) bool succeeded = true; try{ - core::map modified_blocks; + std::map modified_blocks; removeNodeAndUpdate(p, modified_blocks); // Copy modified_blocks to event - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd()==false; i++) + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { - event.modified_blocks.insert(i.getNode()->getKey(), false); + event.modified_blocks.insert(i->first); } } catch(InvalidPositionException &e){ @@ -1439,33 +1438,31 @@ bool Map::getDayNightDiff(v3s16 blockpos) Updates usage timers */ void Map::timerUpdate(float dtime, float unload_timeout, - core::list *unloaded_blocks) + std::list *unloaded_blocks) { bool save_before_unloading = (mapType() == MAPTYPE_SERVER); // Profile modified reasons Profiler modprofiler; - core::list sector_deletion_queue; + std::list sector_deletion_queue; u32 deleted_blocks_count = 0; u32 saved_blocks_count = 0; u32 block_count_all = 0; - core::map::Iterator si; - beginSave(); - si = m_sectors.getIterator(); - for(; si.atEnd() == false; si++) + for(std::map::iterator si = m_sectors.begin(); + si != m_sectors.end(); ++si) { - MapSector *sector = si.getNode()->getValue(); + MapSector *sector = si->second; bool all_blocks_deleted = true; - core::list blocks; + std::list blocks; sector->getBlocks(blocks); - for(core::list::Iterator i = blocks.begin(); - i != blocks.end(); i++) + for(std::list::iterator i = blocks.begin(); + i != blocks.end(); ++i) { MapBlock *block = (*i); @@ -1476,11 +1473,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++; } @@ -1501,7 +1498,7 @@ void Map::timerUpdate(float dtime, float unload_timeout, if(all_blocks_deleted) { - sector_deletion_queue.push_back(si.getNode()->getKey()); + sector_deletion_queue.push_back(si->first); } } endSave(); @@ -1526,17 +1523,22 @@ void Map::timerUpdate(float dtime, float unload_timeout, } } -void Map::deleteSectors(core::list &list) +void Map::unloadUnreferencedBlocks(std::list *unloaded_blocks) +{ + timerUpdate(0.0, -1.0, unloaded_blocks); +} + +void Map::deleteSectors(std::list &list) { - core::list::Iterator j; - for(j=list.begin(); j!=list.end(); j++) + for(std::list::iterator j = list.begin(); + j != list.end(); ++j) { MapSector *sector = m_sectors[*j]; // If sector is in sector cache, remove it from there if(m_sector_cache == sector) m_sector_cache = NULL; // Remove from map and delete - m_sectors.remove(*j); + m_sectors.erase(*j); delete sector; } } @@ -1615,7 +1617,6 @@ struct NodeNeighbor { NeighborType t; v3s16 p; bool l; //can liquid - bool i; //infinity }; void Map::transforming_liquid_add(v3s16 p) { @@ -1626,310 +1627,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(core::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"); - - /*if(initial_size != 0) - infostream<<"transformLiquids(): initial_size="< must_reflow, must_reflow_second; - - // List of MapBlocks that will require a lighting update (due to lava) - core::map lighting_modified_blocks; - - 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 >= 1000) - break; - loopcount++; - /* - Get a queued transforming liquid node - */ - v3s16 p0 = m_transforming_liquid.pop_front(); - u16 total_level = 0; - NodeNeighbor neighbors[7]; // surrounding flowing liquid nodes - s8 liquid_levels[7] = {-1, -1, -1, -1, -1, -1, -1}; // current level of every block - s8 liquid_levels_want[7] = {-1, -1, -1, -1, -1, -1, -1}; // target levels - 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] = 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.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="<ndef(); DSTACK(__FUNCTION_NAME); @@ -1945,12 +1644,14 @@ void Map::transformLiquids(core::map & modified_blocks) UniqueQueue must_reflow; // List of MapBlocks that will require a lighting update (due to lava) - core::map lighting_modified_blocks; + std::map lighting_modified_blocks; + + u16 loop_max = g_settings->getU16("liquid_loop_max"); 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 >= 10000) + if(loopcount >= initial_size || loopcount >= loop_max) break; loopcount++; @@ -2060,6 +1761,7 @@ void Map::transformLiquids(core::map & modified_blocks) content_t new_node_content; s8 new_node_level = -1; s8 max_node_level = -1; + u8 range = rangelim(nodemgr->get(liquid_kind).liquid_range, 0, 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) // or the flowing alternative of the first of the surrounding sources (if it's air), so @@ -2069,6 +1771,8 @@ void Map::transformLiquids(core::map & modified_blocks) // 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; } else { // no surrounding sources, so get the maximum level that can flow into this node for (u16 i = 0; i < num_flows; i++) { @@ -2109,7 +1813,7 @@ void Map::transformLiquids(core::map & modified_blocks) } else new_node_level = max_node_level; - if (new_node_level >= 0) + if (max_node_level >= (LIQUID_LEVEL_MAX+1-range)) new_node_content = liquid_kind; else new_node_content = CONTENT_AIR; @@ -2129,6 +1833,7 @@ void Map::transformLiquids(core::map & modified_blocks) /* update the current node */ + MapNode n00 = n0; //bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK)); if (nodemgr->get(new_node_content).liquid_type == LIQUID_FLOWING) { // set level to last 3 bits, flowing down bit to 4th bit @@ -2165,9 +1870,10 @@ void Map::transformLiquids(core::map & modified_blocks) v3s16 blockpos = getNodeBlockPos(p0); MapBlock *block = getBlockNoCreateNoEx(blockpos); if(block != NULL) { - modified_blocks.insert(blockpos, block); - // If node emits light, MapBlock requires lighting update - if(nodemgr->get(n0).light_source != 0) + modified_blocks[blockpos] = block; + // If new or old node emits light, MapBlock requires lighting update + if(nodemgr->get(n0).light_source != 0 || + nodemgr->get(n00).light_source != 0) lighting_modified_blocks[block->getPos()] = block; } @@ -2198,7 +1904,7 @@ void Map::transformLiquids(core::map & modified_blocks) updateLighting(lighting_modified_blocks, modified_blocks); } -NodeMetadata* Map::getNodeMetadata(v3s16 p) +NodeMetadata *Map::getNodeMetadata(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE; @@ -2208,8 +1914,7 @@ NodeMetadata* Map::getNodeMetadata(v3s16 p) <m_node_metadata.set(p_rel, meta); + return true; } void Map::removeNodeMetadata(v3s16 p) @@ -2261,8 +1966,7 @@ NodeTimer Map::getNodeTimer(v3s16 p) <getParamsFromSettings(g_settings); - if (!m_mgparams) - m_mgparams = new MapgenV6Params(); - - m_seed = m_mgparams->seed; - - if (g_settings->get("fixed_map_seed").empty()) - { - m_seed = (((u64)(myrand() & 0xffff) << 0) - | ((u64)(myrand() & 0xffff) << 16) - | ((u64)(myrand() & 0xffff) << 32) - | ((u64)(myrand() & 0xffff) << 48)); - m_mgparams->seed = m_seed; - } - /* - Experimental and debug stuff + Try to load map; if not found, create a new one. */ - { + // Determine which database backend to use + std::string conf_path = savedir + DIR_DELIM + "world.mt"; + Settings conf; + bool succeeded = conf.readConfigFile(conf_path.c_str()); + if (!succeeded || !conf.exists("backend")) { + // fall back to sqlite3 + dbase = new Database_SQLite3(this, savedir); + conf.set("backend", "sqlite3"); + } else { + std::string backend = conf.get("backend"); + if (backend == "dummy") + dbase = new Database_Dummy(this); + else if (backend == "sqlite3") + dbase = new Database_SQLite3(this, savedir); + #if USE_LEVELDB + else if (backend == "leveldb") + dbase = new Database_LevelDB(this, savedir); + #endif + #if USE_REDIS + else if (backend == "redis") + dbase = new Database_Redis(this, savedir); + #endif + else + throw BaseException("Unknown map backend"); } - /* - Try to load map; if not found, create a new one. - */ - m_savedir = savedir; m_map_saving_enabled = false; @@ -2379,7 +2082,7 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer infostream<<"ServerMap: Successfully loaded map " <<"metadata from "<params.seed; +} + +s16 ServerMap::getWaterLevel() +{ + return m_emerge->params.water_level; +} + bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) { bool enable_mapgen_debug_info = m_emerge->mapgen_debug_info; EMERGE_DBG_OUT("initBlockMake(): " PP(blockpos) " - " PP(blockpos)); - //s16 chunksize = 3; - //v3s16 chunk_offset(-1,-1,-1); - //s16 chunksize = 4; - //v3s16 chunk_offset(-1,-1,-1); - s16 chunksize = 5; - v3s16 chunk_offset(-2,-2,-2); + s16 chunksize = m_emerge->params.chunksize; + s16 coffset = -chunksize / 2; + v3s16 chunk_offset(coffset, coffset, coffset); v3s16 blockpos_div = getContainerPos(blockpos - chunk_offset, chunksize); v3s16 blockpos_min = blockpos_div * chunksize; v3s16 blockpos_max = blockpos_div * chunksize + v3s16(1,1,1)*(chunksize-1); blockpos_min += chunk_offset; blockpos_max += chunk_offset; - //v3s16 extra_borders(1,1,1); v3s16 extra_borders(1,1,1); // Do nothing if not inside limits (+-1 because of neighbors) @@ -2480,7 +2184,7 @@ bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) blockpos_over_limit(blockpos_max + extra_borders)) return false; - data->seed = m_seed; + data->seed = m_emerge->params.seed; data->blockpos_min = blockpos_min; data->blockpos_max = blockpos_max; data->blockpos_requested = blockpos; @@ -2501,6 +2205,7 @@ bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) // Sector metadata is loaded from disk if not already loaded. ServerMapSector *sector = createSector(sectorpos); assert(sector); + (void) sector; for(s16 y=blockpos_min.Y-extra_borders.Y; y<=blockpos_max.Y+extra_borders.Y; y++) @@ -2548,9 +2253,9 @@ bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) // Add the area { //TimeTaker timer("initBlockMake() initialEmerge"); - data->vmanip->initialEmerge(bigarea_blocks_min, bigarea_blocks_max); + 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++) { @@ -2570,8 +2275,8 @@ bool ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos) return true; } -MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, - core::map &changed_blocks) +void ServerMap::finishBlockMake(BlockMakeData *data, + std::map &changed_blocks) { v3s16 blockpos_min = data->blockpos_min; v3s16 blockpos_max = data->blockpos_max; @@ -2607,7 +2312,7 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, { // 70ms @cs=8 //TimeTaker timer("finishBlockMake() blitBackAll"); - data->vmanip->blitBackAll(&changed_blocks); + data->vmanip->blitBackAll(&changed_blocks, false); } EMERGE_DBG_OUT("finishBlockMake: changed_blocks.size()=" << changed_blocks.size()); @@ -2664,7 +2369,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 @@ -2676,11 +2383,12 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, /* Go through changed blocks */ - for(core::map::Iterator i = changed_blocks.getIterator(); - i.atEnd() == false; i++) + for(std::map::iterator i = changed_blocks.begin(); + i != changed_blocks.end(); ++i) { - MapBlock *block = i.getNode()->getValue(); - assert(block); + MapBlock *block = i->second; + if (!block) + continue; /* Update day/night difference cache of the MapBlocks */ @@ -2701,7 +2409,8 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, { v3s16 p(x, y, z); MapBlock *block = getBlockNoCreateNoEx(p); - assert(block); + if (!block) + continue; block->setGenerated(true); } @@ -2714,6 +2423,8 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, /*infostream<<"finishBlockMake() done for ("< &modified_blocks + std::map &modified_blocks ) { DSTACKF("%s: p=(%d,%d,%d)", __FUNCTION_NAME, p.X, p.Y, p.Z); @@ -3006,9 +2714,11 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank) return block; } - /*if(allow_generate) + +#if 0 + if(allow_generate) { - core::map modified_blocks; + std::map modified_blocks; MapBlock *block = generateBlock(p, modified_blocks); if(block) { @@ -3017,11 +2727,11 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank) event.p = p; // Copy modified_blocks to event - for(core::map::Iterator - i = modified_blocks.getIterator(); - i.atEnd()==false; i++) + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { - event.modified_blocks.insert(i.getNode()->getKey(), false); + event.modified_blocks.insert(i->first); } // Queue event @@ -3029,11 +2739,24 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank) return block; } - }*/ + } +#endif return NULL; } +MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d) +{ + MapBlock *block = getBlockNoCreateNoEx(p3d); + if (block == NULL) + m_emerge->enqueueBlockEmerge(PEER_ID_INEXISTENT, p3d, false); + + return block; +} + +void ServerMap::prepareBlock(MapBlock *block) { +} + s16 ServerMap::findGroundLevel(v2s16 p2d) { #if 0 @@ -3078,81 +2801,12 @@ plan_b: //return (s16)level; } -void ServerMap::createDatabase() { - int e; - assert(m_database); - e = sqlite3_exec(m_database, - "CREATE TABLE IF NOT EXISTS `blocks` (" - "`pos` INT NOT NULL PRIMARY KEY," - "`data` BLOB" - ");" - , NULL, NULL, NULL); - if(e == SQLITE_ABORT) - throw FileNotGoodException("Could not create database structure"); - else - infostream<<"ServerMap: Database structure was created"; -} - -void ServerMap::verifyDatabase() { - if(m_database) - return; - - { - std::string dbp = m_savedir + DIR_DELIM + "map.sqlite"; - bool needs_create = false; - int d; - - /* - Open the database connection - */ - - createDirs(m_savedir); - - if(!fs::PathExists(dbp)) - needs_create = true; - - d = sqlite3_open_v2(dbp.c_str(), &m_database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); - if(d != SQLITE_OK) { - infostream<<"WARNING: Database failed to open: "<Initialized() && !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite")) // ? return true; return false; } -sqlite3_int64 ServerMap::getBlockAsInteger(const v3s16 pos) { - return (sqlite3_int64)pos.Z*16777216 + - (sqlite3_int64)pos.Y*4096 + (sqlite3_int64)pos.X; -} - void ServerMap::createDirs(std::string path) { if(fs::CreateAllDirs(path) == false) @@ -3182,24 +2836,26 @@ std::string ServerMap::getSectorDir(v2s16 pos, int layout) return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc; default: assert(false); + return ""; } } v2s16 ServerMap::getSectorPos(std::string dirname) { - unsigned int x, y; + unsigned int x = 0, y = 0; int r; - size_t spos = dirname.rfind(DIR_DELIM_C) + 1; - assert(spos != std::string::npos); - if(dirname.size() - spos == 8) + std::string component; + fs::RemoveLastPathComponent(dirname, &component, 1); + if(component.size() == 8) { // Old layout - r = sscanf(dirname.substr(spos).c_str(), "%4x%4x", &x, &y); + r = sscanf(component.c_str(), "%4x%4x", &x, &y); } - else if(dirname.size() - spos == 3) + else if(component.size() == 3) { // New layout - r = sscanf(dirname.substr(spos-4).c_str(), "%3x" DIR_DELIM "%3x", &x, &y); + fs::RemoveLastPathComponent(dirname, &component, 2); + r = sscanf(component.c_str(), "%3x" DIR_DELIM "%3x", &x, &y); // Sign-extend the 12 bit values up to 16 bits... if(x&0x800) x|=0xF000; if(y&0x800) y|=0xF000; @@ -3262,10 +2918,10 @@ void ServerMap::save(ModifiedState save_level) // Don't do anything with sqlite unless something is really saved bool save_started = false; - core::map::Iterator i = m_sectors.getIterator(); - for(; i.atEnd() == false; i++) + for(std::map::iterator i = m_sectors.begin(); + i != m_sectors.end(); ++i) { - ServerMapSector *sector = (ServerMapSector*)i.getNode()->getValue(); + ServerMapSector *sector = (ServerMapSector*)i->second; assert(sector->getId() == MAPSECTOR_SERVER); if(sector->differs_from_disk || save_level == MOD_STATE_CLEAN) @@ -3273,11 +2929,11 @@ void ServerMap::save(ModifiedState save_level) saveSectorMeta(sector); sector_meta_count++; } - core::list blocks; + std::list blocks; sector->getBlocks(blocks); - core::list::Iterator j; - for(j=blocks.begin(); j!=blocks.end(); j++) + for(std::list::iterator j = blocks.begin(); + j != blocks.end(); ++j) { MapBlock *block = *j; @@ -3324,47 +2980,30 @@ void ServerMap::save(ModifiedState save_level) } } -static s32 unsignedToSigned(s32 i, s32 max_positive) -{ - if(i < max_positive) - return i; - else - return i - 2*max_positive; -} - -// modulo of a negative number does not work consistently in C -static sqlite3_int64 pythonmodulo(sqlite3_int64 i, sqlite3_int64 mod) -{ - if(i >= 0) - return i % mod; - return mod - ((-i) % mod); -} - -v3s16 ServerMap::getIntegerAsBlock(sqlite3_int64 i) -{ - s32 x = unsignedToSigned(pythonmodulo(i, 4096), 2048); - i = (i - x) / 4096; - s32 y = unsignedToSigned(pythonmodulo(i, 4096), 2048); - i = (i - y) / 4096; - s32 z = unsignedToSigned(pythonmodulo(i, 4096), 2048); - return v3s16(x,y,z); -} - -void ServerMap::listAllLoadableBlocks(core::list &dst) +void ServerMap::listAllLoadableBlocks(std::list &dst) { if(loadFromFolders()){ errorstream<<"Map::listAllLoadableBlocks(): Result will be missing " <<"all blocks that are stored in flat files"<listAllLoadableBlocks(dst); +} +void ServerMap::listAllLoadedBlocks(std::list &dst) +{ + for(std::map::iterator si = m_sectors.begin(); + si != m_sectors.end(); ++si) { - verifyDatabase(); + MapSector *sector = si->second; - while(sqlite3_step(m_database_list) == SQLITE_ROW) + std::list blocks; + sector->getBlocks(blocks); + + for(std::list::iterator i = blocks.begin(); + i != blocks.end(); ++i) { - sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0); - v3s16 p = getIntegerAsBlock(block_i); - //dstream<<"block_i="<setParamsToSettings(¶ms); - params.writeLines(os); + m_emerge->saveParamsToSettings(¶ms); + params.writeLines(ss); - os<<"[end_of_params]\n"; + ss<<"[end_of_params]\n"; + + if(!fs::safeWriteToFile(fullpath, ss.str())) + { + infostream<<"ERROR: ServerMap::saveMapMeta(): " + <<"could not write "<getParamsFromSettings(¶ms); - if (mgparams) { - if (m_mgparams) - delete m_mgparams; - m_mgparams = mgparams; - m_seed = mgparams->seed; - } else { - if (params.exists("seed")) { - m_seed = params.getU64("seed"); - m_mgparams->seed = m_seed; - } - } + m_emerge->loadParamsFromSettings(¶ms); - verbosestream<<"ServerMap::loadMapMeta(): "<<"seed="<serialize(ss, version); - sector->serialize(o, version); + if(!fs::safeWriteToFile(fullpath, ss.str())) + throw FileNotGoodException("Cannot write sector metafile"); sector->differs_from_disk = false; } @@ -3487,7 +3118,7 @@ MapSector* ServerMap::loadSectorMeta(std::string sectordir, bool save_after_load <<" Continuing with a sector with no metadata." <beginSave(); } -void ServerMap::endSave() { - verifyDatabase(); - if(sqlite3_exec(m_database, "COMMIT;", NULL, NULL, NULL) != SQLITE_OK) - infostream<<"WARNING: endSave() failed, map might not have saved."; +void ServerMap::endSave() +{ + dbase->endSave(); } -void ServerMap::saveBlock(MapBlock *block) +bool ServerMap::saveBlock(MapBlock *block) { - DSTACK(__FUNCTION_NAME); - /* - Dummy blocks are not written - */ - if(block->isDummy()) - { - /*v3s16 p = block->getPos(); - infostream<<"ServerMap::saveBlock(): WARNING: Not writing dummy block " - <<"("<getPos(); + // Dummy blocks are not written + if (block->isDummy()) { + errorstream << "WARNING: saveBlock: Not writing dummy block " + << PP(p3d) << std::endl; + return true; + } -#if 0 - v2s16 p2d(p3d.X, p3d.Z); - std::string sectordir = getSectorDir(p2d); - - createDirs(sectordir); + // Format used for writing + u8 version = SER_FMT_VER_HIGHEST_WRITE; - std::string fullpath = sectordir+DIR_DELIM+getBlockFilename(p3d); - std::ofstream o(fullpath.c_str(), std::ios_base::binary); - if(o.good() == false) - throw FileNotGoodException("Cannot open block data"); -#endif /* [0] u8 serialization version [1] data */ - - verifyDatabase(); - std::ostringstream o(std::ios_base::binary); - - o.write((char*)&version, 1); - - // Write basic data + o.write((char*) &version, 1); block->serialize(o, version, true); - // Write block to database - - std::string tmp = o.str(); - const char *bytes = tmp.c_str(); - - bool success = true; - if(sqlite3_bind_int64(m_database_write, 1, getBlockAsInteger(p3d)) != SQLITE_OK) { - infostream<<"WARNING: Block position failed to bind: "<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) @@ -3757,7 +3350,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto Save blocks loaded in old format in new format */ - if(version < SER_FMT_VER_HIGHEST || save_after_load) + if(version < SER_FMT_VER_HIGHEST_WRITE || save_after_load) { saveBlock(block); @@ -3776,7 +3369,7 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto <<" (SerializationError). " <<"what()="<loadBlock(blockpos); + 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. // 1 - original sectors/xxxxzzzz/ @@ -3952,167 +3521,10 @@ void ServerMap::PrintInfo(std::ostream &out) out<<"ServerMap: "; } -/* - MapVoxelManipulator -*/ - -MapVoxelManipulator::MapVoxelManipulator(Map *map) -{ - m_map = map; -} - -MapVoxelManipulator::~MapVoxelManipulator() -{ - /*infostream<<"MapVoxelManipulator: blocks: "<::Node *n; - n = m_loaded_blocks.find(p); - if(n != NULL) - 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.insert(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_create_area(false), + m_map(map) { } @@ -4120,14 +3532,8 @@ 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) +void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min, + v3s16 blockpos_max, bool load_if_inexistent) { TimeTaker timer1("initialEmerge", &emerge_time); @@ -4156,9 +3562,9 @@ void ManualMapVoxelManipulator::initialEmerge( u8 flags = 0; MapBlock *block; v3s16 p(x,y,z); - core::map::Node *n; + std::map::iterator n; n = m_loaded_blocks.find(p); - if(n != NULL) + if(n != m_loaded_blocks.end()) continue; bool block_data_inexistent = false; @@ -4179,18 +3585,28 @@ void ManualMapVoxelManipulator::initialEmerge( if(block_data_inexistent) { - 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 - 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); + + if (load_if_inexistent) { + ServerMap *svrmap = (ServerMap *)m_map; + block = svrmap->emergeBlock(p, false); + if (block == NULL) + block = svrmap->createBlock(p); + else + 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_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_NO_DATA, MAP_BLOCKSIZE); + } } } /*else if (block->getNode(0, 0, 0).getContent() == CONTENT_IGNORE) @@ -4199,12 +3615,13 @@ void ManualMapVoxelManipulator::initialEmerge( flags |= VMANIP_BLOCK_CONTAINS_CIGNORE; }*/ - m_loaded_blocks.insert(p, flags); + m_loaded_blocks[p] = flags; } } void ManualMapVoxelManipulator::blitBackAll( - core::map * modified_blocks) + std::map *modified_blocks, + bool overwrite_generated) { if(m_area.getExtent() == v3s16(0,0,0)) return; @@ -4212,37 +3629,21 @@ void ManualMapVoxelManipulator::blitBackAll( /* Copy data of all blocks */ - for(core::map::Iterator - i = m_loaded_blocks.getIterator(); - i.atEnd() == false; i++) + for(std::map::iterator + i = m_loaded_blocks.begin(); + i != m_loaded_blocks.end(); ++i) { - v3s16 p = i.getNode()->getKey(); - u8 flags = i.getNode()->getValue(); - - bool existed = !(flags & VMANIP_BLOCK_DATA_INEXIST); - if(existed == false) - { - // The Great Bug was found using this - /*infostream<<"ManualMapVoxelManipulator::blitBackAll: " - <<"Inexistent ("<first; MapBlock *block = m_map->getBlockNoCreateNoEx(p); - if(block == NULL) - { - infostream<<"WARNING: "<<__FUNCTION_NAME - <<": got NULL block " - <<"("<second & VMANIP_BLOCK_DATA_INEXIST); + if ((existed == false) || (block == NULL) || + (overwrite_generated == false && block->isGenerated() == true)) continue; - } block->copyFrom(*this); - + if(modified_blocks) - modified_blocks->insert(p, block); + (*modified_blocks)[p] = block; } }