Mapgen is better now. Not a lot, but a bit!

This commit is contained in:
Perttu Ahola 2011-04-02 20:55:22 +03:00
parent 2990f5d90b
commit bc66bb2d40
9 changed files with 1074 additions and 210 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

After

Width:  |  Height:  |  Size: 512 B

@ -194,7 +194,7 @@ TODO: Copy the text of the last picked sign to inventory in creative
TODO: Check what goes wrong with caching map to disk (Kray) TODO: Check what goes wrong with caching map to disk (Kray)
- Nothing? - Nothing?
FIXME: Server went into some infinite PeerNotFoundException loop FIXME: Server sometimes goes into some infinite PeerNotFoundException loop
* Fix the problem with the server constantly saving one or a few * Fix the problem with the server constantly saving one or a few
blocks? List the first saved block, maybe it explains. blocks? List the first saved block, maybe it explains.
@ -259,7 +259,7 @@ FEATURE: Erosion simulation at map generation time
- 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
Mapgen v2: Mapgen v2 (not doing):
* only_from_disk might not work anymore - check and fix it. * only_from_disk might not work anymore - check and fix it.
* Make the generator to run in background and not blocking block * Make the generator to run in background and not blocking block
placement and transfer placement and transfer
@ -280,7 +280,7 @@ Mapgen v4 (not doing):
* Make chunks to be tiled vertically too * Make chunks to be tiled vertically too
* MAKE IT FASTER * MAKE IT FASTER
Mapgen v3: Mapgen v3 (not doing):
* Generate trees better * Generate trees better
- Add a "trees_added" flag to sector, or something - Add a "trees_added" flag to sector, or something
* How 'bout making turbulence controlled so that for a given 2d position * How 'bout making turbulence controlled so that for a given 2d position
@ -292,7 +292,7 @@ Mapgen v3:
Mapgen v4: Mapgen v4:
* This will be the final way. * This will be the final way.
* Generate blocks in the same way as chunks, by copying a voxelmanipulator * Generate blocks in the same way as chunks, by copying a VoxelManipulator
from the map that is one block larger in all directions. from the map that is one block larger in all directions.
Misc. stuff: Misc. stuff:

File diff suppressed because it is too large Load Diff

106
src/map.h

@ -38,7 +38,6 @@ 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"
/* /*
Some exposed functions Some exposed functions
@ -336,81 +335,29 @@ public:
Map generation 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. True if the block and its neighbors are fully generated.
It means the block will not be touched in the future by the
generator. If false, generateBlock will make it true.
*/ */
MapChunk *getChunk(v2s16 chunkpos) bool blockNonVolatile(v3s16 blockpos)
{ {
core::map<v2s16, MapChunk*>::Node *n; for(s16 x=-1; x<=1; x++)
n = m_chunks.find(chunkpos); for(s16 y=-1; y<=1; y++)
if(n == NULL) for(s16 z=-1; z<=1; z++)
return NULL;
return n->getValue();
}
/*
True if the chunk and its neighbors are fully generated.
It means the chunk will not be touched in the future by the
generator. If false, generateChunk will make it true.
*/
bool chunkNonVolatile(v2s16 chunkpos)
{
/*for(s16 x=-1; x<=1; x++)
for(s16 y=-1; y<=1; y++)*/
s16 x=0;
s16 y=0;
{ {
v2s16 chunkpos0 = chunkpos + v2s16(x,y); v3s16 blockpos0 = blockpos + v3s16(x,y,z);
MapChunk *chunk = getChunk(chunkpos); MapBlock *block = getBlockNoCreateNoEx(blockpos);
if(chunk == NULL) if(block == NULL)
return false; return false;
if(chunk->getGenLevel() != GENERATED_FULLY) if(block->isFullyGenerated() == false)
return false; return false;
} }
return true; return true;
} }
/*
Generate a chunk.
All chunks touching this one can be altered also.
*/
MapChunk* generateChunkRaw(v2s16 chunkpos,
core::map<v3s16, MapBlock*> &changed_blocks,
bool force=false);
/*
Generate a chunk and its neighbors so that it won't be touched
anymore.
*/
MapChunk* generateChunk(v2s16 chunkpos,
core::map<v3s16, MapBlock*> &changed_blocks);
/* /*
Generate a sector. Generate a sector.
This is mainly called by generateChunkRaw.
*/ */
//ServerMapSector * generateSector(v2s16 p); //ServerMapSector * generateSector(v2s16 p);
@ -437,6 +384,27 @@ public:
return emergeSector(p, changed_blocks); return emergeSector(p, changed_blocks);
} }
/*MapBlock * generateBlock(
v3s16 p,
MapBlock *original_dummy,
ServerMapSector *sector,
core::map<v3s16, MapBlock*> &changed_blocks,
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
);*/
/*
Generate a block.
All blocks touching this one can be altered also.
*/
MapBlock* generateBlockRaw(v3s16 blockpos,
core::map<v3s16, MapBlock*> &changed_blocks,
bool force=false);
/*
Generate a block and its neighbors so that it won't be touched
anymore.
*/
MapBlock * generateBlock( MapBlock * generateBlock(
v3s16 p, v3s16 p,
MapBlock *original_dummy, MapBlock *original_dummy,
@ -444,6 +412,8 @@ 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
); );
/*MapBlock* generateBlock(v3s16 blockpos,
core::map<v3s16, MapBlock*> &changed_blocks);*/
/* /*
Get a block from somewhere. Get a block from somewhere.
@ -516,9 +486,6 @@ public:
void saveMapMeta(); void saveMapMeta();
void loadMapMeta(); void loadMapMeta();
void saveChunkMeta();
void loadChunkMeta();
// The sector mutex should be locked when calling most of these // The sector mutex should be locked when calling most of these
// This only saves sector-specific data such as the heightmap // This only saves sector-specific data such as the heightmap
@ -551,11 +518,6 @@ 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;
}; };
/* /*

@ -36,6 +36,7 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
is_underground(false), is_underground(false),
m_lighting_expired(true), m_lighting_expired(true),
m_day_night_differs(false), m_day_night_differs(false),
m_not_fully_generated(false),
m_objects(this) m_objects(this)
{ {
data = NULL; data = NULL;
@ -1762,6 +1763,8 @@ void MapBlock::serialize(std::ostream &os, u8 version)
flags |= 0x02; flags |= 0x02;
if(m_lighting_expired) if(m_lighting_expired)
flags |= 0x04; flags |= 0x04;
if(m_not_fully_generated)
flags |= 0x08;
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;
@ -1884,6 +1887,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
is_underground = (flags & 0x01) ? true : false; is_underground = (flags & 0x01) ? true : false;
m_day_night_differs = (flags & 0x02) ? true : false; m_day_night_differs = (flags & 0x02) ? true : false;
m_lighting_expired = (flags & 0x04) ? true : false; m_lighting_expired = (flags & 0x04) ? true : false;
m_not_fully_generated = (flags & 0x08) ? true : false;
// Uncompress data // Uncompress data
std::ostringstream os(std::ios_base::binary); std::ostringstream os(std::ios_base::binary);

@ -244,6 +244,17 @@ public:
return m_lighting_expired; return m_lighting_expired;
} }
bool isFullyGenerated()
{
return !m_not_fully_generated;
}
void setFullyGenerated(bool b)
{
setChangedFlag();
m_not_fully_generated = !b;
}
bool isValid() bool isValid()
{ {
if(m_lighting_expired) if(m_lighting_expired)
@ -655,12 +666,28 @@ private:
// Whether day and night lighting differs // Whether day and night lighting differs
bool m_day_night_differs; bool m_day_night_differs;
/*
Whether everything that is mainly located on this block has
been added to the world.
While this is false, a block can still be changed a bit when
stuff is added to the neighboring blocks that extends to this
one.
When this is false on every one of a 3x3x3 chunk of blocks, the
central one will not be changed by the map generator in the
future.
TODO: Save in file
*/
bool m_not_fully_generated;
MapBlockObjectList m_objects; MapBlockObjectList m_objects;
// Object spawning stuff // Object spawning stuff
float m_spawn_timer; float m_spawn_timer;
#ifndef SERVER #ifndef SERVER // Only on client
/* /*
Set to true if the mesh has been ordered to be updated Set to true if the mesh has been ordered to be updated
sometime in the background. sometime in the background.

@ -1,66 +0,0 @@
/*
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 16x16)
*/
// These should fit in 8 bits, as they are saved as such.
enum{
GENERATED_FULLY = 0,
GENERATED_PARTLY = 10,
GENERATED_NOT = 20
};
class MapChunk
{
public:
MapChunk():
m_generation_level(GENERATED_NOT)
{
}
/*
Generation level. Possible values:
GENERATED_FULLY = 0 = fully generated
GENERATED_PARTLY = partly generated
GENERATED_NOT = not generated
*/
u16 getGenLevel(){ return m_generation_level; }
void setGenLevel(u16 lev){ m_generation_level = lev; }
void serialize(std::ostream &os, u8 version)
{
os.write((char*)&m_generation_level, 1);
}
void deSerialize(std::istream &is, u8 version)
{
is.read((char*)&m_generation_level, 1);
}
private:
u8 m_generation_level;
};
#endif

@ -13,9 +13,9 @@ void setStoneLikeDiggingProperties(u8 material, float toughness)
DiggingProperties(true, 15.0*toughness, 0)); DiggingProperties(true, 15.0*toughness, 0));
g_material_properties[material].setDiggingProperties("WPick", g_material_properties[material].setDiggingProperties("WPick",
DiggingProperties(true, 1.5*toughness, 65535./30.*toughness)); DiggingProperties(true, 1.3*toughness, 65535./30.*toughness));
g_material_properties[material].setDiggingProperties("STPick", g_material_properties[material].setDiggingProperties("STPick",
DiggingProperties(true, 0.7*toughness, 65535./100.*toughness)); DiggingProperties(true, 0.65*toughness, 65535./100.*toughness));
/*g_material_properties[material].setDiggingProperties("MesePick", /*g_material_properties[material].setDiggingProperties("MesePick",
DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/ DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/

@ -544,11 +544,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
block_is_invalid = true; block_is_invalid = true;
} }
v2s16 p2d(p.X, p.Z); if(block->isFullyGenerated() == false)
ServerMap *map = (ServerMap*)(&server->m_env.getMap()); {
v2s16 chunkpos = map->sector_to_chunk(p2d);
if(map->chunkNonVolatile(chunkpos) == false)
block_is_invalid = true; block_is_invalid = true;
}
} }
/* /*
@ -3420,16 +3419,6 @@ Player *Server::emergePlayer(const char *name, const char *password,
nodepos = v2s16(-range + (myrand()%(range*2)), nodepos = v2s16(-range + (myrand()%(range*2)),
-range + (myrand()%(range*2))); -range + (myrand()%(range*2)));
v2s16 sectorpos = getNodeSectorPos(nodepos); v2s16 sectorpos = getNodeSectorPos(nodepos);
/*
Ignore position if it is near a chunk edge.
Otherwise it would cause excessive loading time at
initial generation
*/
{
if(m_env.getServerMap().sector_to_chunk(sectorpos+v2s16(1,1))
!= m_env.getServerMap().sector_to_chunk(sectorpos+v2s16(-1,-1)))
continue;
}
// Get sector (NOTE: Don't get because it's slow) // Get sector (NOTE: Don't get because it's slow)
//m_env.getMap().emergeSector(sectorpos); //m_env.getMap().emergeSector(sectorpos);
// Get ground height at point (fallbacks to heightmap function) // Get ground height at point (fallbacks to heightmap function)