From 8cfcc2915c1e9cdea78b6003511e99a3511058d0 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Wed, 22 Feb 2012 21:20:20 +0000 Subject: [PATCH] Rewritten ore generation from scratch, using a different (much faster) algorithm. Chunk generation now about 2x faster :) git-svn-id: http://mc-server.googlecode.com/svn/trunk@321 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/cWorldGenerator.cpp | 134 ++++++++++++++++++++++++++++++------- source/cWorldGenerator.h | 2 + 2 files changed, 111 insertions(+), 25 deletions(-) diff --git a/source/cWorldGenerator.cpp b/source/cWorldGenerator.cpp index 8722372c4..5d9f82bae 100644 --- a/source/cWorldGenerator.cpp +++ b/source/cWorldGenerator.cpp @@ -35,6 +35,36 @@ static struct +// 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; + + + + + cWorldGenerator::cWorldGenerator(cWorld * a_World) : m_World(a_World) { @@ -223,41 +253,20 @@ void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, } 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 - { - a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_STONE; + a_BlockData[ MakeIndex(x, y, z) ] = BLOCK_STONE; } } else { - a_BlockData[ MakeIndex(x, y, z) ] = E_BLOCK_DIRT; + 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)] = E_BLOCK_GRASS; + a_BlockData[MakeIndex(x, Top - 1, z)] = BLOCK_GRASS; // Generate small foliage (1-block): int TopY = Top - 1; @@ -309,6 +318,81 @@ void cWorldGenerator::GenerateTerrain(int a_ChunkX, int a_ChunkY, int a_ChunkZ, } // 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); +} + + + + + +void cWorldGenerator::GenerateOre(char a_OreType, int a_MaxHeight, int a_NumNests, int a_NestSize, char * 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(16); + int BaseY = r1.randInt(a_MaxHeight); + int BaseZ = r1.randInt(16); + 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 >= 16) || (itr->y >= 127) || (itr->z >= 16)) + { + 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 } @@ -335,7 +419,7 @@ void cWorldGenerator::GenerateFoliage(int a_ChunkX, int a_ChunkY, int a_ChunkZ) int TopY = m_World->GetHeight(xx, zz); int index = MakeIndex(x, TopY - 1, z); - if (BlockType[index] == E_BLOCK_GRASS ) + 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 ); diff --git a/source/cWorldGenerator.h b/source/cWorldGenerator.h index 1852e74d2..3083b37dd 100644 --- a/source/cWorldGenerator.h +++ b/source/cWorldGenerator.h @@ -28,6 +28,8 @@ protected: // Thread-unsafe: MTRand r1; + + void GenerateOre(char a_OreType, int a_MaxHeight, int a_NumNests, int a_NestSize, char * a_BlockData); static unsigned int MakeIndex(int x, int y, int z );