From a4a418a679f1ac760a8763edd856f0178cfc6dde Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Fri, 25 May 2012 07:18:52 +0000 Subject: Merged the composable_generator branch into the trunk git-svn-id: http://mc-server.googlecode.com/svn/trunk@504 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cWorldGenerator.cpp | 438 --------------------------------------------- 1 file changed, 438 deletions(-) delete mode 100644 source/cWorldGenerator.cpp (limited to 'source/cWorldGenerator.cpp') diff --git a/source/cWorldGenerator.cpp b/source/cWorldGenerator.cpp deleted file mode 100644 index cdb3951b8..000000000 --- a/source/cWorldGenerator.cpp +++ /dev/null @@ -1,438 +0,0 @@ - -#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules - -#include "cWorldGenerator.h" -#include "cNoise.h" -#include "cWorld.h" -#include "cGenSettings.h" - -#include "BlockID.h" -#include "Vector3i.h" - - - - - -// 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}, -} ; - - - - - -// You can use GLASS for these instead for debugging ore generation ;) -// Beware though, client has problems with this much glass! -const char BLOCK_STONE = E_BLOCK_STONE; -const char BLOCK_DIRT = E_BLOCK_DIRT; -const char BLOCK_GRASS = E_BLOCK_GRASS; - -const int MAX_HEIGHT_COAL = 127; -const int NUM_NESTS_COAL = 40; -const int NEST_SIZE_COAL = 10; - -const int MAX_HEIGHT_IRON = 70; -const int NUM_NESTS_IRON = 10; -const int NEST_SIZE_IRON = 6; - -const int MAX_HEIGHT_REDSTONE = 40; -const int NUM_NESTS_REDSTONE = 10; -const int NEST_SIZE_REDSTONE = 6; - -const int MAX_HEIGHT_GOLD = 35; -const int NUM_NESTS_GOLD = 6; -const int NEST_SIZE_GOLD = 6; - -const int MAX_HEIGHT_DIAMOND = 16; -const int NUM_NESTS_DIAMOND = 6; -const int NEST_SIZE_DIAMOND = 5; - -const int MAX_HEIGHT_LAPIS = 16; -const int NUM_NESTS_LAPIS = 6; -const int NEST_SIZE_LAPIS = 5; - - - - - -cWorldGenerator::cWorldGenerator(cWorld * a_World) : - m_World(a_World) -{ -} - - - - - -cWorldGenerator::~cWorldGenerator() -{ -} - - - - - -void cWorldGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, BLOCKTYPE * a_BlockData, cEntityList & a_Entities, cBlockEntityList & a_BlockEntities) -{ - GenerateTerrain(a_ChunkX, a_ChunkY, a_ChunkZ, a_BlockData); -} - - - - - -void cWorldGenerator::PostGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) -{ - // Check the chunk just generated and all its 8-way neighbors - - // Make the chunks stay loaded in the surrounding 5x5 area: - cChunkStay Stay(m_World); - Stay.Add(a_ChunkX, a_ChunkY, a_ChunkZ); - for (int x = -2; x <= 2; x++) - { - for (int z = -2; z <= 2; z++) - { - Stay.Add(a_ChunkX + x, a_ChunkY, a_ChunkZ + z); - } // for z - } // for x - Stay.Enable(); - - m_World->LoadChunks(Stay); - - 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; - float oct2 = a_Noise.CubicNoise2D( x*cGenSettings::HeightFreq2, y*cGenSettings::HeightFreq2 )*cGenSettings::HeightAmp2; - float oct3 = a_Noise.CubicNoise2D( x*cGenSettings::HeightFreq3, y*cGenSettings::HeightFreq3 )*cGenSettings::HeightAmp3; - - float height = a_Noise.CubicNoise2D( x*0.1f, y*0.1f )*2; - - float flatness = ((a_Noise.CubicNoise2D( x*0.5f, y*0.5f ) + 1.f ) * 0.5f) * 1.1f; // 0 ... 1.5 - flatness *= flatness * flatness; - - return (oct1 + oct2 + oct3) * flatness + height; -} - - - - - -#define PI_2 (1.57079633f) -static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise ) -{ - float oct1 = (a_Noise.CubicNoise3D( x*0.1f, y*0.1f, z*0.1f ))*4; - - oct1 = oct1 * oct1 * oct1; - if( oct1 < 0.f ) oct1 = PI_2; - if( oct1 > PI_2 ) oct1 = PI_2; - - return oct1; -} - - - - - -unsigned int cWorldGenerator::MakeIndex(int x, int y, int z ) -{ - ASSERT((x < cChunkDef::Width) && (x > -1) && (y < cChunkDef::Height) && (y > -1) && (z < cChunkDef::Width) && (z > -1)); - - return cChunkDef::MakeIndexNoCheck( x, y, z ); -} - - - - - -void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, BLOCKTYPE * a_BlockData) -{ - const int WATER_LEVEL = 60; - const int SAND_LEVEL = 3; - - memset(a_BlockData, E_BLOCK_AIR, cChunkDef::BlockDataSize); - - cNoise Noise(m_World->GetWorldSeed()); - - for (int z = 0; z < cChunkDef::Width; z++) - { - const float zz = (float)(a_ChunkZ * cChunkDef::Width + z); - for (int x = 0; x < cChunkDef::Width; x++) - { - // Place bedrock on bottom layer - a_BlockData[MakeIndex(x, 0, z)] = E_BLOCK_BEDROCK; - - const float xx = (float)(a_ChunkX * cChunkDef::Width + x); - - int Height = (int)(GetNoise( xx * 0.05f, zz * 0.05f, Noise ) * 16); - const int Lower = 64; - if ( Height + Lower > 127 ) - { - Height = 127 - Lower; - } - if (Height < -63) - { - Height = -63; - } - 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; - // V prevent caves from getting too close to the surface - if( (Top - y > (WaveNoise*2) ) && cosf(GetMarbleNoise( xx, yy*0.5f, zz, Noise )) * fabs( cosf( yy*0.2f + WaveNoise*2 )*0.75f + WaveNoise ) > 0.5f ) - { - if( y > 4 ) - { - 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 - { - a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STATIONARY_LAVA; - } - } - else if ((y < 61) && (Top - y < SAND_LEVEL )) - { - a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_SAND; - } - else if ((y < 61) && (Top - y < 4 )) - { - 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 - { - { - a_BlockData[ MakeIndex(x, y, z) ] = BLOCK_STONE; - } - } - else - { - a_BlockData[ MakeIndex(x, y, z) ] = BLOCK_DIRT; - } - } // for y - - if (Top + 1 >= WATER_LEVEL + SAND_LEVEL) - { - // Replace top dirt with grass: - a_BlockData[MakeIndex(x, Top - 1, z)] = BLOCK_GRASS; - - // Generate small foliage (1-block): - int TopY = Top - 1; - float val1 = Noise.CubicNoise2D(xx * 0.1f, zz * 0.1f ); - float val2 = Noise.CubicNoise2D(xx * 0.01f, zz * 0.01f ); - 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; - } - } // if (Top above beach-level) - else if (Top > WATER_LEVEL) - { - // This is the sandy shore, generate cacti here - 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 ((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 - { - // 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; - } - } // else (Top is under waterlevel) - } // for x - } // for z - - // Generate ores: - GenerateOre(E_BLOCK_COAL_ORE, MAX_HEIGHT_COAL, NUM_NESTS_COAL, NEST_SIZE_COAL, a_BlockData); - GenerateOre(E_BLOCK_IRON_ORE, MAX_HEIGHT_IRON, NUM_NESTS_IRON, NEST_SIZE_IRON, a_BlockData); - GenerateOre(E_BLOCK_REDSTONE_ORE, MAX_HEIGHT_REDSTONE, NUM_NESTS_REDSTONE, NEST_SIZE_REDSTONE, a_BlockData); - GenerateOre(E_BLOCK_GOLD_ORE, MAX_HEIGHT_GOLD, NUM_NESTS_GOLD, NEST_SIZE_GOLD, a_BlockData); - GenerateOre(E_BLOCK_DIAMOND_ORE, MAX_HEIGHT_DIAMOND, NUM_NESTS_DIAMOND, NEST_SIZE_DIAMOND, a_BlockData); - GenerateOre(E_BLOCK_LAPIS_ORE, MAX_HEIGHT_LAPIS, NUM_NESTS_LAPIS, NEST_SIZE_LAPIS, a_BlockData); -} - - - - - -void cWorldGenerator::GenerateOre(char a_OreType, int a_MaxHeight, int a_NumNests, int a_NestSize, BLOCKTYPE * a_BlockData) -{ - // This function generates several "nests" of ore, each nest consisting of number of ore blocks relatively adjacent to each other. - // It does so by making a random XYZ walk and adding ore along the way in cuboids of different (random) sizes - // Only stone gets replaced with ore, all other blocks stay (so the nest can actually be smaller than specified). - for (int i = 0; i < a_NumNests; i++) - { - int BaseX = r1.randInt(cChunkDef::Width); - int BaseY = r1.randInt(a_MaxHeight); - int BaseZ = r1.randInt(cChunkDef::Width); - sSetBlockList OreBlocks; - size_t NestSize = (size_t)(a_NestSize + r1.randInt(a_NestSize / 4)); // The actual nest size may be up to 1/4 larger - while (OreBlocks.size() < NestSize) - { - // Put a cuboid around [BaseX, BaseY, BaseZ] - for (int x = r1.randInt(2); x >= 0; --x) - { - for (int y = r1.randInt(2); y >= 0; --y) - { - for (int z = r1.randInt(2); z >= 0; --z) - { - if (OreBlocks.size() < NestSize) - { - OreBlocks.push_back(sSetBlock(BaseX + x, BaseY + y, BaseZ + z, a_OreType, 0)); - } - } // for z - } // for y - } // for x - - // Move the base to a neighbor voxel - switch (r1.randInt(4)) - { - case 0: BaseX--; break; - case 1: BaseX++; break; - } - switch (r1.randInt(4)) - { - case 0: BaseY--; break; - case 1: BaseY++; break; - } - switch (r1.randInt(4)) - { - case 0: BaseZ--; break; - case 1: BaseZ++; break; - } - } // while (OreBlocks.size() < NumBlocks) - - // Replace stone with the queued ore blocks: - for (sSetBlockList::iterator itr = OreBlocks.begin(); itr != OreBlocks.end(); ++itr) - { - if ((itr->x < 0) || (itr->y < 0) || (itr->z < 0) || (itr->x >= cChunkDef::Width) || (itr->y >= cChunkDef::Height-1) || (itr->z >= cChunkDef::Width)) - { - continue; - } - int Index = MakeIndex(itr->x, itr->y, itr->z); - if (a_BlockData[Index] == BLOCK_STONE) - { - a_BlockData[Index] = a_OreType; - } - } // for itr - OreBlocks[] - OreBlocks.clear(); - } // for i -} - - - - - -void cWorldGenerator::GenerateFoliage(int a_ChunkX, int a_ChunkY, int a_ChunkZ) -{ - BLOCKTYPE BlockType[cChunkDef::NumBlocks]; - - if (!m_World->GetChunkBlockTypes(a_ChunkX, a_ChunkY, a_ChunkZ, BlockType)) - { - LOGWARNING("Cannot generate foliage on chunk [%d, %d]", a_ChunkX, a_ChunkZ); - return; - } - - cNoise Noise(m_World->GetWorldSeed()); - for (int z = 0; z < cChunkDef::Width; z++) - { - int zz = z + a_ChunkZ * cChunkDef::Width; - for (int x = 0; x < cChunkDef::Width; x++) - { - int xx = x + a_ChunkX * cChunkDef::Width; - - int TopY = m_World->GetHeight(xx, zz); - int index = cChunkDef::MakeIndexNoCheck(x, MAX(TopY - 1, 0), z); - if (BlockType[index] == BLOCK_GRASS) - { - 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)) - { - m_World->GrowTree( xx, TopY, zz ); - } - } // if (Grass) - } // for x - } // for z -} - - - - -- cgit v1.2.3