X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmap.cpp;h=6d53351efeed2b1bc15ae8f773823063fff4686a;hb=e8faa2afb7106ca916f4207766ec106c81bb98ce;hp=a1389fd104eee0f9bb4491b4e6cb651fbbb1fe33;hpb=e9ceead81dd989936e2de3ff7cd7496aecd09d39;p=dragonfireclient.git diff --git a/src/map.cpp b/src/map.cpp index a1389fd10..6d53351ef 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -62,8 +62,7 @@ with this program; if not, write to the Free Software Foundation, Inc., Map */ -Map::Map(std::ostream &dout, IGameDef *gamedef): - m_dout(dout), +Map::Map(IGameDef *gamedef): m_gamedef(gamedef), m_nodedef(gamedef->ndef()) { @@ -89,14 +88,14 @@ void Map::removeEventReceiver(MapEventReceiver *event_receiver) m_event_receivers.erase(event_receiver); } -void Map::dispatchEvent(MapEditEvent *event) +void Map::dispatchEvent(const MapEditEvent &event) { for (MapEventReceiver *event_receiver : m_event_receivers) { event_receiver->onMapEditEvent(event); } } -MapSector * Map::getSectorNoGenerateNoExNoLock(v2s16 p) +MapSector * Map::getSectorNoGenerateNoLock(v2s16 p) { if(m_sector_cache != NULL && p == m_sector_cache_p){ MapSector * sector = m_sector_cache; @@ -117,24 +116,15 @@ MapSector * Map::getSectorNoGenerateNoExNoLock(v2s16 p) return sector; } -MapSector * Map::getSectorNoGenerateNoEx(v2s16 p) -{ - return getSectorNoGenerateNoExNoLock(p); -} - MapSector * Map::getSectorNoGenerate(v2s16 p) { - MapSector *sector = getSectorNoGenerateNoEx(p); - if(sector == NULL) - throw InvalidPositionException(); - - return sector; + return getSectorNoGenerateNoLock(p); } MapBlock * Map::getBlockNoCreateNoEx(v3s16 p3d) { v2s16 p2d(p3d.X, p3d.Z); - MapSector * sector = getSectorNoGenerateNoEx(p2d); + MapSector * sector = getSectorNoGenerate(p2d); if(sector == NULL) return NULL; MapBlock *block = sector->getBlockNoCreateNoEx(p3d.Y); @@ -149,11 +139,26 @@ MapBlock * Map::getBlockNoCreate(v3s16 p3d) return block; } +void Map::listAllLoadedBlocks(std::vector &dst) +{ + for (auto §or_it : m_sectors) { + MapSector *sector = sector_it.second; + + MapBlockVect blocks; + sector->getBlocks(blocks); + + for (MapBlock *block : blocks) { + v3s16 p = block->getPos(); + dst.push_back(p); + } + } +} + bool Map::isNodeUnderground(v3s16 p) { v3s16 blockpos = getNodeBlockPos(p); MapBlock *block = getBlockNoCreateNoEx(blockpos); - return block && block->getIsUnderground(); + return block && block->getIsUnderground(); } bool Map::isValidPosition(v3s16 p) @@ -188,7 +193,7 @@ void Map::setNode(v3s16 p, MapNode & n) v3s16 blockpos = getNodeBlockPos(p); MapBlock *block = getBlockNoCreate(blockpos); v3s16 relpos = p - blockpos*MAP_BLOCKSIZE; - // Never allow placing CONTENT_IGNORE, it fucks up stuff + // Never allow placing CONTENT_IGNORE, it causes problems if(n.getContent() == CONTENT_IGNORE){ bool temp_bool; errorstream<<"Map::setNode(): Not allowing to place CONTENT_IGNORE" @@ -283,7 +288,7 @@ bool Map::addNodeWithEvent(v3s16 p, MapNode n, bool remove_metadata) succeeded = false; } - dispatchEvent(&event); + dispatchEvent(event); return succeeded; } @@ -308,7 +313,7 @@ bool Map::removeNodeWithEvent(v3s16 p) succeeded = false; } - dispatchEvent(&event); + dispatchEvent(event); return succeeded; } @@ -487,6 +492,16 @@ void Map::PrintInfo(std::ostream &out) #define WATER_DROP_BOOST 4 +const static v3s16 liquid_6dirs[6] = { + // order: upper before same level before lower + v3s16( 0, 1, 0), + v3s16( 0, 0, 1), + v3s16( 1, 0, 0), + v3s16( 0, 0,-1), + v3s16(-1, 0, 0), + v3s16( 0,-1, 0) +}; + enum NeighborType : u8 { NEIGHBOR_UPPER, NEIGHBOR_SAME_LEVEL, @@ -577,7 +592,7 @@ void Map::transformLiquids(std::map &modified_blocks, switch (liquid_type) { case LIQUID_SOURCE: liquid_level = LIQUID_LEVEL_SOURCE; - liquid_kind = m_nodedef->getId(cf.liquid_alternative_flowing); + liquid_kind = cf.liquid_alternative_flowing_id; break; case LIQUID_FLOWING: liquid_level = (n0.param2 & LIQUID_LEVEL_MASK); @@ -596,7 +611,6 @@ void Map::transformLiquids(std::map &modified_blocks, /* Collect information about the environment */ - const v3s16 *dirs = g_6dirs; NodeNeighbor sources[6]; // surrounding sources int num_sources = 0; NodeNeighbor flows[6]; // surrounding flowing liquid nodes @@ -610,16 +624,16 @@ void Map::transformLiquids(std::map &modified_blocks, for (u16 i = 0; i < 6; i++) { NeighborType nt = NEIGHBOR_SAME_LEVEL; switch (i) { - case 1: + case 0: nt = NEIGHBOR_UPPER; break; - case 4: + case 5: nt = NEIGHBOR_LOWER; break; default: break; } - v3s16 npos = p0 + dirs[i]; + v3s16 npos = p0 + liquid_6dirs[i]; NodeNeighbor nb(getNode(npos), nt, npos); const ContentFeatures &cfnb = m_nodedef->get(nb.n); switch (m_nodedef->get(nb.n.getContent()).liquid_type) { @@ -650,20 +664,24 @@ void Map::transformLiquids(std::map &modified_blocks, case LIQUID_SOURCE: // if this node is not (yet) of a liquid type, choose the first liquid type we encounter if (liquid_kind == CONTENT_AIR) - liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing); - if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) { + liquid_kind = cfnb.liquid_alternative_flowing_id; + if (cfnb.liquid_alternative_flowing_id != liquid_kind) { neutrals[num_neutrals++] = nb; } else { // Do not count bottom source, it will screw things up - if(dirs[i].Y != -1) + if(nt != NEIGHBOR_LOWER) sources[num_sources++] = nb; } break; case LIQUID_FLOWING: - // if this node is not (yet) of a liquid type, choose the first liquid type we encounter - if (liquid_kind == CONTENT_AIR) - liquid_kind = m_nodedef->getId(cfnb.liquid_alternative_flowing); - if (m_nodedef->getId(cfnb.liquid_alternative_flowing) != liquid_kind) { + if (nb.t != NEIGHBOR_SAME_LEVEL || + (nb.n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK) { + // if this node is not (yet) of a liquid type, choose the first liquid type we encounter + // but exclude falling liquids on the same level, they cannot flow here anyway + if (liquid_kind == CONTENT_AIR) + liquid_kind = cfnb.liquid_alternative_flowing_id; + } + if (cfnb.liquid_alternative_flowing_id != liquid_kind) { neutrals[num_neutrals++] = nb; } else { flows[num_flows++] = nb; @@ -689,7 +707,7 @@ void Map::transformLiquids(std::map &modified_blocks, // 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 // it's perfectly safe to use liquid_kind here to determine the new node content. - new_node_content = m_nodedef->getId(m_nodedef->get(liquid_kind).liquid_alternative_source); + new_node_content = m_nodedef->get(liquid_kind).liquid_alternative_source_id; } else if (num_sources >= 1 && sources[0].t != NEIGHBOR_LOWER) { // liquid_kind is set properly, see above max_node_level = new_node_level = LIQUID_LEVEL_MAX; @@ -770,8 +788,8 @@ void Map::transformLiquids(std::map &modified_blocks, // set level to last 3 bits, flowing down bit to 4th bit n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK); } else { - // set the liquid level and flow bit to 0 - n0.param2 = ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK); + // set the liquid level and flow bits to 0 + n0.param2 &= ~(LIQUID_LEVEL_MASK | LIQUID_FLOW_DOWN_MASK); } // change the node. @@ -1041,24 +1059,95 @@ void Map::removeNodeTimer(v3s16 p) block->m_node_timers.remove(p_rel); } -bool Map::isOccluded(v3s16 p0, v3s16 p1, float step, float stepfac, - float start_off, float end_off, u32 needed_count) +bool Map::determineAdditionalOcclusionCheck(const v3s16 &pos_camera, + const core::aabbox3d &block_bounds, v3s16 &check) { - float d0 = (float)BS * p0.getDistanceFrom(p1); - v3s16 u0 = p1 - p0; - v3f uf = v3f(u0.X, u0.Y, u0.Z) * BS; - uf.normalize(); - v3f p0f = v3f(p0.X, p0.Y, p0.Z) * BS; + /* + This functions determines the node inside the target block that is + closest to the camera position. This increases the occlusion culling + accuracy in straight and diagonal corridors. + The returned position will be occlusion checked first in addition to the + others (8 corners + center). + No position is returned if + - the closest node is a corner, corners are checked anyway. + - the camera is inside the target block, it will never be occluded. + */ +#define CLOSEST_EDGE(pos, bounds, axis) \ + ((pos).axis <= (bounds).MinEdge.axis) ? (bounds).MinEdge.axis : \ + (bounds).MaxEdge.axis + + bool x_inside = (block_bounds.MinEdge.X <= pos_camera.X) && + (pos_camera.X <= block_bounds.MaxEdge.X); + bool y_inside = (block_bounds.MinEdge.Y <= pos_camera.Y) && + (pos_camera.Y <= block_bounds.MaxEdge.Y); + bool z_inside = (block_bounds.MinEdge.Z <= pos_camera.Z) && + (pos_camera.Z <= block_bounds.MaxEdge.Z); + + if (x_inside && y_inside && z_inside) + return false; // Camera inside target mapblock + + // straight + if (x_inside && y_inside) { + check = v3s16(pos_camera.X, pos_camera.Y, 0); + check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z); + return true; + } else if (y_inside && z_inside) { + check = v3s16(0, pos_camera.Y, pos_camera.Z); + check.X = CLOSEST_EDGE(pos_camera, block_bounds, X); + return true; + } else if (x_inside && z_inside) { + check = v3s16(pos_camera.X, 0, pos_camera.Z); + check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y); + return true; + } + + // diagonal + if (x_inside) { + check = v3s16(pos_camera.X, 0, 0); + check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y); + check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z); + return true; + } else if (y_inside) { + check = v3s16(0, pos_camera.Y, 0); + check.X = CLOSEST_EDGE(pos_camera, block_bounds, X); + check.Z = CLOSEST_EDGE(pos_camera, block_bounds, Z); + return true; + } else if (z_inside) { + check = v3s16(0, 0, pos_camera.Z); + check.X = CLOSEST_EDGE(pos_camera, block_bounds, X); + check.Y = CLOSEST_EDGE(pos_camera, block_bounds, Y); + return true; + } + + // Closest node would be a corner, none returned + return false; +} + +bool Map::isOccluded(const v3s16 &pos_camera, const v3s16 &pos_target, + float step, float stepfac, float offset, float end_offset, u32 needed_count) +{ + v3f direction = intToFloat(pos_target - pos_camera, BS); + float distance = direction.getLength(); + + // Normalize direction vector + if (distance > 0.0f) + direction /= distance; + + v3f pos_origin_f = intToFloat(pos_camera, BS); u32 count = 0; - for(float s=start_off; sget(n); - if(f.drawtype == NDT_NORMAL){ - // not transparent, see ContentFeature::updateTextures + bool is_valid_position; + + for (; offset < distance + end_offset; offset += step) { + v3f pos_node_f = pos_origin_f + direction * offset; + v3s16 pos_node = floatToInt(pos_node_f, BS); + + MapNode node = getNode(pos_node, &is_valid_position); + + if (is_valid_position && + !m_nodedef->get(node).light_propagates) { + // Cannot see through light-blocking nodes --> occluded count++; - if(count >= needed_count) + if (count >= needed_count) return true; } step *= stepfac; @@ -1066,52 +1155,67 @@ bool Map::isOccluded(v3s16 p0, v3s16 p1, float step, float stepfac, return false; } -bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes) { - v3s16 cpn = block->getPos() * MAP_BLOCKSIZE; - cpn += v3s16(MAP_BLOCKSIZE / 2, MAP_BLOCKSIZE / 2, MAP_BLOCKSIZE / 2); - float step = BS * 1; - float stepfac = 1.1; - float startoff = BS * 1; +bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes) +{ + // Check occlusion for center and all 8 corners of the mapblock + // Overshoot a little for less flickering + static const s16 bs2 = MAP_BLOCKSIZE / 2 + 1; + static const v3s16 dir9[9] = { + v3s16( 0, 0, 0), + v3s16( 1, 1, 1) * bs2, + v3s16( 1, 1, -1) * bs2, + v3s16( 1, -1, 1) * bs2, + v3s16( 1, -1, -1) * bs2, + v3s16(-1, 1, 1) * bs2, + v3s16(-1, 1, -1) * bs2, + v3s16(-1, -1, 1) * bs2, + v3s16(-1, -1, -1) * bs2, + }; + + v3s16 pos_blockcenter = block->getPosRelative() + (MAP_BLOCKSIZE / 2); + + // Starting step size, value between 1m and sqrt(3)m + float step = BS * 1.2f; + // Multiply step by each iteraction by 'stepfac' to reduce checks in distance + float stepfac = 1.05f; + + float start_offset = BS * 1.0f; + // The occlusion search of 'isOccluded()' must stop short of the target - // point by distance 'endoff' (end offset) to not enter the target mapblock. - // For the 8 mapblock corners 'endoff' must therefore be the maximum diagonal - // of a mapblock, because we must consider all view angles. + // point by distance 'end_offset' to not enter the target mapblock. + // For the 8 mapblock corners 'end_offset' must therefore be the maximum + // diagonal of a mapblock, because we must consider all view angles. // sqrt(1^2 + 1^2 + 1^2) = 1.732 - float endoff = -BS * MAP_BLOCKSIZE * 1.732050807569; - s16 bs2 = MAP_BLOCKSIZE / 2 + 1; + float end_offset = -BS * MAP_BLOCKSIZE * 1.732f; + // to reduce the likelihood of falsely occluded blocks // require at least two solid blocks // this is a HACK, we should think of a more precise algorithm u32 needed_count = 2; - return ( - // For the central point of the mapblock 'endoff' can be halved - isOccluded(cam_pos_nodes, cpn, - step, stepfac, startoff, endoff / 2.0f, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(bs2,bs2,bs2), - step, stepfac, startoff, endoff, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(bs2,bs2,-bs2), - step, stepfac, startoff, endoff, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(bs2,-bs2,bs2), - step, stepfac, startoff, endoff, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(bs2,-bs2,-bs2), - step, stepfac, startoff, endoff, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(-bs2,bs2,bs2), - step, stepfac, startoff, endoff, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(-bs2,bs2,-bs2), - step, stepfac, startoff, endoff, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(-bs2,-bs2,bs2), - step, stepfac, startoff, endoff, needed_count) && - isOccluded(cam_pos_nodes, cpn + v3s16(-bs2,-bs2,-bs2), - step, stepfac, startoff, endoff, needed_count)); + // Additional occlusion check, see comments in that function + v3s16 check; + if (determineAdditionalOcclusionCheck(cam_pos_nodes, block->getBox(), check)) { + // node is always on a side facing the camera, end_offset can be lower + if (!isOccluded(cam_pos_nodes, check, step, stepfac, start_offset, + -1.0f, needed_count)) + return false; + } + + for (const v3s16 &dir : dir9) { + if (!isOccluded(cam_pos_nodes, pos_blockcenter + dir, step, stepfac, + start_offset, end_offset, needed_count)) + return false; + } + return true; } /* ServerMap */ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef, - EmergeManager *emerge): - Map(dout_server, gamedef), + EmergeManager *emerge, MetricsBackend *mb): + Map(gamedef), settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"), m_emerge(emerge) { @@ -1144,6 +1248,8 @@ ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef, m_savedir = savedir; m_map_saving_enabled = false; + m_save_time_counter = mb->addCounter("minetest_core_map_save_time", "Map save time (in nanoseconds)"); + try { // If directory exists, check contents and load if possible if (fs::PathExists(m_savedir)) { @@ -1208,8 +1314,7 @@ ServerMap::~ServerMap() Close database if it was opened */ delete dbase; - if (dbase_ro) - delete dbase_ro; + delete dbase_ro; #if 0 /* @@ -1236,11 +1341,6 @@ u64 ServerMap::getSeed() return getMapgenParams()->seed; } -s16 ServerMap::getWaterLevel() -{ - return getMapgenParams()->water_level; -} - bool ServerMap::blockpos_over_mapgen_limit(v3s16 p) { const s16 mapgen_limit_bp = rangelim( @@ -1260,6 +1360,9 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data) v3s16 bpmin = EmergeManager::getContainingChunk(blockpos, csize); v3s16 bpmax = bpmin + v3s16(1, 1, 1) * (csize - 1); + if (!m_chunks_in_progress.insert(bpmin).second) + return false; + bool enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info; EMERGE_DBG_OUT("initBlockMake(): " PP(bpmin) " - " PP(bpmax)); @@ -1275,7 +1378,6 @@ bool ServerMap::initBlockMake(v3s16 blockpos, BlockMakeData *data) data->seed = getSeed(); data->blockpos_min = bpmin; data->blockpos_max = bpmax; - data->blockpos_requested = blockpos; data->nodedef = m_nodedef; /* @@ -1397,6 +1499,7 @@ void ServerMap::finishBlockMake(BlockMakeData *data, NOTE: Will be saved later. */ //save(MOD_STATE_WRITE_AT_UNLOAD); + m_chunks_in_progress.erase(bpmin); } MapSector *ServerMap::createSector(v2s16 p2d) @@ -1404,7 +1507,7 @@ MapSector *ServerMap::createSector(v2s16 p2d) /* Check if it exists already in memory */ - MapSector *sector = getSectorNoGenerateNoEx(p2d); + MapSector *sector = getSectorNoGenerate(p2d); if (sector) return sector; @@ -1641,140 +1744,6 @@ void ServerMap::updateVManip(v3s16 pos) vm->m_is_dirty = true; } -s16 ServerMap::findGroundLevel(v2s16 p2d) -{ -#if 0 - /* - Uh, just do something random... - */ - // Find existing map from top to down - s16 max=63; - s16 min=-64; - v3s16 p(p2d.X, max, p2d.Y); - for(; p.Y>min; p.Y--) - { - MapNode n = getNodeNoEx(p); - if(n.getContent() != CONTENT_IGNORE) - break; - } - if(p.Y == min) - goto plan_b; - // If this node is not air, go to plan b - if(getNodeNoEx(p).getContent() != CONTENT_AIR) - goto plan_b; - // Search existing walkable and return it - for(; p.Y>min; p.Y--) - { - MapNode n = getNodeNoEx(p); - if(content_walkable(n.d) && n.getContent() != CONTENT_IGNORE) - return p.Y; - } - - // Move to plan b -plan_b: -#endif - - /* - Determine from map generator noise functions - */ - - s16 level = m_emerge->getGroundLevelAtPoint(p2d); - return level; - - //double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT; - //return (s16)level; -} - -bool ServerMap::loadFromFolders() { - if (!dbase->initialized() && - !fs::PathExists(m_savedir + DIR_DELIM + "map.sqlite")) - return true; - return false; -} - -void ServerMap::createDirs(const std::string &path) -{ - if (!fs::CreateAllDirs(path)) { - m_dout<<"ServerMap: Failed to create directory " - <<"\""<increment(end_time - start_time); } void ServerMap::listAllLoadableBlocks(std::vector &dst) { - if (loadFromFolders()) { - errorstream << "Map::listAllLoadableBlocks(): Result will be missing " - << "all blocks that are stored in flat files." << std::endl; - } dbase->listAllLoadableBlocks(dst); if (dbase_ro) dbase_ro->listAllLoadableBlocks(dst); } -void ServerMap::listAllLoadedBlocks(std::vector &dst) -{ - for (auto §or_it : m_sectors) { - MapSector *sector = sector_it.second; - - MapBlockVect blocks; - sector->getBlocks(blocks); - - for (MapBlock *block : blocks) { - v3s16 p = block->getPos(); - dst.push_back(p); - } - } -} - MapDatabase *ServerMap::createDatabase( const std::string &name, const std::string &savedir, @@ -1941,83 +1896,6 @@ bool ServerMap::saveBlock(MapBlock *block, MapDatabase *db) return ret; } -void ServerMap::loadBlock(const std::string §ordir, const std::string &blockfile, - MapSector *sector, bool save_after_load) -{ - std::string fullpath = sectordir + DIR_DELIM + blockfile; - try { - std::ifstream is(fullpath.c_str(), std::ios_base::binary); - if (!is.good()) - throw FileNotGoodException("Cannot open block file"); - - v3s16 p3d = getBlockPos(sectordir, blockfile); - v2s16 p2d(p3d.X, p3d.Z); - - assert(sector->getPos() == p2d); - - u8 version = SER_FMT_VER_INVALID; - is.read((char*)&version, 1); - - if(is.fail()) - throw SerializationError("ServerMap::loadBlock(): Failed" - " to read MapBlock version"); - - /*u32 block_size = MapBlock::serializedLength(version); - SharedBuffer data(block_size); - is.read((char*)*data, block_size);*/ - - // This will always return a sector because we're the server - //MapSector *sector = emergeSector(p2d); - - MapBlock *block = NULL; - bool created_new = false; - block = sector->getBlockNoCreateNoEx(p3d.Y); - if(block == NULL) - { - block = sector->createBlankBlockNoInsert(p3d.Y); - created_new = true; - } - - // Read basic data - block->deSerialize(is, version, true); - - // If it's a new block, insert it to the map - if (created_new) { - sector->insertBlock(block); - ReflowScan scanner(this, m_emerge->ndef); - scanner.scan(block, &m_transforming_liquid); - } - - /* - Save blocks loaded in old format in new format - */ - - if(version < SER_FMT_VER_HIGHEST_WRITE || save_after_load) - { - saveBlock(block); - - // Should be in database now, so delete the old file - fs::RecursiveDelete(fullpath); - } - - // We just loaded it from the disk, so it's up-to-date. - block->resetModified(); - - } - catch(SerializationError &e) - { - warningstream<<"Invalid block data on disk " - <<"fullpath="<getBlockNoCreate(p); - if(block->isDummy()) + block = m_map->getBlockNoCreateNoEx(p); + if (!block || block->isDummy()) block_data_inexistent = true; else block->copyTo(*this); } - catch(InvalidPositionException &e) - { - block_data_inexistent = true; - } if(block_data_inexistent) {