]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/map.cpp
improved old map support
[dragonfireclient.git] / src / map.cpp
index 334de40defc41fc437c20955d1910d2fbcdacaca..ff823af94aaf05bf24da6d4650f17f515407134f 100644 (file)
@@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "porting.h"
 #include "mineral.h"
 #include "noise.h"
+#include "serverobject.h"
 
 /*
        Map
@@ -1800,7 +1801,6 @@ ServerMap::ServerMap(std::string savedir):
        //m_chunksize = 4;
        //m_chunksize = 2;
        
-       // TODO: Save to and load from a file
        m_seed = (((u64)(myrand()%0xffff)<<0)
                        + ((u64)(myrand()%0xffff)<<16)
                        + ((u64)(myrand()%0xffff)<<32)
@@ -1834,11 +1834,19 @@ ServerMap::ServerMap(std::string savedir):
                        }
                        else
                        {
-                               // Load map metadata (seed, chunksize)
-                               loadMapMeta();
-                               
-                               // Load chunk metadata
-                               loadChunkMeta();
+                               try{
+                                       // Load map metadata (seed, chunksize)
+                                       loadMapMeta();
+
+                                       // Load chunk metadata
+                                       loadChunkMeta();
+                               }
+                               catch(FileNotGoodException &e){
+                                       dstream<<DTIME<<"WARNING: Server: Could not load "
+                                                       <<"metafile(s). Disabling chunk-based "
+                                                       <<"generation."<<std::endl;
+                                       m_chunksize = 0;
+                               }
                        
                                /*// Load sector (0,0) and throw and exception on fail
                                if(loadSectorFull(v2s16(0,0)) == false)
@@ -2170,25 +2178,11 @@ void addRandomObjects(MapBlock *block)
        This is the main map generation method
 */
 
