2012-01-29 19:28:19 +00:00
#include "Globals.h"
2011-12-25 12:55:20 +00:00
#include "cChunkGenerator.h"
#include "cWorld.h"
2012-05-25 07:18:52 +00:00
#include "../iniFile/iniFile.h"
#include "BioGen.h"
#include "HeiGen.h"
#include "CompoGen.h"
#include "StructGen.h"
#include "FinishGen.h"
2012-06-05 15:20:48 +00:00
#include "cRoot.h"
#include "cPluginManager.h"
2011-12-25 12:55:20 +00:00
2012-01-29 14:29:26 +00:00
/// If the generation queue size exceeds this number, a warning will be output
2012-02-13 21:47:03 +00:00
const int QUEUE_WARNING_LIMIT = 1000 ;
/// If the generation queue size exceeds this number, chunks with no clients will be skipped
2012-02-28 10:01:42 +00:00
const int QUEUE_SKIP_LIMIT = 500 ;
2012-01-29 14:29:26 +00:00
2011-12-25 12:55:20 +00:00
2012-06-09 15:26:52 +00:00
static BLOCKTYPE GetIniBlock ( cIniFile & a_IniFile , const AString & a_SectionName , const AString & a_ValueName , const AString & a_Default )
{
AString BlockType = a_IniFile . GetValueSet ( a_SectionName , a_ValueName , a_Default );
BLOCKTYPE Block = BlockStringToType ( BlockType );
if ( Block < 0 )
{
LOGWARN ( "[&s].%s Could not parse block value \" %s \" . Using default: \" %s \" ." , a_SectionName . c_str (), a_ValueName . c_str (), BlockType . c_str (), a_Default . c_str ());
return BlockStringToType ( a_Default );
}
return Block ;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cChunkGenerator:
2012-02-13 21:47:03 +00:00
cChunkGenerator :: cChunkGenerator ( void )
: super ( "cChunkGenerator" )
, m_World ( NULL )
2012-05-25 07:18:52 +00:00
, m_BiomeGen ( NULL )
, m_HeightGen ( NULL )
, m_CompositionGen ( NULL )
2011-12-25 12:55:20 +00:00
{
2012-02-13 21:47:03 +00:00
}
2012-01-29 14:29:26 +00:00
2012-02-13 21:47:03 +00:00
cChunkGenerator ::~ cChunkGenerator ()
{
Stop ();
}
2012-01-29 14:29:26 +00:00
2011-12-25 12:55:20 +00:00
2012-05-25 07:18:52 +00:00
bool cChunkGenerator :: Start ( cWorld * a_World , cIniFile & a_IniFile )
2011-12-25 12:55:20 +00:00
{
2012-05-25 07:18:52 +00:00
MTRand rnd ;
2012-02-13 21:47:03 +00:00
m_World = a_World ;
2012-06-09 15:26:52 +00:00
m_Seed = a_IniFile . GetValueSetI ( "Seed" , "Seed" , rnd . randInt ());
2012-05-25 07:18:52 +00:00
InitBiomeGen ( a_IniFile );
InitHeightGen ( a_IniFile );
InitCompositionGen ( a_IniFile );
InitStructureGens ( a_IniFile );
InitFinishGens ( a_IniFile );
a_IniFile . WriteFile ();
2012-02-13 21:47:03 +00:00
return super :: Start ();
2011-12-25 12:55:20 +00:00
}
2012-01-29 14:29:26 +00:00
2012-02-13 21:47:03 +00:00
void cChunkGenerator :: Stop ( void )
2011-12-25 12:55:20 +00:00
{
2012-03-10 17:37:00 +00:00
m_ShouldTerminate = true ;
2012-02-13 21:47:03 +00:00
m_Event . Set ();
2012-02-18 17:53:22 +00:00
m_evtRemoved . Set (); // Wake up anybody waiting for empty queue
2012-02-13 21:47:03 +00:00
Wait ();
2012-05-25 07:18:52 +00:00
// 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 )
{
2012-06-09 15:26:52 +00:00
AString BiomeGenName = a_IniFile . GetValueSet ( "Generator" , "BiomeGen" , "" );
2012-05-25 07:18:52 +00:00
if ( BiomeGenName . empty ())
{
2012-06-09 15:26:52 +00:00
LOGWARN ( "[Generator]::BiomeGen value not found in world.ini, using \" DistortedVoronoi \" ." );
BiomeGenName = "DistortedVoronoi" ;
2012-05-25 07:18:52 +00:00
}
2012-02-13 21:47:03 +00:00
2012-06-02 13:21:59 +00:00
bool CacheOffByDefault = false ;
2012-05-25 07:18:52 +00:00
if ( NoCaseCompare ( BiomeGenName , "constant" ) == 0 )
{
2012-06-09 15:26:52 +00:00
AString Biome = a_IniFile . GetValueSet ( "Generator" , "ConstantBiome" , "Plains" );
2012-05-27 10:57:36 +00:00
EMCSBiome b = StringToBiome ( Biome );
if ( b == - 1 )
{
2012-06-02 12:19:20 +00:00
LOGWARN ( "[Generator]::ConstantBiome value \" %s \" not recognized, using \" Plains \" ." , Biome . c_str ());
2012-05-27 10:57:36 +00:00
b = biPlains ;
}
m_BiomeGen = new cBioGenConstant ( b );
2012-06-02 13:21:59 +00:00
CacheOffByDefault = true ; // we're generating faster than a cache would retrieve data :)
2012-05-25 07:18:52 +00:00
}
else if ( NoCaseCompare ( BiomeGenName , "checkerboard" ) == 0 )
{
2012-06-09 15:26:52 +00:00
int BiomeSize = a_IniFile . GetValueSetI ( "Generator" , "CheckerboardBiomeSize" , 64 );
AString Biomes = a_IniFile . GetValueSet ( "Generator" , "CheckerBoardBiomes" , "" );
2012-05-27 10:51:04 +00:00
m_BiomeGen = new cBioGenCheckerboard ( BiomeSize , Biomes );
2012-06-02 13:21:59 +00:00
CacheOffByDefault = true ; // we're (probably) generating faster than a cache would retrieve data
2012-05-25 07:18:52 +00:00
}
2012-05-27 14:17:47 +00:00
else if ( NoCaseCompare ( BiomeGenName , "voronoi" ) == 0 )
{
2012-06-09 15:26:52 +00:00
int CellSize = a_IniFile . GetValueSetI ( "Generator" , "VoronoiCellSize" , 64 );
AString Biomes = a_IniFile . GetValueSet ( "Generator" , "VoronoiBiomes" , "" );
2012-05-27 14:17:47 +00:00
m_BiomeGen = new cBioGenVoronoi ( m_Seed , CellSize , Biomes );
}
2012-05-25 07:18:52 +00:00
else
{
if ( NoCaseCompare ( BiomeGenName , "distortedvoronoi" ) != 0 )
{
2012-06-09 15:26:52 +00:00
LOGWARNING ( "Unknown BiomeGen \" %s \" , using \" DistortedVoronoi \" instead." , BiomeGenName . c_str ());
2012-05-25 07:18:52 +00:00
}
2012-06-09 15:26:52 +00:00
int CellSize = a_IniFile . GetValueSetI ( "Generator" , "DistortedVoronoiCellSize" , 96 );
AString Biomes = a_IniFile . GetValueSet ( "Generator" , "DistortedVoronoiBiomes" , "" );
2012-05-31 20:34:58 +00:00
m_BiomeGen = new cBioGenDistortedVoronoi ( m_Seed , CellSize , Biomes );
2012-05-25 07:18:52 +00:00
}
2012-06-02 13:21:59 +00:00
// Add a cache, if requested:
2012-06-09 15:26:52 +00:00
int CacheSize = a_IniFile . GetValueSetI ( "Generator" , "BiomeGenCacheSize" , CacheOffByDefault ? 0 : 64 );
2012-06-02 13:21:59 +00:00
if ( CacheSize > 0 )
{
if ( CacheSize < 4 )
{
LOGWARNING ( "Biomegen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d" ,
CacheSize , 4
);
CacheSize = 4 ;
}
LOGINFO ( "Using a cache for biomegen of size %d." , CacheSize );
m_BiomeGen = new cBioGenCache ( m_BiomeGen , CacheSize );
}
2012-05-25 07:18:52 +00:00
}
void cChunkGenerator :: InitHeightGen ( cIniFile & a_IniFile )
{
2012-06-09 15:26:52 +00:00
AString HeightGenName = a_IniFile . GetValueSet ( "Generator" , "HeightGen" , "" );
2012-05-25 07:18:52 +00:00
if ( HeightGenName . empty ())
{
2012-06-09 15:26:52 +00:00
LOGWARN ( "[Generator]::HeightGen value not found in world.ini, using \" Biomal \" ." );
HeightGenName = "Biomal" ;
2012-05-25 07:18:52 +00:00
}
2012-06-02 13:45:57 +00:00
bool CacheOffByDefault = false ;
2012-05-25 07:18:52 +00:00
if ( NoCaseCompare ( HeightGenName , "flat" ) == 0 )
{
2012-06-09 15:26:52 +00:00
int Height = a_IniFile . GetValueSetI ( "Generator" , "FlatHeight" , 5 );
2012-05-25 07:18:52 +00:00
m_HeightGen = new cHeiGenFlat ( Height );
2012-06-02 13:45:57 +00:00
CacheOffByDefault = true ; // We're generating faster than a cache would retrieve data
2012-05-25 07:18:52 +00:00
}
2012-06-02 12:19:20 +00:00
else if ( NoCaseCompare ( HeightGenName , "classic" ) == 0 )
2012-05-25 07:18:52 +00:00
{
// These used to be in terrain.ini, but now they are in world.ini (so that multiple worlds can have different values):
2012-06-09 15:26:52 +00:00
float HeightFreq1 = ( float ) a_IniFile . GetValueSetF ( "Generator" , "ClassicHeightFreq1" , 0.1 );
float HeightFreq2 = ( float ) a_IniFile . GetValueSetF ( "Generator" , "ClassicHeightFreq2" , 1.0 );
float HeightFreq3 = ( float ) a_IniFile . GetValueSetF ( "Generator" , "ClassicHeightFreq3" , 2.0 );
float HeightAmp1 = ( float ) a_IniFile . GetValueSetF ( "Generator" , "ClassicHeightAmp1" , 1.0 );
float HeightAmp2 = ( float ) a_IniFile . GetValueSetF ( "Generator" , "ClassicHeightAmp2" , 0.5 );
float HeightAmp3 = ( float ) a_IniFile . GetValueSetF ( "Generator" , "ClassicHeightAmp3" , 0.5 );
2012-05-25 07:18:52 +00:00
m_HeightGen = new cHeiGenClassic ( m_Seed , HeightFreq1 , HeightAmp1 , HeightFreq2 , HeightAmp2 , HeightFreq3 , HeightAmp3 );
}
2012-06-02 12:19:20 +00:00
else // "biomal" or <not found>
{
if ( NoCaseCompare ( HeightGenName , "biomal" ) != 0 )
{
LOGWARN ( "Unknown HeightGen \" %s \" , using \" Biomal \" instead." , HeightGenName . c_str ());
}
m_HeightGen = new cHeiGenBiomal ( m_Seed , * m_BiomeGen );
}
2012-06-02 13:45:57 +00:00
// Add a cache, if requested:
2012-06-09 15:26:52 +00:00
int CacheSize = a_IniFile . GetValueSetI ( "Generator" , "HeightGenCacheSize" , CacheOffByDefault ? 0 : 64 );
2012-06-02 13:45:57 +00:00
if ( CacheSize > 0 )
{
if ( CacheSize < 4 )
{
LOGWARNING ( "Heightgen cache size set too low, would hurt performance instead of helping. Increasing from %d to %d" ,
CacheSize , 4
);
CacheSize = 4 ;
}
LOGINFO ( "Using a cache for Heightgen of size %d." , CacheSize );
m_HeightGen = new cHeiGenCache ( m_HeightGen , CacheSize );
}
2012-05-25 07:18:52 +00:00
}
2012-06-08 12:16:39 +00:00
2012-05-25 07:18:52 +00:00
void cChunkGenerator :: InitCompositionGen ( cIniFile & a_IniFile )
{
2012-06-09 15:26:52 +00:00
AString CompoGenName = a_IniFile . GetValueSet ( "Generator" , "CompositionGen" , "" );
2012-05-25 07:18:52 +00:00
if ( CompoGenName . empty ())
{
2012-06-09 15:26:52 +00:00
LOGWARN ( "[Generator]::CompositionGen value not found in world.ini, using \" Biomal \" ." );
CompoGenName = "Biomal" ;
2012-05-25 07:18:52 +00:00
}
if ( NoCaseCompare ( CompoGenName , "sameblock" ) == 0 )
{
2012-06-09 15:26:52 +00:00
AString BlockType = a_IniFile . GetValueSet ( "Generator" , "SameBlockType" , "" );
2012-05-25 07:18:52 +00:00
if ( BlockType . empty ())
{
LOGWARN ( "[Generator]::SameBlockType value not found in world.ini, using \" stone \" ." );
BlockType = "stone" ;
}
2012-06-09 15:26:52 +00:00
int Block = GetIniBlock ( a_IniFile , "[Generator]" , "SameBlockType" , "stone" );
2012-06-09 15:37:34 +00:00
bool Bedrocked = ( a_IniFile . GetValueSetI ( "Generator" , "SameBlockBedrocked" , 1 ) != 0 );
2012-05-25 07:18:52 +00:00
m_CompositionGen = new cCompoGenSameBlock (( BLOCKTYPE ) Block , Bedrocked );
}
else if ( NoCaseCompare ( CompoGenName , "debugbiomes" ) == 0 )
{
2012-06-02 20:44:15 +00:00
m_CompositionGen = new cCompoGenDebugBiomes ;
2012-05-25 07:18:52 +00:00
}
2012-06-02 20:44:15 +00:00
else if ( NoCaseCompare ( CompoGenName , "classic" ) == 0 )
2012-05-25 07:18:52 +00:00
{
2012-06-09 15:37:34 +00:00
int SeaLevel = a_IniFile . GetValueSetI ( "Generator" , "ClassicSeaLevel" , 60 );
int BeachHeight = a_IniFile . GetValueSetI ( "Generator" , "ClassicBeachHeight" , 2 );
int BeachDepth = a_IniFile . GetValueSetI ( "Generator" , "ClassicBeachDepth" , 4 );
2012-06-09 15:26:52 +00:00
BLOCKTYPE BlockTop = GetIniBlock ( a_IniFile , "Generator" , "ClassicBlockTop" , "grass" );
BLOCKTYPE BlockMiddle = GetIniBlock ( a_IniFile , "Generator" , "ClassicBlockMiddle" , "dirt" );
BLOCKTYPE BlockBottom = GetIniBlock ( a_IniFile , "Generator" , "ClassicBlockBottom" , "stone" );
BLOCKTYPE BlockBeach = GetIniBlock ( a_IniFile , "Generator" , "ClassicBlockBeach" , "sand" );
BLOCKTYPE BlockBeachBottom = GetIniBlock ( a_IniFile , "Generator" , "ClassicBlockBeachBottom" , "sandstone" );
BLOCKTYPE BlockSea = GetIniBlock ( a_IniFile , "Generator" , "ClassicBlockSea" , "9" );
2012-06-08 12:16:39 +00:00
m_CompositionGen = new cCompoGenClassic (
SeaLevel , BeachHeight , BeachDepth , BlockTop , BlockMiddle , BlockBottom , BlockBeach ,
BlockBeachBottom , BlockSea
);
2012-05-25 07:18:52 +00:00
}
2012-06-02 20:44:15 +00:00
else
{
if ( NoCaseCompare ( CompoGenName , "biomal" ) != 0 )
{
LOGWARN ( "Unknown CompositionGen \" %s \" , using \" biomal \" instead." , CompoGenName . c_str ());
}
2012-06-09 15:26:52 +00:00
int SeaLevel = a_IniFile . GetValueSetI ( "Generator" , "BiomalSeaLevel" , 62 );
2012-06-02 20:44:15 +00:00
m_CompositionGen = new cCompoGenBiomal ( m_Seed , SeaLevel );
}
2012-05-25 07:18:52 +00:00
}
void cChunkGenerator :: InitStructureGens ( cIniFile & a_IniFile )
{
2012-06-09 15:26:52 +00:00
AString Structures = a_IniFile . GetValueSet ( "Generator" , "Structures" , "Trees,MarbleCaves,OreNests" );
2012-05-25 07:18:52 +00:00
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[]
2011-12-25 12:55:20 +00:00
}
2012-01-29 14:29:26 +00:00
2012-05-25 07:18:52 +00:00
void cChunkGenerator :: InitFinishGens ( cIniFile & a_IniFile )
{
2012-06-09 15:26:52 +00:00
AString Structures = a_IniFile . GetValueSet ( "Generator" , "Finishers" , "SprinkleFoliage,Ice,Snow" );
2012-05-25 07:18:52 +00:00
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 )
2011-12-25 12:55:20 +00:00
{
{
2012-02-28 16:59:59 +00:00
cCSLock Lock ( m_CS );
// Check if it is already in the queue:
for ( cChunkCoordsList :: iterator itr = m_Queue . begin (); itr != m_Queue . end (); ++ itr )
{
if (( itr -> m_ChunkX == a_ChunkX ) && ( itr -> m_ChunkY == a_ChunkY ) && ( itr -> m_ChunkZ == a_ChunkZ ))
{
// Already in the queue, bail out
return ;
}
} // for itr - m_Queue[]
// Add to queue, issue a warning if too many:
if ( m_Queue . size () >= QUEUE_WARNING_LIMIT )
2011-12-25 12:55:20 +00:00
{
2012-02-28 16:59:59 +00:00
LOGWARN ( "WARNING: Adding chunk [%i, %i] to generation queue; Queue is too big! (%i)" , a_ChunkX , a_ChunkZ , m_Queue . size ());
2011-12-25 12:55:20 +00:00
}
2012-02-28 16:59:59 +00:00
m_Queue . push_back ( cChunkCoords ( a_ChunkX , a_ChunkY , a_ChunkZ ));
2011-12-25 12:55:20 +00:00
}
2012-01-29 14:29:26 +00:00
2012-02-13 21:47:03 +00:00
m_Event . Set ();
2011-12-25 12:55:20 +00:00
}
2012-01-29 14:29:26 +00:00
2012-05-25 07:18:52 +00:00
void cChunkGenerator :: GenerateBiomes ( int a_ChunkX , int a_ChunkZ , cChunkDef :: BiomeMap & a_BiomeMap )
{
m_BiomeGen -> GenBiomes ( a_ChunkX , a_ChunkZ , a_BiomeMap );
}
2012-02-18 17:53:22 +00:00
void cChunkGenerator :: WaitForQueueEmpty ( void )
{
cCSLock Lock ( m_CS );
2012-03-10 17:37:00 +00:00
while ( ! m_ShouldTerminate && ! m_Queue . empty ())
2012-02-18 17:53:22 +00:00
{
cCSUnlock Unlock ( Lock );
m_evtRemoved . Wait ();
}
}
int cChunkGenerator :: GetQueueLength ( void )
{
cCSLock Lock ( m_CS );
return ( int ) m_Queue . size ();
}
2012-05-25 07:18:52 +00:00
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 );
}
2012-02-13 21:47:03 +00:00
void cChunkGenerator :: Execute ( void )
2011-12-25 12:55:20 +00:00
{
2012-03-10 17:37:00 +00:00
while ( ! m_ShouldTerminate )
2011-12-25 12:55:20 +00:00
{
2012-02-13 21:47:03 +00:00
cCSLock Lock ( m_CS );
while ( m_Queue . size () == 0 )
2011-12-25 12:55:20 +00:00
{
2012-01-29 14:29:26 +00:00
cCSUnlock Unlock ( Lock );
2012-02-13 21:47:03 +00:00
m_Event . Wait ();
2012-03-10 17:37:00 +00:00
if ( m_ShouldTerminate )
2012-02-13 21:47:03 +00:00
{
return ;
}
2011-12-25 12:55:20 +00:00
}
2012-01-29 14:29:26 +00:00
2012-02-13 21:47:03 +00:00
cChunkCoords coords = m_Queue . front (); // Get next coord from queue
m_Queue . erase ( m_Queue . begin () ); // Remove coordinate from queue
bool SkipEnabled = ( m_Queue . size () > QUEUE_SKIP_LIMIT );
2012-01-29 14:29:26 +00:00
Lock . Unlock (); // Unlock ASAP
2012-02-18 17:53:22 +00:00
m_evtRemoved . Set ();
2011-12-25 12:55:20 +00:00
2012-04-10 11:22:11 +00:00
// Hack for regenerating chunks: if Y != 0, the chunk is considered invalid, even if it has its data set
if (( coords . m_ChunkY == 0 ) && m_World -> IsChunkValid ( coords . m_ChunkX , coords . m_ChunkY , coords . m_ChunkZ ))
2012-02-13 21:47:03 +00:00
{
2012-04-10 11:22:11 +00:00
LOGD ( "Chunk [%d, %d] already generated, skipping generation" , coords . m_ChunkX , coords . m_ChunkZ );
2012-02-28 10:01:42 +00:00
// Already generated, ignore request
continue ;
}
if ( SkipEnabled && ! m_World -> HasChunkAnyClients ( coords . m_ChunkX , coords . m_ChunkY , coords . m_ChunkZ ))
{
2012-04-10 11:22:11 +00:00
LOGWARNING ( "Chunk generator overloaded, skipping chunk [%d, %d, %d]" , coords . m_ChunkX , coords . m_ChunkY , coords . m_ChunkZ );
2011-12-25 12:55:20 +00:00
continue ;
}
2012-02-16 17:45:26 +00:00
2012-02-18 17:53:22 +00:00
LOGD ( "Generating chunk [%d, %d, %d]" , coords . m_ChunkX , coords . m_ChunkY , coords . m_ChunkZ );
2012-02-17 17:56:25 +00:00
DoGenerate ( coords . m_ChunkX , coords . m_ChunkY , coords . m_ChunkZ );
2012-02-13 21:47:03 +00:00
2012-02-16 17:45:26 +00:00
// Save the chunk right after generating, so that we don't have to generate it again on next run
2012-02-17 17:56:25 +00:00
m_World -> GetStorage (). QueueSaveChunk ( coords . m_ChunkX , coords . m_ChunkY , coords . m_ChunkZ );
2012-01-29 14:29:26 +00:00
} // while (!bStop)
2011-12-25 12:55:20 +00:00
}
2012-01-29 14:29:26 +00:00
2012-02-17 17:56:25 +00:00
void cChunkGenerator :: DoGenerate ( int a_ChunkX , int a_ChunkY , int a_ChunkZ )
{
2012-05-25 07:18:52 +00:00
cChunkDef :: BiomeMap BiomeMap ;
cChunkDef :: BlockTypes BlockTypes ;
cChunkDef :: BlockNibbles BlockMeta ;
cChunkDef :: HeightMap HeightMap ;
2012-02-18 17:53:22 +00:00
cEntityList Entities ;
cBlockEntityList BlockEntities ;
2012-03-14 20:56:09 +00:00
2012-05-25 07:18:52 +00:00
// Use the composed generator:
m_BiomeGen -> GenBiomes ( a_ChunkX , a_ChunkZ , BiomeMap );
m_HeightGen -> GenHeightMap ( a_ChunkX , a_ChunkZ , HeightMap );
2012-06-02 20:44:15 +00:00
m_CompositionGen -> ComposeTerrain ( a_ChunkX , a_ChunkZ , BlockTypes , BlockMeta , HeightMap , BiomeMap , Entities , BlockEntities );
2012-05-25 07:18:52 +00:00
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 (
2012-03-14 20:56:09 +00:00
a_ChunkX , a_ChunkY , a_ChunkZ ,
2012-05-25 07:18:52 +00:00
BlockTypes , BlockMeta ,
NULL , NULL , // We don't have lighting, chunk will be lighted when needed
& HeightMap , & BiomeMap ,
Entities , BlockEntities ,
true
2012-03-14 20:56:09 +00:00
);
2012-06-05 15:20:48 +00:00
cRoot :: Get () -> GetPluginManager () -> CallHook ( cPluginManager :: E_PLUGIN_CHUNK_GENERATED , 3 , m_World , a_ChunkX , a_ChunkZ );
2012-02-17 17:56:25 +00:00
}