#include "porting.h"
#include "mineral.h"
#include "noise.h"
+#include "serverobject.h"
/*
Map
//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)
}
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)
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;
/*
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;
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);
// 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
//###################################################################
//###################################################################
-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);
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;
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++)
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
*/
}
}
+ /*
+ 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);
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)
/*
Set central chunk non-volatile
*/
- MapChunk *chunk = getChunk(chunkpos);
+ MapChunk *chunk = getChunk(data.chunkpos);
assert(chunk);
// Set non-volatile
//chunk->setIsVolatile(false);
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)
return chunk;
}
+// NOTE: Deprecated
MapChunk* ServerMap::generateChunk(v2s16 chunkpos1,
core::map<v3s16, MapBlock*> &changed_blocks)
{
MapChunk *chunk = getChunk(chunkpos1);
return chunk;
}
+#endif
ServerMapSector * ServerMap::createSector(v2s16 p2d)
{
return sector;
}
+#if 0
MapSector * ServerMap::emergeSector(v2s16 p2d,
core::map<v3s16, MapBlock*> &changed_blocks)
{
*/
//return generateSector();
}
+#endif
/*
NOTE: This is not used for main map generation, only for blocks
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<<")"
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;
<<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;
}
}
+#if 0
+// NOTE: Doing this is insane. Deprecated and probably broken.
void ServerMap::loadAll()
{
DSTACK(__FUNCTION_NAME);
}
dstream<<DTIME<<"ServerMap: Map loaded."<<std::endl;
}
+#endif
#if 0
void ServerMap::saveMasterHeightmap()
{
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";
{
dstream<<"ERROR: ServerMap::loadMapMeta(): "
<<"could not open"<<fullpath<<std::endl;
- throw FileNotGoodException("Cannot open chunk metadata");
+ throw FileNotGoodException("Cannot open map metadata");
}
Settings params;
void ServerMap::saveChunkMeta()
{
DSTACK(__FUNCTION_NAME);
+
+ // This should not be called if chunks are disabled.
+ assert(m_chunksize != 0);
u32 count = m_chunks.size();
// 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;