From be851871cd43316d12fd9a5f2cc6dec98a1c9ce0 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 30 Jan 2011 01:44:54 +0200 Subject: map generation framework under development... not quite operational at this point. --- src/map.cpp | 564 ++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 416 insertions(+), 148 deletions(-) (limited to 'src/map.cpp') diff --git a/src/map.cpp b/src/map.cpp index 2782cef03..cc1a6d638 100644 --- a/src/map.cpp +++ b/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){ MapSector * sector = m_sector_cache; // Reset inactivity timer @@ -79,11 +77,9 @@ MapSector * Map::getSectorNoGenerate(v2s16 p) } core::map::Node *n = m_sectors.find(p); - // If sector doesn't exist, throw an exception + if(n == NULL) - { - throw InvalidPositionException(); - } + return NULL; MapSector *sector = n->getValue(); @@ -91,13 +87,27 @@ MapSector * Map::getSectorNoGenerate(v2s16 p) m_sector_cache_p = p; m_sector_cache = sector; - //MapSector * ref(sector); - // Reset inactivity timer sector->usage_timer = 0.0; 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) { v2s16 p2d(p3d.X, p3d.Z); @@ -630,6 +640,8 @@ void Map::updateLighting(enum LightBank bank, // For debugging //bool debug=true; //u32 count_was = modified_blocks.size(); + + core::map blocks_to_update; core::map light_sources; @@ -650,6 +662,8 @@ void Map::updateLighting(enum LightBank bank, v3s16 pos = block->getPos(); modified_blocks.insert(pos, block); + blocks_to_update.insert(pos, block); + /* Clear all light from block */ @@ -699,10 +713,12 @@ void Map::updateLighting(enum LightBank bank, } else if(bank == LIGHTBANK_NIGHT) { + // For night lighting, sunlight is not propagated break; } else { + // Invalid lighting bank assert(0); } @@ -710,7 +726,7 @@ void Map::updateLighting(enum LightBank bank, <::Iterator i; - i = a_blocks.getIterator(); + i = blocks_to_update.getIterator(); for(; i.atEnd() == false; i++) { MapBlock *block = i.getNode()->getValue(); v3s16 p = block->getPos(); + + // Add all surrounding blocks 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"); vmanip.unspreadLight(bank, unlight_from, light_sources); @@ -1407,6 +1443,8 @@ void Map::transformLiquids(core::map & modified_blocks) u32 loopcount = 0; u32 initial_size = m_transforming_liquid.size(); + //dstream<<"transformLiquids(): initial_size="<addPoint(v3s16(0,0,0), Attribute(10)); list_randfactor->addPoint(v3s16(0,0,0), Attribute(0.65));*/ } - + /* Try to load map; if not found, create a new one. */ @@ -1917,18 +1961,6 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp): dstream<::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) { - DSTACK("%s: p2d=(%d,%d)", - __FUNCTION_NAME, - p2d.X, p2d.Y); - // Check that it doesn't exist already - try{ - return getSectorNoGenerate(p2d); + // Return if chunk already exists + MapChunk *chunk = getChunk(chunkpos); + if(chunk) + return chunk; + + /* + Add all sectors + */ + + dstream<<"generateChunkRaw(): " + <<"("< changed_blocks; + core::map lighting_invalidated_blocks; + + u32 generated_block_count = 0; + + for(s16 y=0; ygetBlockNoCreateNoEx(y2)) + continue; + + generateBlock(p, NULL, sector, changed_blocks, + lighting_invalidated_blocks); + + generated_block_count++; + } + } } - catch(InvalidPositionException &e) + + dstream<<"generateChunkRaw generated "< 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) +{ /* - Try to load the sector from disk. + Generate chunk and neighbors */ - if(loadSectorFull(p2d) == true) + for(s16 x=-1; x<=1; x++) + for(s16 y=-1; y<=1; y++) { - return getSectorNoGenerate(p2d); + 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)", + __FUNCTION_NAME, + p2d.X, p2d.Y); + + // Check that it doesn't exist already + ServerMapSector *sector = (ServerMapSector*)getSectorNoGenerateNoEx(p2d); + if(sector != NULL) + return sector; + /* If there is no master heightmap, throw. */ @@ -2016,7 +2153,7 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) // Heightmap side width 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 v2s16 nodepos2d = p2d * MAP_BLOCKSIZE; @@ -2068,7 +2205,9 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) Get local attributes */ - float local_plants_amount = 0.0; + float local_plants_amount = 0.5; + +#if 0 { //dstream<<"emergeSector(): Reading point attribute lists"<getInterpolatedFloat(nodepos2d); } +#endif /* Generate sector heightmap @@ -2201,91 +2341,104 @@ MapSector * ServerMap::emergeSector(v2s16 p2d) /* Insert to container */ - JMutexAutoLock lock(m_sector_mutex); m_sectors.insert(p2d, sector); return sector; } -MapBlock * ServerMap::emergeBlock( - v3s16 p, - bool only_from_disk, - core::map &changed_blocks, - core::map &lighting_invalidated_blocks -) +MapSector * ServerMap::emergeSector(v2s16 p2d) { - DSTACK("%s: p=(%d,%d,%d), only_from_disk=%d", + DSTACK("%s: p2d=(%d,%d)", __FUNCTION_NAME, - p.X, p.Y, p.Z, only_from_disk); - - /*dstream<<"ServerMap::emergeBlock(): " - <<"("<getIsVolatile() == false) + chunk_exists = true; /* - OK; Not found. - - Go on generating the block. + 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); - TODO: If a dungeon gets generated so that it's side gets - revealed to the outside air, the lighting should be - recalculated. + /* + Generate directly */ + //return generateSector(); +} + +MapBlock * ServerMap::generateBlock( + v3s16 p, + MapBlock *original_dummy, + ServerMapSector *sector, + core::map &changed_blocks, + core::map &lighting_invalidated_blocks +) +{ + DSTACK("%s: p=(%d,%d,%d)", + __FUNCTION_NAME, + p.X, p.Y, p.Z); + + /*dstream<<"generateBlock(): " + <<"("<getInterpolatedFloat(nodepos2d); } +#endif - //dstream<<"emergeBlock(): Done"<setIsUnderground(completely_underground); @@ -3075,7 +3230,7 @@ continue_generating: } else { - dstream<<"ServerMap::emergeBlock(): " + dstream<<"ServerMap::generateBlock(): " "Invalid heightmap object" <remove(*i); } + + /* + Translate sector's changed blocks to global changed blocks + */ + + for(core::map::Iterator + i = changed_blocks_sector.getIterator(); + i.atEnd() == false; i++) + { + MapBlock *block = i.getNode()->getValue(); + + changed_blocks.insert(block->getPos(), block); + } + + block->setLightingExpired(true); + +#if 0 + /* + Debug information + */ + dstream + <<"lighting_invalidated_blocks.size()" + <<", has_dungeons" + <<", completely_ug" + <<", some_part_ug" + <<" "< &changed_blocks, + core::map &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(): " + <<"("<getId() == MAPSECTOR_SERVER); + } + /*catch(InvalidPositionException &e) + { + dstream<<"emergeBlock: emergeSector() failed"<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"<insertBlock(block); + } + // Done. + return block; + } + + //dstream<<"Not found on disk, generating."< making one"<getPos()] = block; } @@ -3122,37 +3420,7 @@ continue_generating: lighting_invalidated_blocks[block->getPos()] = block; } } - - /* - Translate sector's changed blocks to global changed blocks - */ - for(core::map::Iterator - i = changed_blocks_sector.getIterator(); - i.atEnd() == false; i++) - { - MapBlock *block = i.getNode()->getValue(); - - changed_blocks.insert(block->getPos(), block); - } - - /* - Debug information - */ - if(0) - { - dstream - <<"lighting_invalidated_blocks.size()" - <<", has_dungeons" - <<", completely_ug" - <<", some_part_ug" - <<" "<