summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/cChunk.cpp10
-rw-r--r--source/cChunk.h9
-rw-r--r--source/cChunkGenerator.cpp1
-rw-r--r--source/cChunkMap.cpp16
-rw-r--r--source/cChunkMap.h1
-rw-r--r--source/cWorld.cpp43
-rw-r--r--source/cWorld.h1
-rw-r--r--source/cWorldGenerator.cpp221
-rw-r--r--source/cWorldGenerator.h6
-rw-r--r--source/cWorldGenerator_Test.cpp6
-rw-r--r--source/cWorldGenerator_Test.h2
11 files changed, 205 insertions, 111 deletions
diff --git a/source/cChunk.cpp b/source/cChunk.cpp
index b5e56f3c6..afa69fb68 100644
--- a/source/cChunk.cpp
+++ b/source/cChunk.cpp
@@ -248,6 +248,16 @@ void cChunk::SetAllData(const char * a_BlockData, cEntityList & a_Entities, cBlo
+/// Copies m_BlockData into a_Blocks, only the block types
+void cChunk::GetBlocks(char * a_Blocks)
+{
+ memcpy(a_Blocks, m_BlockData, cChunk::c_NumBlocks);
+}
+
+
+
+
+
/// Returns true if there is a block entity at the coords specified
bool cChunk::HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ)
{
diff --git a/source/cChunk.h b/source/cChunk.h
index 60e11b133..2576e2412 100644
--- a/source/cChunk.h
+++ b/source/cChunk.h
@@ -73,6 +73,9 @@ public:
class cChunk
{
public:
+ static const int c_NumBlocks = 16 * 128 * 16;
+ static const int c_BlockDataSize = c_NumBlocks * 2 + (c_NumBlocks/2); // 2.5 * numblocks
+
cChunk(int a_X, int a_Y, int a_Z, cWorld* a_World);
~cChunk();
@@ -98,6 +101,9 @@ public:
/// Sets all chunk data
void SetAllData(const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
+ /// Copies m_BlockData into a_Blocks, only the block types
+ void GetBlocks(char a_Blocks[cChunk::c_NumBlocks]);
+
/// Returns true if there is a block entity at the coords specified
bool HasBlockEntityAt(int a_BlockX, int a_BlockY, int a_BlockZ);
@@ -183,9 +189,6 @@ public:
m_IsSaving = false;
}
- static const int c_NumBlocks = 16*128*16;
- static const int c_BlockDataSize = c_NumBlocks * 2 + (c_NumBlocks/2); // 2.5 * numblocks
-
private:
bool m_IsValid; // True if the chunk is loaded / generated
diff --git a/source/cChunkGenerator.cpp b/source/cChunkGenerator.cpp
index c0fea1fae..c66d20082 100644
--- a/source/cChunkGenerator.cpp
+++ b/source/cChunkGenerator.cpp
@@ -182,6 +182,7 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
cBlockEntityList BlockEntities;
m_pWorldGenerator->GenerateChunk(a_ChunkX, a_ChunkY, a_ChunkZ, BlockData, Entities, BlockEntities);
m_World->ChunkDataGenerated(a_ChunkX, a_ChunkY, a_ChunkZ, BlockData, Entities, BlockEntities);
+ m_pWorldGenerator->PostGenerateChunk(a_ChunkX, a_ChunkY, a_ChunkZ);
}
diff --git a/source/cChunkMap.cpp b/source/cChunkMap.cpp
index 96d3b14e0..c5512dd68 100644
--- a/source/cChunkMap.cpp
+++ b/source/cChunkMap.cpp
@@ -271,6 +271,22 @@ void cChunkMap::GetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDat
+bool cChunkMap::GetChunkBlocks(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_Blocks)
+{
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoGen(a_ChunkX, a_ChunkY, a_ChunkZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
+ {
+ return false;
+ }
+ Chunk->GetBlocks(a_Blocks);
+ return true;
+}
+
+
+
+
+
bool cChunkMap::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
cCSLock Lock(m_CSLayers);
diff --git a/source/cChunkMap.h b/source/cChunkMap.h
index ffea1d504..7c26a14c0 100644
--- a/source/cChunkMap.h
+++ b/source/cChunkMap.h
@@ -42,6 +42,7 @@ public:
void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void ChunkDataGenerated (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
+ bool GetChunkBlocks (int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_Blocks);
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
bool HasChunkAnyClients (int a_ChunkX, int a_ChunkY, int a_ChunkZ);
void SpreadChunkLighting(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
diff --git a/source/cWorld.cpp b/source/cWorld.cpp
index f57c8b5cf..2cde3ac7b 100644
--- a/source/cWorld.cpp
+++ b/source/cWorld.cpp
@@ -431,7 +431,9 @@ void cWorld::InitializeSpawn()
int ChunkX = 0, ChunkY = 0, ChunkZ = 0;
BlockToChunk( (int)m_SpawnX, (int)m_SpawnY, (int)m_SpawnZ, ChunkX, ChunkY, ChunkZ );
- int ViewDist = 20; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is
+ // DEBUG:
+ // int ViewDist = 20; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is
+ int ViewDist = 5; // Always prepare an area 20 chunks across, no matter what the actual cClientHandle::VIEWDISTANCE is
LOG("Preparing spawn area in world \"%s\"", m_WorldName.c_str());
for (int x = 0; x < ViewDist; x++)
@@ -744,32 +746,42 @@ void cWorld::GrowTree( int a_X, int a_Y, int a_Z )
int trunk = r1.randInt() % (7 - 5 + 1) + 5;
for (int i = 0; i < trunk; i++)
{
- if( GetBlock( a_X, a_Y + i, a_Z ) == E_BLOCK_AIR )
- FastSetBlock( a_X, a_Y + i, a_Z, E_BLOCK_LOG, 0 );
+ FastSetBlock( a_X, a_Y + i, a_Z, E_BLOCK_LOG, 0 );
}
// build tree
- for (int j = 0; j < trunk; j++) {
+ for (int j = 0; j < trunk; j++)
+ {
int radius = trunk - j;
- if (radius < 4) {
- if (radius > 2) {
+ if (radius < 4)
+ {
+ if (radius > 2)
+ {
radius = 2;
}
- for (int i = a_X - radius; i <= a_X + radius; i++) {
- for (int k = a_Z-radius; k <= a_Z + radius; k++) {
+ for (int i = a_X - radius; i <= a_X + radius; i++)
+ {
+ for (int k = a_Z-radius; k <= a_Z + radius; k++)
+ {
// small chance to be missing a block to add a little random
- if (k != a_Z || i != a_X && (r1.randInt() % 100 + 1) > 20) {
+ if (k != a_Z || i != a_X && (r1.randInt() % 100 + 1) > 20)
+ {
if( GetBlock( i, a_Y + j, k ) == E_BLOCK_AIR )
+ {
FastSetBlock(i, a_Y+j, k, E_BLOCK_LEAVES, 0 );
+ }
}
- else {
+ else
+ {
//if( m_BlockType[ MakeIndex(i, TopY+j, k) ] == E_BLOCK_AIR )
// m_BlockType[ MakeIndex(i, TopY+j, k) ] = E_BLOCK_LEAVES;
}
}
}
- if( GetBlock( a_X, a_Y+j, a_Z ) == E_BLOCK_AIR )
+ if (GetBlock( a_X, a_Y+j, a_Z ) == E_BLOCK_AIR )
+ {
FastSetBlock( a_X, a_Y+j, a_Z, E_BLOCK_LOG, 0 );
+ }
}
}
@@ -1069,6 +1081,15 @@ void cWorld::GetChunkData(int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCa
+bool cWorld::GetChunkBlocks(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_Blocks)
+{
+ return m_ChunkMap->GetChunkBlocks(a_ChunkX, a_ChunkY, a_ChunkZ, a_Blocks);
+}
+
+
+
+
+
bool cWorld::IsChunkValid(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const
{
return m_ChunkMap->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ);
diff --git a/source/cWorld.h b/source/cWorld.h
index 131361d21..569fe8d32 100644
--- a/source/cWorld.h
+++ b/source/cWorld.h
@@ -76,6 +76,7 @@ public:
void ChunkDataLoaded (int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void ChunkDataGenerated(int a_ChunkX, int a_ChunkY, int a_ChunkZ, const char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
void GetChunkData (int a_ChunkX, int a_ChunkY, int a_ChunkZ, cChunkDataCallback * a_Callback);
+ bool GetChunkBlocks (int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_Blocks);
bool IsChunkValid (int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
bool HasChunkAnyClients(int a_ChunkX, int a_ChunkY, int a_ChunkZ) const;
void UnloadUnusedChunks(void);
diff --git a/source/cWorldGenerator.cpp b/source/cWorldGenerator.cpp
index 284b4c478..b1f868cad 100644
--- a/source/cWorldGenerator.cpp
+++ b/source/cWorldGenerator.cpp
@@ -14,6 +14,27 @@
+// An array describing an 8-way neighbor coords deltas
+static struct
+{
+ int m_X;
+ int m_Z;
+} g_NeighborCoords[] =
+{
+ {-1, -1},
+ {-1, 0},
+ {-1, 1},
+ {0, -1},
+ {0, 1},
+ {1, -1},
+ {1, 0},
+ {1, 1},
+} ;
+
+
+
+
+
cWorldGenerator::cWorldGenerator(cWorld * a_World) :
m_World(a_World)
{
@@ -40,6 +61,46 @@ void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, ch
+void cWorldGenerator::PostGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+{
+ // Check the chunk just generated and all its 8-way neighbors
+ CheckNeighbors(a_ChunkX, a_ChunkY, a_ChunkZ);
+ for (int i = 0; i < ARRAYCOUNT(g_NeighborCoords); i++)
+ {
+ CheckNeighbors(a_ChunkX + g_NeighborCoords[i].m_X, a_ChunkY, a_ChunkZ + g_NeighborCoords[i].m_Z);
+ } // for i - g_NeighborCoords[]
+}
+
+
+
+
+
+void cWorldGenerator::CheckNeighbors(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+{
+ if (!m_World->IsChunkValid(a_ChunkX, a_ChunkY, a_ChunkZ))
+ {
+ return;
+ }
+
+ // Check all 8-way neighbors, if they are all valid, generate foliage in this chunk:
+ int NumNeighbors = 0;
+ for (int i = 0; i < ARRAYCOUNT(g_NeighborCoords); i++)
+ {
+ if (m_World->IsChunkValid(a_ChunkX + g_NeighborCoords[i].m_X, a_ChunkY, a_ChunkZ + g_NeighborCoords[i].m_Z))
+ {
+ NumNeighbors++;
+ }
+ } // for i - g_NeighborCoords[]
+ if (NumNeighbors == 8)
+ {
+ GenerateFoliage(a_ChunkX, a_ChunkY, a_ChunkZ);
+ }
+}
+
+
+
+
+
static float GetNoise( float x, float y, cNoise & a_Noise )
{
float oct1 = a_Noise.CubicNoise2D( x*cGenSettings::HeightFreq1, y*cGenSettings::HeightFreq1 )*cGenSettings::HeightAmp1;
@@ -187,7 +248,8 @@ void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ,
{
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIRT;
}
- }
+ } // for y
+
if (Top + 1 >= WATER_LEVEL + SAND_LEVEL)
{
// Replace top dirt with grass:
@@ -201,111 +263,84 @@ void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ,
a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_WATER;
}
}
- }
- }
+
+ // Generate small foliage (1-block):
+ int index = MakeIndex(x, Top - 1, z);
+ int TopY = Top - 1;
+ float val1 = Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f );
+ float val2 = Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f );
+ if( a_BlockData[index] == E_BLOCK_SAND )
+ {
+ if ((val1 + val2 > 0.f) && ((r1.randInt() % 128) > 124))
+ {
+ a_BlockData[ MakeIndex(x, TopY + 1, z) ] = E_BLOCK_CACTUS;
+ if ((r1.randInt() & 3) == 3)
+ {
+ a_BlockData[ MakeIndex(x, TopY + 2, z) ] = E_BLOCK_CACTUS;
+ }
+ continue;
+ }
+ }
+ else if( a_BlockData[index] == E_BLOCK_GRASS )
+ {
+ float val3 = Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10 );
+ float val4 = Noise.CubicNoise2D(xx * 0.05f + 20, zz * 0.05f + 20 );
+ if( val3 > 0.2f && (r1.randInt()%128) > 124 )
+ {
+ a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER;
+ }
+ else if( val4 > 0.2f && (r1.randInt()%128) > 124 )
+ {
+ a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE;
+ }
+ else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
+ {
+ a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM;
+ }
+ else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
+ {
+ a_BlockData[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM;
+ }
+ }
+ } // for x
+ } // for z
}
-void cWorldGenerator::GenerateFoliage( cChunkPtr & a_Chunk )
+void cWorldGenerator::GenerateFoliage(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
- const ENUM_BLOCK_ID GrassID = E_BLOCK_GRASS;
- const ENUM_BLOCK_ID DirtID = E_BLOCK_DIRT;
- const ENUM_BLOCK_ID SandID = E_BLOCK_SAND;
- const ENUM_BLOCK_ID SandStoneID = E_BLOCK_SANDSTONE;
- const ENUM_BLOCK_ID CaveID = E_BLOCK_AIR;
-
- int PosX = a_Chunk->GetPosX();
- int PosZ = a_Chunk->GetPosZ();
-
- cWorld* World = a_Chunk->GetWorld();
- cNoise m_Noise( World->GetWorldSeed() );
- char* BlockType = a_Chunk->pGetType();
-
- for(int z = 0; z < 16; z++) for(int x = 0; x < 16; x++)
+ char BlockType[cChunk::c_NumBlocks];
+
+ if (!m_World->GetChunkBlocks(a_ChunkX, a_ChunkY, a_ChunkZ, BlockType))
{
- // Find top most Y
- int TopY = -1;
- for(int y = 127; y > 0; y--)
- {
- int index = MakeIndex( x, y, z );
- if( BlockType[index] != E_BLOCK_AIR )
- {
- TopY = y;
- break;
- }
- }
- if( TopY > 0 )
+ LOGWARNING("Cannot generate foliage on chunk [%d, %d]", a_ChunkX, a_ChunkZ);
+ return;
+ }
+
+ cNoise Noise(m_World->GetWorldSeed());
+ for (int z = 0; z < 16; z++)
+ {
+ int zz = z + a_ChunkZ * 16;
+ for (int x = 0; x < 16; x++)
{
- // Change top dirt into grass and prevent sand from floating over caves
- 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 ) {
-
- if( BlockType[index1] == CaveID ) {
- BlockType[ index ] = (char)SandStoneID;
- } else if( BlockType[index2] == CaveID ) {
- BlockType[ index1 ] = (char)SandStoneID;
- } else if( BlockType[index3] == CaveID ) {
- BlockType[ index2 ] = (char)SandStoneID;
- } else if( BlockType[index4] == CaveID ) {
- BlockType[ index3 ] = (char)SandStoneID;
- } else if( BlockType[index5] == CaveID ) {
- BlockType[ index4 ] = (char)SandStoneID;
- }
-
- }
-
- if( BlockType[index] == DirtID )
- {
- BlockType[ index ] = (char)GrassID;
- }
+ int xx = x + a_ChunkX * 16;
- // Plant sum trees
+ int TopY = m_World->GetHeight(xx, zz);
+ int index = MakeIndex(x, TopY - 1, z);
+ if (BlockType[index] == E_BLOCK_GRASS )
{
- int xx = x + PosX*16;
- int zz = z + PosZ*16;
-
- float val1 = m_Noise.CubicNoise2D( xx*0.1f, zz*0.1f );
- float val2 = m_Noise.CubicNoise2D( xx*0.01f, zz*0.01f );
- if( BlockType[index] == SandID )
- {
- if( (val1 + val2 > 0.f) && (r1.randInt()%128) > 124 && BlockType[index] == E_BLOCK_SAND )
- {
- BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_CACTUS;
- if( (r1.randInt() & 3) == 3 )
- {
- BlockType[ MakeIndex(x, TopY+2, z) ] = E_BLOCK_CACTUS;
- }
- continue;
- }
- }
- else if( BlockType[index] == GrassID )
+ float val1 = Noise.CubicNoise2D( xx * 0.1f, zz * 0.1f );
+ float val2 = Noise.CubicNoise2D( xx * 0.01f, zz * 0.01f );
+ if ((val1 + val2 > 0.2f) && ((r1.randInt() % 128) > 124))
{
- float val3 = m_Noise.CubicNoise2D( xx*0.01f+10, zz*0.01f+10 );
- float val4 = m_Noise.CubicNoise2D( xx*0.05f+20, zz*0.05f+20 );
- if( val1 + val2 > 0.2f && (r1.randInt()%128) > 124 )
- World->GrowTree( xx, TopY, zz );
- else if( val3 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_YELLOW_FLOWER;
- else if( val4 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_ROSE;
- else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_RED_MUSHROOM;
- else if( val1+val2+val3+val4 > 0.2f && (r1.randInt()%128) > 124 )
- BlockType[ MakeIndex(x, TopY+1, z) ] = E_BLOCK_BROWN_MUSHROOM;
+ m_World->GrowTree( xx, TopY, zz );
}
- }
-
- }
- }
+ } // if (Grass)
+ } // for x
+ } // for z
}
diff --git a/source/cWorldGenerator.h b/source/cWorldGenerator.h
index 92c2a1d0c..1852e74d2 100644
--- a/source/cWorldGenerator.h
+++ b/source/cWorldGenerator.h
@@ -19,6 +19,8 @@ public:
~cWorldGenerator();
virtual void GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities);
+
+ virtual void PostGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ); // Called when the chunk has been already generated and set valid
protected:
@@ -31,8 +33,10 @@ protected:
virtual void GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData);
- virtual void GenerateFoliage(cChunkPtr & a_Chunk );
+ virtual void GenerateFoliage(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ /// Checks if the chunk has all 8 neighbors valid, if so, foliage is generated on that chunk
+ void CheckNeighbors(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
};
diff --git a/source/cWorldGenerator_Test.cpp b/source/cWorldGenerator_Test.cpp
index 1ffcdbfbe..7f0c58bb8 100644
--- a/source/cWorldGenerator_Test.cpp
+++ b/source/cWorldGenerator_Test.cpp
@@ -25,9 +25,11 @@ void cWorldGenerator_Test::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_Chu
-void cWorldGenerator_Test::GenerateFoliage( cChunkPtr & a_Chunk )
+void cWorldGenerator_Test::GenerateFoliage(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
- (void)a_Chunk;
+ (void)a_ChunkX;
+ (void)a_ChunkY;
+ (void)a_ChunkZ;
}
diff --git a/source/cWorldGenerator_Test.h b/source/cWorldGenerator_Test.h
index 8c4dc0e99..d5580ffc8 100644
--- a/source/cWorldGenerator_Test.h
+++ b/source/cWorldGenerator_Test.h
@@ -17,7 +17,7 @@ public:
protected:
virtual void GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, char * a_BlockData) override;
- virtual void GenerateFoliage(cChunkPtr & a_Chunk ) override;
+ virtual void GenerateFoliage(int a_ChunkX, int a_ChunkY, int a_ChunkZ) override;
};