bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { v2s16 p2d(p.X, p.Z); //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire JMutexAutoLock envlock(m_server->m_env_mutex); // Load sector if it isn't loaded if (map->getSectorNoGenerateNoEx(p2d) == NULL) map->loadSectorMeta(p2d); // Attempt to load block MapBlock *block = map->getBlockNoCreateNoEx(p); if (!block || block->isDummy() || !block->isGenerated()) { EMERGE_DBG_OUT("not in memory, attempting to load from disk"); block = map->loadBlock(p); if (block && block->isGenerated()) map->prepareBlock(block); } // If could not load and allowed to generate, // start generation inside this same envlock if (allow_gen && (block == NULL || !block->isGenerated())) { EMERGE_DBG_OUT("generating"); *b = block; return map->initBlockMake(data, p); } *b = block; return false; }
bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire //JMutexAutoLock envlock(m_server->m_env_mutex); // Attempt to load block MapBlock *block = map->getBlockNoCreateNoEx(p); if (!block || block->isDummy()) { EMERGE_DBG_OUT("not in memory, attempting to load from disk ag="<<allow_gen<<" block="<<block<<" p="<<p); block = map->loadBlock(p); if(block) { // block->pushElementsToCircuit(m_circuit); // m_circuit->processElementsQueue(*map, map->getNodeDefManager()); } if (block && block->isGenerated()) map->prepareBlock(block); } // If could not load and allowed to generate, // start generation inside this same envlock if (allow_gen && (!block)) { EMERGE_DBG_OUT("generating b="<<block); *b = block; return map->initBlockMake(data, p); } *b = block; return false; }
bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { #if !ENABLE_THREADS auto lock = map->m_nothread_locker.lock_unique_rec(); #endif MapBlock *block; { //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire //JMutexAutoLock envlock(m_server->m_env_mutex); // Attempt to load block block = map->getBlockNoCreateNoEx(p); if (!block || block->isDummy()) { EMERGE_DBG_OUT("not in memory, attempting to load from disk ag="<<allow_gen<<" block="<<block<<" p="<<p); block = map->loadBlock(p); if (block && block->isGenerated()) map->prepareBlock(block); } } // If could not load and allowed to generate, // start generation inside this same envlock if (allow_gen && (!block)) { EMERGE_DBG_OUT("generating b="<<block); *b = block; return map->initBlockMake(data, p); } *b = block; return false; }
MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata, std::map<v3s16, MapBlock *> *modified_blocks) { //MutexAutoLock envlock(m_server->m_env_mutex); ScopeProfiler sp(g_profiler, "EmergeThread: after Mapgen::makeChunk", SPT_AVG); /* Perform post-processing on blocks (invalidate lighting, queue liquid transforms, etc.) to finish block make */ m_map->finishBlockMake(bmdata, modified_blocks); MapBlock *block = m_map->getBlockNoCreateNoEx(pos, false, true); if (!block) { errorstream << "EmergeThread::finishGen: Couldn't grab block we " "just generated: " << PP(pos) << std::endl; return NULL; } v3s16 minp = bmdata->blockpos_min * MAP_BLOCKSIZE; v3s16 maxp = bmdata->blockpos_max * MAP_BLOCKSIZE + v3s16(1,1,1) * (MAP_BLOCKSIZE - 1); // Ignore map edit events, they will not need to be sent // to anybody because the block hasn't been sent to anybody /* thread unsafe MapEditEventAreaIgnorer ign( &m_server->m_ignore_map_edit_events_area, VoxelArea(minp, maxp)); */ /* Run Lua on_generated callbacks */ try { MAP_NOTHREAD_LOCK(m_map); m_server->getScriptIface()->environment_OnGenerated( minp, maxp, m_mapgen->blockseed); } catch (LuaError &e) { m_server->setAsyncFatalError("Lua: " + std::string(e.what())); } EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); /* Activate the block */ m_server->m_env->activateBlock(block, 0); return block; }
EmergeAction EmergeThread::getBlockOrStartGen( v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata) { //MutexAutoLock envlock(m_server->m_env_mutex); { MAP_NOTHREAD_LOCK(m_map); // 1). Attempt to fetch block from memory *block = m_map->getBlockNoCreateNoEx(pos, false, true); } if (*block && !(*block)->isDummy() && (*block)->isGenerated()) return EMERGE_FROM_MEMORY; { MAP_NOTHREAD_LOCK(m_map); // 2). Attempt to load block from disk *block = m_map->loadBlock(pos); } if (*block && (*block)->isGenerated()) { MAP_NOTHREAD_LOCK(m_map); m_map->prepareBlock(*block); return EMERGE_FROM_DISK; } { MAP_NOTHREAD_LOCK(m_map); // 3). Attempt to start generation if (allow_gen && m_map->initBlockMake(pos, bmdata)) return EMERGE_GENERATED; } /* verbosestream << "EmergeThread::getBlockOrStartGen : cancel pos=" << pos << " block="<< *block; if (*block) verbosestream << "dummy=" << (*block)->isDummy() << " generated="<< (*block)->isGenerated(); verbosestream << std::endl; */ // All attempts failed; cancel this block emerge return EMERGE_CANCELLED; }
EmergeAction EmergeThread::getBlockOrStartGen( v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata) { MutexAutoLock envlock(m_server->m_env_mutex); // 1). Attempt to fetch block from memory *block = m_map->getBlockNoCreateNoEx(pos); if (*block && !(*block)->isDummy() && (*block)->isGenerated()) return EMERGE_FROM_MEMORY; // 2). Attempt to load block from disk *block = m_map->loadBlock(pos); if (*block && (*block)->isGenerated()) return EMERGE_FROM_DISK; // 3). Attempt to start generation if (allow_gen && m_map->initBlockMake(pos, bmdata)) return EMERGE_GENERATED; // All attempts failed; cancel this block emerge return EMERGE_CANCELLED; }
void *EmergeThread::Thread() { ThreadStarted(); log_register_thread("EmergeThread" + itos(id)); DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER v3s16 last_tried_pos(-32768,-32768,-32768); // For error output v3s16 p; u8 flags = 0; map = (ServerMap *)&(m_server->m_env->getMap()); emerge = m_server->m_emerge; mapgen = emerge->mapgen[id]; enable_mapgen_debug_info = emerge->mapgen_debug_info; porting::setThreadName("EmergeThread"); while (!StopRequested()) try { if (!popBlockEmerge(&p, &flags)) { qevent.wait(); continue; } last_tried_pos = p; if (blockpos_over_limit(p)) continue; bool allow_generate = flags & BLOCK_EMERGE_ALLOWGEN; EMERGE_DBG_OUT("p=" PP(p) " allow_generate=" << allow_generate); /* Try to fetch block from memory or disk. If not found and asked to generate, initialize generator. */ BlockMakeData data; MapBlock *block = NULL; std::map<v3s16, MapBlock *> modified_blocks; if (getBlockOrStartGen(p, &block, &data, allow_generate) && mapgen) { { ScopeProfiler sp(g_profiler, "EmergeThread: Mapgen::makeChunk", SPT_AVG); TimeTaker t("mapgen::make_block()"); mapgen->makeChunk(&data); if (enable_mapgen_debug_info == false) t.stop(true); // Hide output } { //envlock: usually 0ms, but can take either 30 or 400ms to acquire JMutexAutoLock envlock(m_server->m_env_mutex); ScopeProfiler sp(g_profiler, "EmergeThread: after " "Mapgen::makeChunk (envlock)", SPT_AVG); map->finishBlockMake(&data, modified_blocks); block = map->getBlockNoCreateNoEx(p); if (block) { /* Do some post-generate stuff */ v3s16 minp = data.blockpos_min * MAP_BLOCKSIZE; v3s16 maxp = data.blockpos_max * MAP_BLOCKSIZE + v3s16(1,1,1) * (MAP_BLOCKSIZE - 1); // Ignore map edit events, they will not need to be sent // to anybody because the block hasn't been sent to anybody MapEditEventAreaIgnorer ign(&m_server->m_ignore_map_edit_events_area, VoxelArea(minp, maxp)); try { // takes about 90ms with -O1 on an e3-1230v2 m_server->getScriptIface()->environment_OnGenerated( minp, maxp, emerge->getBlockSeed(minp)); } catch(LuaError &e) { m_server->setAsyncFatalError(e.what()); } EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); m_server->m_env->activateBlock(block, 0); } } } /* Set sent status of modified blocks on clients */ // Add the originally fetched block to the modified list if (block) modified_blocks[p] = block; if (modified_blocks.size() > 0) { m_server->SetBlocksNotSent(modified_blocks); } } catch (VersionMismatchException &e) { std::ostringstream err; err << "World data version mismatch in MapBlock "<<PP(last_tried_pos)<<std::endl; err << "----"<<std::endl; err << "\""<<e.what()<<"\""<<std::endl; err << "See debug.txt."<<std::endl; err << "World probably saved by a newer version of Minetest."<<std::endl; m_server->setAsyncFatalError(err.str()); } catch (SerializationError &e) { std::ostringstream err; err << "Invalid data in MapBlock "<<PP(last_tried_pos)<<std::endl; err << "----"<<std::endl; err << "\""<<e.what()<<"\""<<std::endl; err << "See debug.txt."<<std::endl; err << "You can ignore this using [ignore_world_load_errors = true]."<<std::endl; m_server->setAsyncFatalError(err.str()); } END_DEBUG_EXCEPTION_HANDLER(errorstream) log_deregister_thread(); return NULL; }