Beispiel #1
0
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);

	// Load sector if it isn't loaded
	if (map->getSectorNoGenerateNoEx(p2d) == NULL)
		map->loadSectorMeta(p2d);

	// Attempt to load block
	MapBlock *block = map->getBlockNoCreateNoEx(p);
	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");
		*b = block;
		return map->initBlockMake(data, p);
	}

	*b = block;
	return false;
}
Beispiel #2
0
bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b,
									BlockMakeData *data, bool allow_gen) {
	//envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire
	//JMutexAutoLock envlock(m_server->m_env_mutex);

	// Attempt to load block
	MapBlock *block = map->getBlockNoCreateNoEx(p);
	if (!block || block->isDummy()) {
		EMERGE_DBG_OUT("not in memory, attempting to load from disk ag="<<allow_gen<<" block="<<block<<" p="<<p);
		block = map->loadBlock(p);
		if(block)
		{
// 			block->pushElementsToCircuit(m_circuit);
// 			m_circuit->processElementsQueue(*map, map->getNodeDefManager());
		}
		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)) {
		EMERGE_DBG_OUT("generating b="<<block);
		*b = block;
		return map->initBlockMake(data, p);
	}

	*b = block;
	return false;
}
Beispiel #3
0
bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b,
	BlockMakeData *data, bool allow_gen)
{
#if !ENABLE_THREADS
	auto lock = map->m_nothread_locker.lock_unique_rec();
#endif

	MapBlock *block;
	{

	//envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire
	//JMutexAutoLock envlock(m_server->m_env_mutex);


	// Attempt to load block
	block = map->getBlockNoCreateNoEx(p);
	if (!block || block->isDummy()) {
		EMERGE_DBG_OUT("not in memory, attempting to load from disk ag="<<allow_gen<<" block="<<block<<" p="<<p);
		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)) {
		EMERGE_DBG_OUT("generating b="<<block);
		*b = block;
		return map->initBlockMake(data, p);
	}

	*b = block;
	return false;
}
Beispiel #4
0
MapBlock *EmergeThread::finishGen(v3s16 pos, BlockMakeData *bmdata,
	std::map<v3s16, MapBlock *> *modified_blocks)
{
	//MutexAutoLock envlock(m_server->m_env_mutex);
	ScopeProfiler sp(g_profiler,
		"EmergeThread: after Mapgen::makeChunk", SPT_AVG);

	/*
		Perform post-processing on blocks (invalidate lighting, queue liquid
		transforms, etc.) to finish block make
	*/
	m_map->finishBlockMake(bmdata, modified_blocks);

	MapBlock *block = m_map->getBlockNoCreateNoEx(pos, false, true);
	if (!block) {
		errorstream << "EmergeThread::finishGen: Couldn't grab block we "
			"just generated: " << PP(pos) << std::endl;
		return NULL;
	}

	v3s16 minp = bmdata->blockpos_min * MAP_BLOCKSIZE;
	v3s16 maxp = bmdata->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

/* thread unsafe
	MapEditEventAreaIgnorer ign(
		&m_server->m_ignore_map_edit_events_area,
		VoxelArea(minp, maxp));
*/

	/*
		Run Lua on_generated callbacks
	*/
	try {
		MAP_NOTHREAD_LOCK(m_map);
		m_server->getScriptIface()->environment_OnGenerated(
			minp, maxp, m_mapgen->blockseed);
	} catch (LuaError &e) {
		m_server->setAsyncFatalError("Lua: " + std::string(e.what()));
	}

	EMERGE_DBG_OUT("ended up with: " << analyze_block(block));

	/*
		Activate the block
	*/
	m_server->m_env->activateBlock(block, 0);

	return block;
}
Beispiel #5
0
EmergeAction EmergeThread::getBlockOrStartGen(
	v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata)
{
	//MutexAutoLock envlock(m_server->m_env_mutex);

	{
	MAP_NOTHREAD_LOCK(m_map);
	// 1). Attempt to fetch block from memory
	*block = m_map->getBlockNoCreateNoEx(pos, false, true);
	}
	if (*block && !(*block)->isDummy() && (*block)->isGenerated())
		return EMERGE_FROM_MEMORY;

	{
	MAP_NOTHREAD_LOCK(m_map);
	// 2). Attempt to load block from disk
	*block = m_map->loadBlock(pos);
	}

	if (*block && (*block)->isGenerated())
	{
		MAP_NOTHREAD_LOCK(m_map);
		m_map->prepareBlock(*block);
		return EMERGE_FROM_DISK;
	}

	{
	MAP_NOTHREAD_LOCK(m_map);
	// 3). Attempt to start generation
	if (allow_gen && m_map->initBlockMake(pos, bmdata))
		return EMERGE_GENERATED;
	}

/*
	verbosestream << "EmergeThread::getBlockOrStartGen : cancel pos=" << pos << " block="<< *block;
	if (*block)
		verbosestream << "dummy=" << (*block)->isDummy() << " generated="<< (*block)->isGenerated();
	verbosestream << std::endl;
*/

	// All attempts failed; cancel this block emerge
	return EMERGE_CANCELLED;
}
Beispiel #6
0
EmergeAction EmergeThread::getBlockOrStartGen(
	v3s16 pos, bool allow_gen, MapBlock **block, BlockMakeData *bmdata)
{
	MutexAutoLock envlock(m_server->m_env_mutex);

	// 1). Attempt to fetch block from memory
	*block = m_map->getBlockNoCreateNoEx(pos);
	if (*block && !(*block)->isDummy() && (*block)->isGenerated())
		return EMERGE_FROM_MEMORY;

	// 2). Attempt to load block from disk
	*block = m_map->loadBlock(pos);
	if (*block && (*block)->isGenerated())
		return EMERGE_FROM_DISK;

	// 3). Attempt to start generation
	if (allow_gen && m_map->initBlockMake(pos, bmdata))
		return EMERGE_GENERATED;

	// All attempts failed; cancel this block emerge
	return EMERGE_CANCELLED;
}
Beispiel #7
0
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;
}