#endif
#include "settings.h"
#include "log.h"
+#include "profiler.h"
+
+#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
/*
SQLite format specification:
v3s16 blockpos = getNodeBlockPos(p);
v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
MapBlock *block = getBlockNoCreateNoEx(blockpos);
- if(block == NULL)
+ if(!block){
+ infostream<<"Map::getNodeMetadata(): Need to emerge "
+ <<PP(blockpos)<<std::endl;
+ block = emergeBlock(blockpos, false);
+ }
+ if(!block)
{
- infostream<<"WARNING: Map::setNodeMetadata(): Block not found"
+ infostream<<"WARNING: Map::getNodeMetadata(): Block not found"
<<std::endl;
return NULL;
}
v3s16 blockpos = getNodeBlockPos(p);
v3s16 p_rel = p - blockpos*MAP_BLOCKSIZE;
MapBlock *block = getBlockNoCreateNoEx(blockpos);
- if(block == NULL)
+ if(!block){
+ infostream<<"Map::setNodeMetadata(): Need to emerge "
+ <<PP(blockpos)<<std::endl;
+ block = emergeBlock(blockpos, false);
+ }
+ if(!block)
{
infostream<<"WARNING: Map::setNodeMetadata(): Block not found"
<<std::endl;
return NULL;
}
-#if 0
- /*
- Do not generate over-limit
- */
- if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
- || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
- || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
- || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
- || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
- || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
- throw InvalidPositionException("emergeBlock(): pos. over limit");
-
- v2s16 p2d(p.X, p.Z);
- s16 block_y = p.Y;
- /*
- This will create or load a sector if not found in memory.
- If block exists on disk, it will be loaded.
- */
- ServerMapSector *sector;
- try{
- sector = createSector(p2d);
- //sector = emergeSector(p2d, changed_blocks);
- }
- catch(InvalidPositionException &e)
- {
- infostream<<"emergeBlock: createSector() failed: "
- <<e.what()<<std::endl;
- infostream<<"Path to failed sector: "<<getSectorDir(p2d)
- <<std::endl
- <<"You could try to delete it."<<std::endl;
- throw e;
- }
- catch(VersionMismatchException &e)
- {
- infostream<<"emergeBlock: createSector() failed: "
- <<e.what()<<std::endl;
- infostream<<"Path to failed sector: "<<getSectorDir(p2d)
- <<std::endl
- <<"You could try to delete it."<<std::endl;
- throw e;
- }
-
- /*
- Try to get a block from the sector
- */
-
- bool does_not_exist = false;
- bool lighting_expired = false;
- MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
-
- // If not found, try loading from disk
- if(block == NULL)
- {
- block = loadBlock(p);
- }
-
- // Handle result
- if(block == NULL)
- {
- does_not_exist = true;
- }
- else if(block->isDummy() == true)
- {
- does_not_exist = true;
- }
- else if(block->getLightingExpired())
- {
- lighting_expired = true;
- }
- else
- {
- // Valid block
- //infostream<<"emergeBlock(): Returning already valid block"<<std::endl;
- return block;
- }
-
- /*
- If block was not found on disk and not going to generate a
- new one, make sure there is a dummy block in place.
- */
- if(only_from_disk && (does_not_exist || lighting_expired))
- {
- //infostream<<"emergeBlock(): Was not on disk but not generating"<<std::endl;
-
- if(block == NULL)
- {
- // Create dummy block
- block = new MapBlock(this, p, true);
-
- // Add block to sector
- sector->insertBlock(block);
- }
- // Done.
- return block;
- }
-
- //infostream<<"Not found on disk, generating."<<std::endl;
- // 0ms
- //TimeTaker("emergeBlock() generate");
-
- //infostream<<"emergeBlock(): Didn't find valid block -> making one"<<std::endl;
-
- /*
- If the block doesn't exist, generate the block.
- */
- if(does_not_exist)
- {
- block = generateBlock(p, block, sector, changed_blocks,
- lighting_invalidated_blocks);
- }
-
- if(lighting_expired)
- {
- lighting_invalidated_blocks.insert(p, block);
- }
-
-#if 0
- /*
- Initially update sunlight
- */
- {
- core::map<v3s16, bool> light_sources;
- bool black_air_left = false;
- bool bottom_invalid =
- block->propagateSunlight(light_sources, true,
- &black_air_left);
-
- // If sunlight didn't reach everywhere and part of block is
- // above ground, lighting has to be properly updated
- //if(black_air_left && some_part_underground)
- if(black_air_left)
- {
- lighting_invalidated_blocks[block->getPos()] = block;
- }
-
- if(bottom_invalid)
- {
- lighting_invalidated_blocks[block->getPos()] = block;
- }
- }
-#endif
-
- return block;
-}
-#endif
-
s16 ServerMap::findGroundLevel(v2s16 p2d)
{
#if 0
return;
{
- std::string dbp = m_savedir + "/map.sqlite";
+ std::string dbp = m_savedir + DIR_DELIM + "map.sqlite";
bool needs_create = false;
int d;
throw FileNotGoodException("Cannot prepare write statement");
}
+ d = sqlite3_prepare(m_database, "SELECT `pos` FROM `blocks`", -1, &m_database_list, NULL);
+ if(d != SQLITE_OK) {
+ infostream<<"WARNING: Database list statment failed to prepare: "<<sqlite3_errmsg(m_database)<<std::endl;
+ throw FileNotGoodException("Cannot prepare read statement");
+ }
+
infostream<<"Server: Database opened"<<std::endl;
}
}
bool ServerMap::loadFromFolders() {
- if(!m_database && !fs::PathExists(m_savedir + "/map.sqlite"))
+ if(!m_database && !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite"))
return true;
return false;
}
(unsigned int)pos.X&0xffff,
(unsigned int)pos.Y&0xffff);
- return m_savedir + "/sectors/" + cc;
+ return m_savedir + DIR_DELIM + "sectors" + DIR_DELIM + cc;
case 2:
- snprintf(cc, 9, "%.3x/%.3x",
+ snprintf(cc, 9, "%.3x" DIR_DELIM "%.3x",
(unsigned int)pos.X&0xfff,
(unsigned int)pos.Y&0xfff);
- return m_savedir + "/sectors2/" + cc;
+ return m_savedir + DIR_DELIM + "sectors2" + DIR_DELIM + cc;
default:
assert(false);
}
{
unsigned int x, y;
int r;
- size_t spos = dirname.rfind('/') + 1;
+ size_t spos = dirname.rfind(DIR_DELIM_C) + 1;
assert(spos != std::string::npos);
if(dirname.size() - spos == 8)
{
else if(dirname.size() - spos == 3)
{
// New layout
- r = sscanf(dirname.substr(spos-4).c_str(), "%3x/%3x", &x, &y);
+ r = sscanf(dirname.substr(spos-4).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;
}
}
+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<v3s16> &dst)
+{
+ if(loadFromFolders()){
+ errorstream<<"Map::listAllLoadableBlocks(): Result will be missing "
+ <<"all blocks that are stored in flat files"<<std::endl;
+ }
+
+ {
+ verifyDatabase();
+
+ while(sqlite3_step(m_database_list) == SQLITE_ROW)
+ {
+ sqlite3_int64 block_i = sqlite3_column_int64(m_database_list, 0);
+ v3s16 p = getIntegerAsBlock(block_i);
+ //dstream<<"block_i="<<block_i<<" p="<<PP(p)<<std::endl;
+ dst.push_back(p);
+ }
+ }
+}
+
void ServerMap::saveMapMeta()
{
DSTACK(__FUNCTION_NAME);
createDirs(m_savedir);
- std::string fullpath = m_savedir + "/map_meta.txt";
+ std::string fullpath = m_savedir + DIR_DELIM + "map_meta.txt";
std::ofstream os(fullpath.c_str(), std::ios_base::binary);
if(os.good() == false)
{
infostream<<"ServerMap::loadMapMeta(): Loading map metadata"
<<std::endl;
- std::string fullpath = m_savedir + "/map_meta.txt";
+ std::string fullpath = m_savedir + DIR_DELIM + "map_meta.txt";
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
if(is.good() == false)
{
std::string dir = getSectorDir(pos);
createDirs(dir);
- std::string fullpath = dir + "/meta";
+ std::string fullpath = dir + DIR_DELIM + "meta";
std::ofstream o(fullpath.c_str(), std::ios_base::binary);
if(o.good() == false)
throw FileNotGoodException("Cannot open sector metafile");
ServerMapSector *sector = NULL;
- std::string fullpath = sectordir + "/meta";
+ std::string fullpath = sectordir + DIR_DELIM + "meta";
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
if(is.good() == false)
{
createDirs(sectordir);
- std::string fullpath = sectordir+"/"+getBlockFilename(p3d);
+ 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");
{
DSTACK(__FUNCTION_NAME);
- std::string fullpath = sectordir+"/"+blockfile;
+ std::string fullpath = sectordir+DIR_DELIM+blockfile;
try{
std::ifstream is(fullpath.c_str(), std::ios_base::binary);
*/
std::string blockfilename = getBlockFilename(blockpos);
- if(fs::PathExists(sectordir+"/"+blockfilename) == false)
+ if(fs::PathExists(sectordir+DIR_DELIM+blockfilename) == false)
return NULL;
/*
p_nodes_max.Z / MAP_BLOCKSIZE + 1);
u32 vertex_count = 0;
+ u32 meshbuffer_count = 0;
// For limiting number of mesh updates per frame
u32 mesh_update_count = 0;
sector_blocks_drawn++;
u32 c = mesh->getMeshBufferCount();
+ meshbuffer_count += c;
for(u32 i=0; i<c; i++)
{
}
}
+ if(pass == scene::ESNRP_SOLID){
+ g_profiler->avg("CM: blocks drawn on solid pass", blocks_drawn);
+ g_profiler->avg("CM: vertices drawn on solid pass", vertex_count);
+ if(blocks_drawn != 0)
+ g_profiler->avg("CM: solid meshbuffers per block",
+ (float)meshbuffer_count / (float)blocks_drawn);
+ } else {
+ g_profiler->avg("CM: blocks drawn on transparent pass", blocks_drawn);
+ g_profiler->avg("CM: vertices drawn on transparent pass", vertex_count);
+ }
+
m_control.blocks_drawn = blocks_drawn;
m_control.blocks_would_have_drawn = blocks_would_have_drawn;