mirror of
https://github.com/minetest/minetest.git
synced 2024-11-04 14:53:45 +01:00
map generation framework under development... not quite operational at this point.
This commit is contained in:
parent
8788fffec0
commit
be851871cd
@ -76,21 +76,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
// is very low
|
// is very low
|
||||||
#define BLOCK_SEND_DISABLE_LIMITS_MAX_D 1
|
#define BLOCK_SEND_DISABLE_LIMITS_MAX_D 1
|
||||||
|
|
||||||
// The fps limiter will leave this much free time
|
|
||||||
//#define FREETIME_RATIO 0.15
|
|
||||||
//#define FREETIME_RATIO 0.0
|
|
||||||
#define FREETIME_RATIO 0.05
|
|
||||||
|
|
||||||
#define PLAYER_INVENTORY_SIZE (8*4)
|
#define PLAYER_INVENTORY_SIZE (8*4)
|
||||||
|
|
||||||
#define SIGN_TEXT_MAX_LENGTH 50
|
#define SIGN_TEXT_MAX_LENGTH 50
|
||||||
|
|
||||||
// Whether to catch all std::exceptions.
|
// Whether to catch all std::exceptions.
|
||||||
// Assert will be called on such an event.
|
// Assert will be called on such an event.
|
||||||
#ifdef DEBUG
|
// In debug mode, leave these for the debugger and don't catch them.
|
||||||
#define CATCH_UNHANDLED_EXCEPTIONS 0
|
#ifdef NDEBUG
|
||||||
#else
|
|
||||||
#define CATCH_UNHANDLED_EXCEPTIONS 1
|
#define CATCH_UNHANDLED_EXCEPTIONS 1
|
||||||
|
#else
|
||||||
|
#define CATCH_UNHANDLED_EXCEPTIONS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -49,8 +49,8 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||||
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||||
g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
|
g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
|
||||||
g_settings.setDefault("max_block_send_distance", "6");
|
g_settings.setDefault("max_block_send_distance", "7");
|
||||||
g_settings.setDefault("max_block_generate_distance", "6");
|
g_settings.setDefault("max_block_generate_distance", "7");
|
||||||
g_settings.setDefault("time_send_interval", "20");
|
g_settings.setDefault("time_send_interval", "20");
|
||||||
g_settings.setDefault("time_speed", "96");
|
g_settings.setDefault("time_speed", "96");
|
||||||
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
|
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
|
||||||
|
77
src/main.cpp
77
src/main.cpp
@ -168,7 +168,7 @@ TODO: Make fetching sector's blocks more efficient when rendering
|
|||||||
|
|
||||||
TODO: Flowing water animation
|
TODO: Flowing water animation
|
||||||
|
|
||||||
FIXME: The new texture stuff is slow on wine
|
FIXME(FIXED): The new texture stuff is slow on wine
|
||||||
- A basic grassy ground block takes 20-40ms
|
- A basic grassy ground block takes 20-40ms
|
||||||
- A bit more complicated block can take 270ms
|
- A bit more complicated block can take 270ms
|
||||||
- On linux, a similar one doesn't take long at all (14ms)
|
- On linux, a similar one doesn't take long at all (14ms)
|
||||||
@ -182,6 +182,15 @@ FIXME: The new texture stuff is slow on wine
|
|||||||
is fast to compare, which refers to a cached string, or
|
is fast to compare, which refers to a cached string, or
|
||||||
* Make TextureSpec for using instead of strings
|
* Make TextureSpec for using instead of strings
|
||||||
|
|
||||||
|
FIXME(FIXED): A lock condition is possible:
|
||||||
|
1) MapBlock::updateMesh() is called from client asynchronously:
|
||||||
|
- AsyncProcessData() -> Map::updateMeshes()
|
||||||
|
2) Asynchronous locks m_temp_mods_mutex
|
||||||
|
3) MapBlock::updateMesh() is called from client synchronously:
|
||||||
|
- Client::step() -> Environment::step()
|
||||||
|
4) Synchronous starts waiting for m_temp_mods_mutex
|
||||||
|
5) Asynchronous calls getTexture, which starts waiting for main thread
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@ -255,6 +264,20 @@ Map:
|
|||||||
NOTE: There are some lighting-related todos and fixmes in
|
NOTE: There are some lighting-related todos and fixmes in
|
||||||
ServerMap::emergeBlock. And there always will be. 8)
|
ServerMap::emergeBlock. And there always will be. 8)
|
||||||
|
|
||||||
|
TODO: Mineral and ground material properties
|
||||||
|
- This way mineral ground toughness can be calculated with just
|
||||||
|
some formula, as well as tool strengths
|
||||||
|
|
||||||
|
TODO: Change AttributeList to split the area into smaller sections so
|
||||||
|
that searching won't be as heavy.
|
||||||
|
|
||||||
|
TODO: Remove HMParams
|
||||||
|
|
||||||
|
TODO: Flowing water to actually contain flow direction information
|
||||||
|
|
||||||
|
TODO: Remove duplicate lighting implementation from Map (leave
|
||||||
|
VoxelManipulator, which is faster)
|
||||||
|
|
||||||
FEATURE: Map generator version 2
|
FEATURE: Map generator version 2
|
||||||
- Create surface areas based on central points; a given point's
|
- Create surface areas based on central points; a given point's
|
||||||
area type is given by the nearest central point
|
area type is given by the nearest central point
|
||||||
@ -269,6 +292,11 @@ FEATURE: Map generator version 2
|
|||||||
FEATURE: The map could be generated procedually:
|
FEATURE: The map could be generated procedually:
|
||||||
- This would need the map to be generated in larger pieces
|
- This would need the map to be generated in larger pieces
|
||||||
- How large? How do they connect to each other?
|
- How large? How do they connect to each other?
|
||||||
|
- It has to be split vertically also
|
||||||
|
- Lighting would not have to be necessarily calculated until
|
||||||
|
the blocks are actually needed - it would be quite fast
|
||||||
|
- Something like 64*64*16 MapBlocks?
|
||||||
|
- TODO: Separate lighting and block generation
|
||||||
* Make the stone level with a heightmap
|
* Make the stone level with a heightmap
|
||||||
* Carve out stuff in the stone
|
* Carve out stuff in the stone
|
||||||
* Dump dirt all around, and simulate it falling off steep
|
* Dump dirt all around, and simulate it falling off steep
|
||||||
@ -283,20 +311,13 @@ FEATURE: The map could be generated procedually:
|
|||||||
parameter field is free for this.
|
parameter field is free for this.
|
||||||
- Simulate rock falling from cliffs when water has removed
|
- Simulate rock falling from cliffs when water has removed
|
||||||
enough solid rock from the bottom
|
enough solid rock from the bottom
|
||||||
|
TODO: Lazy lighting updates:
|
||||||
TODO: Mineral and ground material properties
|
- Set updateLighting to ignore MapBlocks with expired lighting,
|
||||||
- This way mineral ground toughness can be calculated with just
|
except the blocks specified to it
|
||||||
some formula, as well as tool strengths
|
- When a MapBlock is generated, lighting expires in all blocks
|
||||||
|
touching it (26 blocks + self)
|
||||||
TODO: Change AttributeList to split the area into smaller sections so
|
- When a lighting-wise valid MapBlock is needed and lighting of it
|
||||||
that searching won't be as heavy.
|
has expired, what to do?
|
||||||
|
|
||||||
TODO: Remove HMParams
|
|
||||||
|
|
||||||
TODO: Flowing water to actually contain flow direction information
|
|
||||||
|
|
||||||
TODO: Remove duplicate lighting implementation from Map (leave
|
|
||||||
VoxelManipulator, which is faster)
|
|
||||||
|
|
||||||
Doing now:
|
Doing now:
|
||||||
----------
|
----------
|
||||||
@ -1522,6 +1543,16 @@ int main(int argc, char *argv[])
|
|||||||
srand(time(0));
|
srand(time(0));
|
||||||
mysrand(time(0));
|
mysrand(time(0));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pre-initialize some stuff with a dummy irrlicht wrapper.
|
||||||
|
|
||||||
|
These are needed for unit tests at least.
|
||||||
|
*/
|
||||||
|
|
||||||
|
IIrrlichtWrapper irrlicht_dummy;
|
||||||
|
|
||||||
|
init_mapnode(&irrlicht_dummy);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Run unit tests
|
Run unit tests
|
||||||
*/
|
*/
|
||||||
@ -1684,7 +1715,7 @@ int main(int argc, char *argv[])
|
|||||||
skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0));
|
skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Preload some textures
|
Preload some textures and stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
init_content_inventory_texture_paths();
|
init_content_inventory_texture_paths();
|
||||||
@ -2131,20 +2162,6 @@ int main(int argc, char *argv[])
|
|||||||
dtime_jitter1_max_fraction
|
dtime_jitter1_max_fraction
|
||||||
= dtime_jitter1_max_sample / (dtime_avg1+0.001);
|
= dtime_jitter1_max_sample / (dtime_avg1+0.001);
|
||||||
jitter1_max = 0.0;
|
jitter1_max = 0.0;
|
||||||
|
|
||||||
/*
|
|
||||||
Control freetime ratio
|
|
||||||
*/
|
|
||||||
/*if(dtime_jitter1_max_fraction > DTIME_JITTER_MAX_FRACTION)
|
|
||||||
{
|
|
||||||
if(g_freetime_ratio < FREETIME_RATIO_MAX)
|
|
||||||
g_freetime_ratio += 0.01;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(g_freetime_ratio > FREETIME_RATIO_MIN)
|
|
||||||
g_freetime_ratio -= 0.01;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
580
src/map.cpp
580
src/map.cpp
@ -67,10 +67,8 @@ Map::~Map()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MapSector * Map::getSectorNoGenerate(v2s16 p)
|
MapSector * Map::getSectorNoGenerateNoExNoLock(v2s16 p)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
|
||||||
|
|
||||||
if(m_sector_cache != NULL && p == m_sector_cache_p){
|
if(m_sector_cache != NULL && p == m_sector_cache_p){
|
||||||
MapSector * sector = m_sector_cache;
|
MapSector * sector = m_sector_cache;
|
||||||
// Reset inactivity timer
|
// Reset inactivity timer
|
||||||
@ -79,11 +77,9 @@ MapSector * Map::getSectorNoGenerate(v2s16 p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
core::map<v2s16, MapSector*>::Node *n = m_sectors.find(p);
|
core::map<v2s16, MapSector*>::Node *n = m_sectors.find(p);
|
||||||
// If sector doesn't exist, throw an exception
|
|
||||||
if(n == NULL)
|
if(n == NULL)
|
||||||
{
|
return NULL;
|
||||||
throw InvalidPositionException();
|
|
||||||
}
|
|
||||||
|
|
||||||
MapSector *sector = n->getValue();
|
MapSector *sector = n->getValue();
|
||||||
|
|
||||||
@ -91,13 +87,27 @@ MapSector * Map::getSectorNoGenerate(v2s16 p)
|
|||||||
m_sector_cache_p = p;
|
m_sector_cache_p = p;
|
||||||
m_sector_cache = sector;
|
m_sector_cache = sector;
|
||||||
|
|
||||||
//MapSector * ref(sector);
|
|
||||||
|
|
||||||
// Reset inactivity timer
|
// Reset inactivity timer
|
||||||
sector->usage_timer = 0.0;
|
sector->usage_timer = 0.0;
|
||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapSector * Map::getSectorNoGenerateNoEx(v2s16 p)
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_sector_mutex);
|
||||||
|
|
||||||
|
return getSectorNoGenerateNoExNoLock(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
MapSector * Map::getSectorNoGenerate(v2s16 p)
|
||||||
|
{
|
||||||
|
MapSector *sector = getSectorNoGenerateNoEx(p);
|
||||||
|
if(sector == NULL)
|
||||||
|
throw InvalidPositionException();
|
||||||
|
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
MapBlock * Map::getBlockNoCreate(v3s16 p3d)
|
MapBlock * Map::getBlockNoCreate(v3s16 p3d)
|
||||||
{
|
{
|
||||||
v2s16 p2d(p3d.X, p3d.Z);
|
v2s16 p2d(p3d.X, p3d.Z);
|
||||||
@ -631,6 +641,8 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
//bool debug=true;
|
//bool debug=true;
|
||||||
//u32 count_was = modified_blocks.size();
|
//u32 count_was = modified_blocks.size();
|
||||||
|
|
||||||
|
core::map<v3s16, MapBlock*> blocks_to_update;
|
||||||
|
|
||||||
core::map<v3s16, bool> light_sources;
|
core::map<v3s16, bool> light_sources;
|
||||||
|
|
||||||
core::map<v3s16, u8> unlight_from;
|
core::map<v3s16, u8> unlight_from;
|
||||||
@ -650,6 +662,8 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
v3s16 pos = block->getPos();
|
v3s16 pos = block->getPos();
|
||||||
modified_blocks.insert(pos, block);
|
modified_blocks.insert(pos, block);
|
||||||
|
|
||||||
|
blocks_to_update.insert(pos, block);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Clear all light from block
|
Clear all light from block
|
||||||
*/
|
*/
|
||||||
@ -699,10 +713,12 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
}
|
}
|
||||||
else if(bank == LIGHTBANK_NIGHT)
|
else if(bank == LIGHTBANK_NIGHT)
|
||||||
{
|
{
|
||||||
|
// For night lighting, sunlight is not propagated
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Invalid lighting bank
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,7 +726,7 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
<<pos.X<<","<<pos.Y<<","<<pos.Z<<") not valid"
|
<<pos.X<<","<<pos.Y<<","<<pos.Z<<") not valid"
|
||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
|
|
||||||
// Else get the block below and loop to it
|
// Bottom sunlight is not valid; get the block and loop to it
|
||||||
|
|
||||||
pos.Y--;
|
pos.Y--;
|
||||||
try{
|
try{
|
||||||
@ -737,13 +753,6 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
dstream<<"unspreadLight modified "<<diff<<std::endl;
|
dstream<<"unspreadLight modified "<<diff<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Spread light from propagated sunlight?
|
|
||||||
// Yes, add it to light_sources... somehow.
|
|
||||||
// It has to be added at somewhere above, in the loop.
|
|
||||||
// TODO
|
|
||||||
// NOTE: This actually works fine without doing so
|
|
||||||
// - Find out why it works
|
|
||||||
|
|
||||||
{
|
{
|
||||||
TimeTaker timer("spreadLight");
|
TimeTaker timer("spreadLight");
|
||||||
spreadLight(bank, light_sources, modified_blocks);
|
spreadLight(bank, light_sources, modified_blocks);
|
||||||
@ -760,16 +769,43 @@ void Map::updateLighting(enum LightBank bank,
|
|||||||
{
|
{
|
||||||
//MapVoxelManipulator vmanip(this);
|
//MapVoxelManipulator vmanip(this);
|
||||||
|
|
||||||
|
// Make a manual voxel manipulator and load all the blocks
|
||||||
|
// that touch the requested blocks
|
||||||
ManualMapVoxelManipulator vmanip(this);
|
ManualMapVoxelManipulator vmanip(this);
|
||||||
|
|
||||||
core::map<v3s16, MapBlock*>::Iterator i;
|
core::map<v3s16, MapBlock*>::Iterator i;
|
||||||
i = a_blocks.getIterator();
|
i = blocks_to_update.getIterator();
|
||||||
for(; i.atEnd() == false; i++)
|
for(; i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
MapBlock *block = i.getNode()->getValue();
|
MapBlock *block = i.getNode()->getValue();
|
||||||
v3s16 p = block->getPos();
|
v3s16 p = block->getPos();
|
||||||
|
|
||||||
|
// Add all surrounding blocks
|
||||||
vmanip.initialEmerge(p - v3s16(1,1,1), p + v3s16(1,1,1));
|
vmanip.initialEmerge(p - v3s16(1,1,1), p + v3s16(1,1,1));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add all surrounding blocks that have up-to-date lighting
|
||||||
|
NOTE: This doesn't quite do the job (not everything
|
||||||
|
appropriate is lighted)
|
||||||
|
*/
|
||||||
|
/*for(s16 z=-1; z<=1; z++)
|
||||||
|
for(s16 y=-1; y<=1; y++)
|
||||||
|
for(s16 x=-1; x<=1; x++)
|
||||||
|
{
|
||||||
|
v3s16 p(x,y,z);
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(p);
|
||||||
|
if(block == NULL)
|
||||||
|
continue;
|
||||||
|
if(block->isDummy())
|
||||||
|
continue;
|
||||||
|
if(block->getLightingExpired())
|
||||||
|
continue;
|
||||||
|
vmanip.initialEmerge(p, p);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Lighting of block will be updated completely
|
||||||
|
block->setLightingExpired(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
//TimeTaker timer("unSpreadLight");
|
//TimeTaker timer("unSpreadLight");
|
||||||
vmanip.unspreadLight(bank, unlight_from, light_sources);
|
vmanip.unspreadLight(bank, unlight_from, light_sources);
|
||||||
@ -1407,6 +1443,8 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
|||||||
u32 loopcount = 0;
|
u32 loopcount = 0;
|
||||||
u32 initial_size = m_transforming_liquid.size();
|
u32 initial_size = m_transforming_liquid.size();
|
||||||
|
|
||||||
|
//dstream<<"transformLiquids(): initial_size="<<initial_size<<std::endl;
|
||||||
|
|
||||||
while(m_transforming_liquid.size() != 0)
|
while(m_transforming_liquid.size() != 0)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1682,6 +1720,12 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
|
|||||||
Map(dout_server),
|
Map(dout_server),
|
||||||
m_heightmap(NULL)
|
m_heightmap(NULL)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//m_chunksize = 64;
|
||||||
|
//m_chunksize = 16;
|
||||||
|
//m_chunksize = 8;
|
||||||
|
m_chunksize = 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Experimental and debug stuff
|
Experimental and debug stuff
|
||||||
*/
|
*/
|
||||||
@ -1917,18 +1961,6 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
|
|||||||
dstream<<DTIME<<"Initializing new map."<<std::endl;
|
dstream<<DTIME<<"Initializing new map."<<std::endl;
|
||||||
|
|
||||||
// Create master heightmap
|
// Create master heightmap
|
||||||
/*ValueGenerator *maxgen =
|
|
||||||
ValueGenerator::deSerialize(hmp.randmax);
|
|
||||||
ValueGenerator *factorgen =
|
|
||||||
ValueGenerator::deSerialize(hmp.randfactor);
|
|
||||||
ValueGenerator *basegen =
|
|
||||||
ValueGenerator::deSerialize(hmp.base);
|
|
||||||
m_heightmap = new UnlimitedHeightmap
|
|
||||||
(hmp.blocksize, maxgen, factorgen, basegen, &m_padb);*/
|
|
||||||
|
|
||||||
/*m_heightmap = new UnlimitedHeightmap
|
|
||||||
(hmp.blocksize, &m_padb);*/
|
|
||||||
|
|
||||||
m_heightmap = new UnlimitedHeightmap
|
m_heightmap = new UnlimitedHeightmap
|
||||||
(32, &m_padb);
|
(32, &m_padb);
|
||||||
|
|
||||||
@ -1966,28 +1998,133 @@ ServerMap::~ServerMap()
|
|||||||
|
|
||||||
if(m_heightmap != NULL)
|
if(m_heightmap != NULL)
|
||||||
delete m_heightmap;
|
delete m_heightmap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Free all MapChunks
|
||||||
|
*/
|
||||||
|
core::map<v2s16, MapChunk*>::Iterator i = m_chunks.getIterator();
|
||||||
|
for(; i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
MapChunk *chunk = i.getNode()->getValue();
|
||||||
|
delete chunk;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MapSector * ServerMap::emergeSector(v2s16 p2d)
|
MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos)
|
||||||
|
{
|
||||||
|
// Return if chunk already exists
|
||||||
|
MapChunk *chunk = getChunk(chunkpos);
|
||||||
|
if(chunk)
|
||||||
|
return chunk;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add all sectors
|
||||||
|
*/
|
||||||
|
|
||||||
|
dstream<<"generateChunkRaw(): "
|
||||||
|
<<"("<<chunkpos.X<<","<<chunkpos.Y<<")"
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
|
TimeTaker timer("generateChunkRaw()");
|
||||||
|
|
||||||
|
v2s16 sectorpos_base = chunk_to_sector(chunkpos);
|
||||||
|
|
||||||
|
core::map<v3s16, MapBlock*> changed_blocks;
|
||||||
|
core::map<v3s16, MapBlock*> lighting_invalidated_blocks;
|
||||||
|
|
||||||
|
u32 generated_block_count = 0;
|
||||||
|
|
||||||
|
for(s16 y=0; y<m_chunksize; y++)
|
||||||
|
{
|
||||||
|
/*dstream<<"Generating sectors "
|
||||||
|
<<"("<<sectorpos_base.X<<"..."
|
||||||
|
<<(sectorpos_base.X+m_chunksize-1)
|
||||||
|
<<", "<<y<<")"
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
// With caves_amount attribute fetch: ~90ms (379ms peaks)
|
||||||
|
// Without: ~38ms (396ms peaks)
|
||||||
|
//TimeTaker timer("Chunk sector row");
|
||||||
|
|
||||||
|
for(s16 x=0; x<m_chunksize; x++)
|
||||||
|
{
|
||||||
|
v2s16 sectorpos = sectorpos_base + v2s16(x,y);
|
||||||
|
|
||||||
|
/*dstream<<"Generating sector "
|
||||||
|
<<"("<<sectorpos.X<<","<<sectorpos.Y<<")"
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
// Generate sector
|
||||||
|
ServerMapSector *sector = generateSector(sectorpos);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate main blocks of sector
|
||||||
|
*/
|
||||||
|
s16 d = 8;
|
||||||
|
for(s16 y2=-d/2; y2<d/2; y2++)
|
||||||
|
{
|
||||||
|
v3s16 p(x,y2,y);
|
||||||
|
|
||||||
|
// Check that the block doesn't exist already
|
||||||
|
if(sector->getBlockNoCreateNoEx(y2))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
generateBlock(p, NULL, sector, changed_blocks,
|
||||||
|
lighting_invalidated_blocks);
|
||||||
|
|
||||||
|
generated_block_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dstream<<"generateChunkRaw generated "<<generated_block_count
|
||||||
|
<<" blocks"<<std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
TimeTaker timer2("generateChunkRaw() lighting");
|
||||||
|
// Update lighting
|
||||||
|
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
||||||
|
updateLighting(lighting_invalidated_blocks, lighting_modified_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add chunk meta information
|
||||||
|
chunk = new MapChunk();
|
||||||
|
m_chunks.insert(chunkpos, chunk);
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapChunk* ServerMap::generateChunk(v2s16 chunkpos)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Generate chunk and neighbors
|
||||||
|
*/
|
||||||
|
for(s16 x=-1; x<=1; x++)
|
||||||
|
for(s16 y=-1; y<=1; y++)
|
||||||
|
{
|
||||||
|
generateChunkRaw(chunkpos + v2s16(x,y));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get chunk
|
||||||
|
*/
|
||||||
|
MapChunk *chunk = getChunk(chunkpos);
|
||||||
|
assert(chunk);
|
||||||
|
// Set non-volatile
|
||||||
|
chunk->setIsVolatile(false);
|
||||||
|
// Return it
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerMapSector * ServerMap::generateSector(v2s16 p2d)
|
||||||
{
|
{
|
||||||
DSTACK("%s: p2d=(%d,%d)",
|
DSTACK("%s: p2d=(%d,%d)",
|
||||||
__FUNCTION_NAME,
|
__FUNCTION_NAME,
|
||||||
p2d.X, p2d.Y);
|
p2d.X, p2d.Y);
|
||||||
// Check that it doesn't exist already
|
|
||||||
try{
|
|
||||||
return getSectorNoGenerate(p2d);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
// Check that it doesn't exist already
|
||||||
Try to load the sector from disk.
|
ServerMapSector *sector = (ServerMapSector*)getSectorNoGenerateNoEx(p2d);
|
||||||
*/
|
if(sector != NULL)
|
||||||
if(loadSectorFull(p2d) == true)
|
return sector;
|
||||||
{
|
|
||||||
return getSectorNoGenerate(p2d);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If there is no master heightmap, throw.
|
If there is no master heightmap, throw.
|
||||||
@ -2016,7 +2153,7 @@ MapSector * ServerMap::emergeSector(v2s16 p2d)
|
|||||||
// Heightmap side width
|
// Heightmap side width
|
||||||
s16 hm_d = MAP_BLOCKSIZE / hm_split;
|
s16 hm_d = MAP_BLOCKSIZE / hm_split;
|
||||||
|
|
||||||
ServerMapSector *sector = new ServerMapSector(this, p2d, hm_split);
|
sector = new ServerMapSector(this, p2d, hm_split);
|
||||||
|
|
||||||
// Sector position on map in nodes
|
// Sector position on map in nodes
|
||||||
v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
|
v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
|
||||||
@ -2068,7 +2205,9 @@ MapSector * ServerMap::emergeSector(v2s16 p2d)
|
|||||||
Get local attributes
|
Get local attributes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
float local_plants_amount = 0.0;
|
float local_plants_amount = 0.5;
|
||||||
|
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
//dstream<<"emergeSector(): Reading point attribute lists"<<std::endl;
|
//dstream<<"emergeSector(): Reading point attribute lists"<<std::endl;
|
||||||
//TimeTaker attrtimer("emergeSector() attribute fetch");
|
//TimeTaker attrtimer("emergeSector() attribute fetch");
|
||||||
@ -2081,6 +2220,7 @@ MapSector * ServerMap::emergeSector(v2s16 p2d)
|
|||||||
local_plants_amount =
|
local_plants_amount =
|
||||||
palist->getInterpolatedFloat(nodepos2d);
|
palist->getInterpolatedFloat(nodepos2d);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generate sector heightmap
|
Generate sector heightmap
|
||||||
@ -2201,90 +2341,103 @@ MapSector * ServerMap::emergeSector(v2s16 p2d)
|
|||||||
/*
|
/*
|
||||||
Insert to container
|
Insert to container
|
||||||
*/
|
*/
|
||||||
JMutexAutoLock lock(m_sector_mutex);
|
|
||||||
m_sectors.insert(p2d, sector);
|
m_sectors.insert(p2d, sector);
|
||||||
|
|
||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock * ServerMap::emergeBlock(
|
MapSector * ServerMap::emergeSector(v2s16 p2d)
|
||||||
|
{
|
||||||
|
DSTACK("%s: p2d=(%d,%d)",
|
||||||
|
__FUNCTION_NAME,
|
||||||
|
p2d.X, p2d.Y);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if it exists already in memory
|
||||||
|
*/
|
||||||
|
MapSector *sector = getSectorNoGenerateNoEx(p2d);
|
||||||
|
if(sector != NULL)
|
||||||
|
return sector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Try to load it from disk
|
||||||
|
*/
|
||||||
|
if(loadSectorFull(p2d) == true)
|
||||||
|
{
|
||||||
|
MapSector *sector = getSectorNoGenerateNoEx(p2d);
|
||||||
|
if(sector == NULL)
|
||||||
|
{
|
||||||
|
dstream<<"ServerMap::emergeSector(): loadSectorFull didn't make a sector"<<std::endl;
|
||||||
|
throw InvalidPositionException("");
|
||||||
|
}
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check chunk status
|
||||||
|
*/
|
||||||
|
v2s16 chunkpos = sector_to_chunk(p2d);
|
||||||
|
bool chunk_exists = false;
|
||||||
|
MapChunk *chunk = getChunk(chunkpos);
|
||||||
|
if(chunk && chunk->getIsVolatile() == false)
|
||||||
|
chunk_exists = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If chunk is not generated, generate chunk
|
||||||
|
*/
|
||||||
|
if(chunk_exists == false)
|
||||||
|
{
|
||||||
|
// Generate chunk and neighbors
|
||||||
|
generateChunk(chunkpos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return sector if it exists now
|
||||||
|
*/
|
||||||
|
sector = getSectorNoGenerateNoEx(p2d);
|
||||||
|
if(sector != NULL)
|
||||||
|
return sector;
|
||||||
|
|
||||||
|
/*
|
||||||
|
generateChunk should have generated the sector
|
||||||
|
*/
|
||||||
|
assert(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate directly
|
||||||
|
*/
|
||||||
|
//return generateSector();
|
||||||
|
}
|
||||||
|
|
||||||
|
MapBlock * ServerMap::generateBlock(
|
||||||
v3s16 p,
|
v3s16 p,
|
||||||
bool only_from_disk,
|
MapBlock *original_dummy,
|
||||||
|
ServerMapSector *sector,
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DSTACK("%s: p=(%d,%d,%d), only_from_disk=%d",
|
DSTACK("%s: p=(%d,%d,%d)",
|
||||||
__FUNCTION_NAME,
|
__FUNCTION_NAME,
|
||||||
p.X, p.Y, p.Z, only_from_disk);
|
p.X, p.Y, p.Z);
|
||||||
|
|
||||||
/*dstream<<"ServerMap::emergeBlock(): "
|
/*dstream<<"generateBlock(): "
|
||||||
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||||
<<", only_from_disk="<<only_from_disk<<std::endl;*/
|
<<std::endl;*/
|
||||||
|
|
||||||
|
MapBlock *block = original_dummy;
|
||||||
|
|
||||||
v2s16 p2d(p.X, p.Z);
|
v2s16 p2d(p.X, p.Z);
|
||||||
s16 block_y = p.Y;
|
s16 block_y = p.Y;
|
||||||
/*
|
|
||||||
This will create or load a sector if not found in memory.
|
|
||||||
If block exists on disk, it will be loaded.
|
|
||||||
|
|
||||||
NOTE: On old save formats, this will be slow, as it generates
|
|
||||||
lighting on blocks for them.
|
|
||||||
*/
|
|
||||||
ServerMapSector *sector = (ServerMapSector*)emergeSector(p2d);
|
|
||||||
assert(sector->getId() == MAPSECTOR_SERVER);
|
|
||||||
|
|
||||||
// Try to get a block from the sector
|
|
||||||
MapBlock *block = NULL;
|
|
||||||
bool not_on_disk = false;
|
|
||||||
try{
|
|
||||||
block = sector->getBlockNoCreate(block_y);
|
|
||||||
if(block->isDummy() == true)
|
|
||||||
not_on_disk = true;
|
|
||||||
else
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
not_on_disk = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
If block was not found on disk and not going to generate a
|
|
||||||
new one, make sure there is a dummy block in place.
|
|
||||||
*/
|
|
||||||
if(not_on_disk && only_from_disk)
|
|
||||||
{
|
|
||||||
if(block == NULL)
|
|
||||||
{
|
|
||||||
// Create dummy block
|
|
||||||
block = new MapBlock(this, p, true);
|
|
||||||
|
|
||||||
// Add block to sector
|
|
||||||
sector->insertBlock(block);
|
|
||||||
}
|
|
||||||
// Done.
|
|
||||||
return block;
|
|
||||||
}
|
|
||||||
|
|
||||||
//dstream<<"Not found on disk, generating."<<std::endl;
|
|
||||||
// 0ms
|
|
||||||
//TimeTaker("emergeBlock() generate");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do not generate over-limit
|
Do not generate over-limit
|
||||||
*/
|
*/
|
||||||
if(blockpos_over_limit(p))
|
if(blockpos_over_limit(p))
|
||||||
throw InvalidPositionException("emergeBlock(): pos. over limit");
|
{
|
||||||
|
dstream<<__FUNCTION_NAME<<": Block position over limit"<<std::endl;
|
||||||
/*
|
throw InvalidPositionException("generateBlock(): pos. over limit");
|
||||||
OK; Not found.
|
}
|
||||||
|
|
||||||
Go on generating the block.
|
|
||||||
|
|
||||||
TODO: If a dungeon gets generated so that it's side gets
|
|
||||||
revealed to the outside air, the lighting should be
|
|
||||||
recalculated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If block doesn't exist, create one.
|
If block doesn't exist, create one.
|
||||||
@ -2318,7 +2471,7 @@ MapBlock * ServerMap::emergeBlock(
|
|||||||
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
|
||||||
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
|
||||||
{
|
{
|
||||||
//dstream<<"emergeBlock: x0="<<x0<<", z0="<<z0<<std::endl;
|
//dstream<<"generateBlock: x0="<<x0<<", z0="<<z0<<std::endl;
|
||||||
|
|
||||||
float surface_y_f = sector->getGroundHeight(v2s16(x0,z0));
|
float surface_y_f = sector->getGroundHeight(v2s16(x0,z0));
|
||||||
//assert(surface_y_f > GROUNDHEIGHT_VALID_MINVALUE);
|
//assert(surface_y_f > GROUNDHEIGHT_VALID_MINVALUE);
|
||||||
@ -2451,23 +2604,25 @@ MapBlock * ServerMap::emergeBlock(
|
|||||||
Get local attributes
|
Get local attributes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//dstream<<"emergeBlock(): Getting local attributes"<<std::endl;
|
//dstream<<"generateBlock(): Getting local attributes"<<std::endl;
|
||||||
|
|
||||||
float caves_amount = 0;
|
float caves_amount = 0.5;
|
||||||
|
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
NOTE: BEWARE: Too big amount of attribute points slows verything
|
NOTE: BEWARE: Too big amount of attribute points slows verything
|
||||||
down by a lot.
|
down by a lot.
|
||||||
1 interpolation from 5000 points takes 2-3ms.
|
1 interpolation from 5000 points takes 2-3ms.
|
||||||
*/
|
*/
|
||||||
//TimeTaker timer("emergeBlock() local attribute retrieval");
|
//TimeTaker timer("generateBlock() local attribute retrieval");
|
||||||
v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
|
v2s16 nodepos2d = p2d * MAP_BLOCKSIZE;
|
||||||
PointAttributeList *list_caves_amount = m_padb.getList("caves_amount");
|
PointAttributeList *list_caves_amount = m_padb.getList("caves_amount");
|
||||||
caves_amount = list_caves_amount->getInterpolatedFloat(nodepos2d);
|
caves_amount = list_caves_amount->getInterpolatedFloat(nodepos2d);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//dstream<<"emergeBlock(): Done"<<std::endl;
|
//dstream<<"generateBlock(): Done"<<std::endl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generate dungeons
|
Generate dungeons
|
||||||
@ -2617,10 +2772,10 @@ continue_generating:
|
|||||||
do_generate_dungeons = false;
|
do_generate_dungeons = false;
|
||||||
}
|
}
|
||||||
// Don't generate if mostly underwater surface
|
// Don't generate if mostly underwater surface
|
||||||
else if(mostly_underwater_surface)
|
/*else if(mostly_underwater_surface)
|
||||||
{
|
{
|
||||||
do_generate_dungeons = false;
|
do_generate_dungeons = false;
|
||||||
}
|
}*/
|
||||||
// Partly underground = cave
|
// Partly underground = cave
|
||||||
else if(!completely_underground)
|
else if(!completely_underground)
|
||||||
{
|
{
|
||||||
@ -2723,7 +2878,7 @@ continue_generating:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
This is used for guessing whether or not the block should
|
This is used for guessing whether or not the block should
|
||||||
receive sunlight from the top if the top block doesn't exist
|
receive sunlight from the top if the block above doesn't exist
|
||||||
*/
|
*/
|
||||||
block->setIsUnderground(completely_underground);
|
block->setIsUnderground(completely_underground);
|
||||||
|
|
||||||
@ -3075,7 +3230,7 @@ continue_generating:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dstream<<"ServerMap::emergeBlock(): "
|
dstream<<"ServerMap::generateBlock(): "
|
||||||
"Invalid heightmap object"
|
"Invalid heightmap object"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
}
|
}
|
||||||
@ -3099,30 +3254,6 @@ continue_generating:
|
|||||||
objects->remove(*i);
|
objects->remove(*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Initially update sunlight
|
|
||||||
*/
|
|
||||||
|
|
||||||
{
|
|
||||||
core::map<v3s16, bool> light_sources;
|
|
||||||
bool black_air_left = false;
|
|
||||||
bool bottom_invalid =
|
|
||||||
block->propagateSunlight(light_sources, true,
|
|
||||||
&black_air_left, true);
|
|
||||||
|
|
||||||
// If sunlight didn't reach everywhere and part of block is
|
|
||||||
// above ground, lighting has to be properly updated
|
|
||||||
if(black_air_left && some_part_underground)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks[block->getPos()] = block;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bottom_invalid)
|
|
||||||
{
|
|
||||||
lighting_invalidated_blocks[block->getPos()] = block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Translate sector's changed blocks to global changed blocks
|
Translate sector's changed blocks to global changed blocks
|
||||||
*/
|
*/
|
||||||
@ -3136,21 +3267,158 @@ continue_generating:
|
|||||||
changed_blocks.insert(block->getPos(), block);
|
changed_blocks.insert(block->getPos(), block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
block->setLightingExpired(true);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
Debug information
|
Debug information
|
||||||
*/
|
*/
|
||||||
if(0)
|
dstream
|
||||||
|
<<"lighting_invalidated_blocks.size()"
|
||||||
|
<<", has_dungeons"
|
||||||
|
<<", completely_ug"
|
||||||
|
<<", some_part_ug"
|
||||||
|
<<" "<<lighting_invalidated_blocks.size()
|
||||||
|
<<", "<<has_dungeons
|
||||||
|
<<", "<<completely_underground
|
||||||
|
<<", "<<some_part_underground
|
||||||
|
<<std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapBlock * ServerMap::emergeBlock(
|
||||||
|
v3s16 p,
|
||||||
|
bool only_from_disk,
|
||||||
|
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||||
|
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DSTACK("%s: p=(%d,%d,%d), only_from_disk=%d",
|
||||||
|
__FUNCTION_NAME,
|
||||||
|
p.X, p.Y, p.Z, only_from_disk);
|
||||||
|
|
||||||
|
/*dstream<<"emergeBlock(): "
|
||||||
|
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||||
|
<<std::endl;*/
|
||||||
|
|
||||||
|
v2s16 p2d(p.X, p.Z);
|
||||||
|
s16 block_y = p.Y;
|
||||||
|
/*
|
||||||
|
This will create or load a sector if not found in memory.
|
||||||
|
If block exists on disk, it will be loaded.
|
||||||
|
|
||||||
|
NOTE: On old save formats, this will be slow, as it generates
|
||||||
|
lighting on blocks for them.
|
||||||
|
*/
|
||||||
|
ServerMapSector *sector;
|
||||||
|
try{
|
||||||
|
sector = (ServerMapSector*)emergeSector(p2d);
|
||||||
|
assert(sector->getId() == MAPSECTOR_SERVER);
|
||||||
|
}
|
||||||
|
/*catch(InvalidPositionException &e)
|
||||||
{
|
{
|
||||||
dstream
|
dstream<<"emergeBlock: emergeSector() failed"<<std::endl;
|
||||||
<<"lighting_invalidated_blocks.size()"
|
throw e;
|
||||||
<<", has_dungeons"
|
}*/
|
||||||
<<", completely_ug"
|
catch(std::exception &e)
|
||||||
<<", some_part_ug"
|
{
|
||||||
<<" "<<lighting_invalidated_blocks.size()
|
dstream<<"emergeBlock: emergeSector() failed: "
|
||||||
<<", "<<has_dungeons
|
<<e.what()<<std::endl;
|
||||||
<<", "<<completely_underground
|
throw e;
|
||||||
<<", "<<some_part_underground
|
}
|
||||||
<<std::endl;
|
|
||||||
|
/*
|
||||||
|
Try to get a block from the sector
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool does_not_exist = false;
|
||||||
|
bool lighting_expired = false;
|
||||||
|
MapBlock *block = sector->getBlockNoCreateNoEx(block_y);
|
||||||
|
|
||||||
|
if(block == NULL)
|
||||||
|
{
|
||||||
|
does_not_exist = true;
|
||||||
|
}
|
||||||
|
else if(block->isDummy() == true)
|
||||||
|
{
|
||||||
|
does_not_exist = true;
|
||||||
|
}
|
||||||
|
else if(block->getLightingExpired())
|
||||||
|
{
|
||||||
|
lighting_expired = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Valid block
|
||||||
|
//dstream<<"emergeBlock(): Returning already valid block"<<std::endl;
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If block was not found on disk and not going to generate a
|
||||||
|
new one, make sure there is a dummy block in place.
|
||||||
|
*/
|
||||||
|
if(only_from_disk && (does_not_exist || lighting_expired))
|
||||||
|
{
|
||||||
|
//dstream<<"emergeBlock(): Was not on disk but not generating"<<std::endl;
|
||||||
|
|
||||||
|
if(block == NULL)
|
||||||
|
{
|
||||||
|
// Create dummy block
|
||||||
|
block = new MapBlock(this, p, true);
|
||||||
|
|
||||||
|
// Add block to sector
|
||||||
|
sector->insertBlock(block);
|
||||||
|
}
|
||||||
|
// Done.
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
//dstream<<"Not found on disk, generating."<<std::endl;
|
||||||
|
// 0ms
|
||||||
|
//TimeTaker("emergeBlock() generate");
|
||||||
|
|
||||||
|
//dstream<<"emergeBlock(): Didn't find valid block -> making one"<<std::endl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
If the block doesn't exist, generate the block.
|
||||||
|
*/
|
||||||
|
if(does_not_exist)
|
||||||
|
{
|
||||||
|
block = generateBlock(p, block, sector, changed_blocks,
|
||||||
|
lighting_invalidated_blocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lighting_expired)
|
||||||
|
{
|
||||||
|
lighting_invalidated_blocks.insert(p, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initially update sunlight
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
core::map<v3s16, bool> light_sources;
|
||||||
|
bool black_air_left = false;
|
||||||
|
bool bottom_invalid =
|
||||||
|
block->propagateSunlight(light_sources, true,
|
||||||
|
&black_air_left, true);
|
||||||
|
|
||||||
|
// If sunlight didn't reach everywhere and part of block is
|
||||||
|
// above ground, lighting has to be properly updated
|
||||||
|
//if(black_air_left && some_part_underground)
|
||||||
|
if(black_air_left)
|
||||||
|
{
|
||||||
|
lighting_invalidated_blocks[block->getPos()] = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bottom_invalid)
|
||||||
|
{
|
||||||
|
lighting_invalidated_blocks[block->getPos()] = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
105
src/map.h
105
src/map.h
@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "mapsector.h"
|
#include "mapsector.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
|
#include "mapchunk.h"
|
||||||
|
|
||||||
#define MAPTYPE_BASE 0
|
#define MAPTYPE_BASE 0
|
||||||
#define MAPTYPE_SERVER 1
|
#define MAPTYPE_SERVER 1
|
||||||
@ -86,8 +87,13 @@ public:
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//bool sectorExists(v2s16 p);
|
// On failure returns NULL
|
||||||
|
MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
|
||||||
|
// On failure returns NULL
|
||||||
|
MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
|
||||||
|
// On failure throws InvalidPositionException
|
||||||
MapSector * getSectorNoGenerate(v2s16 p2d);
|
MapSector * getSectorNoGenerate(v2s16 p2d);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This is overloaded by ClientMap and ServerMap to allow
|
This is overloaded by ClientMap and ServerMap to allow
|
||||||
their differing fetch methods.
|
their differing fetch methods.
|
||||||
@ -318,9 +324,90 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Forcefully get a sector from somewhere
|
Map generation
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Returns the position of the chunk where the sector is in
|
||||||
|
v2s16 sector_to_chunk(v2s16 sectorpos)
|
||||||
|
{
|
||||||
|
sectorpos.X += m_chunksize / 2;
|
||||||
|
sectorpos.Y += m_chunksize / 2;
|
||||||
|
v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
|
||||||
|
return chunkpos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the position of the (0,0) sector of the chunk
|
||||||
|
v2s16 chunk_to_sector(v2s16 chunkpos)
|
||||||
|
{
|
||||||
|
v2s16 sectorpos(
|
||||||
|
chunkpos.X * m_chunksize,
|
||||||
|
chunkpos.Y * m_chunksize
|
||||||
|
);
|
||||||
|
sectorpos.X -= m_chunksize / 2;
|
||||||
|
sectorpos.Y -= m_chunksize / 2;
|
||||||
|
return sectorpos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get a chunk.
|
||||||
|
*/
|
||||||
|
MapChunk *getChunk(v2s16 chunkpos)
|
||||||
|
{
|
||||||
|
core::map<v2s16, MapChunk*>::Node *n;
|
||||||
|
n = m_chunks.find(chunkpos);
|
||||||
|
if(n == NULL)
|
||||||
|
return NULL;
|
||||||
|
return n->getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate a chunk.
|
||||||
|
|
||||||
|
All chunks touching this one can be altered also.
|
||||||
|
|
||||||
|
Doesn't update lighting.
|
||||||
|
*/
|
||||||
|
MapChunk* generateChunkRaw(v2s16 chunkpos);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate a chunk and its neighbors so that it won't be touched
|
||||||
|
anymore.
|
||||||
|
|
||||||
|
Doesn't update lighting.
|
||||||
|
*/
|
||||||
|
MapChunk* generateChunk(v2s16 chunkpos);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate a sector.
|
||||||
|
|
||||||
|
This is mainly called by generateChunkRaw.
|
||||||
|
*/
|
||||||
|
ServerMapSector * generateSector(v2s16 p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get a sector from somewhere.
|
||||||
|
- Check memory
|
||||||
|
- Check disk
|
||||||
|
- Generate chunk
|
||||||
*/
|
*/
|
||||||
MapSector * emergeSector(v2s16 p);
|
MapSector * emergeSector(v2s16 p);
|
||||||
|
|
||||||
|
MapBlock * generateBlock(
|
||||||
|
v3s16 p,
|
||||||
|
MapBlock *original_dummy,
|
||||||
|
ServerMapSector *sector,
|
||||||
|
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||||
|
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||||
|
);
|
||||||
|
|
||||||
|
MapBlock * emergeBlock(
|
||||||
|
v3s16 p,
|
||||||
|
bool only_from_disk,
|
||||||
|
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||||
|
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||||
|
);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/*
|
/*
|
||||||
Forcefully get a block from somewhere.
|
Forcefully get a block from somewhere.
|
||||||
|
|
||||||
@ -346,7 +433,12 @@ public:
|
|||||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||||
);
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Misc. helper functions for fiddling with directory and file
|
||||||
|
names when saving
|
||||||
|
*/
|
||||||
void createDir(std::string path);
|
void createDir(std::string path);
|
||||||
void createSaveDir();
|
void createSaveDir();
|
||||||
// returns something like "xxxxxxxx"
|
// returns something like "xxxxxxxx"
|
||||||
@ -396,8 +488,17 @@ private:
|
|||||||
|
|
||||||
std::string m_savedir;
|
std::string m_savedir;
|
||||||
bool m_map_saving_enabled;
|
bool m_map_saving_enabled;
|
||||||
|
|
||||||
|
// Chunk size in MapSectors
|
||||||
|
s16 m_chunksize;
|
||||||
|
// Chunks
|
||||||
|
core::map<v2s16, MapChunk*> m_chunks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
ClientMap stuff
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
|
||||||
struct MapDrawControl
|
struct MapDrawControl
|
||||||
|
@ -293,7 +293,8 @@ void MapBlock::makeFastFace(TileSpec tile, u8 light, v3f p,
|
|||||||
Gets node tile from any place relative to block.
|
Gets node tile from any place relative to block.
|
||||||
Returns TILE_NODE if doesn't exist or should not be drawn.
|
Returns TILE_NODE if doesn't exist or should not be drawn.
|
||||||
*/
|
*/
|
||||||
TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
|
TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||||
|
NodeModMap &temp_mods)
|
||||||
{
|
{
|
||||||
TileSpec spec;
|
TileSpec spec;
|
||||||
spec = mn.getTile(face_dir);
|
spec = mn.getTile(face_dir);
|
||||||
@ -301,13 +302,15 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
|
|||||||
/*
|
/*
|
||||||
Check temporary modifications on this node
|
Check temporary modifications on this node
|
||||||
*/
|
*/
|
||||||
core::map<v3s16, NodeMod>::Node *n;
|
/*core::map<v3s16, NodeMod>::Node *n;
|
||||||
n = m_temp_mods.find(p);
|
n = m_temp_mods.find(p);
|
||||||
|
|
||||||
// If modified
|
// If modified
|
||||||
if(n != NULL)
|
if(n != NULL)
|
||||||
{
|
{
|
||||||
struct NodeMod mod = n->getValue();
|
struct NodeMod mod = n->getValue();*/
|
||||||
|
NodeMod mod;
|
||||||
|
if(temp_mods.get(p, &mod))
|
||||||
|
{
|
||||||
if(mod.type == NODEMOD_CHANGECONTENT)
|
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||||
{
|
{
|
||||||
MapNode mn2(mod.param);
|
MapNode mn2(mod.param);
|
||||||
@ -326,18 +329,20 @@ TileSpec MapBlock::getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir)
|
|||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 MapBlock::getNodeContent(v3s16 p, MapNode mn)
|
u8 MapBlock::getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Check temporary modifications on this node
|
Check temporary modifications on this node
|
||||||
*/
|
*/
|
||||||
core::map<v3s16, NodeMod>::Node *n;
|
/*core::map<v3s16, NodeMod>::Node *n;
|
||||||
n = m_temp_mods.find(p);
|
n = m_temp_mods.find(p);
|
||||||
|
|
||||||
// If modified
|
// If modified
|
||||||
if(n != NULL)
|
if(n != NULL)
|
||||||
{
|
{
|
||||||
struct NodeMod mod = n->getValue();
|
struct NodeMod mod = n->getValue();*/
|
||||||
|
NodeMod mod;
|
||||||
|
if(temp_mods.get(p, &mod))
|
||||||
|
{
|
||||||
if(mod.type == NODEMOD_CHANGECONTENT)
|
if(mod.type == NODEMOD_CHANGECONTENT)
|
||||||
{
|
{
|
||||||
// Overrides content
|
// Overrides content
|
||||||
@ -376,7 +381,8 @@ void MapBlock::updateFastFaceRow(
|
|||||||
v3f translate_dir_f,
|
v3f translate_dir_f,
|
||||||
v3s16 face_dir,
|
v3s16 face_dir,
|
||||||
v3f face_dir_f,
|
v3f face_dir_f,
|
||||||
core::array<FastFace> &dest)
|
core::array<FastFace> &dest,
|
||||||
|
NodeModMap &temp_mods)
|
||||||
{
|
{
|
||||||
v3s16 p = startpos;
|
v3s16 p = startpos;
|
||||||
|
|
||||||
@ -387,8 +393,8 @@ void MapBlock::updateFastFaceRow(
|
|||||||
|
|
||||||
u8 light = getFaceLight(daynight_ratio, n0, n1, face_dir);
|
u8 light = getFaceLight(daynight_ratio, n0, n1, face_dir);
|
||||||
|
|
||||||
TileSpec tile0 = getNodeTile(n0, p, face_dir);
|
TileSpec tile0 = getNodeTile(n0, p, face_dir, temp_mods);
|
||||||
TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir);
|
TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods);
|
||||||
|
|
||||||
for(u16 j=0; j<length; j++)
|
for(u16 j=0; j<length; j++)
|
||||||
{
|
{
|
||||||
@ -406,8 +412,8 @@ void MapBlock::updateFastFaceRow(
|
|||||||
p_next = p + translate_dir;
|
p_next = p + translate_dir;
|
||||||
n0_next = getNodeParentNoEx(p_next);
|
n0_next = getNodeParentNoEx(p_next);
|
||||||
n1_next = getNodeParentNoEx(p_next + face_dir);
|
n1_next = getNodeParentNoEx(p_next + face_dir);
|
||||||
tile0_next = getNodeTile(n0_next, p_next, face_dir);
|
tile0_next = getNodeTile(n0_next, p_next, face_dir, temp_mods);
|
||||||
tile1_next = getNodeTile(n1_next, p_next + face_dir, -face_dir);
|
tile1_next = getNodeTile(n1_next,p_next+face_dir,-face_dir, temp_mods);
|
||||||
light_next = getFaceLight(daynight_ratio, n0_next, n1_next, face_dir);
|
light_next = getFaceLight(daynight_ratio, n0_next, n1_next, face_dir);
|
||||||
|
|
||||||
if(tile0_next == tile0
|
if(tile0_next == tile0
|
||||||
@ -427,8 +433,8 @@ void MapBlock::updateFastFaceRow(
|
|||||||
*/
|
*/
|
||||||
//u8 mf = face_contents(tile0, tile1);
|
//u8 mf = face_contents(tile0, tile1);
|
||||||
// This is hackish
|
// This is hackish
|
||||||
u8 content0 = getNodeContent(p, n0);
|
u8 content0 = getNodeContent(p, n0, temp_mods);
|
||||||
u8 content1 = getNodeContent(p + face_dir, n1);
|
u8 content1 = getNodeContent(p + face_dir, n1, temp_mods);
|
||||||
u8 mf = face_contents(content0, content1);
|
u8 mf = face_contents(content0, content1);
|
||||||
|
|
||||||
if(mf != 0)
|
if(mf != 0)
|
||||||
@ -594,6 +600,16 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
v3f posRelative_f(getPosRelative().X, getPosRelative().Y,
|
v3f posRelative_f(getPosRelative().X, getPosRelative().Y,
|
||||||
getPosRelative().Z); // floating point conversion
|
getPosRelative().Z); // floating point conversion
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Avoid interlocks by copying m_temp_mods
|
||||||
|
*/
|
||||||
|
NodeModMap temp_mods;
|
||||||
|
{
|
||||||
|
JMutexAutoLock lock(m_temp_mods_mutex);
|
||||||
|
m_temp_mods.copy(temp_mods);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We are including the faces of the trailing edges of the block.
|
We are including the faces of the trailing edges of the block.
|
||||||
This means that when something changes, the caller must
|
This means that when something changes, the caller must
|
||||||
@ -606,9 +622,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
// 4-23ms for MAP_BLOCKSIZE=16
|
// 4-23ms for MAP_BLOCKSIZE=16
|
||||||
//TimeTaker timer2("updateMesh() collect");
|
//TimeTaker timer2("updateMesh() collect");
|
||||||
|
|
||||||
// Lock this, as m_temp_mods will be used directly
|
|
||||||
JMutexAutoLock lock(m_temp_mods_mutex);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Go through every y,z and get top faces in rows of x+
|
Go through every y,z and get top faces in rows of x+
|
||||||
*/
|
*/
|
||||||
@ -620,7 +633,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
v3f (1,0,0),
|
v3f (1,0,0),
|
||||||
v3s16(0,1,0), //face dir
|
v3s16(0,1,0), //face dir
|
||||||
v3f (0,1,0),
|
v3f (0,1,0),
|
||||||
fastfaces_new);
|
fastfaces_new,
|
||||||
|
temp_mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -634,7 +648,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
v3f (0,0,1),
|
v3f (0,0,1),
|
||||||
v3s16(1,0,0),
|
v3s16(1,0,0),
|
||||||
v3f (1,0,0),
|
v3f (1,0,0),
|
||||||
fastfaces_new);
|
fastfaces_new,
|
||||||
|
temp_mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -648,7 +663,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
v3f (1,0,0),
|
v3f (1,0,0),
|
||||||
v3s16(0,0,1),
|
v3s16(0,0,1),
|
||||||
v3f (0,0,1),
|
v3f (0,0,1),
|
||||||
fastfaces_new);
|
fastfaces_new,
|
||||||
|
temp_mods);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1297,10 +1313,6 @@ void MapBlock::copyTo(VoxelManipulator &dst)
|
|||||||
getPosRelative(), data_size);
|
getPosRelative(), data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void getPseudoObjects(v3f origin, f32 max_d,
|
|
||||||
core::array<DistanceSortedObject> &dest)
|
|
||||||
{
|
|
||||||
}*/
|
|
||||||
void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1501,6 +1513,8 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
|||||||
flags |= 1;
|
flags |= 1;
|
||||||
if(m_day_night_differs)
|
if(m_day_night_differs)
|
||||||
flags |= 2;
|
flags |= 2;
|
||||||
|
if(m_lighting_expired)
|
||||||
|
flags |= 3;
|
||||||
os.write((char*)&flags, 1);
|
os.write((char*)&flags, 1);
|
||||||
|
|
||||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||||
@ -1622,6 +1636,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
|||||||
is.read((char*)&flags, 1);
|
is.read((char*)&flags, 1);
|
||||||
is_underground = (flags & 1) ? true : false;
|
is_underground = (flags & 1) ? true : false;
|
||||||
m_day_night_differs = (flags & 2) ? true : false;
|
m_day_night_differs = (flags & 2) ? true : false;
|
||||||
|
m_lighting_expired = (flags & 3) ? true : false;
|
||||||
|
|
||||||
// Uncompress data
|
// Uncompress data
|
||||||
std::ostringstream os(std::ios_base::binary);
|
std::ostringstream os(std::ios_base::binary);
|
||||||
|
306
src/mapblock.h
306
src/mapblock.h
@ -70,6 +70,74 @@ struct NodeMod
|
|||||||
u16 param;
|
u16 param;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NodeModMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
returns true if the mod was different last time
|
||||||
|
*/
|
||||||
|
bool set(v3s16 p, const NodeMod &mod)
|
||||||
|
{
|
||||||
|
// See if old is different, cancel if it is not different.
|
||||||
|
core::map<v3s16, NodeMod>::Node *n = m_mods.find(p);
|
||||||
|
if(n)
|
||||||
|
{
|
||||||
|
NodeMod old = n->getValue();
|
||||||
|
if(old == mod)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
n->setValue(mod);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_mods.insert(p, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Returns true if there was one
|
||||||
|
bool get(v3s16 p, NodeMod *mod)
|
||||||
|
{
|
||||||
|
core::map<v3s16, NodeMod>::Node *n;
|
||||||
|
n = m_mods.find(p);
|
||||||
|
if(n == NULL)
|
||||||
|
return false;
|
||||||
|
if(mod)
|
||||||
|
*mod = n->getValue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool clear(v3s16 p)
|
||||||
|
{
|
||||||
|
if(m_mods.find(p))
|
||||||
|
{
|
||||||
|
m_mods.remove(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool clear()
|
||||||
|
{
|
||||||
|
if(m_mods.size() == 0)
|
||||||
|
return false;
|
||||||
|
m_mods.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void copy(NodeModMap &dest)
|
||||||
|
{
|
||||||
|
dest.m_mods.clear();
|
||||||
|
|
||||||
|
for(core::map<v3s16, NodeMod>::Iterator
|
||||||
|
i = m_mods.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
dest.m_mods.insert(i.getNode()->getKey(), i.getNode()->getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
core::map<v3s16, NodeMod> m_mods;
|
||||||
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
NODECONTAINER_ID_MAPBLOCK,
|
NODECONTAINER_ID_MAPBLOCK,
|
||||||
@ -104,11 +172,26 @@ public:
|
|||||||
return m_parent;
|
return m_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reallocate()
|
||||||
|
{
|
||||||
|
if(data != NULL)
|
||||||
|
delete[] data;
|
||||||
|
u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
||||||
|
data = new MapNode[l];
|
||||||
|
for(u32 i=0; i<l; i++){
|
||||||
|
data[i] = MapNode();
|
||||||
|
}
|
||||||
|
setChangedFlag();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Flags
|
||||||
|
*/
|
||||||
|
|
||||||
bool isDummy()
|
bool isDummy()
|
||||||
{
|
{
|
||||||
return (data == NULL);
|
return (data == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unDummify()
|
void unDummify()
|
||||||
{
|
{
|
||||||
assert(isDummy());
|
assert(isDummy());
|
||||||
@ -119,36 +202,14 @@ public:
|
|||||||
{
|
{
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetChangedFlag()
|
void resetChangedFlag()
|
||||||
{
|
{
|
||||||
changed = false;
|
changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setChangedFlag()
|
void setChangedFlag()
|
||||||
{
|
{
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
#ifndef SERVER
|
|
||||||
void setMeshExpired(bool expired)
|
|
||||||
{
|
|
||||||
m_mesh_expired = expired;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getMeshExpired()
|
|
||||||
{
|
|
||||||
return m_mesh_expired;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
v3s16 getPos()
|
|
||||||
{
|
|
||||||
return m_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
v3s16 getPosRelative()
|
|
||||||
{
|
|
||||||
return m_pos * MAP_BLOCKSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getIsUnderground()
|
bool getIsUnderground()
|
||||||
{
|
{
|
||||||
@ -161,6 +222,51 @@ public:
|
|||||||
setChangedFlag();
|
setChangedFlag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef SERVER
|
||||||
|
void setMeshExpired(bool expired)
|
||||||
|
{
|
||||||
|
m_mesh_expired = expired;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getMeshExpired()
|
||||||
|
{
|
||||||
|
return m_mesh_expired;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void setLightingExpired(bool expired)
|
||||||
|
{
|
||||||
|
m_lighting_expired = expired;
|
||||||
|
setChangedFlag();
|
||||||
|
}
|
||||||
|
bool getLightingExpired()
|
||||||
|
{
|
||||||
|
return m_lighting_expired;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid()
|
||||||
|
{
|
||||||
|
if(m_lighting_expired)
|
||||||
|
return false;
|
||||||
|
if(data == NULL)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Position stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
v3s16 getPos()
|
||||||
|
{
|
||||||
|
return m_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
v3s16 getPosRelative()
|
||||||
|
{
|
||||||
|
return m_pos * MAP_BLOCKSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
core::aabbox3d<s16> getBox()
|
core::aabbox3d<s16> getBox()
|
||||||
{
|
{
|
||||||
return core::aabbox3d<s16>(getPosRelative(),
|
return core::aabbox3d<s16>(getPosRelative(),
|
||||||
@ -169,17 +275,9 @@ public:
|
|||||||
- v3s16(1,1,1));
|
- v3s16(1,1,1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void reallocate()
|
/*
|
||||||
{
|
Regular MapNode get-setters
|
||||||
if(data != NULL)
|
*/
|
||||||
delete[] data;
|
|
||||||
u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
|
||||||
data = new MapNode[l];
|
|
||||||
for(u32 i=0; i<l; i++){
|
|
||||||
data[i] = MapNode();
|
|
||||||
}
|
|
||||||
setChangedFlag();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isValidPosition(v3s16 p)
|
bool isValidPosition(v3s16 p)
|
||||||
{
|
{
|
||||||
@ -190,10 +288,6 @@ public:
|
|||||||
&& p.Z >= 0 && p.Z < MAP_BLOCKSIZE);
|
&& p.Z >= 0 && p.Z < MAP_BLOCKSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Regular MapNode get-setters
|
|
||||||
*/
|
|
||||||
|
|
||||||
MapNode getNode(s16 x, s16 y, s16 z)
|
MapNode getNode(s16 x, s16 y, s16 z)
|
||||||
{
|
{
|
||||||
if(data == NULL)
|
if(data == NULL)
|
||||||
@ -271,9 +365,14 @@ public:
|
|||||||
setNode(x0+x, y0+y, z0+z, node);
|
setNode(x0+x, y0+y, z0+z, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Graphics-related methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
// A quick version with nodes passed as parameters
|
||||||
u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
||||||
v3s16 face_dir);
|
v3s16 face_dir);
|
||||||
|
// A more convenient version
|
||||||
u8 getFaceLight(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
|
u8 getFaceLight(u32 daynight_ratio, v3s16 p, v3s16 face_dir)
|
||||||
{
|
{
|
||||||
return getFaceLight(daynight_ratio,
|
return getFaceLight(daynight_ratio,
|
||||||
@ -288,11 +387,16 @@ public:
|
|||||||
v3s16 dir, v3f scale, v3f posRelative_f,
|
v3s16 dir, v3f scale, v3f posRelative_f,
|
||||||
core::array<FastFace> &dest);
|
core::array<FastFace> &dest);
|
||||||
|
|
||||||
TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir);
|
TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
|
||||||
u8 getNodeContent(v3s16 p, MapNode mn);
|
NodeModMap &temp_mods);
|
||||||
|
u8 getNodeContent(v3s16 p, MapNode mn,
|
||||||
|
NodeModMap &temp_mods);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
startpos:
|
Generates the FastFaces of a node row. This has a
|
||||||
|
ridiculous amount of parameters because that way they
|
||||||
|
can be precalculated by the caller.
|
||||||
|
|
||||||
translate_dir: unit vector with only one of x, y or z
|
translate_dir: unit vector with only one of x, y or z
|
||||||
face_dir: unit vector with only one of x, y or z
|
face_dir: unit vector with only one of x, y or z
|
||||||
*/
|
*/
|
||||||
@ -305,12 +409,14 @@ public:
|
|||||||
v3f translate_dir_f,
|
v3f translate_dir_f,
|
||||||
v3s16 face_dir,
|
v3s16 face_dir,
|
||||||
v3f face_dir_f,
|
v3f face_dir_f,
|
||||||
core::array<FastFace> &dest);
|
core::array<FastFace> &dest,
|
||||||
|
NodeModMap &temp_mods);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Thread-safely updates the whole mesh of the mapblock.
|
||||||
|
*/
|
||||||
void updateMesh(u32 daynight_ratio);
|
void updateMesh(u32 daynight_ratio);
|
||||||
/*void updateMesh(s32 daynight_i);
|
|
||||||
// Updates all DAYNIGHT_CACHE_COUNT meshes
|
|
||||||
void updateMeshes(s32 first_i=0);*/
|
|
||||||
#endif // !SERVER
|
#endif // !SERVER
|
||||||
|
|
||||||
// See comments in mapblock.cpp
|
// See comments in mapblock.cpp
|
||||||
@ -322,7 +428,7 @@ public:
|
|||||||
void copyTo(VoxelManipulator &dst);
|
void copyTo(VoxelManipulator &dst);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Object stuff
|
MapBlockObject stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void serializeObjects(std::ostream &os, u8 version)
|
void serializeObjects(std::ostream &os, u8 version)
|
||||||
@ -384,9 +490,6 @@ public:
|
|||||||
m_objects.getObjects(origin, max_d, dest);
|
m_objects.getObjects(origin, max_d, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void getPseudoObjects(v3f origin, f32 max_d,
|
|
||||||
core::array<DistanceSortedObject> &dest);*/
|
|
||||||
|
|
||||||
s32 getObjectCount()
|
s32 getObjectCount()
|
||||||
{
|
{
|
||||||
return m_objects.getCount();
|
return m_objects.getCount();
|
||||||
@ -399,7 +502,7 @@ public:
|
|||||||
|
|
||||||
returns true if the mod was different last time
|
returns true if the mod was different last time
|
||||||
*/
|
*/
|
||||||
bool setTempMod(v3s16 p, NodeMod mod)
|
bool setTempMod(v3s16 p, const NodeMod &mod)
|
||||||
{
|
{
|
||||||
/*dstream<<"setTempMod called on block"
|
/*dstream<<"setTempMod called on block"
|
||||||
<<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
<<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
|
||||||
@ -408,52 +511,33 @@ public:
|
|||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
JMutexAutoLock lock(m_temp_mods_mutex);
|
JMutexAutoLock lock(m_temp_mods_mutex);
|
||||||
|
|
||||||
// See if old is different, cancel if it is not different.
|
return m_temp_mods.set(p, mod);
|
||||||
core::map<v3s16, NodeMod>::Node *n = m_temp_mods.find(p);
|
|
||||||
if(n)
|
|
||||||
{
|
|
||||||
NodeMod old = n->getValue();
|
|
||||||
if(old == mod)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_temp_mods[p] = mod;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
// Returns true if there was one
|
// Returns true if there was one
|
||||||
bool getTempMod(v3s16 p, struct NodeMod *mod)
|
bool getTempMod(v3s16 p, NodeMod *mod)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_temp_mods_mutex);
|
JMutexAutoLock lock(m_temp_mods_mutex);
|
||||||
core::map<v3s16, NodeMod>::Node *n;
|
|
||||||
n = m_temp_mods.find(p);
|
return m_temp_mods.get(p, mod);
|
||||||
if(n == NULL)
|
|
||||||
return false;
|
|
||||||
if(mod)
|
|
||||||
*mod = n->getValue();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
bool clearTempMod(v3s16 p)
|
bool clearTempMod(v3s16 p)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_temp_mods_mutex);
|
JMutexAutoLock lock(m_temp_mods_mutex);
|
||||||
if(m_temp_mods.find(p))
|
|
||||||
{
|
return m_temp_mods.clear(p);
|
||||||
m_temp_mods.remove(p);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
bool clearTempMods()
|
bool clearTempMods()
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_temp_mods_mutex);
|
JMutexAutoLock lock(m_temp_mods_mutex);
|
||||||
if(m_temp_mods.size() == 0)
|
|
||||||
return false;
|
return m_temp_mods.clear();
|
||||||
m_temp_mods.clear();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Day-night lighting difference
|
Update day-night lighting difference flag.
|
||||||
|
|
||||||
|
Sets m_day_night_differs to appropriate value.
|
||||||
|
|
||||||
These methods don't care about neighboring blocks.
|
These methods don't care about neighboring blocks.
|
||||||
It means that to know if a block really doesn't need a mesh
|
It means that to know if a block really doesn't need a mesh
|
||||||
@ -490,17 +574,10 @@ public:
|
|||||||
|
|
||||||
void deSerialize(std::istream &is, u8 version);
|
void deSerialize(std::istream &is, u8 version);
|
||||||
|
|
||||||
/*
|
|
||||||
Public member variables
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SERVER
|
|
||||||
//scene::SMesh *mesh[DAYNIGHT_CACHE_COUNT];
|
|
||||||
scene::SMesh *mesh;
|
|
||||||
JMutex mesh_mutex;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/*
|
||||||
|
Private methods
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Used only internally, because changes can't be tracked
|
Used only internally, because changes can't be tracked
|
||||||
@ -520,29 +597,59 @@ private:
|
|||||||
return getNodeRef(p.X, p.Y, p.Z);
|
return getNodeRef(p.X, p.Y, p.Z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
Public member variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SERVER
|
||||||
|
scene::SMesh *mesh;
|
||||||
|
JMutex mesh_mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*
|
||||||
|
Private member variables
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Parent container (practically the Map)
|
||||||
|
// Not a MapSector, it is just a structural element.
|
||||||
NodeContainer *m_parent;
|
NodeContainer *m_parent;
|
||||||
// Position in blocks on parent
|
// Position in blocks on parent
|
||||||
v3s16 m_pos;
|
v3s16 m_pos;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If NULL, block is a dummy block.
|
If NULL, block is a dummy block.
|
||||||
Dummy blocks are used for caching not-found-on-disk blocks.
|
Dummy blocks are used for caching not-found-on-disk blocks.
|
||||||
*/
|
*/
|
||||||
MapNode * data;
|
MapNode * data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
- On the client, this is used for checking whether to
|
|
||||||
recalculate the face cache. (Is it anymore?)
|
|
||||||
- On the server, this is used for telling whether the
|
- On the server, this is used for telling whether the
|
||||||
block has been changed from the one on disk.
|
block has been changed from the one on disk.
|
||||||
|
- On the client, this is used for nothing.
|
||||||
*/
|
*/
|
||||||
bool changed;
|
bool changed;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Used for some initial lighting stuff.
|
When propagating sunlight and the above block doesn't exist,
|
||||||
At least /has been/ used. 8)
|
sunlight is assumed if this is false.
|
||||||
It's probably useless now.
|
|
||||||
|
In practice this is set to true if the block is completely
|
||||||
|
undeground with nothing visible above the ground except
|
||||||
|
caves.
|
||||||
*/
|
*/
|
||||||
bool is_underground;
|
bool is_underground;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set to true if changes has been made that make the old lighting
|
||||||
|
values wrong but the lighting hasn't been actually updated.
|
||||||
|
|
||||||
|
If this is false, lighting is exactly right.
|
||||||
|
If this is true, lighting might be wrong or right.
|
||||||
|
*/
|
||||||
|
bool m_lighting_expired;
|
||||||
|
|
||||||
// Whether day and night lighting differs
|
// Whether day and night lighting differs
|
||||||
bool m_day_night_differs;
|
bool m_day_night_differs;
|
||||||
|
|
||||||
@ -552,11 +659,16 @@ private:
|
|||||||
float m_spawn_timer;
|
float m_spawn_timer;
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
/*
|
||||||
|
Set to true if the mesh has been ordered to be updated
|
||||||
|
sometime in the background.
|
||||||
|
In practice this is set when the day/night lighting switches.
|
||||||
|
*/
|
||||||
bool m_mesh_expired;
|
bool m_mesh_expired;
|
||||||
|
|
||||||
// Temporary modifications to nodes
|
// Temporary modifications to nodes
|
||||||
// These are only used when drawing
|
// These are only used when drawing
|
||||||
core::map<v3s16, NodeMod> m_temp_mods;
|
NodeModMap m_temp_mods;
|
||||||
JMutex m_temp_mods_mutex;
|
JMutex m_temp_mods_mutex;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
51
src/mapchunk.h
Normal file
51
src/mapchunk.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
Minetest-c55
|
||||||
|
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAPCHUNK_HEADER
|
||||||
|
#define MAPCHUNK_HEADER
|
||||||
|
|
||||||
|
/*
|
||||||
|
MapChunk contains map-generation-time metadata for an area of
|
||||||
|
some MapSectors. (something like 64x64)
|
||||||
|
*/
|
||||||
|
|
||||||
|
class MapChunk
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MapChunk():
|
||||||
|
m_is_volatile(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
If is_volatile is true, chunk can be modified when
|
||||||
|
neighboring chunks are generated.
|
||||||
|
|
||||||
|
It is set to false when all the 8 neighboring chunks have
|
||||||
|
been generated.
|
||||||
|
*/
|
||||||
|
bool getIsVolatile(){ return m_is_volatile; }
|
||||||
|
void setIsVolatile(bool is){ m_is_volatile = is; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_is_volatile;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -82,11 +82,16 @@ MapBlock * MapSector::getBlockBuffered(s16 y)
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapBlock * MapSector::getBlockNoCreate(s16 y)
|
MapBlock * MapSector::getBlockNoCreateNoEx(s16 y)
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_mutex);
|
JMutexAutoLock lock(m_mutex);
|
||||||
|
|
||||||
MapBlock *block = getBlockBuffered(y);
|
return getBlockBuffered(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
MapBlock * MapSector::getBlockNoCreate(s16 y)
|
||||||
|
{
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(y);
|
||||||
|
|
||||||
if(block == NULL)
|
if(block == NULL)
|
||||||
throw InvalidPositionException();
|
throw InvalidPositionException();
|
||||||
|
@ -67,6 +67,7 @@ public:
|
|||||||
return m_pos;
|
return m_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapBlock * getBlockNoCreateNoEx(s16 y);
|
||||||
MapBlock * getBlockNoCreate(s16 y);
|
MapBlock * getBlockNoCreate(s16 y);
|
||||||
MapBlock * createBlankBlockNoInsert(s16 y);
|
MapBlock * createBlankBlockNoInsert(s16 y);
|
||||||
MapBlock * createBlankBlock(s16 y);
|
MapBlock * createBlankBlock(s16 y);
|
||||||
|
@ -156,20 +156,18 @@ void * EmergeThread::Thread()
|
|||||||
only_from_disk = true;
|
only_from_disk = true;
|
||||||
|
|
||||||
// First check if the block already exists
|
// First check if the block already exists
|
||||||
if(only_from_disk)
|
//block = map.getBlockNoCreate(p);
|
||||||
{
|
|
||||||
block = map.getBlockNoCreate(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(block == NULL)
|
if(block == NULL)
|
||||||
{
|
{
|
||||||
|
//dstream<<"Calling emergeBlock"<<std::endl;
|
||||||
block = map.emergeBlock(
|
block = map.emergeBlock(
|
||||||
p,
|
p,
|
||||||
only_from_disk,
|
only_from_disk,
|
||||||
changed_blocks,
|
changed_blocks,
|
||||||
lighting_invalidated_blocks);
|
lighting_invalidated_blocks);
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
/*
|
/*
|
||||||
EXPERIMENTAL: Create a few other blocks too
|
EXPERIMENTAL: Create a few other blocks too
|
||||||
*/
|
*/
|
||||||
@ -206,6 +204,12 @@ void * EmergeThread::Thread()
|
|||||||
{
|
{
|
||||||
//dstream<<"EmergeThread: Got a dummy block"<<std::endl;
|
//dstream<<"EmergeThread: Got a dummy block"<<std::endl;
|
||||||
got_block = false;
|
got_block = false;
|
||||||
|
|
||||||
|
if(only_from_disk == false)
|
||||||
|
{
|
||||||
|
dstream<<"EmergeThread: wanted to generate a block but got a dummy"<<std::endl;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(InvalidPositionException &e)
|
catch(InvalidPositionException &e)
|
||||||
@ -581,16 +585,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
/*
|
/*
|
||||||
Check if map has this block
|
Check if map has this block
|
||||||
*/
|
*/
|
||||||
MapBlock *block = NULL;
|
MapBlock *block = server->m_env.getMap().getBlockNoCreateNoEx(p);
|
||||||
try
|
|
||||||
{
|
|
||||||
block = server->m_env.getMap().getBlockNoCreate(p);
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool surely_not_found_on_disk = false;
|
bool surely_not_found_on_disk = false;
|
||||||
|
bool block_is_invalid = false;
|
||||||
if(block != NULL)
|
if(block != NULL)
|
||||||
{
|
{
|
||||||
/*if(block->isIncomplete())
|
/*if(block->isIncomplete())
|
||||||
@ -603,6 +601,11 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
{
|
{
|
||||||
surely_not_found_on_disk = true;
|
surely_not_found_on_disk = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(block->isValid() == false)
|
||||||
|
{
|
||||||
|
block_is_invalid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -627,8 +630,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
/*
|
/*
|
||||||
Add inexistent block to emerge queue.
|
Add inexistent block to emerge queue.
|
||||||
*/
|
*/
|
||||||
if(block == NULL || surely_not_found_on_disk)
|
if(block == NULL || surely_not_found_on_disk || block_is_invalid)
|
||||||
{
|
{
|
||||||
|
//dstream<<"asd"<<std::endl;
|
||||||
|
|
||||||
/*SharedPtr<JMutexAutoLock> lock
|
/*SharedPtr<JMutexAutoLock> lock
|
||||||
(m_num_blocks_in_emerge_queue.getLock());*/
|
(m_num_blocks_in_emerge_queue.getLock());*/
|
||||||
|
|
||||||
@ -636,6 +641,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||||||
// Allow only one block in emerge queue
|
// Allow only one block in emerge queue
|
||||||
if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
|
if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
|
||||||
{
|
{
|
||||||
|
//dstream<<"Adding block to emerge queue"<<std::endl;
|
||||||
|
|
||||||
// Add it to the emerge queue and trigger the thread
|
// Add it to the emerge queue and trigger the thread
|
||||||
|
|
||||||
u8 flags = 0;
|
u8 flags = 0;
|
||||||
|
@ -538,6 +538,23 @@ inline v3s16 getContainerPos(v3s16 p, s16 d)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline v2s16 getContainerPos(v2s16 p, v2s16 d)
|
||||||
|
{
|
||||||
|
return v2s16(
|
||||||
|
getContainerPos(p.X, d.X),
|
||||||
|
getContainerPos(p.Y, d.Y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline v3s16 getContainerPos(v3s16 p, v3s16 d)
|
||||||
|
{
|
||||||
|
return v3s16(
|
||||||
|
getContainerPos(p.X, d.X),
|
||||||
|
getContainerPos(p.Y, d.Y),
|
||||||
|
getContainerPos(p.Z, d.Z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isInArea(v3s16 p, s16 d)
|
inline bool isInArea(v3s16 p, s16 d)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
|
@ -536,10 +536,13 @@ void VoxelManipulator::spreadLight(enum LightBank bank, v3s16 p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
/*
|
/*
|
||||||
Lights neighbors of from_nodes, collects all them and then
|
Lights neighbors of from_nodes, collects all them and then
|
||||||
goes on recursively.
|
goes on recursively.
|
||||||
|
|
||||||
|
NOTE: This is faster in small areas but will overflow the
|
||||||
|
stack on large areas. Thus it is not used.
|
||||||
*/
|
*/
|
||||||
void VoxelManipulator::spreadLight(enum LightBank bank,
|
void VoxelManipulator::spreadLight(enum LightBank bank,
|
||||||
core::map<v3s16, bool> & from_nodes)
|
core::map<v3s16, bool> & from_nodes)
|
||||||
@ -560,7 +563,7 @@ void VoxelManipulator::spreadLight(enum LightBank bank,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
/*
|
/*
|
||||||
Lights neighbors of from_nodes, collects all them and then
|
Lights neighbors of from_nodes, collects all them and then
|
||||||
goes on recursively.
|
goes on recursively.
|
||||||
|
Loading…
Reference in New Issue
Block a user