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; }
void *EmergeThread::run() { DSTACK(FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER v3s16 pos; m_map = (ServerMap *)&(m_server->m_env->getMap()); m_emerge = m_server->m_emerge; m_mapgen = m_emerge->m_mapgens[id]; enable_mapgen_debug_info = m_emerge->enable_mapgen_debug_info; try { while (!stopRequested()) { std::map<v3s16, MapBlock *> modified_blocks; BlockEmergeData bedata; BlockMakeData bmdata; EmergeAction action; MapBlock *block; if (!popBlockEmerge(&pos, &bedata)) { m_queue_event.wait(); continue; } if (blockpos_over_limit(pos)) continue; bool allow_gen = bedata.flags & BLOCK_EMERGE_ALLOW_GEN; EMERGE_DBG_OUT("pos=" PP(pos) " allow_gen=" << allow_gen); action = getBlockOrStartGen(pos, allow_gen, &block, &bmdata); if (action == EMERGE_GENERATED) { { ScopeProfiler sp(g_profiler, "EmergeThread: Mapgen::makeChunk", SPT_AVG); TimeTaker t("mapgen::make_block()"); m_mapgen->makeChunk(&bmdata); if (enable_mapgen_debug_info == false) t.stop(true); // Hide output } block = finishGen(pos, &bmdata, &modified_blocks); } runCompletionCallbacks(pos, action, bedata.callbacks); if (block) modified_blocks[pos] = 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(pos) << std::endl << "----" << std::endl << "\"" << e.what() << "\"" << std::endl << "See debug.txt." << std::endl << "World probably saved by a newer version of " PROJECT_NAME_C "." << std::endl; m_server->setAsyncFatalError(err.str()); } catch (SerializationError &e) { std::ostringstream err; err << "Invalid data in MapBlock " << PP(pos) << std::endl << "----" << std::endl << "\"" << e.what() << "\"" << std::endl << "See debug.txt." << std::endl << "You can ignore this using [ignore_world_load_errors = true]." << std::endl; m_server->setAsyncFatalError(err.str()); } END_DEBUG_EXCEPTION_HANDLER return NULL; }