-struct ChunkMakeData
-{
-       ManualMapVoxelManipulator vmanip;
-       u64 seed;
-       s16 y_blocks_min;
-       s16 y_blocks_max;
-       v2s16 sectorpos_base;
-       s16 sectorpos_base_size;
-       v2s16 sectorpos_bigbase;
-       s16 sectorpos_bigbase_size;
-       s16 max_spread_amount;
-
-       ChunkMakeData():
-               vmanip(NULL)
-       {}
-};
-
 void makeChunk(ChunkMakeData *data)
 {
+       if(data->no_op)
+               return;
+       
        s16 y_nodes_min = data->y_blocks_min * MAP_BLOCKSIZE;
        s16 y_nodes_max = data->y_blocks_max * MAP_BLOCKSIZE + MAP_BLOCKSIZE - 1;
        s16 h_blocks = data->y_blocks_max - data->y_blocks_min + 1;
@@ -2235,11 +2229,11 @@ void makeChunk(ChunkMakeData *data)
                /*
                        Skip of already generated
                */
-               {
+               /*{
                        v3s16 p(p2d.X, y_nodes_min, p2d.Y);
                        if(data->vmanip.m_data[data->vmanip.m_area.index(p)].d != CONTENT_AIR)
                                continue;
-               }
+               }*/
 
                // Ground height at this point
                float surface_y_f = 0.0;
@@ -2270,6 +2264,13 @@ void makeChunk(ChunkMakeData *data)
                        u32 i = data->vmanip.m_area.index(v3s16(p2d.X, y_nodes_min, p2d.Y));
                        for(s16 y=y_nodes_min; y<surface_y && y<=y_nodes_max; y++)
                        {
+                               // Skip if already generated.
+                               // This is done here because there might be a cave at
+                               // any point in ground, which could look like it
+                               // wasn't generated.
+                               if(data->vmanip.m_data[i].d != CONTENT_AIR)
+                                       break;
+
                                data->vmanip.m_data[i].d = CONTENT_STONE;
 
                                data->vmanip.m_area.add_y(em, i, 1);
@@ -2947,8 +2948,8 @@ void makeChunk(ChunkMakeData *data)
 
                                        // Add to transforming liquid queue (in case it'd
                                        // start flowing)
-                                       /*v3s16 p = v3s16(p2d.X, y, p2d.Y);
-                                       m_transforming_liquid.push_back(p);*/
+                                       v3s16 p = v3s16(p2d.X, y, p2d.Y);
+                                       data->transforming_liquid.push_back(p);
                                }
                                
                                // Next one
@@ -3426,33 +3427,16 @@ void makeChunk(ChunkMakeData *data)
 //###################################################################
 //###################################################################
 
-MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
-               core::map<v3s16, MapBlock*> &changed_blocks,
-               bool force)
+void ServerMap::initChunkMake(ChunkMakeData &data, v2s16 chunkpos)
 {
-       DSTACK(__FUNCTION_NAME);
-
-       /*
-               Don't generate if already fully generated
-       */
-       if(force == false)
+       if(m_chunksize == 0)
        {
-               MapChunk *chunk = getChunk(chunkpos);
-               if(chunk != NULL && chunk->getGenLevel() == GENERATED_FULLY)
-               {
-                       dstream<<"generateChunkRaw(): Chunk "
-                                       <<"("<<chunkpos.X<<","<<chunkpos.Y<<")"
-                                       <<" already generated"<<std::endl;
-                       return chunk;
-               }
+               data.no_op = true;
+               return;
        }
 
-       dstream<<"generateChunkRaw(): Generating chunk "
-                       <<"("<<chunkpos.X<<","<<chunkpos.Y<<")"
-                       <<std::endl;
-       
-       TimeTaker timer("generateChunkRaw()");
-       
+       data.no_op = false;
+
        // The distance how far into the neighbors the generator is allowed to go.
        s16 max_spread_amount_sectors = 2;
        assert(max_spread_amount_sectors <= m_chunksize);
@@ -3469,8 +3453,8 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
        s16 sectorpos_bigbase_size =
                        sectorpos_base_size + 2 * max_spread_amount_sectors;
                        
-       ChunkMakeData data;
        data.seed = m_seed;
+       data.chunkpos = chunkpos;
        data.y_blocks_min = y_blocks_min;
        data.y_blocks_max = y_blocks_max;
        data.sectorpos_base = sectorpos_base;
@@ -3483,7 +3467,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
                Create the whole area of this and the neighboring chunks
        */
        {
-               TimeTaker timer("generateChunkRaw() create area");
+               TimeTaker timer("initChunkMake() create area");
                
                for(s16 x=0; x<sectorpos_bigbase_size; x++)
                for(s16 z=0; z<sectorpos_bigbase_size; z++)
@@ -3537,13 +3521,18 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
        data.vmanip.setMap(this);
        // Add the area
        {
-               TimeTaker timer("generateChunkRaw() initialEmerge");
+               TimeTaker timer("initChunkMake() initialEmerge");
                data.vmanip.initialEmerge(bigarea_blocks_min, bigarea_blocks_max);
        }
        
-       // Generate stuff
-       makeChunk(&data);
+}
 
+MapChunk* ServerMap::finishChunkMake(ChunkMakeData &data,
+               core::map<v3s16, MapBlock*> &changed_blocks)
+{
+       if(data.no_op)
+               return NULL;
+       
        /*
                Blit generated stuff to map
        */
@@ -3565,18 +3554,27 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
                }
        }
 
+       /*
+               Copy transforming liquid information
+       */
+       while(data.transforming_liquid.size() > 0)
+       {
+               v3s16 p = data.transforming_liquid.pop_front();
+               m_transforming_liquid.push_back(p);
+       }
+
        /*
                Add random objects to blocks
        */
        {
-               for(s16 x=0; x<sectorpos_base_size; x++)
-               for(s16 z=0; z<sectorpos_base_size; z++)
+               for(s16 x=0; x<data.sectorpos_base_size; x++)
+               for(s16 z=0; z<data.sectorpos_base_size; z++)
                {
-                       v2s16 sectorpos = sectorpos_base + v2s16(x,z);
+                       v2s16 sectorpos = data.sectorpos_base + v2s16(x,z);
                        ServerMapSector *sector = createSector(sectorpos);
                        assert(sector);
 
-                       for(s16 y=y_blocks_min; y<=y_blocks_max; y++)
+                       for(s16 y=data.y_blocks_min; y<=data.y_blocks_max; y++)
                        {
                                v3s16 blockpos(sectorpos.X, y, sectorpos.Y);
                                MapBlock *block = createBlock(blockpos);
@@ -3592,7 +3590,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
        for(s16 x=-1; x<=1; x++)
        for(s16 y=-1; y<=1; y++)
        {
-               v2s16 chunkpos0 = chunkpos + v2s16(x,y);
+               v2s16 chunkpos0 = data.chunkpos + v2s16(x,y);
                // Add chunk meta information
                MapChunk *chunk = getChunk(chunkpos0);
                if(chunk == NULL)
@@ -3608,7 +3606,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
        /*
                Set central chunk non-volatile
        */
-       MapChunk *chunk = getChunk(chunkpos);
+       MapChunk *chunk = getChunk(data.chunkpos);
        assert(chunk);
        // Set non-volatile
        //chunk->setIsVolatile(false);
@@ -3618,6 +3616,49 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
                Save changed parts of map
        */
        save(true);
+       
+       return chunk;
+}
+
+#if 0
+// NOTE: Deprecated
+MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
+               core::map<v3s16, MapBlock*> &changed_blocks,
+               bool force)
+{
+       DSTACK(__FUNCTION_NAME);
+
+       /*
+               Don't generate if already fully generated
+       */
+       if(force == false)
+       {
+               MapChunk *chunk = getChunk(chunkpos);
+               if(chunk != NULL && chunk->getGenLevel() == GENERATED_FULLY)
+               {
+                       dstream<<"generateChunkRaw(): Chunk "
+                                       <<"("<<chunkpos.X<<","<<chunkpos.Y<<")"
+                                       <<" already generated"<<std::endl;
+                       return chunk;
+               }
+       }
+
+       dstream<<"generateChunkRaw(): Generating chunk "
+                       <<"("<<chunkpos.X<<","<<chunkpos.Y<<")"
+                       <<std::endl;
+       
+       TimeTaker timer("generateChunkRaw()");
+
+       ChunkMakeData data;
+       
+       // Initialize generation
+       initChunkMake(data, chunkpos);
+       
+       // Generate stuff
+       makeChunk(&data);
+
+       // Finalize generation
+       MapChunk *chunk = finishChunkMake(data, changed_blocks);
 
        /*
                Return central chunk (which was requested)
@@ -3625,6 +3666,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
        return chunk;
 }
 
+// NOTE: Deprecated
 MapChunk* ServerMap::generateChunk(v2s16 chunkpos1,
                core::map<v3s16, MapBlock*> &changed_blocks)
 {
@@ -3650,6 +3692,7 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos1,
        MapChunk *chunk = getChunk(chunkpos1);
        return chunk;
 }
+#endif
 
 ServerMapSector * ServerMap::createSector(v2s16 p2d)
 {
@@ -3704,6 +3747,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
        return sector;
 }
 
+#if 0
 MapSector * ServerMap::emergeSector(v2s16 p2d,
                core::map<v3s16, MapBlock*> &changed_blocks)
 {
@@ -3790,6 +3834,7 @@ MapSector * ServerMap::emergeSector(v2s16 p2d,
        */
        //return generateSector();
 }
+#endif
 
 /*
        NOTE: This is not used for main map generation, only for blocks
@@ -3806,6 +3851,14 @@ MapBlock * ServerMap::generateBlock(
        DSTACK("%s: p=(%d,%d,%d)",
                        __FUNCTION_NAME,
                        p.X, p.Y, p.Z);
+
+       // If chunks are disabled
+       /*if(m_chunksize == 0)
+       {
+               dstream<<"ServerMap::generateBlock(): Chunks disabled -> "
+                               <<"not generating."<<std::endl;
+               return NULL;
+       }*/
        
        /*dstream<<"generateBlock(): "
                        <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
@@ -3858,6 +3911,9 @@ MapBlock * ServerMap::generateBlock(
 
                s16 surface_y = base_rock_level_2d(m_seed, p2d_nodes+v2s16(x0,z0))
                                + AVERAGE_MUD_AMOUNT;
+               // If chunks are disabled
+               if(m_chunksize == 0)
+                       surface_y = WATER_LEVEL + 1;
 
                if(surface_y < lowest_ground_y)
                        lowest_ground_y = surface_y;
@@ -4724,7 +4780,12 @@ void ServerMap::save(bool only_changed)
                                <<std::endl;
        
        saveMapMeta();
-       saveChunkMeta();
+
+       // Disable saving chunk metadata file if chunks are disabled
+       if(m_chunksize != 0)
+       {
+               saveChunkMeta();
+       }
        
        u32 sector_meta_count = 0;
        u32 block_count = 0;
@@ -4778,6 +4839,8 @@ void ServerMap::save(bool only_changed)
        }
 }
 
+#if 0
+// NOTE: Doing this is insane. Deprecated and probably broken.
 void ServerMap::loadAll()
 {
        DSTACK(__FUNCTION_NAME);
@@ -4838,6 +4901,7 @@ void ServerMap::loadAll()
        }
        dstream<<DTIME<<"ServerMap: Map loaded."<<std::endl;
 }
+#endif
 
 #if 0
 void ServerMap::saveMasterHeightmap()
@@ -4903,7 +4967,7 @@ void ServerMap::loadMapMeta()
 {
        DSTACK(__FUNCTION_NAME);
        
-       dstream<<"INFO: ServerMap::loadMapMeta(): Loading chunk metadata"
+       dstream<<"INFO: ServerMap::loadMapMeta(): Loading map metadata"
                        <<std::endl;
 
        std::string fullpath = m_savedir + "/map_meta.txt";
@@ -4912,7 +4976,7 @@ void ServerMap::loadMapMeta()
        {
                dstream<<"ERROR: ServerMap::loadMapMeta(): "
                                <<"could not open"<<fullpath<<std::endl;
-               throw FileNotGoodException("Cannot open chunk metadata");
+               throw FileNotGoodException("Cannot open map metadata");
        }
 
        Settings params;
@@ -4941,6 +5005,9 @@ void ServerMap::loadMapMeta()
 void ServerMap::saveChunkMeta()
 {
        DSTACK(__FUNCTION_NAME);
+
+       // This should not be called if chunks are disabled.
+       assert(m_chunksize != 0);
        
        u32 count = m_chunks.size();
 
@@ -5054,14 +5121,31 @@ MapSector* ServerMap::loadSectorMeta(std::string dirname)
        // Get destination
        v2s16 p2d = getSectorPos(dirname);
        std::string dir = m_savedir + "/sectors/" + dirname;
+
+       ServerMapSector *sector = NULL;
        
        std::string fullpath = dir + "/meta";
        std::ifstream is(fullpath.c_str(), std::ios_base::binary);
        if(is.good() == false)
-               throw FileNotGoodException("Cannot open sector metafile");
-
-       ServerMapSector *sector = ServerMapSector::deSerialize
-                       (is, this, p2d, m_sectors);
+       {
+               // If the directory exists anyway, it probably is in some old
+               // format. Just go ahead and create the sector.
+               if(fs::PathExists(dir))
+               {
+                       dstream<<"ServerMap::loadSectorMeta(): Sector metafile "
+                                       <<fullpath<<" doesn't exist but directory does."
+                                       <<" Continuing with a sector with no metadata."
+                                       <<std::endl;
+                       sector = createSector(p2d);
+               }
+               else
+                       throw FileNotGoodException("Cannot open sector metafile");
+       }
+       else
+       {
+               sector = ServerMapSector::deSerialize
+                               (is, this, p2d, m_sectors);
+       }
        
        sector->differs_from_disk = false;