2012-06-14 09:06:06 -04:00
2013-01-25 05:12:29 -05:00
// ChunkGenerator.h
2012-06-14 09:06:06 -04:00
// Interfaces to the cChunkGenerator class representing the thread that generates chunks
/*
The object takes requests for generating chunks and processes them in a separate thread one by one .
The requests are not added to the queue if there is already a request with the same coords
Before generating , the thread checks if the chunk hasn ' t been already generated .
It is theoretically possible to have multiple generator threads by having multiple instances of this object ,
but then it MAY happen that the chunk is generated twice .
If the generator queue is overloaded , the generator skips chunks with no clients in them
*/
# pragma once
2012-09-23 17:23:33 -04:00
# include "../OSSupport/IsThread.h"
2012-09-23 16:14:04 -04:00
# include "../ChunkDef.h"
2012-06-14 09:06:06 -04:00
// fwd:
class cIniFile ;
2013-01-25 05:12:29 -05:00
class cChunkDesc ;
2012-06-14 09:06:06 -04:00
class cChunkGenerator :
cIsThread
{
typedef cIsThread super ;
public :
2014-01-10 16:22:54 -05:00
/** The interface that a class has to implement to become a generator */
2013-01-25 05:12:29 -05:00
class cGenerator
{
public :
cGenerator ( cChunkGenerator & a_ChunkGenerator ) ;
2014-07-22 18:36:13 -04:00
virtual ~ cGenerator ( ) { } // Force a virtual destructor
2013-01-25 05:12:29 -05:00
2015-07-31 10:49:10 -04:00
/** Called to initialize the generator on server startup. */
2014-01-10 16:22:54 -05:00
virtual void Initialize ( cIniFile & a_IniFile ) ;
2013-01-25 05:12:29 -05:00
2015-07-31 10:49:10 -04:00
/** Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading. */
2013-01-25 05:12:29 -05:00
virtual void GenerateBiomes ( int a_ChunkX , int a_ChunkZ , cChunkDef : : BiomeMap & a_BiomeMap ) = 0 ;
2015-07-31 10:49:10 -04:00
/** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome. Default implementation uses GenerateBiomes(). */
2013-01-25 05:12:29 -05:00
virtual EMCSBiome GetBiomeAt ( int a_BlockX , int a_BlockZ ) ;
2015-07-31 10:49:10 -04:00
/** Called in a separate thread to do the actual chunk generation. Generator should generate into a_ChunkDesc. */
2013-02-08 11:01:44 -05:00
virtual void DoGenerate ( int a_ChunkX , int a_ChunkZ , cChunkDesc & a_ChunkDesc ) = 0 ;
2013-01-25 05:12:29 -05:00
protected :
cChunkGenerator & m_ChunkGenerator ;
2014-01-10 16:22:54 -05:00
} ;
/** The interface through which the plugins are called for their OnChunkGenerating / OnChunkGenerated hooks. */
class cPluginInterface
{
public :
// Force a virtual destructor
virtual ~ cPluginInterface ( ) { }
/** Called when the chunk is about to be generated.
2015-07-31 10:49:10 -04:00
The generator may be partly or fully overriden by the implementation . */
2014-01-10 16:22:54 -05:00
virtual void CallHookChunkGenerating ( cChunkDesc & a_ChunkDesc ) = 0 ;
/** Called after the chunk is generated, before it is handed to the chunk sink.
2015-07-31 10:49:10 -04:00
a_ChunkDesc contains the generated chunk data . Implementation may modify this data . */
2014-01-10 16:22:54 -05:00
virtual void CallHookChunkGenerated ( cChunkDesc & a_ChunkDesc ) = 0 ;
} ;
/** The interface through which the generated chunks are handed to the cWorld or whoever created us. */
class cChunkSink
{
public :
// Force a virtual destructor
virtual ~ cChunkSink ( ) { }
/** Called after the chunk has been generated
The interface may store the chunk , send it over network , whatever .
The chunk is not expected to be modified , but the generator will survive if the implementation
2015-07-31 10:49:10 -04:00
changes the data within . All changes are ignored , though . */
2014-01-10 16:22:54 -05:00
virtual void OnChunkGenerated ( cChunkDesc & a_ChunkDesc ) = 0 ;
/** Called just before the chunk generation is started,
to verify that it hasn ' t been generated in the meantime .
2015-07-31 10:49:10 -04:00
If this callback returns true , the chunk is not generated . */
2014-01-10 16:22:54 -05:00
virtual bool IsChunkValid ( int a_ChunkX , int a_ChunkZ ) = 0 ;
/** Called when the generator is overloaded to skip chunks that are no longer needed.
2015-07-31 10:49:10 -04:00
If this callback returns false , the chunk is not generated . */
2014-01-10 16:22:54 -05:00
virtual bool HasChunkAnyClients ( int a_ChunkX , int a_ChunkZ ) = 0 ;
2014-09-05 16:16:48 -04:00
/** Called to check whether the specified chunk is in the queued state.
Currently used only in Debug - mode asserts . */
virtual bool IsChunkQueued ( int a_ChunkX , int a_ChunkZ ) = 0 ;
2013-01-25 05:12:29 -05:00
} ;
2012-06-14 09:06:06 -04:00
cChunkGenerator ( void ) ;
~ cChunkGenerator ( ) ;
2014-01-10 16:22:54 -05:00
bool Start ( cPluginInterface & a_PluginInterface , cChunkSink & a_ChunkSink , cIniFile & a_IniFile ) ;
2012-06-14 09:06:06 -04:00
void Stop ( void ) ;
2014-12-10 16:35:16 -05:00
/** Queues the chunk for generation
If a - ForceGenerate is set , the chunk is regenerated even if the data is already present in the chunksink .
a_Callback is called after the chunk is generated . If the chunk was already present , the callback is still called , even if not regenerating .
It is legal to set the callback to nullptr , no callback is called then .
If the generator becomes overloaded and skips this chunk , the callback is still called . */
void QueueGenerateChunk ( int a_ChunkX , int a_ChunkZ , bool a_ForceGenerate , cChunkCoordCallback * a_Callback = nullptr ) ;
2012-06-14 09:06:06 -04:00
2015-07-31 10:49:10 -04:00
/** Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading. */
2012-06-14 09:06:06 -04:00
void GenerateBiomes ( int a_ChunkX , int a_ChunkZ , cChunkDef : : BiomeMap & a_BiomeMap ) ;
void WaitForQueueEmpty ( void ) ;
int GetQueueLength ( void ) ;
int GetSeed ( void ) const { return m_Seed ; }
2014-12-10 16:35:16 -05:00
/** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome */
2012-06-14 09:06:06 -04:00
EMCSBiome GetBiomeAt ( int a_BlockX , int a_BlockZ ) ;
2014-12-10 16:35:16 -05:00
/** Reads a block type from the ini file; returns the blocktype on success, emits a warning and returns a_Default's representation on failure. */
2013-01-25 05:12:29 -05:00
static BLOCKTYPE GetIniBlock ( cIniFile & a_IniFile , const AString & a_SectionName , const AString & a_ValueName , const AString & a_Default ) ;
2012-06-14 09:06:06 -04:00
private :
2014-12-10 16:35:16 -05:00
struct cQueueItem
{
/** The chunk coords */
int m_ChunkX , m_ChunkZ ;
/** Force the regeneration of an already existing chunk */
bool m_ForceGenerate ;
2015-07-31 10:49:10 -04:00
/** Callback to call after generating. */
2014-12-10 16:35:16 -05:00
cChunkCoordCallback * m_Callback ;
} ;
typedef std : : list < cQueueItem > cGenQueue ;
/** Seed used for the generator. */
2012-06-14 09:06:06 -04:00
int m_Seed ;
2014-12-10 16:35:16 -05:00
/** CS protecting access to the queue. */
cCriticalSection m_CS ;
/** Queue of the chunks to be generated. Protected against multithreaded access by m_CS. */
cGenQueue m_Queue ;
/** Set when an item is added to the queue or the thread should terminate. */
cEvent m_Event ;
/** Set when an item is removed from the queue. */
cEvent m_evtRemoved ;
2012-06-14 09:06:06 -04:00
2014-12-10 16:35:16 -05:00
/** The actual generator engine used to generate chunks. */
cGenerator * m_Generator ;
2014-01-10 16:22:54 -05:00
/** The plugin interface that may modify the generated chunks */
cPluginInterface * m_PluginInterface ;
/** The destination where the generated chunks are sent */
cChunkSink * m_ChunkSink ;
2013-01-25 05:12:29 -05:00
2012-06-14 09:06:06 -04:00
// cIsThread override:
virtual void Execute ( void ) override ;
2014-12-10 16:35:16 -05:00
/** Generates the specified chunk and sets it into the chunksink. */
2014-08-28 05:36:35 -04:00
void DoGenerate ( int a_ChunkX , int a_ChunkZ ) ;
2012-06-14 09:06:06 -04:00
} ;