X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmap.cpp;h=4b0d2e2d8e846d8e5ee664ece1e245a8e4b4faaa;hb=5da6896d51ae3ee5140dc1041eff44a616751231;hp=ea82194b85ccca4211797f6de18d51d08d256674;hpb=1d248cce30105a66a411d327b5400f37a35db3b9;p=dragonfireclient.git diff --git a/src/map.cpp b/src/map.cpp index ea82194b8..4b0d2e2d8 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1,6 +1,6 @@ /* -Minetest-c55 -Copyright (C) 2010-2011 celeron55, Perttu Ahola +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -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,8 +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 "mg_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<<")" @@ -63,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() @@ -72,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); } } @@ -110,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; @@ -177,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) @@ -206,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 "< & 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(); @@ -255,9 +281,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 @@ -267,9 +291,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 @@ -291,12 +316,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++) @@ -307,88 +332,83 @@ void Map::unspreadLight(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 + 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.insert(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) == NULL) + 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.insert(blockpos, block); - } - block_checked_in_modified = true; + infostream<<"Removed from light_sources"< & 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); } @@ -421,8 +441,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(); @@ -440,9 +460,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 @@ -452,16 +470,14 @@ 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=("<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 @@ -495,69 +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) { - lighted_nodes.insert(n2pos, true); - //lighted_nodes.push_back(n2pos); + 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, true); - //lighted_nodes.push_back(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) == NULL) - { - modified_blocks.insert(blockpos, block); - } - block_checked_in_modified = true; + modified_blocks[blockpos] = block; } - } - catch(InvalidPositionException &e) - { - continue; + block_checked_in_modified = true; } } } @@ -576,10 +584,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); } @@ -605,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; @@ -634,7 +640,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(); @@ -654,14 +660,17 @@ 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) { n.setLight(LIGHTBANK_DAY, LIGHT_SUN, nodemgr); block->setNode(relpos, n); - modified_blocks.insert(blockpos, block); + modified_blocks[blockpos] = block; } else { @@ -673,8 +682,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(); @@ -687,22 +696,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(;;) { @@ -712,9 +720,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 @@ -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[p + posnodes] = true; - - // 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.insert(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) @@ -911,8 +916,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); @@ -920,11 +925,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(); } } @@ -932,7 +937,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(); @@ -948,10 +954,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 @@ -964,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 @@ -987,13 +990,13 @@ 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); MapBlock * block = getBlockNoCreate(blockpos); assert(block != NULL); - modified_blocks.insert(blockpos, block); + modified_blocks[blockpos] = block; assert(isValidPosition(p)); @@ -1019,8 +1022,9 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, /* Remove node metadata */ - - removeNodeMetadata(p); + if (remove_metadata) { + removeNodeMetadata(p); + } /* Set the node on the map @@ -1043,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) { @@ -1077,12 +1078,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(); } /* @@ -1111,27 +1111,21 @@ 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) - { - } } } /* */ void Map::removeNodeAndUpdate(v3s16 p, - core::map &modified_blocks) + std::map &modified_blocks) { INodeDefManager *ndef = m_gamedef->ndef(); @@ -1155,17 +1149,13 @@ 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; - core::map light_sources; + std::set light_sources; enum LightBank banks[] = { @@ -1180,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); } @@ -1213,7 +1203,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 @@ -1240,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); } } @@ -1258,7 +1246,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) @@ -1269,12 +1257,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(); } /* @@ -1303,41 +1290,36 @@ 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) - { - } } } -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){ @@ -1357,15 +1339,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){ @@ -1438,33 +1420,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); @@ -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++; } @@ -1500,7 +1480,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(); @@ -1525,17 +1505,22 @@ void Map::timerUpdate(float dtime, float unload_timeout, } } -void Map::deleteSectors(core::list &list) +void Map::unloadUnreferencedBlocks(std::list *unloaded_blocks) { - core::list::Iterator j; - for(j=list.begin(); j!=list.end(); j++) + timerUpdate(0.0, -1.0, unloaded_blocks); +} + +void Map::deleteSectors(std::list &list) +{ + 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; } } @@ -1613,9 +1598,18 @@ struct NodeNeighbor { MapNode n; NeighborType t; v3s16 p; + bool l; //can liquid }; -void Map::transformLiquids(core::map & modified_blocks) +void Map::transforming_liquid_add(v3s16 p) { + m_transforming_liquid.push_back(p); +} + +s32 Map::transforming_liquid_size() { + return m_transforming_liquid.size(); +} + +void Map::transformLiquids(std::map & modified_blocks) { INodeDefManager *nodemgr = m_gamedef->ndef(); @@ -1632,12 +1626,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++; @@ -1747,6 +1743,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 @@ -1756,6 +1753,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++) { @@ -1796,7 +1795,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; @@ -1816,6 +1815,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 @@ -1852,9 +1852,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; } @@ -1885,7 +1886,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; @@ -1895,8 +1896,7 @@ NodeMetadata* Map::getNodeMetadata(v3s16 p) <m_node_metadata.set(p_rel, meta); + return true; } void Map::removeNodeMetadata(v3s16 p) @@ -1948,8 +1948,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; @@ -2066,7 +2064,7 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer infostream<<"ServerMap: Successfully loaded map " <<"metadata from "<getBool("enable_mapgen_debug_info"); - if(enable_mapgen_debug_info) - infostream<<"initBlockMake(): " - <<"("<params.seed; +} - //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 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 = 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) if(blockpos_over_limit(blockpos_min - extra_borders) || blockpos_over_limit(blockpos_max + extra_borders)) - { - data->no_op = true; - return; - } + return false; - data->no_op = 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; @@ -2196,6 +2187,7 @@ void 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++) @@ -2243,14 +2235,30 @@ void 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++) { + for (s16 x = blockpos_min.X; x <= blockpos_max.X; x++) { + core::map::Node *n; + n = data->vmanip->m_loaded_blocks.find(v3s16(x, y, z)); + if (n == NULL) + continue; + u8 flags = n->getValue(); + flags &= ~VMANIP_BLOCK_CONTAINS_CIGNORE; + n->setValue(flags); + } + } + }*/ + // Data is ready now. + 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; @@ -2261,13 +2269,7 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, v3s16 extra_borders(1,1,1); - if(data->no_op) - { - //infostream<<"finishBlockMake(): no-op"<getBool("enable_mapgen_debug_info"); + bool enable_mapgen_debug_info = m_emerge->mapgen_debug_info; /*infostream<<"Resulting vmanip:"<vmanip.print(infostream);*/ @@ -2295,9 +2297,7 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data, data->vmanip->blitBackAll(&changed_blocks); } - if(enable_mapgen_debug_info) - infostream<<"finishBlockMake: changed_blocks.size()=" - < &modified_blocks + std::map &modified_blocks ) { DSTACKF("%s: p=(%d,%d,%d)", __FUNCTION_NAME, p.X, p.Y, p.Z); @@ -2693,9 +2696,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) { @@ -2704,11 +2709,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 @@ -2716,11 +2721,46 @@ 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) { +} + +// 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) { #if 0 @@ -2765,81 +2805,12 @@ s16 ServerMap::findGroundLevel(v2s16 p2d) //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) @@ -2869,24 +2840,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; @@ -2949,10 +2922,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) @@ -2960,17 +2933,17 @@ 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; block_count_all++; - if(block->getModified() >= save_level) + if(block->getModified() >= (u32)save_level) { // Lazy beginSave() if(!save_started){ @@ -3011,47 +2984,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="<params->mg_name); - params.setU64("seed", m_emerge->params->seed); - params.setS16("water_level", m_emerge->params->water_level); - params.setS16("chunksize", m_emerge->params->chunksize); - params.setS32("mg_flags", m_emerge->params->flags); + m_emerge->saveParamsToSettings(¶ms); + params.writeLines(ss); - m_emerge->params->writeParams(¶ms); + ss<<"[end_of_params]\n"; - params.writeLines(os); - - os<<"[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; } @@ -3181,7 +3110,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) @@ -3451,7 +3342,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); @@ -3470,7 +3361,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/ @@ -3646,158 +3513,11 @@ 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) - { - 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); - } - } - - m_loaded_blocks.insert(p, !block_data_inexistent); - } - - //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) { } @@ -3805,14 +3525,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); @@ -3838,10 +3552,12 @@ void ManualMapVoxelManipulator::initialEmerge( for(s32 y=p_min.Y; y<=p_max.Y; y++) for(s32 x=p_min.X; x<=p_max.X; x++) { + 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; @@ -3849,7 +3565,7 @@ void ManualMapVoxelManipulator::initialEmerge( { TimeTaker timer1("emerge load", &emerge_load_time); - MapBlock *block = m_map->getBlockNoCreate(p); + block = m_map->getBlockNoCreate(p); if(block->isDummy()) block_data_inexistent = true; else @@ -3862,25 +3578,45 @@ void ManualMapVoxelManipulator::initialEmerge( if(block_data_inexistent) { - /* - 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) + { + // Mark that block was loaded as blank + flags |= VMANIP_BLOCK_CONTAINS_CIGNORE; + }*/ - m_loaded_blocks.insert(p, !block_data_inexistent); + m_loaded_blocks[p] = flags; } + + m_is_dirty = false; } void ManualMapVoxelManipulator::blitBackAll( - core::map * modified_blocks) + std::map *modified_blocks, + bool overwrite_generated) { if(m_area.getExtent() == v3s16(0,0,0)) return; @@ -3888,34 +3624,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(); - bool existed = i.getNode()->getValue(); - 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; } }