X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=src%2Femerge.cpp;h=f97763718eacebb79d86f3653de7494c9b25a7a4;hb=45589fae58157c8a66c640a1db5795a42a86fc1c;hp=ee6650f9cd53ae4a4f5304601641abfe8a7e5962;hpb=5ec5b1cbd64a22e628be2cf03391883c44074811;p=dragonfireclient.git diff --git a/src/emerge.cpp b/src/emerge.cpp index ee6650f9c..f97763718 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 @@ -31,34 +32,60 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock.h" #include "serverobject.h" #include "settings.h" -#include "script.h" -#include "scriptapi.h" +#include "cpp_api/scriptapi.h" #include "profiler.h" #include "log.h" #include "nodedef.h" #include "biome.h" #include "emerge.h" #include "mapgen_v6.h" +#include "mapgen_v7.h" +#include "mapgen_indev.h" +#include "mapgen_singlenode.h" +#include "mapgen_math.h" -EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { +/////////////////////////////// Emerge Manager //////////////////////////////// + +EmergeManager::EmergeManager(IGameDef *gamedef) { //register built-in mapgens registerMapgen("v6", new MapgenFactoryV6()); + registerMapgen("v7", new MapgenFactoryV7()); + registerMapgen("indev", new MapgenFactoryIndev()); + registerMapgen("singlenode", new MapgenFactorySinglenode()); + registerMapgen("math", new MapgenFactoryMath()); - this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef); + this->ndef = gamedef->getNodeDefManager(); + this->biomedef = new BiomeDefManager(); this->params = 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"); + this->luaoverride_params = NULL; + this->luaoverride_params_modified = 0; + this->luaoverride_flagmask = 0; + + mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); queuemutex.Init(); - int nthreads = g_settings->get("num_emerge_threads").empty() ? - porting::getNumberOfProcessors() : - g_settings->getU16("num_emerge_threads"); + + int nthreads; + if (g_settings->get("num_emerge_threads").empty()) { + int nprocs = porting::getNumberOfProcessors(); + // leave a proc for the main thread and one for some other misc threads + nthreads = (nprocs > 2) ? nprocs - 2 : 1; + } else { + nthreads = g_settings->getU16("num_emerge_threads"); + } if (nthreads < 1) nthreads = 1; + qlimit_total = g_settings->getU16("emergequeue_limit_total"); + qlimit_diskonly = g_settings->get("emergequeue_limit_diskonly").empty() ? + nthreads * 5 + 1 : + g_settings->getU16("emergequeue_limit_diskonly"); + qlimit_generate = g_settings->get("emergequeue_limit_generate").empty() ? + nthreads + 1 : + g_settings->getU16("emergequeue_limit_generate"); + for (int i = 0; i != nthreads; i++) emergethread.push_back(new EmergeThread((Server *)gamedef, i)); @@ -67,16 +94,31 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { EmergeManager::~EmergeManager() { - for (int i = 0; i != emergethread.size(); i++) { + for (unsigned int i = 0; i != emergethread.size(); i++) { emergethread[i]->setRun(false); emergethread[i]->qevent.signal(); emergethread[i]->stop(); delete emergethread[i]; delete mapgen[i]; } + emergethread.clear(); + mapgen.clear(); + + for (unsigned int i = 0; i < ores.size(); i++) + delete ores[i]; + ores.clear(); + + for (unsigned int i = 0; i < decorations.size(); i++) + delete decorations[i]; + decorations.clear(); + for (std::map::iterator iter = mglist.begin(); + iter != mglist.end(); iter ++) { + delete iter->second; + } + mglist.clear(); + delete biomedef; - delete params; } @@ -86,8 +128,39 @@ void EmergeManager::initMapgens(MapgenParams *mgparams) { if (mapgen.size()) return; + // Resolve names of nodes for things that were registered + // (at this point, the registration period is over) + biomedef->resolveNodeNames(ndef); + + for (size_t i = 0; i != ores.size(); i++) + ores[i]->resolveNodeNames(ndef); + + for (size_t i = 0; i != decorations.size(); i++) + decorations[i]->resolveNodeNames(ndef); + + // Apply mapgen parameter overrides from Lua + if (luaoverride_params) { + if (luaoverride_params_modified & MGPARAMS_SET_MGNAME) + mgparams->mg_name = luaoverride_params->mg_name; + + if (luaoverride_params_modified & MGPARAMS_SET_SEED) + mgparams->seed = luaoverride_params->seed; + + if (luaoverride_params_modified & MGPARAMS_SET_WATER_LEVEL) + mgparams->water_level = luaoverride_params->water_level; + + if (luaoverride_params_modified & MGPARAMS_SET_FLAGS) { + mgparams->flags &= ~luaoverride_flagmask; + mgparams->flags |= luaoverride_params->flags; + } + + delete luaoverride_params; + luaoverride_params = NULL; + } + + // Create the mapgens this->params = mgparams; - for (int i = 0; i != emergethread.size(); i++) { + for (size_t i = 0; i != emergethread.size(); i++) { mg = createMapgen(params->mg_name, 0, params); if (!mg) { infostream << "EmergeManager: falling back to mapgen v6" << std::endl; @@ -100,6 +173,16 @@ void EmergeManager::initMapgens(MapgenParams *mgparams) { } +Mapgen *EmergeManager::getCurrentMapgen() { + for (unsigned int i = 0; i != emergethread.size(); i++) { + if (emergethread[i]->IsSameThread()) + return emergethread[i]->mapgen; + } + + return NULL; +} + + bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) { std::map::const_iterator iter; BlockEmergeData *bedata; @@ -136,8 +219,9 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate peer_queue_count[peer_id] = count + 1; + // insert into the EmergeThread queue with the least items int lowestitems = emergethread[0]->blockqueue.size(); - for (int i = 1; i != emergethread.size(); i++) { + for (unsigned int i = 1; i != emergethread.size(); i++) { int nitems = emergethread[i]->blockqueue.size(); if (nitems < lowestitems) { idx = i; @@ -153,35 +237,8 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate } -bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { - std::map::iterator iter; - JMutexAutoLock queuelock(emerge->queuemutex); - - if (blockqueue.empty()) - return false; - v3s16 p = blockqueue.front(); - blockqueue.pop(); - - *pos = p; - - iter = emerge->blocks_enqueued.find(p); - if (iter == emerge->blocks_enqueued.end()) - return false; //uh oh, queue and map out of sync!! - - BlockEmergeData *bedata = iter->second; - *flags = bedata->flags; - - emerge->peer_queue_count[bedata->peer_requested]--; - - delete bedata; - emerge->blocks_enqueued.erase(iter); - - return true; -} - - int EmergeManager::getGroundLevelAtPoint(v2s16 p) { - if (!mapgen[0]) { + if (mapgen.size() == 0 || !mapgen[0]) { errorstream << "EmergeManager: getGroundLevelAtPoint() called" " before mapgen initialized" << std::endl; return 0; @@ -209,7 +266,7 @@ u32 EmergeManager::getBlockSeed(v3s16 p) { return (u32)(params->seed & 0xFFFFFFFF) + p.Z * 38134234 + p.Y * 42123 + - p.Y * 23; + p.X * 23; } @@ -245,6 +302,8 @@ MapgenParams *EmergeManager::createMapgenParams(std::string mgname) { MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { std::string mg_name = settings->get("mg_name"); MapgenParams *mgparams = createMapgenParams(mg_name); + if (!mgparams) + return NULL; mgparams->mg_name = mg_name; mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed"); @@ -271,69 +330,40 @@ void EmergeManager::setParamsToSettings(Settings *settings) { } -bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { +void EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { mglist.insert(std::make_pair(mgname, mgfactory)); infostream << "EmergeManager: registered mapgen " << mgname << std::endl; } +////////////////////////////// Emerge Thread ////////////////////////////////// -class MapEditEventIgnorer -{ -public: - MapEditEventIgnorer(bool *flag): - m_flag(flag) - { - if(*m_flag == false) - *m_flag = true; - else - m_flag = NULL; - } - - ~MapEditEventIgnorer() - { - if(m_flag) - { - assert(*m_flag); - *m_flag = false; - } - } - -private: - bool *m_flag; -}; - -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(); - } - } +bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { + std::map::iterator iter; + JMutexAutoLock queuelock(emerge->queuemutex); -private: - VoxelArea *m_ignorevariable; -}; + if (blockqueue.empty()) + return false; + v3s16 p = blockqueue.front(); + blockqueue.pop(); + + *pos = p; + + iter = emerge->blocks_enqueued.find(p); + if (iter == emerge->blocks_enqueued.end()) + return false; //uh oh, queue and map out of sync!! + BlockEmergeData *bedata = iter->second; + *flags = bedata->flags; + + emerge->peer_queue_count[bedata->peer_requested]--; -#if 1 + delete bedata; + emerge->blocks_enqueued.erase(iter); + + 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) { @@ -356,8 +386,8 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, // 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; @@ -367,7 +397,7 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, void *EmergeThread::Thread() { ThreadStarted(); - log_register_thread("EmergeThread"); + log_register_thread("EmergeThread" + itos(id)); DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER @@ -377,14 +407,14 @@ void *EmergeThread::Thread() { map = (ServerMap *)&(m_server->m_env->getMap()); emerge = m_server->m_emerge; - mapgen = emerge->mapgen[id]; //emerge->getMapgen(); + mapgen = emerge->mapgen[id]; + enable_mapgen_debug_info = emerge->mapgen_debug_info; while (getRun()) try { - while (!popBlockEmerge(&p, &flags)) { + if (!popBlockEmerge(&p, &flags)) { qevent.wait(); - if (!getRun()) - goto exit_emerge_loop; + continue; } last_tried_pos = p; @@ -400,7 +430,7 @@ void *EmergeThread::Thread() { */ BlockMakeData data; MapBlock *block = NULL; - core::map modified_blocks; + std::map modified_blocks; if (getBlockOrStartGen(p, &block, &data, allow_generate)) { { @@ -436,7 +466,7 @@ void *EmergeThread::Thread() { 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, + SERVER_TO_SA(m_server)->environment_OnGenerated( minp, maxp, emerge->getBlockSeed(minp)); } @@ -456,13 +486,21 @@ void *EmergeThread::Thread() { JMutexAutoLock lock(m_server->m_con_mutex); // Add the originally fetched block to the modified list if (block) - modified_blocks.insert(p, block); + modified_blocks[p] = block; + + // Update weather data in mapblock + for(std::map::iterator + i = modified_blocks.begin(); + i != modified_blocks.end(); ++i) { + map->getHeat(m_server->m_env, MAP_BLOCKSIZE*i->first ,i->second); + map->getHumidity(m_server->m_env, MAP_BLOCKSIZE*i->first, i->second); + } // 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(); + for (std::map::iterator + i = m_server->m_clients.begin(); + i != m_server->m_clients.end(); ++i) { + RemoteClient *client = i->second; if (modified_blocks.size() > 0) { // Remove block from sent history client->SetBlocksNotSent(modified_blocks); @@ -489,239 +527,6 @@ void *EmergeThread::Thread() { } 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"<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