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/cChunkGenerator.cpp | 289 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 258 insertions(+), 31 deletions(-) (limited to 'source/cChunkGenerator.cpp') diff --git a/source/cChunkGenerator.cpp b/source/cChunkGenerator.cpp index 67b004a69..321246298 100644 --- a/source/cChunkGenerator.cpp +++ b/source/cChunkGenerator.cpp @@ -3,9 +3,12 @@ #include "cChunkGenerator.h" #include "cWorld.h" -#include "cWorldGenerator.h" -#include "cWorldGenerator_Test.h" -#include "WGFlat.h" +#include "../iniFile/iniFile.h" +#include "BioGen.h" +#include "HeiGen.h" +#include "CompoGen.h" +#include "StructGen.h" +#include "FinishGen.h" @@ -24,7 +27,9 @@ const int QUEUE_SKIP_LIMIT = 500; cChunkGenerator::cChunkGenerator(void) : super("cChunkGenerator") , m_World(NULL) - , m_pWorldGenerator(NULL) + , m_BiomeGen(NULL) + , m_HeightGen(NULL) + , m_CompositionGen(NULL) { } @@ -41,22 +46,24 @@ cChunkGenerator::~cChunkGenerator() -bool cChunkGenerator::Start(cWorld * a_World, const AString & a_WorldGeneratorName) +bool cChunkGenerator::Start(cWorld * a_World, cIniFile & a_IniFile) { + MTRand rnd; m_World = a_World; + m_Seed = a_IniFile.GetValueI("Seed", "Seed", rnd.randInt()); - if (NoCaseCompare(a_WorldGeneratorName, "Test") == 0 ) - { - m_pWorldGenerator = new cWorldGenerator_Test(a_World); - } - else if (NoCaseCompare(a_WorldGeneratorName, "flat") == 0) - { - m_pWorldGenerator = new cWGFlat(a_World); - } - else // Default - { - m_pWorldGenerator = new cWorldGenerator(a_World); - } + // TODO: Remove this after INI file interface changes ( http://forum.mc-server.org/showthread.php?tid=427 ) + a_IniFile.DeleteValue("Seed", "Seed"); + + a_IniFile.SetValueI("Seed", "Seed", m_Seed); + + InitBiomeGen(a_IniFile); + InitHeightGen(a_IniFile); + InitCompositionGen(a_IniFile); + InitStructureGens(a_IniFile); + InitFinishGens(a_IniFile); + + a_IniFile.WriteFile(); return super::Start(); } @@ -71,16 +78,201 @@ void cChunkGenerator::Stop(void) m_Event.Set(); m_evtRemoved.Set(); // Wake up anybody waiting for empty queue Wait(); + + // Delete the generating composition: + for (cFinishGenList::const_iterator itr = m_FinishGens.begin(); itr != m_FinishGens.end(); ++itr) + { + delete *itr; + } + m_FinishGens.clear(); + for (cStructureGenList::const_iterator itr = m_StructureGens.begin(); itr != m_StructureGens.end(); ++itr) + { + delete *itr; + } + m_StructureGens.clear(); + delete m_CompositionGen; + m_CompositionGen = NULL; + delete m_HeightGen; + m_HeightGen = NULL; + delete m_BiomeGen; + m_BiomeGen = NULL; +} + + + + + +void cChunkGenerator::InitBiomeGen(cIniFile & a_IniFile) +{ + AString BiomeGenName = a_IniFile.GetValue("Generator", "BiomeGen", ""); + if (BiomeGenName.empty()) + { + LOGWARN("[Generator]::BiomeGen value not found in world.ini, using \"constant\"."); + BiomeGenName = "constant"; + } - delete m_pWorldGenerator; - m_pWorldGenerator = NULL; + if (NoCaseCompare(BiomeGenName, "constant") == 0) + { + int Biome = a_IniFile.GetValueI("Generator", "ConstantBiome", biPlains); + m_BiomeGen = new cBioGenConstant((EMCSBiome)Biome); + } + else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0) + { + int BiomeSize = a_IniFile.GetValueI("Generator", "CheckerboardBiomeSize", 64); + m_BiomeGen = new cBioGenCheckerboard(BiomeSize); + } + else + { + if (NoCaseCompare(BiomeGenName, "distortedvoronoi") != 0) + { + LOGWARNING("Unknown BiomeGen \"%s\", using \"distortedvoronoi\" instead.", BiomeGenName.c_str()); + } + m_BiomeGen = new cBioGenDistortedVoronoi(m_Seed); + } +} + + + + + +void cChunkGenerator::InitHeightGen(cIniFile & a_IniFile) +{ + AString HeightGenName = a_IniFile.GetValue("Generator", "HeightGen", ""); + if (HeightGenName.empty()) + { + LOGWARN("[Generator]::HeightGen value not found in world.ini, using \"classic\"."); + HeightGenName = "classic"; + } + + if (NoCaseCompare(HeightGenName, "flat") == 0) + { + int Height = a_IniFile.GetValueI("Generator", "FlatHeight", 5); + m_HeightGen = new cHeiGenFlat(Height); + } + else // "classic" or + { + if (NoCaseCompare(HeightGenName, "classic") != 0) + { + LOGWARN("Unknown HeightGen \"%s\", using \"classic\" instead.", HeightGenName.c_str()); + } + // These used to be in terrain.ini, but now they are in world.ini (so that multiple worlds can have different values): + float HeightFreq1 = (float)a_IniFile.GetValueF("Generator", "ClassicHeightFreq1", 0.1); + float HeightFreq2 = (float)a_IniFile.GetValueF("Generator", "ClassicHeightFreq2", 1.0); + float HeightFreq3 = (float)a_IniFile.GetValueF("Generator", "ClassicHeightFreq3", 2.0); + float HeightAmp1 = (float)a_IniFile.GetValueF("Generator", "ClassicHeightAmp1", 1.0); + float HeightAmp2 = (float)a_IniFile.GetValueF("Generator", "ClassicHeightAmp2", 0.5); + float HeightAmp3 = (float)a_IniFile.GetValueF("Generator", "ClassicHeightAmp3", 0.5); + m_HeightGen = new cHeiGenClassic(m_Seed, HeightFreq1, HeightAmp1, HeightFreq2, HeightAmp2, HeightFreq3, HeightAmp3); + } +} + + + + + +void cChunkGenerator::InitCompositionGen(cIniFile & a_IniFile) +{ + AString CompoGenName = a_IniFile.GetValue("Generator", "CompositionGen", ""); + if (CompoGenName.empty()) + { + LOGWARN("[Generator]::CompositionGen value not found in world.ini, using \"classic\"."); + CompoGenName = "classic"; + } + if (NoCaseCompare(CompoGenName, "sameblock") == 0) + { + AString BlockType = a_IniFile.GetValue("Generator", "SameBlockType", ""); + if (BlockType.empty()) + { + LOGWARN("[Generator]::SameBlockType value not found in world.ini, using \"stone\"."); + BlockType = "stone"; + } + int Block = BlockStringToType(BlockType); + if (Block < 0) + { + LOGWARN("World.ini: [Generator]::SameBlockType value \"%s\" not parseable (use a number or alias from items.ini), using \"stone\" (1).", BlockType.c_str()); + Block = E_BLOCK_STONE; + } + bool Bedrocked = (a_IniFile.GetValueI("Generator", "SameBlockBedrocked", 1) != 0); + m_CompositionGen = new cCompoGenSameBlock((BLOCKTYPE)Block, Bedrocked); + } + else if (NoCaseCompare(CompoGenName, "debugbiomes") == 0) + { + m_CompositionGen = new cCompoGenDebugBiomes(m_BiomeGen); + } + else + { + if (NoCaseCompare(CompoGenName, "classic") != 0) + { + LOGWARN("Unknown CompositionGen \"%s\", using \"classic\" instead.", CompoGenName.c_str()); + } + int SeaLevel = a_IniFile.GetValueI("Generator", "ClassicSeaLevel", 60); + int BeachHeight = a_IniFile.GetValueI("Generator", "ClassicBeachHeight", 2); + int BeachDepth = a_IniFile.GetValueI("Generator", "ClassicBeachDepth", 4); + m_CompositionGen = new cCompoGenClassic(SeaLevel, BeachHeight, BeachDepth); + } +} + + + + + +void cChunkGenerator::InitStructureGens(cIniFile & a_IniFile) +{ + AString Structures = a_IniFile.GetValue("Generator", "Structures", "Trees,MarbleCaves"); + + AStringVector Str = StringSplit(Structures, ","); + for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr) + { + if (NoCaseCompare(*itr, "trees") == 0) + { + m_StructureGens.push_back(new cStructGenTrees(m_Seed, m_BiomeGen, m_HeightGen, m_CompositionGen)); + } + else if (NoCaseCompare(*itr, "marblecaves") == 0) + { + m_StructureGens.push_back(new cStructGenMarbleCaves(m_Seed)); + } + else if (NoCaseCompare(*itr, "orenests") == 0) + { + m_StructureGens.push_back(new cStructGenOreNests(m_Seed)); + } + else + { + LOGWARNING("Unknown structure generator: \"%s\". Ignoring.", itr->c_str()); + } + } // for itr - Str[] } -void cChunkGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +void cChunkGenerator::InitFinishGens(cIniFile & a_IniFile) +{ + AString Structures = a_IniFile.GetValue("Generator", "Finishers", "SprinkleFoliage"); + + AStringVector Str = StringSplit(Structures, ","); + for (AStringVector::const_iterator itr = Str.begin(); itr != Str.end(); ++itr) + { + if (NoCaseCompare(*itr, "SprinkleFoliage") == 0) + { + m_FinishGens.push_back(new cFinishGenSprinkleFoliage(m_Seed)); + } + else if (NoCaseCompare(*itr, "Snow") == 0) + { + m_FinishGens.push_back(new cFinishGenSnow); + } + else if (NoCaseCompare(*itr, "Ice") == 0) + { + m_FinishGens.push_back(new cFinishGenIce); + } + } // for itr - Str[] +} + + + + + +void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) { { cCSLock Lock(m_CS); @@ -110,6 +302,15 @@ void cChunkGenerator::GenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ) +void cChunkGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) +{ + m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, a_BiomeMap); +} + + + + + void cChunkGenerator::WaitForQueueEmpty(void) { cCSLock Lock(m_CS); @@ -134,6 +335,20 @@ int cChunkGenerator::GetQueueLength(void) +EMCSBiome cChunkGenerator::GetBiomeAt(int a_BlockX, int a_BlockZ) +{ + cChunkDef::BiomeMap Biomes; + int Y = 0; + int ChunkX, ChunkZ; + cWorld::AbsoluteToRelative(a_BlockX, Y, a_BlockZ, ChunkX, Y, ChunkZ); + m_BiomeGen->GenBiomes(ChunkX, ChunkZ, Biomes); + return cChunkDef::GetBiome(Biomes, a_BlockX, a_BlockZ); +} + + + + + void cChunkGenerator::Execute(void) { while (!m_ShouldTerminate) @@ -182,22 +397,34 @@ void cChunkGenerator::Execute(void) void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ) { - BLOCKTYPE BlockData[cChunkDef::BlockDataSize]; + cChunkDef::BiomeMap BiomeMap; + cChunkDef::BlockTypes BlockTypes; + cChunkDef::BlockNibbles BlockMeta; + cChunkDef::HeightMap HeightMap; cEntityList Entities; cBlockEntityList BlockEntities; - m_pWorldGenerator->GenerateChunk(a_ChunkX, a_ChunkY, a_ChunkZ, BlockData, Entities, BlockEntities); - m_World->ChunkDataGenerated( + // Use the composed generator: + m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, BiomeMap); + m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap); + m_CompositionGen->ComposeTerrain(a_ChunkX, a_ChunkZ, BlockTypes, BlockMeta, HeightMap, Entities, BlockEntities); + for (cStructureGenList::iterator itr = m_StructureGens.begin(); itr != m_StructureGens.end(); ++itr) + { + (*itr)->GenStructures(a_ChunkX, a_ChunkZ, BlockTypes, BlockMeta, HeightMap, Entities, BlockEntities); + } // for itr - m_StructureGens[] + for (cFinishGenList::iterator itr = m_FinishGens.begin(); itr != m_FinishGens.end(); ++itr) + { + (*itr)->GenFinish(a_ChunkX, a_ChunkZ, BlockTypes, BlockMeta, HeightMap, BiomeMap, Entities, BlockEntities); + } // for itr - m_FinishGens[] + + m_World->SetChunkData( a_ChunkX, a_ChunkY, a_ChunkZ, - BlockData, - BlockData + cChunkDef::MetaOffset, - BlockData + cChunkDef::LightOffset, - BlockData + cChunkDef::SkyLightOffset, - NULL, - Entities, BlockEntities + BlockTypes, BlockMeta, + NULL, NULL, // We don't have lighting, chunk will be lighted when needed + &HeightMap, &BiomeMap, + Entities, BlockEntities, + true ); - - m_pWorldGenerator->PostGenerateChunk(a_ChunkX, a_ChunkY, a_ChunkZ); } -- cgit v1.2.3