X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Femerge.cpp;h=32e7d9f24d0492de3fc96a3df17599a8857329ad;hb=fb4815c660d6d9cfc9df76a3ba763095b9701925;hp=8719a9eb37c9d0719db9d8af789d7784c5bd3207;hpb=2efae3ffd720095222c800e016286a45c9fe1e5c;p=dragonfireclient.git diff --git a/src/emerge.cpp b/src/emerge.cpp index 8719a9eb3..32e7d9f24 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -34,15 +34,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "map.h" #include "mapblock.h" -#include "mg_biome.h" -#include "mg_ore.h" -#include "mg_decoration.h" -#include "mg_schematic.h" +#include "mapgen/mg_biome.h" +#include "mapgen/mg_ore.h" +#include "mapgen/mg_decoration.h" +#include "mapgen/mg_schematic.h" #include "nodedef.h" #include "profiler.h" -#include "serverscripting.h" +#include "scripting_server.h" #include "server.h" -#include "serverobject.h" #include "settings.h" #include "voxel.h" @@ -52,18 +51,18 @@ class EmergeThread : public Thread { int id; EmergeThread(Server *server, int ethreadid); - ~EmergeThread(); + ~EmergeThread() = default; void *run(); void signal(); // Requires queue mutex held - bool pushBlock(v3s16 pos); + bool pushBlock(const v3s16 &pos); void cancelPendingItems(); static void runCompletionCallbacks( - v3s16 pos, EmergeAction action, + const v3s16 &pos, EmergeAction action, const EmergeCallbackList &callbacks); private: @@ -78,13 +77,63 @@ class EmergeThread : public Thread { bool popBlockEmerge(v3s16 *pos, BlockEmergeData *bedata); EmergeAction getBlockOrStartGen( - v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *data); + const v3s16 &pos, bool allow_gen, MapBlock **block, BlockMakeData *data); MapBlock *finishGen(v3s16 pos, BlockMakeData *bmdata, std::map *modified_blocks); friend class EmergeManager; }; +class MapEditEventAreaIgnorer +{ +public: + MapEditEventAreaIgnorer(VoxelArea *ignorevariable, const VoxelArea &a): + m_ignorevariable(ignorevariable) + { + if(m_ignorevariable->getVolume() == 0) + *m_ignorevariable = a; + else + m_ignorevariable = NULL; + } + + ~MapEditEventAreaIgnorer() + { + if(m_ignorevariable) + { + assert(m_ignorevariable->getVolume() != 0); + *m_ignorevariable = VoxelArea(); + } + } + +private: + VoxelArea *m_ignorevariable; +}; + +EmergeParams::~EmergeParams() +{ + infostream << "EmergeParams: destroying " << this << std::endl; + // Delete everything that was cloned on creation of EmergeParams + delete biomegen; + delete biomemgr; + delete oremgr; + delete decomgr; + delete schemmgr; +} + +EmergeParams::EmergeParams(EmergeManager *parent, const BiomeGen *biomegen, + const BiomeManager *biomemgr, + const OreManager *oremgr, const DecorationManager *decomgr, + const SchematicManager *schemmgr) : + ndef(parent->ndef), + enable_mapgen_debug_info(parent->enable_mapgen_debug_info), + gen_notify_on(parent->gen_notify_on), + gen_notify_on_deco_ids(&parent->gen_notify_on_deco_ids), + biomemgr(biomemgr->clone()), oremgr(oremgr->clone()), + decomgr(decomgr->clone()), schemmgr(schemmgr->clone()) +{ + this->biomegen = biomegen->clone(this->biomemgr); +} + //// //// EmergeManager //// @@ -96,24 +145,28 @@ EmergeManager::EmergeManager(Server *server) this->oremgr = new OreManager(server); this->decomgr = new DecorationManager(server); this->schemmgr = new SchematicManager(server); - this->gen_notify_on = 0; + + // initialized later + this->mgparams = nullptr; + this->biomegen = nullptr; // Note that accesses to this variable are not synchronized. // This is because the *only* thread ever starting or stopping // EmergeThreads should be the ServerThread. - this->m_threads_active = false; enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); - // If unspecified, leave a proc for the main thread and one for + s16 nthreads = 1; + g_settings->getS16NoEx("num_emerge_threads", nthreads); + // If automatic, leave a proc for the main thread and one for // some other misc thread - s16 nthreads = 0; - if (!g_settings->getS16NoEx("num_emerge_threads", nthreads)) + if (nthreads == 0) nthreads = Thread::getNumberOfProcessors() - 2; if (nthreads < 1) nthreads = 1; m_qlimit_total = g_settings->getU16("emergequeue_limit_total"); + // FIXME: these fallback values are probably not good if (!g_settings->getU16NoEx("emergequeue_limit_diskonly", m_qlimit_diskonly)) m_qlimit_diskonly = nthreads * 5 + 1; if (!g_settings->getU16NoEx("emergequeue_limit_generate", m_qlimit_generate)) @@ -146,7 +199,10 @@ EmergeManager::~EmergeManager() } delete thread; - delete m_mapgens[i]; + + // Mapgen init might not be finished if there is an error during startup. + if (m_mapgens.size() > i) + delete m_mapgens[i]; } delete biomemgr; @@ -156,30 +212,66 @@ EmergeManager::~EmergeManager() } -bool EmergeManager::initMapgens(MapgenParams *params) +BiomeManager *EmergeManager::getWritableBiomeManager() { - if (m_mapgens.size()) - return false; + FATAL_ERROR_IF(!m_mapgens.empty(), + "Writable managers can only be returned before mapgen init"); + return biomemgr; +} - this->mgparams = params; +OreManager *EmergeManager::getWritableOreManager() +{ + FATAL_ERROR_IF(!m_mapgens.empty(), + "Writable managers can only be returned before mapgen init"); + return oremgr; +} + +DecorationManager *EmergeManager::getWritableDecorationManager() +{ + FATAL_ERROR_IF(!m_mapgens.empty(), + "Writable managers can only be returned before mapgen init"); + return decomgr; +} + +SchematicManager *EmergeManager::getWritableSchematicManager() +{ + FATAL_ERROR_IF(!m_mapgens.empty(), + "Writable managers can only be returned before mapgen init"); + return schemmgr; +} + + +void EmergeManager::initMapgens(MapgenParams *params) +{ + FATAL_ERROR_IF(!m_mapgens.empty(), "Mapgen already initialised."); + + mgparams = params; + + v3s16 csize = v3s16(1, 1, 1) * (params->chunksize * MAP_BLOCKSIZE); + biomegen = biomemgr->createBiomeGen(BIOMEGEN_ORIGINAL, params->bparams, csize); for (u32 i = 0; i != m_threads.size(); i++) { - Mapgen *mg = Mapgen::createMapgen(params->mgtype, i, params, this); - m_mapgens.push_back(mg); + EmergeParams *p = new EmergeParams(this, biomegen, + biomemgr, oremgr, decomgr, schemmgr); + infostream << "EmergeManager: Created params " << p + << " for thread " << i << std::endl; + m_mapgens.push_back(Mapgen::createMapgen(params->mgtype, params, p)); } - - return true; } Mapgen *EmergeManager::getCurrentMapgen() { + if (!m_threads_active) + return nullptr; + for (u32 i = 0; i != m_threads.size(); i++) { - if (m_threads[i]->isCurrentThread()) - return m_threads[i]->m_mapgen; + EmergeThread *t = m_threads[i]; + if (t->isRunning() && t->isCurrentThread()) + return t->m_mapgen; } - return NULL; + return nullptr; } @@ -221,7 +313,7 @@ bool EmergeManager::isRunning() bool EmergeManager::enqueueBlockEmerge( - u16 peer_id, + session_t peer_id, v3s16 blockpos, bool allow_generate, bool ignore_queue_limits) @@ -238,7 +330,7 @@ bool EmergeManager::enqueueBlockEmerge( bool EmergeManager::enqueueBlockEmergeEx( v3s16 blockpos, - u16 peer_id, + session_t peer_id, u16 flags, EmergeCompletionCallback callback, void *callback_param) @@ -290,7 +382,7 @@ v3s16 EmergeManager::getContainingChunk(v3s16 blockpos, s16 chunksize) int EmergeManager::getSpawnLevelAtPoint(v2s16 p) { - if (m_mapgens.size() == 0 || !m_mapgens[0]) { + if (m_mapgens.empty() || !m_mapgens[0]) { errorstream << "EmergeManager: getSpawnLevelAtPoint() called" " before mapgen init" << std::endl; return 0; @@ -302,7 +394,7 @@ int EmergeManager::getSpawnLevelAtPoint(v2s16 p) int EmergeManager::getGroundLevelAtPoint(v2s16 p) { - if (m_mapgens.size() == 0 || !m_mapgens[0]) { + if (m_mapgens.empty() || !m_mapgens[0]) { errorstream << "EmergeManager: getGroundLevelAtPoint() called" " before mapgen init" << std::endl; return 0; @@ -314,14 +406,7 @@ int EmergeManager::getGroundLevelAtPoint(v2s16 p) // TODO(hmmmm): Move this to ServerMap bool EmergeManager::isBlockUnderground(v3s16 blockpos) { -#if 0 - v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2, - (blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2); - int ground_level = getGroundLevelAtPoint(p); - return blockpos.Y * (MAP_BLOCKSIZE + 1) <= min(water_level, ground_level); -#endif - - // Use a simple heuristic; the above method is wildly inaccurate anyway. + // Use a simple heuristic return blockpos.Y * (MAP_BLOCKSIZE + 1) <= mgparams->water_level; } @@ -344,6 +429,10 @@ bool EmergeManager::pushBlockEmergeData( m_qlimit_generate : m_qlimit_diskonly; if (count_peer >= qlimit_peer) return false; + } else { + // limit block enqueue requests for active blocks to 1/2 of total + if (count_peer * 2 >= m_qlimit_total) + return false; } } @@ -354,7 +443,7 @@ bool EmergeManager::pushBlockEmergeData( *entry_already_exists = !findres.second; if (callback) - bedata.callbacks.push_back(std::make_pair(callback, callback_param)); + bedata.callbacks.emplace_back(callback, callback_param); if (*entry_already_exists) { bedata.flags |= flags; @@ -372,7 +461,7 @@ bool EmergeManager::pushBlockEmergeData( bool EmergeManager::popBlockEmergeData(v3s16 pos, BlockEmergeData *bedata) { std::map::iterator it; - UNORDERED_MAP::iterator it2; + std::unordered_map::iterator it2; it = m_blocks_enqueued.find(pos); if (it == m_blocks_enqueued.end()) @@ -431,19 +520,13 @@ EmergeThread::EmergeThread(Server *server, int ethreadid) : } -EmergeThread::~EmergeThread() -{ - //cancelPendingItems(); -} - - void EmergeThread::signal() { m_queue_event.signal(); } -bool EmergeThread::pushBlock(v3s16 pos) +bool EmergeThread::pushBlock(const v3s16 &pos) { m_block_queue.push(pos); return true; @@ -468,9 +551,7 @@ void EmergeThread::cancelPendingItems() } -void EmergeThread::runCompletionCallbacks( - v3s16 pos, - EmergeAction action, +void EmergeThread::runCompletionCallbacks(const v3s16 &pos, EmergeAction action, const EmergeCallbackList &callbacks) { for (size_t i = 0; i != callbacks.size(); i++) { @@ -502,7 +583,7 @@ bool EmergeThread::popBlockEmerge(v3s16 *pos, BlockEmergeData *bedata) EmergeAction EmergeThread::getBlockOrStartGen( - v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata) + const v3s16 &pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata) { MutexAutoLock envlock(m_server->m_env_mutex); @@ -567,6 +648,11 @@ MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata, m_server->setAsyncFatalError("Lua: finishGen" + std::string(e.what())); } + /* + Clear generate notifier events + */ + m_mapgen->gennotify.clearEvents(); + EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); /* @@ -580,7 +666,6 @@ MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata, void *EmergeThread::run() { - DSTACK(FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER v3s16 pos; @@ -603,7 +688,7 @@ void *EmergeThread::run() continue; } - if (blockpos_over_limit(pos)) + if (blockpos_over_max_limit(pos)) continue; bool allow_gen = bedata.flags & BLOCK_EMERGE_ALLOW_GEN; @@ -614,12 +699,8 @@ void *EmergeThread::run() { 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); @@ -630,7 +711,7 @@ void *EmergeThread::run() if (block) modified_blocks[pos] = block; - if (modified_blocks.size() > 0) + if (!modified_blocks.empty()) m_server->SetBlocksNotSent(modified_blocks); } } catch (VersionMismatchException &e) {