From a2ffa432b31096f2533ecb50f49ba450b29a2989 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Sun, 1 Sep 2019 09:30:00 +0200 Subject: Separated chunk generator from world / plugin interfaces. The generator now only takes care of servicing synchronous "GetChunk(X, Y)" and "GetBiomes(X, Y)" requests. --- src/Generating/ChunkGenerator.h | 184 ++++++---------------------------------- 1 file changed, 25 insertions(+), 159 deletions(-) (limited to 'src/Generating/ChunkGenerator.h') diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h index c4be505da..d11e846dc 100644 --- a/src/Generating/ChunkGenerator.h +++ b/src/Generating/ChunkGenerator.h @@ -1,25 +1,5 @@ - -// ChunkGenerator.h - -// 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 -#include "../OSSupport/IsThread.h" - @@ -32,158 +12,44 @@ class cChunkDesc; -class cChunkGenerator : - public cIsThread +/** The interface that all chunk generators must implement to provide the generated chunks. +Also a static factory that creates the descendants based on INI file settings. +The cChunkGeneratorThread uses this interface to generate chunks for a single world. +Ths calls to generate chunks are synchronous - they don't return until the chunk is fully generated. */ +class cChunkGenerator { - typedef cIsThread super; - public: - /** The interface that a class has to implement to become a generator */ - class cGenerator - { - public: - cGenerator(cChunkGenerator & a_ChunkGenerator); - virtual ~cGenerator() {} // Force a virtual destructor - - /** Called to initialize the generator on server startup. */ - virtual void Initialize(cIniFile & a_IniFile); - - /** Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading. */ - virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) = 0; - - /** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome. Default implementation uses GenerateBiomes(). */ - virtual EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); - - /** Called in a separate thread to do the actual chunk generation. Generator should generate into a_ChunkDesc. */ - virtual void DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) = 0; - - protected: - cChunkGenerator & m_ChunkGenerator; - } ; - - - /** 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. - The generator may be partly or fully overriden by the implementation. */ - virtual void CallHookChunkGenerating(cChunkDesc & a_ChunkDesc) = 0; - - /** Called after the chunk is generated, before it is handed to the chunk sink. - a_ChunkDesc contains the generated chunk data. Implementation may modify this data. */ - 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 - changes the data within. All changes are ignored, though. */ - virtual void OnChunkGenerated(cChunkDesc & a_ChunkDesc) = 0; + virtual ~cChunkGenerator() {} // Force a virtual destructor - /** Called just before the chunk generation is started, - to verify that it hasn't been generated in the meantime. - If this callback returns true, the chunk is not generated. */ - virtual bool IsChunkValid(int a_ChunkX, int a_ChunkZ) = 0; + /** Called to initialize the generator on server startup. + Descendants should call Super::Initialize() before initializing themselves. */ + virtual void Initialize(cIniFile & a_IniFile); - /** Called when the generator is overloaded to skip chunks that are no longer needed. - If this callback returns false, the chunk is not generated. */ - virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 0; + /** Generates the biomes for the specified chunk. + Used by the world loader if biomes failed loading. */ + virtual void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) = 0; - /** 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; - } ; + /** Returns the biome at the specified coords. + Used by ChunkMap if an invalid chunk is queried for biome. + The default implementation uses GenerateBiomes(). */ + virtual EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); + /** Does the actual chunk generation. + Descendants need to override this and generate into a_ChunkDesc. */ + virtual void Generate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc) = 0; - cChunkGenerator (void); - virtual ~cChunkGenerator() override; - - /** Read settings from the ini file and initialize in preperation for being started. */ - bool Initialize(cPluginInterface & a_PluginInterface, cChunkSink & a_ChunkSink, cIniFile & a_IniFile); - - void Stop(void); - - /** 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); - - /** Generates the biomes for the specified chunk (directly, not in a separate thread). Used by the world loader if biomes failed loading. */ - void GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap); - - void WaitForQueueEmpty(void); - - int GetQueueLength(void); - + /** Returns the seed that was read from the INI file. */ int GetSeed(void) const { return m_Seed; } - /** Returns the biome at the specified coords. Used by ChunkMap if an invalid chunk is queried for biome */ - EMCSBiome GetBiomeAt(int a_BlockX, int a_BlockZ); - - /** Reads a block type from the ini file; returns the blocktype on success, emits a warning and returns a_Default's representation on failure. */ - static BLOCKTYPE GetIniBlock(cIniFile & a_IniFile, const AString & a_SectionName, const AString & a_ValueName, const AString & a_Default); - -private: - - struct cQueueItem - { - /** The chunk coords */ - int m_ChunkX, m_ChunkZ; - - /** Force the regeneration of an already existing chunk */ - bool m_ForceGenerate; + /** Creates and initializes the entire generator based on the settings in the INI file. + Initializes the generator, so that it can be used immediately after this call returns. */ + static std::unique_ptr CreateFromIniFile(cIniFile & a_IniFile); - /** Callback to call after generating. */ - cChunkCoordCallback * m_Callback; - }; - typedef std::list cGenQueue; +protected: - - /** Seed used for the generator. */ + /** The main seed, read from the INI file, used for the entire generator. */ int m_Seed; - - /** 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; - - /** The actual generator engine used to generate chunks. */ - cGenerator * m_Generator; - - /** The plugin interface that may modify the generated chunks */ - cPluginInterface * m_PluginInterface; - - /** The destination where the generated chunks are sent */ - cChunkSink * m_ChunkSink; - - - // cIsThread override: - virtual void Execute(void) override; - - /** Generates the specified chunk and sets it into the chunksink. */ - void DoGenerate(int a_ChunkX, int a_ChunkZ); }; -- cgit v1.2.3