+#include "voxel.h"
+
+
+struct MapgenDesc {
+ const char *name;
+ MapgenFactory *factory;
+ bool is_user_visible;
+};
+
+class EmergeThread : public Thread {
+public:
+ bool enable_mapgen_debug_info;
+ int id;
+
+ EmergeThread(Server *server, int ethreadid);
+ ~EmergeThread();
+
+ void *run();
+ void signal();
+
+ // Requires queue mutex held
+ bool pushBlock(v3s16 pos);
+
+ void cancelPendingItems();
+
+ static void runCompletionCallbacks(
+ v3s16 pos, EmergeAction action,
+ const EmergeCallbackList &callbacks);
+
+private:
+ Server *m_server;
+ ServerMap *m_map;
+ EmergeManager *m_emerge;
+ Mapgen *m_mapgen;
+
+ Event m_queue_event;
+ std::queue<v3s16> m_block_queue;
+
+ bool popBlockEmerge(v3s16 *pos, BlockEmergeData *bedata);
+
+ EmergeAction getBlockOrStartGen(
+ v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *data);
+ MapBlock *finishGen(v3s16 pos, BlockMakeData *bmdata,
+ std::map<v3s16, MapBlock *> *modified_blocks);
+
+ friend class EmergeManager;
+};
+
+////
+//// Built-in mapgens
+////
+
+MapgenDesc g_reg_mapgens[] = {
+ {"v5", new MapgenFactoryV5, true},
+ {"v6", new MapgenFactoryV6, true},
+ {"v7", new MapgenFactoryV7, true},
+ {"fractal", new MapgenFactoryFractal, false},
+ {"singlenode", new MapgenFactorySinglenode, false},
+};
+
+////
+//// EmergeManager
+////
+
+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->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
+ // some other misc thread
+ s16 nthreads = 0;
+ if (!g_settings->getS16NoEx("num_emerge_threads", nthreads))
+ nthreads = Thread::getNumberOfProcessors() - 2;
+ if (nthreads < 1)
+ nthreads = 1;
+
+ m_qlimit_total = g_settings->getU16("emergequeue_limit_total");
+ 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))
+ m_qlimit_generate = nthreads + 1;
+
+ // don't trust user input for something very important like this
+ if (m_qlimit_total < 1)
+ m_qlimit_total = 1;
+ if (m_qlimit_diskonly < 1)
+ m_qlimit_diskonly = 1;
+ if (m_qlimit_generate < 1)
+ m_qlimit_generate = 1;
+
+ for (s16 i = 0; i < nthreads; i++)
+ m_threads.push_back(new EmergeThread((Server *)gamedef, i));
+
+ infostream << "EmergeManager: using " << nthreads << " threads" << std::endl;
+}
+
+
+EmergeManager::~EmergeManager()
+{
+ for (u32 i = 0; i != m_threads.size(); i++) {
+ EmergeThread *thread = m_threads[i];
+
+ if (m_threads_active) {
+ thread->stop();
+ thread->signal();
+ thread->wait();
+ }
+
+ delete thread;
+ delete m_mapgens[i];
+ }
+
+ delete biomemgr;
+ delete oremgr;
+ delete decomgr;
+ delete schemmgr;
+
+ delete params.sparams;
+}
+
+
+void EmergeManager::loadMapgenParams()
+{
+ params.load(*g_settings);
+}