X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Femerge.cpp;h=0844707836ded07650d93ef4787acdffdb844d17;hb=2035bfc3a64e7c0c82f0cb100cd7d4cc588d0203;hp=b785c8688cf1d9645fe67db43ce4f1cd37c34396;hpb=76217939e05bdd8d06fa7113902a74b02deeb915;p=dragonfireclient.git diff --git a/src/emerge.cpp b/src/emerge.cpp index b785c8688..084470783 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -1,6 +1,7 @@ /* -Minetest-c55 -Copyright (C) 2010-2011 celeron55, Perttu Ahola +Minetest +Copyright (C) 2010-2013 celeron55, Perttu Ahola +Copyright (C) 2010-2013 kwolekr, Ryan Kwolek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -18,93 +19,236 @@ with this program; if not, write to the Free Software Foundation, Inc., */ +#include "emerge.h" #include "server.h" #include #include -#include "clientserver.h" +#include "threading/event.h" #include "map.h" -#include "jmutexautolock.h" -#include "main.h" +#include "environment.h" +#include "util/container.h" +#include "util/thread.h" #include "constants.h" #include "voxel.h" #include "config.h" #include "mapblock.h" #include "serverobject.h" #include "settings.h" -#include "script.h" -#include "scriptapi.h" +#include "scripting_game.h" #include "profiler.h" #include "log.h" #include "nodedef.h" -#include "biome.h" -#include "emerge.h" +#include "mg_biome.h" +#include "mg_ore.h" +#include "mg_decoration.h" +#include "mg_schematic.h" +#include "mapgen_v5.h" #include "mapgen_v6.h" +#include "mapgen_v7.h" +#include "mapgen_singlenode.h" + +struct MapgenDesc { + const char *name; + MapgenFactory *factory; +}; + +MapgenDesc reg_mapgens[] = { + {"v5", new MapgenFactoryV5}, + {"v6", new MapgenFactoryV6}, + {"v7", new MapgenFactoryV7}, + {"singlenode", new MapgenFactorySinglenode}, +}; + +class EmergeThread : public Thread +{ +public: + Server *m_server; + ServerMap *map; + EmergeManager *emerge; + Mapgen *mapgen; + bool enable_mapgen_debug_info; + int id; + + Event qevent; + std::queue blockqueue; + + EmergeThread(Server *server, int ethreadid): + m_server(server), + map(NULL), + emerge(NULL), + mapgen(NULL), + enable_mapgen_debug_info(false), + id(ethreadid) + { + name = "Emerge-" + itos(id); + } + void *run(); + bool popBlockEmerge(v3s16 *pos, u8 *flags); + bool getBlockOrStartGen(v3s16 p, MapBlock **b, + BlockMakeData *data, bool allow_generate); +}; -EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { - //register built-in mapgens - registerMapgen("v6", new MapgenFactoryV6()); - this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef); - this->params = NULL; - this->mapgen = NULL; - - qlimit_total = g_settings->getU16("emergequeue_limit_total"); - qlimit_diskonly = g_settings->getU16("emergequeue_limit_diskonly"); - qlimit_generate = g_settings->getU16("emergequeue_limit_generate"); +/////////////////////////////// Emerge Manager //////////////////////////////// - queuemutex.Init(); - emergethread = new EmergeThread((Server *)gamedef); +EmergeManager::EmergeManager(IGameDef *gamedef) +{ + this->ndef = gamedef->getNodeDefManager(); + this->biomemgr = new BiomeManager(gamedef); + this->oremgr = new OreManager(gamedef); + this->decomgr = new DecorationManager(gamedef); + this->schemmgr = new SchematicManager(gamedef); + this->gen_notify_on = 0; + + // 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->threads_active = false; + + mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); + + // if unspecified, 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)) + nthreads = Thread::getNumberOfProcessors() - 2; + if (nthreads < 1) + nthreads = 1; + + qlimit_total = g_settings->getU16("emergequeue_limit_total"); + if (!g_settings->getU16NoEx("emergequeue_limit_diskonly", qlimit_diskonly)) + qlimit_diskonly = nthreads * 5 + 1; + if (!g_settings->getU16NoEx("emergequeue_limit_generate", qlimit_generate)) + qlimit_generate = nthreads + 1; + + // don't trust user input for something very important like this + if (qlimit_total < 1) + qlimit_total = 1; + if (qlimit_diskonly < 1) + qlimit_diskonly = 1; + if (qlimit_generate < 1) + qlimit_generate = 1; + + for (s16 i = 0; i < nthreads; i++) + emergethread.push_back(new EmergeThread((Server *) gamedef, i)); + + infostream << "EmergeManager: using " << nthreads << " threads" << std::endl; } -EmergeManager::~EmergeManager() { - emergethread->setRun(false); - emergethread->qevent.signal(); - emergethread->stop(); - - delete emergethread; - delete biomedef; - delete mapgen; - delete params; +EmergeManager::~EmergeManager() +{ + for (u32 i = 0; i != emergethread.size(); i++) { + if (threads_active) { + emergethread[i]->stop(); + emergethread[i]->qevent.signal(); + emergethread[i]->wait(); + } + delete emergethread[i]; + delete mapgen[i]; + } + emergethread.clear(); + mapgen.clear(); + + delete biomemgr; + delete oremgr; + delete decomgr; + delete schemmgr; + + if (params.sparams) { + delete params.sparams; + params.sparams = NULL; + } } -void EmergeManager::initMapgens(MapgenParams *mgparams) { - if (mapgen) - return; - - this->params = mgparams; - this->mapgen = getMapgen(); //only one mapgen for now! +void EmergeManager::loadMapgenParams() +{ + params.load(*g_settings); } -Mapgen *EmergeManager::getMapgen() { - if (!mapgen) { - mapgen = createMapgen(params->mg_name, 0, params, this); - if (!mapgen) { - infostream << "EmergeManager: falling back to mapgen v6" << std::endl; - delete params; - params = createMapgenParams("v6"); - mapgen = createMapgen("v6", 0, params, this); +void EmergeManager::initMapgens() +{ + if (mapgen.size()) + return; + + if (!params.sparams) { + params.sparams = createMapgenParams(params.mg_name); + if (!params.sparams) { + params.mg_name = DEFAULT_MAPGEN; + params.sparams = createMapgenParams(params.mg_name); + assert(params.sparams); } + params.sparams->readParams(g_settings); + } + + // Create the mapgens + for (u32 i = 0; i != emergethread.size(); i++) { + Mapgen *mg = createMapgen(params.mg_name, i, ¶ms); + assert(mg); + mapgen.push_back(mg); } - return mapgen; } -bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) { +Mapgen *EmergeManager::getCurrentMapgen() +{ + for (u32 i = 0; i != emergethread.size(); i++) { + if (emergethread[i]->isSameThread()) + return emergethread[i]->mapgen; + } + + return NULL; +} + + +void EmergeManager::startThreads() +{ + if (threads_active) + return; + + for (u32 i = 0; i != emergethread.size(); i++) + emergethread[i]->start(); + + threads_active = true; +} + + +void EmergeManager::stopThreads() +{ + if (!threads_active) + return; + + // Request thread stop in parallel + for (u32 i = 0; i != emergethread.size(); i++) { + emergethread[i]->stop(); + emergethread[i]->qevent.signal(); + } + + // Then do the waiting for each + for (u32 i = 0; i != emergethread.size(); i++) + emergethread[i]->wait(); + + threads_active = false; +} + + +bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) +{ std::map::const_iterator iter; BlockEmergeData *bedata; u16 count; u8 flags = 0; - + int idx = 0; + if (allow_generate) flags |= BLOCK_EMERGE_ALLOWGEN; { - JMutexAutoLock queuelock(queuemutex); - + MutexAutoLock queuelock(queuemutex); + count = blocks_enqueued.size(); if (count >= qlimit_total) return false; @@ -113,7 +257,7 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate u16 qlimit_peer = allow_generate ? qlimit_generate : qlimit_diskonly; if (count >= qlimit_peer) return false; - + iter = blocks_enqueued.find(p); if (iter != blocks_enqueued.end()) { bedata = iter->second; @@ -125,52 +269,41 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate bedata->flags = flags; bedata->peer_requested = peer_id; blocks_enqueued.insert(std::make_pair(p, bedata)); - - peer_queue_count[peer_id] = count + 1; - - emergethread->blockqueue.push(p); - } - emergethread->qevent.signal(); - - return true; -} + peer_queue_count[peer_id] = count + 1; -bool EmergeManager::popBlockEmerge(v3s16 *pos, u8 *flags) { - std::map::iterator iter; - JMutexAutoLock queuelock(queuemutex); - - if (emergethread->blockqueue.empty()) - return false; - v3s16 p = emergethread->blockqueue.front(); - emergethread->blockqueue.pop(); - - *pos = p; - - iter = blocks_enqueued.find(p); - if (iter == blocks_enqueued.end()) - return false; //uh oh, queue and map out of sync!! + // insert into the EmergeThread queue with the least items + int lowestitems = emergethread[0]->blockqueue.size(); + for (u32 i = 1; i != emergethread.size(); i++) { + int nitems = emergethread[i]->blockqueue.size(); + if (nitems < lowestitems) { + idx = i; + lowestitems = nitems; + } + } - BlockEmergeData *bedata = iter->second; - *flags = bedata->flags; - - peer_queue_count[bedata->peer_requested]--; + emergethread[idx]->blockqueue.push(p); + } + emergethread[idx]->qevent.signal(); - delete bedata; - blocks_enqueued.erase(iter); - return true; } -int EmergeManager::getGroundLevelAtPoint(v2s16 p) { - if (!mapgen) +int EmergeManager::getGroundLevelAtPoint(v2s16 p) +{ + if (mapgen.size() == 0 || !mapgen[0]) { + errorstream << "EmergeManager: getGroundLevelAtPoint() called" + " before mapgen initialized" << std::endl; return 0; - return mapgen->getGroundLevelAtPoint(p); + } + + return mapgen[0]->getGroundLevelAtPoint(p); } -bool EmergeManager::isBlockUnderground(v3s16 blockpos) { +bool EmergeManager::isBlockUnderground(v3s16 blockpos) +{ /* v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2, (blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2); @@ -180,144 +313,85 @@ bool EmergeManager::isBlockUnderground(v3s16 blockpos) { //yuck, but then again, should i bother being accurate? //the height of the nodes in a single block is quite variable - return blockpos.Y * (MAP_BLOCKSIZE + 1) <= params->water_level; + return blockpos.Y * (MAP_BLOCKSIZE + 1) <= params.water_level; } -u32 EmergeManager::getBlockSeed(v3s16 p) { - return (u32)(params->seed & 0xFFFFFFFF) + - p.Z * 38134234 + - p.Y * 42123 + - p.Y * 23; +void EmergeManager::getMapgenNames(std::list &mgnames) +{ + for (u32 i = 0; i != ARRLEN(reg_mapgens); i++) + mgnames.push_back(reg_mapgens[i].name); } -Mapgen *EmergeManager::createMapgen(std::string mgname, int mgid, - MapgenParams *mgparams, EmergeManager *emerge) { - std::map::const_iterator iter = mglist.find(mgname); - if (iter == mglist.end()) { +Mapgen *EmergeManager::createMapgen(const std::string &mgname, int mgid, + MapgenParams *mgparams) +{ + u32 i; + for (i = 0; i != ARRLEN(reg_mapgens) && mgname != reg_mapgens[i].name; i++); + if (i == ARRLEN(reg_mapgens)) { errorstream << "EmergeManager; mapgen " << mgname << - " not registered" << std::endl; + " not registered" << std::endl; return NULL; } - - MapgenFactory *mgfactory = iter->second; - return mgfactory->createMapgen(mgid, mgparams, emerge); -} - -MapgenParams *EmergeManager::createMapgenParams(std::string mgname) { - std::map::const_iterator iter = mglist.find(mgname); - if (iter == mglist.end()) { - errorstream << "EmergeManager: mapgen " << mgname << - " not registered" << std::endl; - return NULL; - } - - MapgenFactory *mgfactory = iter->second; - return mgfactory->createMapgenParams(); + MapgenFactory *mgfactory = reg_mapgens[i].factory; + return mgfactory->createMapgen(mgid, mgparams, this); } -MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { - std::string mg_name = settings->get("mg_name"); - MapgenParams *mgparams = createMapgenParams(mg_name); - - mgparams->mg_name = mg_name; - mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed"); - mgparams->water_level = settings->getS16("water_level"); - mgparams->chunksize = settings->getS16("chunksize"); - mgparams->flags = settings->getS32("mg_flags"); - - if (!mgparams->readParams(settings)) { - delete mgparams; +MapgenSpecificParams *EmergeManager::createMapgenParams(const std::string &mgname) +{ + u32 i; + for (i = 0; i < ARRLEN(reg_mapgens) && mgname != reg_mapgens[i].name; i++); + if (i == ARRLEN(reg_mapgens)) { + errorstream << "EmergeManager: Mapgen " << mgname << + " not registered" << std::endl; return NULL; } - return mgparams; -} - -void EmergeManager::setParamsToSettings(Settings *settings) { - settings->set("mg_name", params->mg_name); - settings->setU64("seed", params->seed); - settings->setS16("water_level", params->water_level); - settings->setS16("chunksize", params->chunksize); - settings->setFlagStr("mg_flags", params->flags, flagdesc_mapgen); - - params->writeParams(settings); -} - - -bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { - mglist.insert(std::make_pair(mgname, mgfactory)); - infostream << "EmergeManager: registered mapgen " << mgname << std::endl; + MapgenFactory *mgfactory = reg_mapgens[i].factory; + return mgfactory->createMapgenParams(); } +////////////////////////////// Emerge Thread ////////////////////////////////// -class MapEditEventIgnorer +bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { -public: - MapEditEventIgnorer(bool *flag): - m_flag(flag) - { - if(*m_flag == false) - *m_flag = true; - else - m_flag = NULL; - } + std::map::iterator iter; + MutexAutoLock queuelock(emerge->queuemutex); - ~MapEditEventIgnorer() - { - if(m_flag) - { - assert(*m_flag); - *m_flag = false; - } - } + if (blockqueue.empty()) + return false; + v3s16 p = blockqueue.front(); + blockqueue.pop(); -private: - bool *m_flag; -}; + *pos = p; -class MapEditEventAreaIgnorer -{ -public: - MapEditEventAreaIgnorer(VoxelArea *ignorevariable, const VoxelArea &a): - m_ignorevariable(ignorevariable) - { - if(m_ignorevariable->getVolume() == 0) - *m_ignorevariable = a; - else - m_ignorevariable = NULL; - } + iter = emerge->blocks_enqueued.find(p); + if (iter == emerge->blocks_enqueued.end()) + return false; //uh oh, queue and map out of sync!! - ~MapEditEventAreaIgnorer() - { - if(m_ignorevariable) - { - assert(m_ignorevariable->getVolume() != 0); - *m_ignorevariable = VoxelArea(); - } - } + BlockEmergeData *bedata = iter->second; + *flags = bedata->flags; -private: - VoxelArea *m_ignorevariable; -}; + emerge->peer_queue_count[bedata->peer_requested]--; + delete bedata; + emerge->blocks_enqueued.erase(iter); -#if 1 + return true; +} -#define EMERGE_DBG_OUT(x) \ - { if (enable_mapgen_debug_info) \ - infostream << "EmergeThread: " x << std::endl; } -bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, - BlockMakeData *data, bool allow_gen) { +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); - + MutexAutoLock envlock(m_server->m_env_mutex); + // Load sector if it isn't loaded if (map->getSectorNoGenerateNoEx(p2d) == NULL) map->loadSectorMeta(p2d); @@ -327,41 +401,42 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, 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"); - map->initBlockMake(data, p); - return true; + *b = block; + return map->initBlockMake(data, p); } - + *b = block; return false; } -void *EmergeThread::Thread() { - ThreadStarted(); - log_register_thread("EmergeThread"); +void *EmergeThread::run() +{ DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER v3s16 last_tried_pos(-32768,-32768,-32768); // For error output v3s16 p; - u8 flags; - + u8 flags = 0; + map = (ServerMap *)&(m_server->m_env->getMap()); emerge = m_server->m_emerge; - mapgen = emerge->getMapgen(); - - while (getRun()) + mapgen = emerge->mapgen[id]; + enable_mapgen_debug_info = emerge->mapgen_debug_info; + + while (!stopRequested()) try { - while (!emerge->popBlockEmerge(&p, &flags)) { + if (!popBlockEmerge(&p, &flags)) { qevent.wait(); - if (!getRun()) - goto exit_emerge_loop; + continue; } last_tried_pos = p; @@ -370,16 +445,16 @@ void *EmergeThread::Thread() { 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; - core::map modified_blocks; - - if (getBlockOrStartGen(p, &block, &data, allow_generate)) { + std::map modified_blocks; + + if (getBlockOrStartGen(p, &block, &data, allow_generate) && mapgen) { { ScopeProfiler sp(g_profiler, "EmergeThread: Mapgen::makeChunk", SPT_AVG); TimeTaker t("mapgen::make_block()"); @@ -392,12 +467,12 @@ void *EmergeThread::Thread() { { //envlock: usually 0ms, but can take either 30 or 400ms to acquire - JMutexAutoLock envlock(m_server->m_env_mutex); + MutexAutoLock 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) { /* @@ -409,16 +484,18 @@ void *EmergeThread::Thread() { // Ignore map edit events, they will not need to be sent // to anybody because the block hasn't been sent to anybody - MapEditEventAreaIgnorer + MapEditEventAreaIgnorer ign(&m_server->m_ignore_map_edit_events_area, VoxelArea(minp, maxp)); - { // takes about 90ms with -O1 on an e3-1230v2 - scriptapi_environment_on_generated(m_server->m_lua, - minp, maxp, emerge->getBlockSeed(minp)); + try { // takes about 90ms with -O1 on an e3-1230v2 + m_server->getScriptIface()->environment_OnGenerated( + minp, maxp, mapgen->blockseed); + } catch (LuaError &e) { + m_server->setAsyncFatalError("Lua: " + std::string(e.what())); } EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); - + m_server->m_env->activateBlock(block, 0); } } @@ -427,278 +504,52 @@ void *EmergeThread::Thread() { /* Set sent status of modified blocks on clients */ - - // NOTE: Server's clients are also behind the connection mutex - //conlock: consistently takes 30-40ms to acquire - JMutexAutoLock lock(m_server->m_con_mutex); // Add the originally fetched block to the modified list if (block) - modified_blocks.insert(p, block); - - // Set the modified blocks unsent for all the clients - for (core::map::Iterator - i = m_server->m_clients.getIterator(); - i.atEnd() == false; i++) { - RemoteClient *client = i.getNode()->getValue(); - if (modified_blocks.size() > 0) { - // Remove block from sent history - client->SetBlocksNotSent(modified_blocks); - } + 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 "<setAsyncFatalError(err.str()); } catch (SerializationError &e) { std::ostringstream err; - err << "Invalid data in MapBlock "<setAsyncFatalError(err.str()); } - - END_DEBUG_EXCEPTION_HANDLER(errorstream) -exit_emerge_loop: - log_deregister_thread(); - return NULL; -} - -#else - -void *EmergeThread::Thread() { - ThreadStarted(); - log_register_thread("EmergeThread"); - DSTACK(__FUNCTION_NAME); - BEGIN_DEBUG_EXCEPTION_HANDLER - - bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); - - v3s16 last_tried_pos(-32768,-32768,-32768); // For error output - ServerMap &map = ((ServerMap&)m_server->m_env->getMap()); - EmergeManager *emerge = m_server->m_emerge; - Mapgen *mapgen = emerge->getMapgen(); - - while(getRun()) - try { - QueuedBlockEmerge *qptr = m_server->m_emerge_queue.pop(); - if(qptr == NULL) - break; - SharedPtr q(qptr); - - v3s16 &p = q->pos; - v2s16 p2d(p.X,p.Z); - - last_tried_pos = p; - - /* - Do not generate over-limit - */ - if (blockpos_over_limit(p)) - continue; - - //infostream<<"EmergeThread::Thread(): running"<::Iterator i; - for (i=q->s.getIterator(); !i.atEnd(); i++) { - u8 flags = i.getNode()->getValue(); - if (!(flags & BLOCK_EMERGE_FLAG_FROMDISK)) { - only_from_disk = false; - break; - } - } - } - if (enable_mapgen_debug_info) - infostream<<"EmergeThread: p=" - <<"("<isGenerated() == false)){ - if(enable_mapgen_debug_info) - infostream<<"EmergeThread: generating"<::iterator iter; + iter = emerge->blocks_enqueued.find(p); + if (iter == emerge->blocks_enqueued.end()) + continue; //uh oh, queue and map out of sync!! - map.initBlockMake(&data, p); - } + BlockEmergeData *bedata = iter->second; + delete bedata; } - - /* - If generator was initialized, generate now when envlock is free. - */ - if(started_generate) { - { - ScopeProfiler sp(g_profiler, "EmergeThread: mapgen::make_block", - SPT_AVG); - TimeTaker t("mapgen::make_block()"); - - mapgen->makeChunk(&data); - - if (enable_mapgen_debug_info == false) - t.stop(true); // Hide output - } - - do{ // enable break - // Lock environment again to access the map - JMutexAutoLock envlock(m_server->m_env_mutex); - - ScopeProfiler sp(g_profiler, "EmergeThread: after " - "mapgen::make_block (envlock)", SPT_AVG); - - // Blit data back on map, update lighting, add mobs and - // whatever this does - map.finishBlockMake(&data, modified_blocks); - - // Get central block - block = map.getBlockNoCreateNoEx(p); - - // If block doesn't exist, don't try doing anything with it - // This happens if the block is not in generation boundaries - if(!block) - break; - - /* - 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)); - { - TimeTaker timer("on_generated"); - scriptapi_environment_on_generated(m_server->m_lua, - minp, maxp, emerge->getBlockSeed(minp)); - //int t = timer.stop(true); - //dstream<<"on_generated took "<m_env->activateBlock(block, 0); - }while(false); - } - - if(block == NULL) - got_block = false; - - /* - Set sent status of modified blocks on clients - */ - - // NOTE: Server's clients are also behind the connection mutex - JMutexAutoLock lock(m_server->m_con_mutex); - - /* - Add the originally fetched block to the modified list - */ - if(got_block) - modified_blocks.insert(p, block); - - /* - Set the modified blocks unsent for all the clients - */ - for(core::map::Iterator - i = m_server->m_clients.getIterator(); - i.atEnd() == false; i++) { - RemoteClient *client = i.getNode()->getValue(); - if(modified_blocks.size() > 0) { - // Remove block from sent history - client->SetBlocksNotSent(modified_blocks); - } - } - - -niters++; - } - catch (VersionMismatchException &e) { - std::ostringstream err; - err << "World data version mismatch in MapBlock "<setAsyncFatalError(err.str()); } - catch (SerializationError &e) { - std::ostringstream err; - err << "Invalid data in MapBlock "<setAsyncFatalError(err.str()); - } -printf("emergethread iterated %d times\n", niters); + END_DEBUG_EXCEPTION_HANDLER(errorstream) - log_deregister_thread(); return NULL; } - -#endif