Make map generator as much threaded as possible (not much benefit with current generator because of small generator chunk size (a single MapBlock))

This commit is contained in:
Perttu Ahola 2011-11-26 15:53:52 +02:00
parent 769cc9879f
commit b2ccbdffc1
3 changed files with 88 additions and 105 deletions

View File

@ -1331,7 +1331,7 @@ minetest.register_on_respawnplayer(function(player)
end) end)
minetest.register_on_generated(function(minp, maxp) minetest.register_on_generated(function(minp, maxp)
--print("on_generated: minp="..dump(minp).." maxp="..dump(maxp)) print("on_generated: minp="..dump(minp).." maxp="..dump(maxp))
--cp = {x=(minp.x+maxp.x)/2, y=(minp.y+maxp.y)/2, z=(minp.z+maxp.z)/2} --cp = {x=(minp.x+maxp.x)/2, y=(minp.y+maxp.y)/2, z=(minp.z+maxp.z)/2}
--minetest.env:add_node(cp, {name="sand"}) --minetest.env:add_node(cp, {name="sand"})
end) end)

View File

@ -2163,6 +2163,16 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
/*infostream<<"Resulting vmanip:"<<std::endl; /*infostream<<"Resulting vmanip:"<<std::endl;
data->vmanip.print(infostream);*/ data->vmanip.print(infostream);*/
// Make sure affected blocks are loaded
for(s16 x=-1; x<=1; x++)
for(s16 z=-1; z<=1; z++)
for(s16 y=-1; y<=1; y++)
{
v3s16 p(blockpos.X+x, blockpos.Y+y, blockpos.Z+z);
// Load from disk if not already in memory
emergeBlock(p, false);
}
/* /*
Blit generated stuff to map Blit generated stuff to map
NOTE: blitBackAll adds nearly everything to changed_blocks NOTE: blitBackAll adds nearly everything to changed_blocks

View File

@ -44,6 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "nodedef.h" #include "nodedef.h"
#include "tooldef.h" #include "tooldef.h"
#include "craftdef.h" #include "craftdef.h"
#include "mapgen.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@ -143,12 +144,7 @@ void * EmergeThread::Thread()
/* /*
Do not generate over-limit Do not generate over-limit
*/ */
if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE if(blockpos_over_limit(p))
|| p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
|| p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
continue; continue;
//infostream<<"EmergeThread::Thread(): running"<<std::endl; //infostream<<"EmergeThread::Thread(): running"<<std::endl;
@ -192,66 +188,91 @@ void * EmergeThread::Thread()
ServerMap &map = ((ServerMap&)m_server->m_env->getMap()); ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
//core::map<v3s16, MapBlock*> changed_blocks;
//core::map<v3s16, MapBlock*> lighting_invalidated_blocks;
MapBlock *block = NULL; MapBlock *block = NULL;
bool got_block = true; bool got_block = true;
core::map<v3s16, MapBlock*> modified_blocks; core::map<v3s16, MapBlock*> modified_blocks;
/* /*
Fetch block from map or generate a single block Try to fetch block from memory or disk.
If not found and asked to generate, initialize generator.
*/ */
bool started_generate = false;
mapgen::BlockMakeData data;
{ {
JMutexAutoLock envlock(m_server->m_env_mutex); JMutexAutoLock envlock(m_server->m_env_mutex);
// Load sector if it isn't loaded // Load sector if it isn't loaded
if(map.getSectorNoGenerateNoEx(p2d) == NULL) if(map.getSectorNoGenerateNoEx(p2d) == NULL)
//map.loadSectorFull(p2d);
map.loadSectorMeta(p2d); map.loadSectorMeta(p2d);
// Attempt to load block
block = map.getBlockNoCreateNoEx(p); block = map.getBlockNoCreateNoEx(p);
if(!block || block->isDummy() || !block->isGenerated()) if(!block || block->isDummy() || !block->isGenerated())
{ {
if(enable_mapgen_debug_info) if(enable_mapgen_debug_info)
infostream<<"EmergeThread: not in memory, loading"<<std::endl; infostream<<"EmergeThread: not in memory, "
<<"attempting to load from disk"<<std::endl;
// Get, load or create sector
/*ServerMapSector *sector =
(ServerMapSector*)map.createSector(p2d);*/
// Load/generate block
/*block = map.emergeBlock(p, sector, changed_blocks,
lighting_invalidated_blocks);*/
block = map.loadBlock(p); block = map.loadBlock(p);
}
if(only_from_disk == false) // If could not load and allowed to generate, start generation
{ // inside this same envlock
if(block == NULL || block->isGenerated() == false) if(only_from_disk == false &&
{ (block == NULL || block->isGenerated() == false)){
if(enable_mapgen_debug_info) if(enable_mapgen_debug_info)
infostream<<"EmergeThread: generating"<<std::endl; infostream<<"EmergeThread: generating"<<std::endl;
block = map.generateBlock(p, modified_blocks); started_generate = true;
map.initBlockMake(&data, p);
}
}
/*
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::make_block(&data);
if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output
}
{
// 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);
/*
Do some post-generate stuff
*/
v3s16 minp = block->getPos()*MAP_BLOCKSIZE; v3s16 minp = block->getPos()*MAP_BLOCKSIZE;
v3s16 maxp = minp + v3s16(1,1,1)*(MAP_BLOCKSIZE-1); v3s16 maxp = minp + v3s16(1,1,1)*(MAP_BLOCKSIZE-1);
scriptapi_environment_on_generated(m_server->m_lua, scriptapi_environment_on_generated(m_server->m_lua,
minp, maxp); minp, maxp);
}
}
if(enable_mapgen_debug_info) if(enable_mapgen_debug_info)
infostream<<"EmergeThread: ended up with: " infostream<<"EmergeThread: ended up with: "
<<analyze_block(block)<<std::endl; <<analyze_block(block)<<std::endl;
if(block == NULL)
{
got_block = false;
}
else
{
/* /*
Ignore map edit events, they will not need to be Ignore map edit events, they will not need to be
sent to anybody because the block hasn't been sent sent to anybody because the block hasn't been sent
@ -263,57 +284,9 @@ void * EmergeThread::Thread()
m_server->m_env->activateBlock(block, 3600); m_server->m_env->activateBlock(block, 3600);
} }
} }
else
{
/*if(block->getLightingExpired()){
lighting_invalidated_blocks[block->getPos()] = block;
}*/
}
// TODO: Some additional checking and lighting updating, if(block == NULL)
// see emergeBlock got_block = false;
}
{//envlock
JMutexAutoLock envlock(m_server->m_env_mutex);
if(got_block)
{
/*
Collect a list of blocks that have been modified in
addition to the fetched one.
*/
#if 0
if(lighting_invalidated_blocks.size() > 0)
{
/*infostream<<"lighting "<<lighting_invalidated_blocks.size()
<<" blocks"<<std::endl;*/
// 50-100ms for single block generation
//TimeTaker timer("** EmergeThread updateLighting");
// Update lighting without locking the environment mutex,
// add modified blocks to changed blocks
map.updateLighting(lighting_invalidated_blocks, modified_blocks);
}
// Add all from changed_blocks to modified_blocks
for(core::map<v3s16, MapBlock*>::Iterator i = changed_blocks.getIterator();
i.atEnd() == false; i++)
{
MapBlock *block = i.getNode()->getValue();
modified_blocks.insert(block->getPos(), block);
}
#endif
}
// If we got no block, there should be no invalidated blocks
else
{
//assert(lighting_invalidated_blocks.size() == 0);
}
}//envlock
/* /*
Set sent status of modified blocks on clients Set sent status of modified blocks on clients