summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/Generating/BioGen.cpp1
-rw-r--r--source/Generating/BioGen.h2
-rw-r--r--source/Generating/ChunkDesc.h16
-rw-r--r--source/Generating/ChunkGenerator.cpp5
-rw-r--r--source/Generating/CompoGen.cpp96
-rw-r--r--source/Generating/CompoGen.h40
-rw-r--r--source/Generating/ComposableGenerator.cpp79
-rw-r--r--source/Generating/ComposableGenerator.h11
-rw-r--r--source/Generating/HeiGen.cpp1
-rw-r--r--source/Generating/HeiGen.h2
10 files changed, 187 insertions, 66 deletions
diff --git a/source/Generating/BioGen.cpp b/source/Generating/BioGen.cpp
index 16b32d711..1a73fe109 100644
--- a/source/Generating/BioGen.cpp
+++ b/source/Generating/BioGen.cpp
@@ -69,7 +69,6 @@ cBioGenCache::~cBioGenCache()
{
delete[] m_CacheData;
delete[] m_CacheOrder;
- delete m_BioGenToCache;
}
diff --git a/source/Generating/BioGen.h b/source/Generating/BioGen.h
index cdb05b92e..f2afc3e8c 100644
--- a/source/Generating/BioGen.h
+++ b/source/Generating/BioGen.h
@@ -47,7 +47,7 @@ class cBioGenCache :
typedef cBiomeGen super;
public:
- cBioGenCache(cBiomeGen * a_BioGenToCache, int a_CacheSize); // Takes ownership of a_BioGenToCache
+ cBioGenCache(cBiomeGen * a_BioGenToCache, int a_CacheSize); // Doesn't take ownership of a_BioGenToCache
~cBioGenCache();
protected:
diff --git a/source/Generating/ChunkDesc.h b/source/Generating/ChunkDesc.h
index bc952fbe4..41b85a814 100644
--- a/source/Generating/ChunkDesc.h
+++ b/source/Generating/ChunkDesc.h
@@ -30,6 +30,9 @@ class cChunkDesc
public:
// tolua_end
+ /// Uncompressed block metas, 1 meta per byte
+ typedef NIBBLETYPE BlockNibbleBytes[cChunkDef::NumBlocks];
+
cChunkDesc(int a_ChunkX, int a_ChunkZ);
~cChunkDesc();
@@ -172,13 +175,14 @@ public:
void AddBlockEntity(cBlockEntity * a_BlockEntity);
// Accessors used by cChunkGenerator::Generator descendants:
- inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; }
- inline cChunkDef::BlockTypes & GetBlockTypes (void) { return *((cChunkDef::BlockTypes *)m_BlockArea.GetBlockTypes()); }
+ inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; }
+ inline cChunkDef::BlockTypes & GetBlockTypes (void) { return *((cChunkDef::BlockTypes *)m_BlockArea.GetBlockTypes()); }
// CANNOT, different compression!
- // inline cChunkDef::BlockNibbles & GetBlockMetas (void) { return *((cChunkDef::BlockNibbles *)m_BlockArea.GetBlockMetas()); }
- inline cChunkDef::HeightMap & GetHeightMap (void) { return m_HeightMap; }
- inline cEntityList & GetEntities (void) { return m_Entities; }
- inline cBlockEntityList & GetBlockEntities(void) { return m_BlockEntities; }
+ // inline cChunkDef::BlockNibbles & GetBlockMetas (void) { return *((cChunkDef::BlockNibbles *)m_BlockArea.GetBlockMetas()); }
+ inline BlockNibbleBytes & GetBlockMetasUncompressed(void) { return *((BlockNibbleBytes *)m_BlockArea.GetBlockMetas()); }
+ inline cChunkDef::HeightMap & GetHeightMap (void) { return m_HeightMap; }
+ inline cEntityList & GetEntities (void) { return m_Entities; }
+ inline cBlockEntityList & GetBlockEntities (void) { return m_BlockEntities; }
/// Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte)
void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas);
diff --git a/source/Generating/ChunkGenerator.cpp b/source/Generating/ChunkGenerator.cpp
index a4717380d..d35b30460 100644
--- a/source/Generating/ChunkGenerator.cpp
+++ b/source/Generating/ChunkGenerator.cpp
@@ -272,6 +272,11 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
cRoot::Get()->GetPluginManager()->CallHookChunkGenerated(m_World, a_ChunkX, a_ChunkZ, &ChunkDesc);
+ #ifdef _DEBUG
+ // Verify that the generator has produced valid data:
+ ChunkDesc.VerifyHeightmap();
+ #endif
+
cChunkDef::BlockNibbles BlockMetas;
ChunkDesc.CompressBlockMetas(BlockMetas);
diff --git a/source/Generating/CompoGen.cpp b/source/Generating/CompoGen.cpp
index 7fad38656..1d2affc94 100644
--- a/source/Generating/CompoGen.cpp
+++ b/source/Generating/CompoGen.cpp
@@ -483,3 +483,99 @@ void cCompoGenNether::ComposeTerrain(cChunkDesc & a_ChunkDesc)
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cCompoGenCache:
+
+cCompoGenCache::cCompoGenCache(cTerrainCompositionGen * a_Underlying, int a_CacheSize) :
+ m_Underlying(a_Underlying),
+ m_CacheSize(a_CacheSize),
+ m_CacheOrder(new int[a_CacheSize]),
+ m_CacheData(new sCacheData[a_CacheSize]),
+ m_NumHits(0),
+ m_NumMisses(0),
+ m_TotalChain(0)
+{
+ for (int i = 0; i < m_CacheSize; i++)
+ {
+ m_CacheOrder[i] = i;
+ m_CacheData[i].m_ChunkX = 0x7fffffff;
+ m_CacheData[i].m_ChunkZ = 0x7fffffff;
+ }
+}
+
+
+
+
+
+cCompoGenCache::~cCompoGenCache()
+{
+ delete[] m_CacheData;
+ delete[] m_CacheOrder;
+}
+
+
+
+
+
+void cCompoGenCache::ComposeTerrain(cChunkDesc & a_ChunkDesc)
+{
+ //*
+ if (((m_NumHits + m_NumMisses) % 1024) == 10)
+ {
+ LOGD("CompoGenCache: %d hits, %d misses, saved %.2f %%", m_NumHits, m_NumMisses, 100.0 * m_NumHits / (m_NumHits + m_NumMisses));
+ LOGD("CompoGenCache: Avg cache chain length: %.2f", (float)m_TotalChain / m_NumHits);
+ }
+ //*/
+
+ int ChunkX = a_ChunkDesc.GetChunkX();
+ int ChunkZ = a_ChunkDesc.GetChunkZ();
+
+ for (int i = 0; i < m_CacheSize; i++)
+ {
+ if (
+ (m_CacheData[m_CacheOrder[i]].m_ChunkX != ChunkX) ||
+ (m_CacheData[m_CacheOrder[i]].m_ChunkZ != ChunkZ)
+ )
+ {
+ continue;
+ }
+ // Found it in the cache
+ int Idx = m_CacheOrder[i];
+
+ // Move to front:
+ for (int j = i; j > 0; j--)
+ {
+ m_CacheOrder[j] = m_CacheOrder[j - 1];
+ }
+ m_CacheOrder[0] = Idx;
+
+ // Use the cached data:
+ memcpy(a_ChunkDesc.GetBlockTypes(), m_CacheData[Idx].m_BlockTypes, sizeof(a_ChunkDesc.GetBlockTypes()));
+ memcpy(a_ChunkDesc.GetBlockMetasUncompressed(), m_CacheData[Idx].m_BlockMetas, sizeof(a_ChunkDesc.GetBlockMetasUncompressed()));
+
+ m_NumHits++;
+ m_TotalChain += i;
+ return;
+ } // for i - cache
+
+ // Not in the cache:
+ m_NumMisses++;
+ m_Underlying->ComposeTerrain(a_ChunkDesc);
+
+ // Insert it as the first item in the MRU order:
+ int Idx = m_CacheOrder[m_CacheSize - 1];
+ for (int i = m_CacheSize - 1; i > 0; i--)
+ {
+ m_CacheOrder[i] = m_CacheOrder[i - 1];
+ } // for i - m_CacheOrder[]
+ m_CacheOrder[0] = Idx;
+ memcpy(m_CacheData[Idx].m_BlockTypes, a_ChunkDesc.GetBlockTypes(), sizeof(a_ChunkDesc.GetBlockTypes()));
+ memcpy(m_CacheData[Idx].m_BlockMetas, a_ChunkDesc.GetBlockMetasUncompressed(), sizeof(a_ChunkDesc.GetBlockMetasUncompressed()));
+ m_CacheData[Idx].m_ChunkX = ChunkX;
+ m_CacheData[Idx].m_ChunkZ = ChunkZ;
+}
+
+
+
+
diff --git a/source/Generating/CompoGen.h b/source/Generating/CompoGen.h
index 57233e2fd..8391de66e 100644
--- a/source/Generating/CompoGen.h
+++ b/source/Generating/CompoGen.h
@@ -6,6 +6,8 @@
- cCompoGenDebugBiomes
- cCompoGenClassic
- cCompoGenBiomal
+ - cCompoGenNether
+ - cCompoGenCache
*/
@@ -139,3 +141,41 @@ protected:
+
+/// Caches most-recently-used chunk composition of another composition generator. Caches only the types and metas
+class cCompoGenCache :
+ public cTerrainCompositionGen
+{
+public:
+ cCompoGenCache(cTerrainCompositionGen * a_Underlying, int a_CacheSize); // Doesn't take ownership of a_Underlying
+ ~cCompoGenCache();
+
+ // cTerrainCompositionGen override:
+ virtual void ComposeTerrain(cChunkDesc & a_ChunkDesc) override;
+
+protected:
+
+ cTerrainCompositionGen * m_Underlying;
+
+ struct sCacheData
+ {
+ int m_ChunkX;
+ int m_ChunkZ;
+ cChunkDef::BlockTypes m_BlockTypes;
+ cChunkDesc::BlockNibbleBytes m_BlockMetas; // The metas are uncompressed, 1 meta per byte
+ } ;
+
+ // To avoid moving large amounts of data for the MRU behavior, we MRU-ize indices to an array of the actual data
+ int m_CacheSize;
+ int * m_CacheOrder; // MRU-ized order, indices into m_CacheData array
+ sCacheData * m_CacheData; // m_CacheData[m_CacheOrder[0]] is the most recently used
+
+ // Cache statistics
+ int m_NumHits;
+ int m_NumMisses;
+ int m_TotalChain; // Number of cache items walked to get to a hit (only added for hits)
+} ;
+
+
+
+
diff --git a/source/Generating/ComposableGenerator.cpp b/source/Generating/ComposableGenerator.cpp
index 0dd14aa50..7cf099c1f 100644
--- a/source/Generating/ComposableGenerator.cpp
+++ b/source/Generating/ComposableGenerator.cpp
@@ -37,10 +37,9 @@ cComposableGenerator::cComposableGenerator(cChunkGenerator & a_ChunkGenerator) :
m_BiomeGen(NULL),
m_HeightGen(NULL),
m_CompositionGen(NULL),
- m_Noise3DComposable(NULL),
- m_NumNoise3DComposableUses(0),
- m_DistortedHeightmap(NULL),
- m_NumDistortedHeightmapUses(0)
+ m_UnderlyingBiomeGen(NULL),
+ m_UnderlyingHeightGen(NULL),
+ m_UnderlyingCompositionGen(NULL)
{
}
@@ -62,26 +61,18 @@ cComposableGenerator::~cComposableGenerator()
}
m_StructureGens.clear();
- // CompositionGen must not be freed if it is shared between HeightGenCache and CompositionGen:
- int NumUsed = 1;
- if (m_CompositionGen == m_Noise3DComposable)
- {
- NumUsed = m_NumNoise3DComposableUses;
- }
- else if (m_CompositionGen == m_DistortedHeightmap)
- {
- NumUsed = m_NumDistortedHeightmapUses;
- }
- if (NumUsed == 1)
- {
- delete m_CompositionGen;
- }
-
+ delete m_CompositionGen;
m_CompositionGen = NULL;
delete m_HeightGen;
m_HeightGen = NULL;
delete m_BiomeGen;
m_BiomeGen = NULL;
+ delete m_UnderlyingCompositionGen;
+ m_UnderlyingCompositionGen = NULL;
+ delete m_UnderlyingHeightGen;
+ m_UnderlyingHeightGen = NULL;
+ delete m_UnderlyingBiomeGen;
+ m_UnderlyingBiomeGen = NULL;
}
@@ -216,7 +207,8 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
CacheSize = 4;
}
LOGINFO("Using a cache for biomegen of size %d.", CacheSize);
- m_BiomeGen = new cBioGenCache(m_BiomeGen, CacheSize);
+ m_UnderlyingBiomeGen = m_BiomeGen;
+ m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize);
}
m_BiomeGen->Initialize(a_IniFile);
}
@@ -255,24 +247,13 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile)
}
else if (NoCaseCompare(HeightGenName, "DistortedHeightmap") == 0)
{
- if (m_DistortedHeightmap == NULL)
- {
- m_DistortedHeightmap = new cDistortedHeightmap(Seed, *m_BiomeGen);
- m_DistortedHeightmap->Initialize(a_IniFile);
- }
- m_HeightGen = m_DistortedHeightmap;
- m_NumDistortedHeightmapUses++;
- // TODO: Optimize by sharing with CompoGen
+ m_HeightGen = new cDistortedHeightmap(Seed, *m_BiomeGen);
+ ((cDistortedHeightmap *)m_HeightGen)->Initialize(a_IniFile);
}
else if (NoCaseCompare(HeightGenName, "Noise3D") == 0)
{
- if (m_Noise3DComposable == NULL)
- {
- m_Noise3DComposable = new cNoise3DComposable(Seed);
- m_Noise3DComposable->Initialize(a_IniFile);
- }
- m_HeightGen = m_Noise3DComposable;
- m_NumNoise3DComposableUses++;
+ m_HeightGen = new cNoise3DComposable(Seed);
+ ((cNoise3DComposable *)m_HeightGen)->Initialize(a_IniFile);
}
else // "biomal" or <not found>
{
@@ -308,7 +289,8 @@ void cComposableGenerator::InitHeightGen(cIniFile & a_IniFile)
CacheSize = 4;
}
LOGINFO("Using a cache for Heightgen of size %d.", CacheSize);
- m_HeightGen = new cHeiGenCache(m_HeightGen, CacheSize);
+ m_UnderlyingHeightGen = m_HeightGen;
+ m_HeightGen = new cHeiGenCache(m_UnderlyingHeightGen, CacheSize);
}
}
@@ -352,13 +334,8 @@ void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
}
else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0)
{
- if (m_DistortedHeightmap == NULL)
- {
- m_DistortedHeightmap = new cDistortedHeightmap(m_ChunkGenerator.GetSeed(), *m_BiomeGen);
- m_DistortedHeightmap->Initialize(a_IniFile);
- }
- m_CompositionGen = m_DistortedHeightmap;
- m_NumDistortedHeightmapUses++;
+ m_CompositionGen = new cDistortedHeightmap(m_ChunkGenerator.GetSeed(), *m_BiomeGen);
+ ((cDistortedHeightmap *)m_CompositionGen)->Initialize(a_IniFile);
}
else if (NoCaseCompare(CompoGenName, "nether") == 0)
{
@@ -366,13 +343,8 @@ void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
}
else if (NoCaseCompare(CompoGenName, "Noise3D") == 0)
{
- if (m_Noise3DComposable == NULL)
- {
- m_Noise3DComposable = new cNoise3DComposable(m_ChunkGenerator.GetSeed());
- m_Noise3DComposable->Initialize(a_IniFile);
- }
- m_CompositionGen = m_Noise3DComposable;
- m_NumNoise3DComposableUses++;
+ m_CompositionGen = new cNoise3DComposable(m_ChunkGenerator.GetSeed());
+ ((cNoise3DComposable *)m_CompositionGen)->Initialize(a_IniFile);
}
else
{
@@ -399,6 +371,13 @@ void cComposableGenerator::InitCompositionGen(cIniFile & a_IniFile)
LOGINFO("CompositionGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
//*/
}
+
+ int CompoGenCacheSize = a_IniFile.GetValueSetI("Generator", "CompositionGenCacheSize", 64);
+ if (CompoGenCacheSize > 1)
+ {
+ m_UnderlyingCompositionGen = m_CompositionGen;
+ m_CompositionGen = new cCompoGenCache(m_UnderlyingCompositionGen, 32);
+ }
}
diff --git a/source/Generating/ComposableGenerator.h b/source/Generating/ComposableGenerator.h
index ee38bdb9d..c32e7181f 100644
--- a/source/Generating/ComposableGenerator.h
+++ b/source/Generating/ComposableGenerator.h
@@ -148,13 +148,12 @@ protected:
cStructureGenList m_StructureGens;
cFinishGenList m_FinishGens;
- // Specific generators that can be reused for different purposes - we don't want to create multiple objects for them
- cNoise3DComposable * m_Noise3DComposable;
- int m_NumNoise3DComposableUses; ///< How many times is it actually used?
- cDistortedHeightmap * m_DistortedHeightmap;
- int m_NumDistortedHeightmapUses; ///< How many times is it actually used?
+ // Generators underlying the caches:
+ cBiomeGen * m_UnderlyingBiomeGen;
+ cTerrainHeightGen * m_UnderlyingHeightGen;
+ cTerrainCompositionGen * m_UnderlyingCompositionGen;
+
-
/// Reads the biome gen settings from the ini and initializes m_BiomeGen accordingly
void InitBiomeGen(cIniFile & a_IniFile);
diff --git a/source/Generating/HeiGen.cpp b/source/Generating/HeiGen.cpp
index 24042e3ff..d012792bb 100644
--- a/source/Generating/HeiGen.cpp
+++ b/source/Generating/HeiGen.cpp
@@ -53,7 +53,6 @@ cHeiGenCache::~cHeiGenCache()
{
delete[] m_CacheData;
delete[] m_CacheOrder;
- delete m_HeiGenToCache;
}
diff --git a/source/Generating/HeiGen.h b/source/Generating/HeiGen.h
index 3bdfef993..4bc55a958 100644
--- a/source/Generating/HeiGen.h
+++ b/source/Generating/HeiGen.h
@@ -44,7 +44,7 @@ class cHeiGenCache :
public cTerrainHeightGen
{
public:
- cHeiGenCache(cTerrainHeightGen * a_HeiGenToCache, int a_CacheSize); // Takes ownership of a_HeiGenToCache
+ cHeiGenCache(cTerrainHeightGen * a_HeiGenToCache, int a_CacheSize); // Doesn't take ownership of a_HeiGenToCache
~cHeiGenCache();
// cTerrainHeightGen override: