From 499745c1c7a865941b3c102532777c19dfb92ca4 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Sat, 18 Feb 2012 17:53:22 +0000 Subject: Thread-safe chunk generation, storage and generator are queried for progress while initializing server Note that this commit breaks foliage generation - there are no trees in the chunks generated! git-svn-id: http://mc-server.googlecode.com/svn/trunk@292 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cWorldGenerator.cpp | 175 +++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 77 deletions(-) (limited to 'source/cWorldGenerator.cpp') diff --git a/source/cWorldGenerator.cpp b/source/cWorldGenerator.cpp index fcbbcdad3..284b4c478 100644 --- a/source/cWorldGenerator.cpp +++ b/source/cWorldGenerator.cpp @@ -31,19 +31,9 @@ cWorldGenerator::~cWorldGenerator() -void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities) { - // TODO: use a raw char array instead of the entire chunk, then set it as chunk's blockdata - - cChunkPtr Chunk = m_World->GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ); - assert(!Chunk->IsValid()); - - memset(Chunk->pGetBlockData(), 0, cChunk::c_BlockDataSize); - GenerateTerrain(Chunk); - GenerateFoliage(Chunk); - Chunk->CalculateHeightmap(); - Chunk->CalculateLighting(); - Chunk->SetValid(); + GenerateTerrain(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData); } @@ -101,40 +91,44 @@ static float GetOreNoise( float x, float y, float z, cNoise & a_Noise ) -void cWorldGenerator::GenerateTerrain( cChunkPtr a_Chunk ) +unsigned int cWorldGenerator::MakeIndex(int x, int y, int z ) { - Vector3i ChunkPos( a_Chunk->GetPosX(), a_Chunk->GetPosY(), a_Chunk->GetPosZ() ); - char* BlockType = a_Chunk->pGetType(); + assert((x < 16) && (x > -1) && (y < 128) && (y > -1) && (z < 16) && (z > -1)); - //const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS; - const ENUM_BLOCK_ID DirtID = E_BLOCK_DIRT; - const ENUM_BLOCK_ID StoneID = E_BLOCK_STONE; - const ENUM_BLOCK_ID SandID = E_BLOCK_SAND; - const ENUM_BLOCK_ID SandStoneID = E_BLOCK_SANDSTONE; - const ENUM_BLOCK_ID CaveID = E_BLOCK_AIR; - const ENUM_BLOCK_ID LavaID = E_BLOCK_STATIONARY_LAVA; - const ENUM_BLOCK_ID CoalID = E_BLOCK_COAL_ORE; - const ENUM_BLOCK_ID IronID = E_BLOCK_IRON_ORE; - const ENUM_BLOCK_ID GoldID = E_BLOCK_GOLD_ORE; - const ENUM_BLOCK_ID DiamondID = E_BLOCK_DIAMOND_ORE; - const ENUM_BLOCK_ID RedID = E_BLOCK_REDSTONE_ORE; - - cNoise Noise( a_Chunk->GetWorld()->GetWorldSeed() ); - for(int z = 0; z < 16; z++) + return y + (z * 128) + (x * 128 * 16); +} + + + + + +void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData) +{ + const int WATER_LEVEL = 60; + const int SAND_LEVEL = 3; + + memset(a_BlockData, E_BLOCK_AIR, cChunk::c_BlockDataSize); + + cNoise Noise(m_World->GetWorldSeed()); + + for (int z = 0; z < 16; z++) { - const float zz = (float)(ChunkPos.z*16 + z); - for(int x = 0; x < 16; x++) + const float zz = (float)(a_ChunkZ * 16 + z); + for (int x = 0; x < 16; x++) { // Place bedrock on bottom layer - BlockType[ cChunk::MakeIndex(x, 0, z) ] = E_BLOCK_BEDROCK; + a_BlockData[MakeIndex(x, 0, z)] = E_BLOCK_BEDROCK; - const float xx = (float)(ChunkPos.x*16 + x); + const float xx = (float)(a_ChunkX * 16 + x); - int Height = (int)(GetNoise( xx*0.05f, zz*0.05f, Noise )*16); + int Height = (int)(GetNoise( xx * 0.05f, zz * 0.05f, Noise ) * 16); const int Lower = 64; - if( Height+Lower > 127 ) Height = 127-Lower; - const int Top = Lower+Height; - const float WaveNoise = 1;//m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f ) + 0.5f; + if ( Height + Lower > 127 ) + { + Height = 127 - Lower; + } + const int Top = Lower + Height; + const float WaveNoise = 1; // m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f ) + 0.5f; for( int y = 1; y < Top; ++y ) { const float yy = (float)y; @@ -143,42 +137,69 @@ void cWorldGenerator::GenerateTerrain( cChunkPtr a_Chunk ) { if( y > 4 ) { - BlockType[ cChunk::MakeIndex(x, y, z) ] = CaveID; - if( z > 0 ) BlockType[ cChunk::MakeIndex(x, y, z-1) ] = CaveID; - if( z < 15 ) BlockType[ cChunk::MakeIndex(x, y, z+1) ] = CaveID; - if( x > 0 ) BlockType[ cChunk::MakeIndex(x-1, y, z) ] = CaveID; - if( x < 15 ) BlockType[ cChunk::MakeIndex(x+1, y, z) ] = CaveID; + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_AIR; + if( z > 0 ) a_BlockData[ MakeIndex(x, y, z-1) ] = E_BLOCK_AIR; + if( z < 15 ) a_BlockData[ MakeIndex(x, y, z+1) ] = E_BLOCK_AIR; + if( x > 0 ) a_BlockData[ MakeIndex(x-1, y, z) ] = E_BLOCK_AIR; + if( x < 15 ) a_BlockData[ MakeIndex(x+1, y, z) ] = E_BLOCK_AIR; } else { - BlockType[ cChunk::MakeIndex(x, y, z) ] = LavaID; + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_LAVA; } } - else if( y < 61 && Top - y < 3 ) - BlockType[ cChunk::MakeIndex(x, y, z) ] = SandID; - else if( y < 61 && Top - y < 4 ) - BlockType[ cChunk::MakeIndex(x, y, z) ] = SandStoneID; - else if( Top - y > ((WaveNoise+1.5f)*1.5f) ) // rock and ores between 1.5 .. 4.5 deep + else if ((y < 61) && (Top - y < SAND_LEVEL )) + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_SAND; + } + else if ((y < 61) && (Top - y < 4 )) { - if( GetOreNoise( xx, yy, zz, Noise ) > 0.5f ) - BlockType[ cChunk::MakeIndex(x, y, z) ] = CoalID; - else if( GetOreNoise( xx, yy+100.f, zz, Noise ) > 0.6f ) - BlockType[ cChunk::MakeIndex(x, y, z) ] = IronID; - else if( yy < 20 && GetOreNoise( xx*1.5f, yy+300.f, zz*1.5f, Noise ) > 0.6f ) - BlockType[ cChunk::MakeIndex(x, y, z) ] = RedID; - else if( yy < 30 && GetOreNoise( xx*2, yy+200.f, zz*2, Noise ) > 0.75f ) - BlockType[ cChunk::MakeIndex(x, y, z) ] = DiamondID; - else if( yy < 40 && GetOreNoise( xx*2, yy+100.f, zz*2, Noise ) > 0.75f ) - BlockType[ cChunk::MakeIndex(x, y, z) ] = GoldID; + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_SANDSTONE; + } + else if (Top - y > ((WaveNoise + 1.5f) * 1.5f)) // rock and ores between 1.5 .. 4.5 deep + { + if ( GetOreNoise( xx, yy, zz, Noise ) > 0.5f ) + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_COAL_ORE; + } + else if ( GetOreNoise( xx, yy+100.f, zz, Noise ) > 0.6f ) + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_IRON_ORE; + } + else if (( yy < 20) && (GetOreNoise( xx * 1.5f, yy + 300.f, zz * 1.5f, Noise ) > 0.6f )) + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_REDSTONE_ORE; + } + else if (( yy < 30) && (GetOreNoise( xx * 2, yy + 200.f, zz * 2, Noise ) > 0.75f )) + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIAMOND_ORE; + } + else if (( yy < 40) && (GetOreNoise( xx * 2, yy + 100.f, zz * 2, Noise ) > 0.75f )) + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_GOLD_ORE; + } else - BlockType[ cChunk::MakeIndex(x, y, z) ] = StoneID; + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STONE; + } } else - BlockType[ cChunk::MakeIndex(x, y, z) ] = DirtID; + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIRT; + } + } + if (Top + 1 >= WATER_LEVEL + SAND_LEVEL) + { + // Replace top dirt with grass: + a_BlockData[MakeIndex(x, Top - 1, z)] = E_BLOCK_GRASS; } - for( int y = Lower+Height; y < 60; ++y ) + else { - BlockType[ cChunk::MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_WATER; + // Add water up to the WATER_LEVEL: + for (int y = Top; y < WATER_LEVEL; ++y ) + { + a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_WATER; + } } } } @@ -188,7 +209,7 @@ void cWorldGenerator::GenerateTerrain( cChunkPtr a_Chunk ) -void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk ) +void cWorldGenerator::GenerateFoliage( cChunkPtr & a_Chunk ) { const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS; const ENUM_BLOCK_ID DirtID = E_BLOCK_DIRT; @@ -209,7 +230,7 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk ) int TopY = -1; for(int y = 127; y > 0; y--) { - int index = cChunk::MakeIndex( x, y, z ); + int index = MakeIndex( x, y, z ); if( BlockType[index] != E_BLOCK_AIR ) { TopY = y; @@ -219,12 +240,12 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk ) if( TopY > 0 ) { // Change top dirt into grass and prevent sand from floating over caves - int index = cChunk::MakeIndex( x, TopY, z ); - int index1 = cChunk::MakeIndex( x, TopY-1, z ); - int index2 = cChunk::MakeIndex( x, TopY-2, z ); - int index3 = cChunk::MakeIndex( x, TopY-3, z ); - int index4 = cChunk::MakeIndex( x, TopY-4, z ); - int index5 = cChunk::MakeIndex( x, TopY-5, z ); + int index = MakeIndex( x, TopY, z ); + int index1 = MakeIndex( x, TopY-1, z ); + int index2 = MakeIndex( x, TopY-2, z ); + int index3 = MakeIndex( x, TopY-3, z ); + int index4 = MakeIndex( x, TopY-4, z ); + int index5 = MakeIndex( x, TopY-5, z ); if( BlockType[index] == SandID ) { @@ -258,10 +279,10 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk ) { if( (val1 + val2 > 0.f) && (r1.randInt()%128) > 124 && BlockType[index] == E_BLOCK_SAND ) { - BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_CACTUS; + BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_CACTUS; if( (r1.randInt() & 3) == 3 ) { - BlockType[ cChunk::MakeIndex(x, TopY+2, z) ] = E_BLOCK_CACTUS; + BlockType[ MakeIndex(x, TopY+2, z) ] = E_BLOCK_CACTUS; } continue; } @@ -273,13 +294,13 @@ void cWorldGenerator::GenerateFoliage( cChunkPtr a_Chunk ) if( val1 + val2 > 0.2f && (r1.randInt()%128) > 124 ) World->GrowTree( xx, TopY, zz ); else if( val3 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER; + BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER; else if( val4 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE; + BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE; else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM; + BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM; else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 ) - BlockType[ cChunk::MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM; + BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM; } } -- cgit v1.2.3