summaryrefslogtreecommitdiffstats
path: root/src/Generating
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Generating/BioGen.cpp250
-rw-r--r--src/Generating/BioGen.h45
-rw-r--r--src/Generating/CMakeLists.txt2
-rw-r--r--src/Generating/Caves.cpp29
-rw-r--r--src/Generating/ChunkGenerator.cpp44
-rw-r--r--src/Generating/ChunkGenerator.h16
-rw-r--r--src/Generating/ComposableGenerator.cpp164
-rw-r--r--src/Generating/DistortedHeightmap.cpp9
-rw-r--r--src/Generating/DungeonRoomsFinisher.cpp279
-rw-r--r--src/Generating/DungeonRoomsFinisher.h52
-rw-r--r--src/Generating/FinishGen.cpp25
-rw-r--r--src/Generating/FinishGen.h11
-rw-r--r--src/Generating/HeiGen.cpp10
-rw-r--r--src/Generating/Noise3DGenerator.cpp9
-rw-r--r--src/Generating/RoughRavines.cpp26
-rw-r--r--src/Generating/StructGen.cpp68
-rw-r--r--src/Generating/StructGen.h38
-rw-r--r--src/Generating/Trees.cpp146
-rw-r--r--src/Generating/Trees.h2
-rw-r--r--src/Generating/VillageGen.cpp2
20 files changed, 962 insertions, 265 deletions
diff --git a/src/Generating/BioGen.cpp b/src/Generating/BioGen.cpp
index 8fad9f5c9..8924a7999 100644
--- a/src/Generating/BioGen.cpp
+++ b/src/Generating/BioGen.cpp
@@ -13,72 +13,6 @@
////////////////////////////////////////////////////////////////////////////////
-// cBiomeGen:
-
-cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault)
-{
- AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", "");
- if (BiomeGenName.empty())
- {
- LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\".");
- BiomeGenName = "MultiStepMap";
- }
-
- cBiomeGen * res = NULL;
- a_CacheOffByDefault = false;
- if (NoCaseCompare(BiomeGenName, "constant") == 0)
- {
- res = new cBioGenConstant;
- a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :)
- }
- else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0)
- {
- res = new cBioGenCheckerboard;
- a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data
- }
- else if (NoCaseCompare(BiomeGenName, "voronoi") == 0)
- {
- res = new cBioGenVoronoi(a_Seed);
- }
- else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0)
- {
- res = new cBioGenDistortedVoronoi(a_Seed);
- }
- else if (NoCaseCompare(BiomeGenName, "twolevel") == 0)
- {
- res = new cBioGenTwoLevel(a_Seed);
- }
- else
- {
- if (NoCaseCompare(BiomeGenName, "multistepmap") != 0)
- {
- LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str());
- }
- res = new cBioGenMultiStepMap(a_Seed);
-
- /*
- // Performance-testing:
- LOGINFO("Measuring performance of cBioGenMultiStepMap...");
- clock_t BeginTick = clock();
- for (int x = 0; x < 5000; x++)
- {
- cChunkDef::BiomeMap Biomes;
- res->GenBiomes(x * 5, x * 5, Biomes);
- }
- clock_t Duration = clock() - BeginTick;
- LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
- //*/
- }
- res->InitializeBiomeGen(a_IniFile);
-
- return res;
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
// cBioGenConstant:
void cBioGenConstant::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
@@ -151,7 +85,7 @@ void cBioGenCache::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a
LOGD("BioGenCache: %d hits, %d misses, saved %.2f %%", m_NumHits, m_NumMisses, 100.0 * m_NumHits / (m_NumHits + m_NumMisses));
LOGD("BioGenCache: Avg cache chain length: %.2f", (float)m_TotalChain / m_NumHits);
}
-
+
for (int i = 0; i < m_CacheSize; i++)
{
if (
@@ -208,6 +142,59 @@ void cBioGenCache::InitializeBiomeGen(cIniFile & a_IniFile)
+////////////////////////////////////////////////////////////////////////////////
+// cBioGenMulticache:
+
+cBioGenMulticache::cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_CacheSize, size_t a_CachesLength) :
+ m_CachesLength(a_CachesLength)
+{
+ m_Caches.reserve(a_CachesLength);
+ for (size_t i = 0; i < a_CachesLength; i++)
+ {
+ m_Caches.push_back(new cBioGenCache(a_BioGenToCache, a_CacheSize));
+ }
+}
+
+
+
+
+
+cBioGenMulticache::~cBioGenMulticache()
+{
+ for (cBiomeGens::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
+ {
+ delete *it;
+ }
+}
+
+
+
+
+
+void cBioGenMulticache::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap)
+{
+ const size_t coefficient = 3;
+ const size_t cacheIdx = ((size_t)a_ChunkX + coefficient * (size_t)a_ChunkZ) % m_CachesLength;
+
+ m_Caches[cacheIdx]->GenBiomes(a_ChunkX, a_ChunkZ, a_BiomeMap);
+}
+
+
+
+
+
+void cBioGenMulticache::InitializeBiomeGen(cIniFile & a_IniFile)
+{
+ for (cBiomeGens::iterator it = m_Caches.begin(); it != m_Caches.end(); it++)
+ {
+ cBiomeGen * tmp = *it;
+ tmp->InitializeBiomeGen(a_IniFile);
+ }
+}
+
+
+
+
////////////////////////////////////////////////////////////////////////////////
// cBiomeGenList:
@@ -349,8 +336,13 @@ void cBioGenVoronoi::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap &
void cBioGenVoronoi::InitializeBiomeGen(cIniFile & a_IniFile)
{
super::InitializeBiomeGen(a_IniFile);
- m_Voronoi.SetCellSize(a_IniFile.GetValueSetI("Generator", "VoronoiCellSize", 64));
- InitializeBiomes (a_IniFile.GetValueSet ("Generator", "VoronoiBiomes", ""));
+ int CellSize = a_IniFile.GetValueSetI("Generator", "VoronoiCellSize", 128);
+ int JitterSize = a_IniFile.GetValueSetI("Generator", "VoronoiJitterSize", CellSize);
+ int OddRowOffset = a_IniFile.GetValueSetI("Generator", "VoronoiOddRowOffset", 0);
+ m_Voronoi.SetCellSize(CellSize);
+ m_Voronoi.SetJitterSize(JitterSize);
+ m_Voronoi.SetOddRowOffset(OddRowOffset);
+ InitializeBiomes(a_IniFile.GetValueSet ("Generator", "VoronoiBiomes", ""));
}
@@ -745,8 +737,6 @@ void cBioGenMultiStepMap::FreezeWaterBiomes(cChunkDef::BiomeMap & a_BiomeMap, co
cBioGenTwoLevel::cBioGenTwoLevel(int a_Seed) :
m_VoronoiLarge(a_Seed + 1000),
m_VoronoiSmall(a_Seed + 2000),
- m_DistortX(a_Seed + 3000),
- m_DistortZ(a_Seed + 4000),
m_Noise1(a_Seed + 5001),
m_Noise2(a_Seed + 5002),
m_Noise3(a_Seed + 5003),
@@ -770,19 +760,17 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
int DistortZ[cChunkDef::Width + 1][cChunkDef::Width + 1];
for (int x = 0; x <= 4; x++) for (int z = 0; z <= 4; z++)
{
- int BlockX = BaseX + x * 4;
- int BlockZ = BaseZ + z * 4;
- float BlockXF = (float)(16 * BlockX) / 128;
- float BlockZF = (float)(16 * BlockZ) / 128;
- double NoiseX = m_Noise1.CubicNoise2D(BlockXF / 16, BlockZF / 16);
- NoiseX += 0.5 * m_Noise2.CubicNoise2D(BlockXF / 8, BlockZF / 8);
- NoiseX += 0.08 * m_Noise3.CubicNoise2D(BlockXF, BlockZF);
- double NoiseZ = m_Noise4.CubicNoise2D(BlockXF / 16, BlockZF / 16);
- NoiseZ += 0.5 * m_Noise5.CubicNoise2D(BlockXF / 8, BlockZF / 8);
- NoiseZ += 0.08 * m_Noise6.CubicNoise2D(BlockXF, BlockZF);
+ float BlockX = BaseX + x * 4;
+ float BlockZ = BaseZ + z * 4;
+ double NoiseX = m_AmpX1 * m_Noise1.CubicNoise2D(BlockX * m_FreqX1, BlockZ * m_FreqX1);
+ NoiseX += m_AmpX2 * m_Noise2.CubicNoise2D(BlockX * m_FreqX2, BlockZ * m_FreqX2);
+ NoiseX += m_AmpX3 * m_Noise3.CubicNoise2D(BlockX * m_FreqX3, BlockZ * m_FreqX3);
+ double NoiseZ = m_AmpZ1 * m_Noise4.CubicNoise2D(BlockX * m_FreqZ1, BlockZ * m_FreqZ1);
+ NoiseZ += m_AmpZ2 * m_Noise5.CubicNoise2D(BlockX * m_FreqZ2, BlockZ * m_FreqZ2);
+ NoiseZ += m_AmpZ3 * m_Noise6.CubicNoise2D(BlockX * m_FreqZ3, BlockZ * m_FreqZ3);
- DistortX[4 * x][4 * z] = BlockX + (int)(64 * NoiseX);
- DistortZ[4 * x][4 * z] = BlockZ + (int)(64 * NoiseZ);
+ DistortX[4 * x][4 * z] = (int)(BlockX + NoiseX);
+ DistortZ[4 * x][4 * z] = (int)(BlockZ + NoiseZ);
}
LinearUpscale2DArrayInPlace<cChunkDef::Width + 1, cChunkDef::Width + 1, 4, 4>(&DistortX[0][0]);
@@ -793,9 +781,10 @@ void cBioGenTwoLevel::GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap
{
for (int x = 0; x < cChunkDef::Width; x++)
{
- int MinDist1, MinDist2;
- int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z], MinDist1, MinDist2) / 7;
- int BiomeIdx = m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], MinDist1, MinDist2) / 11;
+ int SeedX, SeedZ, MinDist2;
+ int BiomeGroup = m_VoronoiLarge.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 7;
+ int BiomeIdx = m_VoronoiSmall.GetValueAt(DistortX[x][z], DistortZ[x][z], SeedX, SeedZ, MinDist2) / 11;
+ int MinDist1 = (DistortX[x][z] - SeedX) * (DistortX[x][z] - SeedX) + (DistortZ[x][z] - SeedZ) * (DistortZ[x][z] - SeedZ);
cChunkDef::SetBiome(a_BiomeMap, x, z, SelectBiome(BiomeGroup, BiomeIdx, (MinDist1 < MinDist2 / 4) ? 0 : 1));
}
}
@@ -920,15 +909,86 @@ EMCSBiome cBioGenTwoLevel::SelectBiome(int a_BiomeGroup, int a_BiomeIdx, int a_D
void cBioGenTwoLevel::InitializeBiomeGen(cIniFile & a_IniFile)
{
- // TODO: Read these from a file
- m_VoronoiLarge.SetCellSize(1024);
- m_VoronoiSmall.SetCellSize(128);
- m_DistortX.AddOctave(0.01f, 16);
- m_DistortX.AddOctave(0.005f, 8);
- m_DistortX.AddOctave(0.0025f, 4);
- m_DistortZ.AddOctave(0.01f, 16);
- m_DistortZ.AddOctave(0.005f, 8);
- m_DistortZ.AddOctave(0.0025f, 4);
+ m_VoronoiLarge.SetCellSize(a_IniFile.GetValueSetI("Generator", "TwoLevelLargeCellSize", 1024));
+ m_VoronoiSmall.SetCellSize(a_IniFile.GetValueSetI("Generator", "TwoLevelSmallCellSize", 128));
+ m_FreqX1 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave1Freq", 0.01);
+ m_AmpX1 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave1Amp", 80);
+ m_FreqX2 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave2Freq", 0.05);
+ m_AmpX2 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave2Amp", 20);
+ m_FreqX3 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave3Freq", 0.1),
+ m_AmpX3 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortXOctave3Amp", 8);
+ m_FreqZ1 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave1Freq", 0.01);
+ m_AmpZ1 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave1Amp", 80);
+ m_FreqZ2 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave2Freq", 0.05);
+ m_AmpZ2 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave2Amp", 20);
+ m_FreqZ3 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave3Freq", 0.1);
+ m_AmpZ3 = (float)a_IniFile.GetValueSetF("Generator", "TwoLevelDistortZOctave3Amp", 8);
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cBiomeGen:
+
+cBiomeGen * cBiomeGen::CreateBiomeGen(cIniFile & a_IniFile, int a_Seed, bool & a_CacheOffByDefault)
+{
+ AString BiomeGenName = a_IniFile.GetValueSet("Generator", "BiomeGen", "");
+ if (BiomeGenName.empty())
+ {
+ LOGWARN("[Generator] BiomeGen value not set in world.ini, using \"MultiStepMap\".");
+ BiomeGenName = "MultiStepMap";
+ }
+
+ cBiomeGen * res = NULL;
+ a_CacheOffByDefault = false;
+ if (NoCaseCompare(BiomeGenName, "constant") == 0)
+ {
+ res = new cBioGenConstant;
+ a_CacheOffByDefault = true; // we're generating faster than a cache would retrieve data :)
+ }
+ else if (NoCaseCompare(BiomeGenName, "checkerboard") == 0)
+ {
+ res = new cBioGenCheckerboard;
+ a_CacheOffByDefault = true; // we're (probably) generating faster than a cache would retrieve data
+ }
+ else if (NoCaseCompare(BiomeGenName, "voronoi") == 0)
+ {
+ res = new cBioGenVoronoi(a_Seed);
+ }
+ else if (NoCaseCompare(BiomeGenName, "distortedvoronoi") == 0)
+ {
+ res = new cBioGenDistortedVoronoi(a_Seed);
+ }
+ else if (NoCaseCompare(BiomeGenName, "twolevel") == 0)
+ {
+ res = new cBioGenTwoLevel(a_Seed);
+ }
+ else
+ {
+ if (NoCaseCompare(BiomeGenName, "multistepmap") != 0)
+ {
+ LOGWARNING("Unknown BiomeGen \"%s\", using \"MultiStepMap\" instead.", BiomeGenName.c_str());
+ }
+ res = new cBioGenMultiStepMap(a_Seed);
+
+ /*
+ // Performance-testing:
+ LOGINFO("Measuring performance of cBioGenMultiStepMap...");
+ clock_t BeginTick = clock();
+ for (int x = 0; x < 5000; x++)
+ {
+ cChunkDef::BiomeMap Biomes;
+ res->GenBiomes(x * 5, x * 5, Biomes);
+ }
+ clock_t Duration = clock() - BeginTick;
+ LOGINFO("cBioGenMultiStepMap for 5000 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
+ //*/
+ }
+ res->InitializeBiomeGen(a_IniFile);
+
+ return res;
}
diff --git a/src/Generating/BioGen.h b/src/Generating/BioGen.h
index 227ec97d7..22ddfae5c 100644
--- a/src/Generating/BioGen.h
+++ b/src/Generating/BioGen.h
@@ -80,6 +80,36 @@ protected:
+class cBioGenMulticache :
+ public cBiomeGen
+{
+
+ typedef cBiomeGen super;
+
+public:
+ /*
+ a_CacheSize defines the size of each singular cache
+ a_CachesLength defines how many caches are used for the multicache
+ */
+ cBioGenMulticache(cBiomeGen * a_BioGenToCache, size_t a_CacheSize, size_t a_CachesLength); // Doesn't take ownership of a_BioGenToCache
+ ~cBioGenMulticache();
+
+protected:
+ typedef std::vector<cBiomeGen *> cBiomeGens;
+
+
+ size_t m_CachesLength;
+ cBiomeGens m_Caches;
+
+
+ virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
+ virtual void InitializeBiomeGen(cIniFile & a_IniFile) override;
+};
+
+
+
+
+
/// Base class for generators that use a list of available biomes. This class takes care of the list.
class cBiomeGenList :
public cBiomeGen
@@ -255,12 +285,7 @@ protected:
/// The Voronoi map that decides biomes inside individual biome groups
cVoronoiMap m_VoronoiSmall;
- /// The noise used to distort the input X coord
- cPerlinNoise m_DistortX;
-
- /// The noise used to distort the inupt Z coord
- cPerlinNoise m_DistortZ;
-
+ // The noises used for the distortion:
cNoise m_Noise1;
cNoise m_Noise2;
cNoise m_Noise3;
@@ -268,6 +293,14 @@ protected:
cNoise m_Noise5;
cNoise m_Noise6;
+ // Frequencies and amplitudes for the distortion noises:
+ float m_FreqX1, m_AmpX1;
+ float m_FreqX2, m_AmpX2;
+ float m_FreqX3, m_AmpX3;
+ float m_FreqZ1, m_AmpZ1;
+ float m_FreqZ2, m_AmpZ2;
+ float m_FreqZ3, m_AmpZ3;
+
// cBiomeGen overrides:
virtual void GenBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef::BiomeMap & a_BiomeMap) override;
diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt
index 58df9d421..33d622b42 100644
--- a/src/Generating/CMakeLists.txt
+++ b/src/Generating/CMakeLists.txt
@@ -12,6 +12,7 @@ SET (SRCS
CompoGen.cpp
ComposableGenerator.cpp
DistortedHeightmap.cpp
+ DungeonRoomsFinisher.cpp
EndGen.cpp
FinishGen.cpp
GridStructGen.cpp
@@ -40,6 +41,7 @@ SET (HDRS
CompoGen.h
ComposableGenerator.h
DistortedHeightmap.h
+ DungeonRoomsFinisher.h
EndGen.h
FinishGen.h
GridStructGen.h
diff --git a/src/Generating/Caves.cpp b/src/Generating/Caves.cpp
index 3b71efb57..fc925a150 100644
--- a/src/Generating/Caves.cpp
+++ b/src/Generating/Caves.cpp
@@ -166,6 +166,9 @@ cCaveTunnel::cCaveTunnel(
if ((a_BlockStartY <= 0) && (a_BlockEndY <= 0))
{
// Don't bother detailing this cave, it's under the world anyway
+ m_MinBlockX = m_MaxBlockX = 0;
+ m_MinBlockY = m_MaxBlockY = -1;
+ m_MinBlockZ = m_MaxBlockZ = 0;
return;
}
@@ -497,29 +500,9 @@ void cCaveTunnel::ProcessChunk(
int SqDist = (DifX - x) * (DifX - x) + (DifY - y) * (DifY - y) + (DifZ - z) * (DifZ - z);
if (4 * SqDist <= SqRad)
{
- switch (cChunkDef::GetBlock(a_BlockTypes, x, y, z))
+ if (cBlockInfo::CanBeTerraformed(cChunkDef::GetBlock(a_BlockTypes, x, y, z)))
{
- // Only carve out these specific block types
- case E_BLOCK_DIRT:
- case E_BLOCK_GRASS:
- case E_BLOCK_STONE:
- case E_BLOCK_COBBLESTONE:
- case E_BLOCK_GRAVEL:
- case E_BLOCK_SAND:
- case E_BLOCK_SANDSTONE:
- case E_BLOCK_SOULSAND:
- case E_BLOCK_NETHERRACK:
- case E_BLOCK_COAL_ORE:
- case E_BLOCK_IRON_ORE:
- case E_BLOCK_GOLD_ORE:
- case E_BLOCK_DIAMOND_ORE:
- case E_BLOCK_REDSTONE_ORE:
- case E_BLOCK_REDSTONE_ORE_GLOWING:
- {
- cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
- break;
- }
- default: break;
+ cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
}
}
} // for y
@@ -772,7 +755,7 @@ void cStructGenDualRidgeCaves::GenFinish(cChunkDesc & a_ChunkDesc)
float n2 = m_Noise2.CubicNoise3D(xx, yy, zz);
float n3 = m_Noise1.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4;
float n4 = m_Noise2.CubicNoise3D(xx * 4, yy * 4, zz * 4) / 4;
- if ((abs(n1 + n3) * abs(n2 + n4)) > m_Threshold)
+ if ((std::abs(n1 + n3) * std::abs(n2 + n4)) > m_Threshold)
{
a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR);
}
diff --git a/src/Generating/ChunkGenerator.cpp b/src/Generating/ChunkGenerator.cpp
index 3d5af152c..d615456c1 100644
--- a/src/Generating/ChunkGenerator.cpp
+++ b/src/Generating/ChunkGenerator.cpp
@@ -27,6 +27,7 @@ const unsigned int QUEUE_SKIP_LIMIT = 500;
cChunkGenerator::cChunkGenerator(void) :
super("cChunkGenerator"),
+ m_Seed(0), // Will be overwritten by the actual generator
m_Generator(NULL),
m_PluginInterface(NULL),
m_ChunkSink(NULL)
@@ -51,10 +52,21 @@ bool cChunkGenerator::Start(cPluginInterface & a_PluginInterface, cChunkSink & a
m_PluginInterface = &a_PluginInterface;
m_ChunkSink = &a_ChunkSink;
- MTRand rnd;
- m_Seed = a_IniFile.GetValueSetI("Seed", "Seed", (int)rnd.randInt());
+ // Get the seed; create a new one and log it if not found in the INI file:
+ if (a_IniFile.HasValue("Seed", "Seed"))
+ {
+ m_Seed = a_IniFile.GetValueI("Seed", "Seed");
+ }
+ else
+ {
+ MTRand rnd;
+ m_Seed = rnd.randInt();
+ LOGINFO("Chosen a new random seed for world: %d", m_Seed);
+ a_IniFile.SetValueI("Seed", "Seed", m_Seed);
+ }
+
+ // Get the generator engine based on the INI file settings:
AString GeneratorName = a_IniFile.GetValueSet("Generator", "Generator", "Composable");
-
if (NoCaseCompare(GeneratorName, "Noise3D") == 0)
{
m_Generator = new cNoise3DGenerator(*this);
@@ -98,15 +110,17 @@ void cChunkGenerator::Stop(void)
-void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate)
{
+ ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
+
{
cCSLock Lock(m_CS);
// Check if it is already in the queue:
- for (cChunkCoordsList::iterator itr = m_Queue.begin(); itr != m_Queue.end(); ++itr)
+ for (cChunkCoordsWithBoolList::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))
+ if ((itr->m_ChunkX == a_ChunkX) && (itr->m_ChunkZ == a_ChunkZ))
{
// Already in the queue, bail out
return;
@@ -118,7 +132,7 @@ void cChunkGenerator::QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_Chunk
{
LOGWARN("WARNING: Adding chunk [%i, %i] to generation queue; Queue is too big! (" SIZE_T_FMT ")", a_ChunkX, a_ChunkZ, m_Queue.size());
}
- m_Queue.push_back(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ m_Queue.push_back(cChunkCoordsWithBool(a_ChunkX, a_ChunkZ, a_ForceGenerate));
}
m_Event.Set();
@@ -228,9 +242,9 @@ void cChunkGenerator::Execute(void)
continue;
}
- cChunkCoords coords = m_Queue.front(); // Get next coord from queue
- m_Queue.erase( m_Queue.begin()); // Remove coordinate from queue
+ cChunkCoordsWithBool coords = m_Queue.front(); // Get next coord from queue
bool SkipEnabled = (m_Queue.size() > QUEUE_SKIP_LIMIT);
+ m_Queue.erase(m_Queue.begin()); // Remove coordinate from queue
Lock.Unlock(); // Unlock ASAP
m_evtRemoved.Set();
@@ -244,8 +258,7 @@ void cChunkGenerator::Execute(void)
LastReportTick = clock();
}
- // 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_ChunkSink->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
+ if (!coords.m_ForceGenerate && m_ChunkSink->IsChunkValid(coords.m_ChunkX, coords.m_ChunkZ))
{
LOGD("Chunk [%d, %d] already generated, skipping generation", coords.m_ChunkX, coords.m_ChunkZ);
// Already generated, ignore request
@@ -258,8 +271,8 @@ void cChunkGenerator::Execute(void)
continue;
}
- LOGD("Generating chunk [%d, %d, %d]", coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
- DoGenerate(coords.m_ChunkX, coords.m_ChunkY, coords.m_ChunkZ);
+ LOGD("Generating chunk [%d, %d]", coords.m_ChunkX, coords.m_ChunkZ);
+ DoGenerate(coords.m_ChunkX, coords.m_ChunkZ);
NumChunksGenerated++;
} // while (!bStop)
@@ -268,11 +281,12 @@ void cChunkGenerator::Execute(void)
-void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ)
{
ASSERT(m_PluginInterface != NULL);
ASSERT(m_ChunkSink != NULL);
-
+ ASSERT(m_ChunkSink->IsChunkQueued(a_ChunkX, a_ChunkZ));
+
cChunkDesc ChunkDesc(a_ChunkX, a_ChunkZ);
m_PluginInterface->CallHookChunkGenerating(ChunkDesc);
m_Generator->DoGenerate(a_ChunkX, a_ChunkZ, ChunkDesc);
diff --git a/src/Generating/ChunkGenerator.h b/src/Generating/ChunkGenerator.h
index 88d71f3f9..190d9e616 100644
--- a/src/Generating/ChunkGenerator.h
+++ b/src/Generating/ChunkGenerator.h
@@ -106,6 +106,10 @@ public:
If this callback returns false, the chunk is not generated.
*/
virtual bool HasChunkAnyClients(int a_ChunkX, int a_ChunkZ) = 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;
} ;
@@ -116,7 +120,7 @@ public:
void Stop(void);
/// Queues the chunk for generation; removes duplicate requests
- void QueueGenerateChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void QueueGenerateChunk(int a_ChunkX, int a_ChunkZ, bool a_ForceGenerate);
/// 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);
@@ -137,10 +141,10 @@ private:
int m_Seed;
- cCriticalSection m_CS;
- cChunkCoordsList m_Queue;
- cEvent m_Event; ///< Set when an item is added to the queue or the thread should terminate
- cEvent m_evtRemoved; ///< Set when an item is removed from the queue
+ cCriticalSection m_CS;
+ cChunkCoordsWithBoolList m_Queue;
+ cEvent m_Event; ///< Set when an item is added to the queue or the thread should terminate
+ cEvent m_evtRemoved; ///< Set when an item is removed from the queue
cGenerator * m_Generator; ///< The actual generator engine used to generate chunks
@@ -154,7 +158,7 @@ private:
// cIsThread override:
virtual void Execute(void) override;
- void DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void DoGenerate(int a_ChunkX, int a_ChunkZ);
};
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index a7659149a..87461b944 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -19,6 +19,7 @@
#include "Caves.h"
#include "DistortedHeightmap.h"
+#include "DungeonRoomsFinisher.h"
#include "EndGen.h"
#include "MineShafts.h"
#include "NetherFortGen.h"
@@ -229,17 +230,29 @@ void cComposableGenerator::InitBiomeGen(cIniFile & a_IniFile)
// Add a cache, if requested:
int CacheSize = a_IniFile.GetValueSetI("Generator", "BiomeGenCacheSize", CacheOffByDefault ? 0 : 64);
- if (CacheSize > 0)
+
+ if (CacheSize <= 0)
+ {
+ return;
+ }
+
+ int MultiCacheLength = a_IniFile.GetValueSetI("Generator", "BiomeGenMultiCacheLength", 4);
+ 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;
+ }
+ LOGD("Using a cache for biomegen of size %d.", CacheSize);
+ m_UnderlyingBiomeGen = m_BiomeGen;
+ if (MultiCacheLength > 0)
+ {
+ LOGD("Enabling multicache for biomegen of length %d.", MultiCacheLength);
+ m_BiomeGen = new cBioGenMulticache(m_UnderlyingBiomeGen, CacheSize, MultiCacheLength);
+ }
+ else
{
- 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;
- }
- LOGD("Using a cache for biomegen of size %d.", CacheSize);
- m_UnderlyingBiomeGen = m_BiomeGen;
m_BiomeGen = new cBioGenCache(m_UnderlyingBiomeGen, CacheSize);
}
}
@@ -343,6 +356,14 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
float Threshold = (float)a_IniFile.GetValueSetF("Generator", "DualRidgeCavesThreshold", 0.3);
m_FinishGens.push_back(new cStructGenDualRidgeCaves(Seed, Threshold));
}
+ else if (NoCaseCompare(*itr, "DungeonRooms") == 0)
+ {
+ int GridSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsGridSize", 48);
+ int MaxSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMaxSize", 7);
+ int MinSize = a_IniFile.GetValueSetI("Generator", "DungeonRoomsMinSize", 5);
+ AString HeightDistrib = a_IniFile.GetValueSet ("Generator", "DungeonRoomsHeightDistrib", "0, 0; 10, 10; 11, 500; 40, 500; 60, 40; 90, 1");
+ m_FinishGens.push_back(new cDungeonRoomsFinisher(*m_HeightGen, Seed, GridSize, MaxSize, MinSize, HeightDistrib));
+ }
else if (NoCaseCompare(*itr, "Ice") == 0)
{
m_FinishGens.push_back(new cFinishGenIce);
@@ -387,6 +408,55 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
m_FinishGens.push_back(new cFinishGenSingleTopBlock(Seed, E_BLOCK_LILY_PAD, AllowedBiomes, 4, AllowedBlocks));
}
+ else if (NoCaseCompare(*itr, "NaturalPatches") == 0)
+ {
+ cStructGenOreNests::OreList Ores;
+
+ // Dirt vein
+ cStructGenOreNests::OreInfo DirtVein;
+ DirtVein.BlockType = E_BLOCK_DIRT;
+ DirtVein.MaxHeight = 127;
+ DirtVein.NumNests = 20;
+ DirtVein.NestSize = 32;
+ Ores.push_back(DirtVein);
+
+ // Gravel vein
+ cStructGenOreNests::OreInfo GravelVein;
+ GravelVein.BlockType = E_BLOCK_GRAVEL;
+ GravelVein.MaxHeight = 127;
+ GravelVein.NumNests = 20;
+ GravelVein.NestSize = 32;
+ Ores.push_back(GravelVein);
+
+ // Granite vein
+ cStructGenOreNests::OreInfo GraniteVein;
+ GraniteVein.BlockType = E_BLOCK_STONE;
+ GraniteVein.BlockMeta = 1;
+ GraniteVein.MaxHeight = 127;
+ GraniteVein.NumNests = 20;
+ GraniteVein.NestSize = 32;
+ Ores.push_back(GraniteVein);
+
+ // Diorite vein
+ cStructGenOreNests::OreInfo DioriteVein;
+ DioriteVein.BlockType = E_BLOCK_STONE;
+ DioriteVein.BlockMeta = 3;
+ DioriteVein.MaxHeight = 127;
+ DioriteVein.NumNests = 20;
+ DioriteVein.NestSize = 32;
+ Ores.push_back(DioriteVein);
+
+ // Andesite vein
+ cStructGenOreNests::OreInfo AndesiteVein;
+ AndesiteVein.BlockType = E_BLOCK_STONE;
+ AndesiteVein.BlockMeta = 5;
+ AndesiteVein.MaxHeight = 127;
+ AndesiteVein.NumNests = 20;
+ AndesiteVein.NestSize = 32;
+ Ores.push_back(AndesiteVein);
+
+ m_FinishGens.push_back(new cStructGenOreNests(Seed, Ores, E_BLOCK_STONE));
+ }
else if (NoCaseCompare(*itr, "NetherClumpFoliage") == 0)
{
m_FinishGens.push_back(new cFinishGenNetherClumpFoliage(Seed));
@@ -398,9 +468,74 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
int MaxDepth = a_IniFile.GetValueSetI("Generator", "NetherFortsMaxDepth", 12);
m_FinishGens.push_back(new cNetherFortGen(Seed, GridSize, MaxOffset, MaxDepth));
}
+ else if (NoCaseCompare(*itr, "NetherOreNests") == 0)
+ {
+ cStructGenOreNests::OreList Ores;
+
+ // Quartz vein
+ cStructGenOreNests::OreInfo QuartzVein;
+ QuartzVein.BlockType = E_BLOCK_NETHER_QUARTZ_ORE;
+ QuartzVein.MaxHeight = 255;
+ QuartzVein.NumNests = 80;
+ QuartzVein.NestSize = 8;
+ Ores.push_back(QuartzVein);
+
+ m_FinishGens.push_back(new cStructGenOreNests(Seed, Ores, E_BLOCK_NETHERRACK));
+
+ }
else if (NoCaseCompare(*itr, "OreNests") == 0)
{
- m_FinishGens.push_back(new cStructGenOreNests(Seed));
+ cStructGenOreNests::OreList Ores;
+
+ // Coal vein
+ cStructGenOreNests::OreInfo CoalVein;
+ CoalVein.BlockType = E_BLOCK_COAL_ORE;
+ CoalVein.MaxHeight = 127;
+ CoalVein.NumNests = 50;
+ CoalVein.NestSize = 10;
+ Ores.push_back(CoalVein);
+
+ // Iron vein
+ cStructGenOreNests::OreInfo IronVein;
+ IronVein.BlockType = E_BLOCK_IRON_ORE;
+ IronVein.MaxHeight = 64;
+ IronVein.NumNests = 14;
+ IronVein.NestSize = 6;
+ Ores.push_back(IronVein);
+
+ // Gold vein
+ cStructGenOreNests::OreInfo GoldVein;
+ GoldVein.BlockType = E_BLOCK_GOLD_ORE;
+ GoldVein.MaxHeight = 32;
+ GoldVein.NumNests = 2;
+ GoldVein.NestSize = 6;
+ Ores.push_back(GoldVein);
+
+ // Redstone vein
+ cStructGenOreNests::OreInfo RedstoneVein;
+ RedstoneVein.BlockType = E_BLOCK_REDSTONE_ORE;
+ RedstoneVein.MaxHeight = 16;
+ RedstoneVein.NumNests = 4;
+ RedstoneVein.NestSize = 6;
+ Ores.push_back(RedstoneVein);
+
+ // Lapis vein
+ cStructGenOreNests::OreInfo LapisVein;
+ LapisVein.BlockType = E_BLOCK_LAPIS_ORE;
+ LapisVein.MaxHeight = 30;
+ LapisVein.NumNests = 2;
+ LapisVein.NestSize = 5;
+ Ores.push_back(LapisVein);
+
+ // Diamond vein
+ cStructGenOreNests::OreInfo DiamondVein;
+ DiamondVein.BlockType = E_BLOCK_DIAMOND_ORE;
+ DiamondVein.MaxHeight = 15;
+ DiamondVein.NumNests = 1;
+ DiamondVein.NestSize = 4;
+ Ores.push_back(DiamondVein);
+
+ m_FinishGens.push_back(new cStructGenOreNests(Seed, Ores, E_BLOCK_STONE));
}
else if (NoCaseCompare(*itr, "POCPieces") == 0)
{
@@ -408,7 +543,12 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
}
else if (NoCaseCompare(*itr, "PreSimulator") == 0)
{
- m_FinishGens.push_back(new cFinishGenPreSimulator);
+ // Load the settings
+ bool PreSimulateFallingBlocks = a_IniFile.GetValueSetB("Generator", "PreSimulatorFallingBlocks", true);
+ bool PreSimulateWater = a_IniFile.GetValueSetB("Generator", "PreSimulatorWater", true);
+ bool PreSimulateLava = a_IniFile.GetValueSetB("Generator", "PreSimulatorLava", true);
+
+ m_FinishGens.push_back(new cFinishGenPreSimulator(PreSimulateFallingBlocks, PreSimulateWater, PreSimulateLava));
}
else if (NoCaseCompare(*itr, "RainbowRoads") == 0)
{
diff --git a/src/Generating/DistortedHeightmap.cpp b/src/Generating/DistortedHeightmap.cpp
index c18c402da..bf8995dcb 100644
--- a/src/Generating/DistortedHeightmap.cpp
+++ b/src/Generating/DistortedHeightmap.cpp
@@ -540,10 +540,11 @@ void cDistortedHeightmap::InitializeCompoGen(cIniFile & a_IniFile)
int cDistortedHeightmap::GetHeightmapAt(NOISE_DATATYPE a_X, NOISE_DATATYPE a_Z)
{
- int ChunkX = (int)floor(a_X / (NOISE_DATATYPE)16);
- int ChunkZ = (int)floor(a_Z / (NOISE_DATATYPE)16);
- int RelX = (int)(a_X - (NOISE_DATATYPE)ChunkX * cChunkDef::Width);
- int RelZ = (int)(a_Z - (NOISE_DATATYPE)ChunkZ * cChunkDef::Width);
+ int RelX = (int)std::floor(a_X);
+ int RelY = 0;
+ int RelZ = (int)std::floor(a_Z);
+ int ChunkX, ChunkZ;
+ cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
// If we're withing the same chunk, return the pre-cached heightmap:
if ((ChunkX == m_CurChunkX) && (ChunkZ == m_CurChunkZ))
diff --git a/src/Generating/DungeonRoomsFinisher.cpp b/src/Generating/DungeonRoomsFinisher.cpp
new file mode 100644
index 000000000..f213455d6
--- /dev/null
+++ b/src/Generating/DungeonRoomsFinisher.cpp
@@ -0,0 +1,279 @@
+
+// DungeonRoomsFinisher.cpp
+
+// Declares the cDungeonRoomsFinisher class representing the finisher that generates dungeon rooms
+
+#include "Globals.h"
+#include "DungeonRoomsFinisher.h"
+#include "../FastRandom.h"
+
+
+
+
+
+/** Height, in blocks, of the internal dungeon room open space. This many air blocks Y-wise. */
+static const int ROOM_HEIGHT = 4;
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cDungeonRoom:
+
+class cDungeonRoom :
+ public cGridStructGen::cStructure
+{
+ typedef cGridStructGen::cStructure super;
+
+public:
+
+ cDungeonRoom(
+ int a_GridX, int a_GridZ,
+ int a_OriginX, int a_OriginZ,
+ int a_HalfSizeX, int a_HalfSizeZ,
+ int a_FloorHeight,
+ cNoise & a_Noise
+ ) :
+ super(a_GridX, a_GridZ, a_OriginX, a_OriginZ),
+ m_StartX(a_OriginX - a_HalfSizeX),
+ m_EndX(a_OriginX + a_HalfSizeX),
+ m_StartZ(a_OriginZ - a_HalfSizeZ),
+ m_EndZ(a_OriginZ + a_HalfSizeZ),
+ m_FloorHeight(a_FloorHeight)
+ {
+ /*
+ Pick coords next to the wall for the chests.
+ This is done by indexing the possible coords, picking any one for the first chest
+ and then picking another position for the second chest that is not adjacent to the first pos
+ */
+ int rnd = a_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7;
+ int SizeX = m_EndX - m_StartX - 1;
+ int SizeZ = m_EndZ - m_StartZ - 1;
+ int NumPositions = 2 * SizeX + 2 * SizeZ;
+ int FirstChestPos = rnd % NumPositions; // The corner positions are a bit more likely, but we don't mind
+ rnd = rnd / 512;
+ int SecondChestPos = (FirstChestPos + 2 + (rnd % (NumPositions - 3))) % NumPositions;
+ m_Chest1 = DecodeChestCoords(FirstChestPos, SizeX, SizeZ);
+ m_Chest2 = DecodeChestCoords(SecondChestPos, SizeX, SizeZ);
+ }
+
+protected:
+
+ // The X range of the room, start inclusive, end exclusive:
+ int m_StartX, m_EndX;
+
+ // The Z range of the room, start inclusive, end exclusive:
+ int m_StartZ, m_EndZ;
+
+ /** The Y coord of the floor of the room */
+ int m_FloorHeight;
+
+ /** The (absolute) coords of the first chest. The Y coord represents the chest's Meta value (facing). */
+ Vector3i m_Chest1;
+
+ /** The (absolute) coords of the second chest. The Y coord represents the chest's Meta value (facing). */
+ Vector3i m_Chest2;
+
+
+
+ /** Decodes the position index along the room walls into a proper 2D position for a chest. */
+ Vector3i DecodeChestCoords(int a_PosIdx, int a_SizeX, int a_SizeZ)
+ {
+ if (a_PosIdx < a_SizeX)
+ {
+ // Return a coord on the ZM side of the room:
+ return Vector3i(m_StartX + a_PosIdx + 1, E_META_CHEST_FACING_ZP, m_StartZ + 1);
+ }
+ a_PosIdx -= a_SizeX;
+ if (a_PosIdx < a_SizeZ)
+ {
+ // Return a coord on the XP side of the room:
+ return Vector3i(m_EndX - 1, E_META_CHEST_FACING_XM, m_StartZ + a_PosIdx + 1);
+ }
+ a_PosIdx -= a_SizeZ;
+ if (a_PosIdx < a_SizeX)
+ {
+ // Return a coord on the ZP side of the room:
+ return Vector3i(m_StartX + a_PosIdx + 1, E_META_CHEST_FACING_ZM, m_StartZ + 1);
+ }
+ a_PosIdx -= a_SizeX;
+ // Return a coord on the XM side of the room:
+ return Vector3i(m_StartX + 1, E_META_CHEST_FACING_XP, m_StartZ + a_PosIdx + 1);
+ }
+
+
+
+ /** Fills the specified area of blocks in the chunk with the specified blocktype if they are one of the overwritten block types.
+ The coords are absolute, start coords are inclusive, end coords are exclusive. */
+ void ReplaceCuboid(cChunkDesc & a_ChunkDesc, int a_StartX, int a_StartY, int a_StartZ, int a_EndX, int a_EndY, int a_EndZ, BLOCKTYPE a_DstBlockType)
+ {
+ int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width - 1);
+ int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width - 1);
+ int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width);
+ int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width);
+ for (int y = a_StartY; y < a_EndY; y++)
+ {
+ for (int z = RelStartZ; z < RelEndZ; z++)
+ {
+ for (int x = RelStartX; x < RelEndX; x++)
+ {
+ if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z)))
+ {
+ a_ChunkDesc.SetBlockType(x, y, z, a_DstBlockType);
+ }
+ } // for x
+ } // for z
+ } // for z
+ }
+
+
+
+ /** Fills the specified area of blocks in the chunk with a random pattern of the specified blocktypes, if they are one of the overwritten block types.
+ The coords are absolute, start coords are inclusive, end coords are exclusive. The first blocktype uses 75% chance, the second 25% chance. */
+ void ReplaceCuboidRandom(cChunkDesc & a_ChunkDesc, int a_StartX, int a_StartY, int a_StartZ, int a_EndX, int a_EndY, int a_EndZ, BLOCKTYPE a_DstBlockType1, BLOCKTYPE a_DstBlockType2)
+ {
+ int BlockX = a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int BlockZ = a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ int RelStartX = Clamp(a_StartX - BlockX, 0, cChunkDef::Width - 1);
+ int RelStartZ = Clamp(a_StartZ - BlockZ, 0, cChunkDef::Width - 1);
+ int RelEndX = Clamp(a_EndX - BlockX, 0, cChunkDef::Width);
+ int RelEndZ = Clamp(a_EndZ - BlockZ, 0, cChunkDef::Width);
+ cFastRandom rnd;
+ for (int y = a_StartY; y < a_EndY; y++)
+ {
+ for (int z = RelStartZ; z < RelEndZ; z++)
+ {
+ for (int x = RelStartX; x < RelEndX; x++)
+ {
+ if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z)))
+ {
+ BLOCKTYPE BlockType = (rnd.NextInt(101) < 75) ? a_DstBlockType1 : a_DstBlockType2;
+ a_ChunkDesc.SetBlockType(x, y, z, BlockType);
+ }
+ } // for x
+ } // for z
+ } // for z
+ }
+
+
+
+ /** Tries to place a chest at the specified (absolute) coords.
+ Does nothing if the coords are outside the chunk. */
+ void TryPlaceChest(cChunkDesc & a_ChunkDesc, const Vector3i & a_Chest)
+ {
+ int RelX = a_Chest.x - a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int RelZ = a_Chest.z - a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ if (
+ (RelX < 0) || (RelX >= cChunkDef::Width) || // The X coord is not in this chunk
+ (RelZ < 0) || (RelZ >= cChunkDef::Width) // The Z coord is not in this chunk
+ )
+ {
+ return;
+ }
+ a_ChunkDesc.SetBlockTypeMeta(RelX, m_FloorHeight + 1, RelZ, E_BLOCK_CHEST, (NIBBLETYPE)a_Chest.y);
+
+ // TODO: Fill the chest with random loot
+ }
+
+
+
+ // cGridStructGen::cStructure override:
+ virtual void DrawIntoChunk(cChunkDesc & a_ChunkDesc) override
+ {
+ if (
+ (m_EndX < a_ChunkDesc.GetChunkX() * cChunkDef::Width) ||
+ (m_StartX >= a_ChunkDesc.GetChunkX() * cChunkDef::Width + cChunkDef::Width) ||
+ (m_EndZ < a_ChunkDesc.GetChunkZ() * cChunkDef::Width) ||
+ (m_StartZ >= a_ChunkDesc.GetChunkZ() * cChunkDef::Width + cChunkDef::Width)
+ )
+ {
+ // The chunk is not intersecting the room at all, bail out
+ return;
+ }
+ int b = m_FloorHeight + 1; // Bottom
+ int t = m_FloorHeight + 1 + ROOM_HEIGHT; // Top
+ ReplaceCuboidRandom(a_ChunkDesc, m_StartX, m_FloorHeight, m_StartZ, m_EndX + 1, b, m_EndZ + 1, E_BLOCK_MOSSY_COBBLESTONE, E_BLOCK_COBBLESTONE); // Floor
+ ReplaceCuboid(a_ChunkDesc, m_StartX + 1, b, m_StartZ + 1, m_EndX, t, m_EndZ, E_BLOCK_AIR); // Insides
+
+ // Walls:
+ ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_StartX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XM wall
+ ReplaceCuboid(a_ChunkDesc, m_EndX, b, m_StartZ, m_EndX + 1, t, m_EndZ, E_BLOCK_COBBLESTONE); // XP wall
+ ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_StartZ, m_EndX + 1, t, m_StartZ + 1, E_BLOCK_COBBLESTONE); // ZM wall
+ ReplaceCuboid(a_ChunkDesc, m_StartX, b, m_EndZ, m_EndX + 1, t, m_EndZ + 1, E_BLOCK_COBBLESTONE); // ZP wall
+
+ // Place chests:
+ TryPlaceChest(a_ChunkDesc, m_Chest1);
+ TryPlaceChest(a_ChunkDesc, m_Chest2);
+
+ // Place the spawner:
+ int CenterX = (m_StartX + m_EndX) / 2 - a_ChunkDesc.GetChunkX() * cChunkDef::Width;
+ int CenterZ = (m_StartZ + m_EndZ) / 2 - a_ChunkDesc.GetChunkZ() * cChunkDef::Width;
+ if (
+ (CenterX >= 0) && (CenterX < cChunkDef::Width) &&
+ (CenterZ >= 0) && (CenterZ < cChunkDef::Width)
+ )
+ {
+ a_ChunkDesc.SetBlockTypeMeta(CenterX, b, CenterZ, E_BLOCK_MOB_SPAWNER, 0);
+ // TODO: Set the spawned mob
+ }
+ }
+} ;
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cDungeonRoomsFinisher:
+
+cDungeonRoomsFinisher::cDungeonRoomsFinisher(cTerrainHeightGen & a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib) :
+ super(a_Seed + 100, a_GridSize, a_GridSize, a_GridSize, a_GridSize, a_MaxSize, a_MaxSize, 1024),
+ m_HeightGen(a_HeightGen),
+ m_MaxHalfSize((a_MaxSize + 1) / 2),
+ m_MinHalfSize((a_MinSize + 1) / 2),
+ m_HeightProbability(cChunkDef::Height)
+{
+ // Initialize the height probability distribution:
+ m_HeightProbability.SetDefString(a_HeightDistrib);
+
+ // Normalize the min and max size:
+ if (m_MinHalfSize > m_MaxHalfSize)
+ {
+ std::swap(m_MinHalfSize, m_MaxHalfSize);
+ }
+}
+
+
+
+
+
+
+cDungeonRoomsFinisher::cStructurePtr cDungeonRoomsFinisher::CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ)
+{
+ // Select a random room size in each direction:
+ int rnd = m_Noise.IntNoise2DInt(a_OriginX, a_OriginZ) / 7;
+ int HalfSizeX = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1));
+ rnd = rnd / 32;
+ int HalfSizeZ = m_MinHalfSize + (rnd % (m_MaxHalfSize - m_MinHalfSize + 1));
+ rnd = rnd / 32;
+
+ // Select a random floor height for the room, based on the height generator:
+ int ChunkX, ChunkZ;
+ int RelX = a_OriginX, RelY = 0, RelZ = a_OriginZ;
+ cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
+ cChunkDef::HeightMap HeightMap;
+ m_HeightGen.GenHeightMap(ChunkX, ChunkZ, HeightMap);
+ int Height = cChunkDef::GetHeight(HeightMap, RelX, RelZ); // Max room height at {a_OriginX, a_OriginZ}
+ Height = Clamp(m_HeightProbability.MapValue(rnd % m_HeightProbability.GetSum()), 10, Height - 5);
+
+ // Create the dungeon room descriptor:
+ return cStructurePtr(new cDungeonRoom(a_GridX, a_GridZ, a_OriginX, a_OriginZ, HalfSizeX, HalfSizeZ, Height, m_Noise));
+}
+
+
+
+
diff --git a/src/Generating/DungeonRoomsFinisher.h b/src/Generating/DungeonRoomsFinisher.h
new file mode 100644
index 000000000..2b52c9de6
--- /dev/null
+++ b/src/Generating/DungeonRoomsFinisher.h
@@ -0,0 +1,52 @@
+
+// DungeonRoomsFinisher.h
+
+// Declares the cDungeonRoomsFinisher class representing the finisher that generates dungeon rooms
+
+
+
+
+
+#pragma once
+
+#include "GridStructGen.h"
+#include "../ProbabDistrib.h"
+
+
+
+
+
+class cDungeonRoomsFinisher :
+ public cGridStructGen
+{
+ typedef cGridStructGen super;
+
+public:
+ /** Creates a new dungeon room finisher.
+ a_HeightGen is the underlying height generator, so that the rooms can always be placed under the terrain.
+ a_MaxSize and a_MinSize are the maximum and minimum sizes of the room's internal (air) area, in blocks across.
+ a_HeightDistrib is the string defining the height distribution for the rooms (cProbabDistrib format). */
+ cDungeonRoomsFinisher(cTerrainHeightGen & a_HeightGen, int a_Seed, int a_GridSize, int a_MaxSize, int a_MinSize, const AString & a_HeightDistrib);
+
+protected:
+
+ /** The height gen that is used for limiting the rooms' Y coords */
+ cTerrainHeightGen & m_HeightGen;
+
+ /** Maximum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 3 (vanilla). */
+ int m_MaxHalfSize;
+
+ /** Minimum half-size (from center to wall) of the dungeon room's inner (air) area. Default is 2 (vanilla). */
+ int m_MinHalfSize;
+
+ /** The height probability distribution to make the spawners more common in layers 10 - 40, less common outside this range. */
+ cProbabDistrib m_HeightProbability;
+
+
+ // cGridStructGen overrides:
+ virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override;
+} ;
+
+
+
+
diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp
index f53addb68..96e3dc26b 100644
--- a/src/Generating/FinishGen.cpp
+++ b/src/Generating/FinishGen.cpp
@@ -15,6 +15,7 @@
#include "../Simulator/FluidSimulator.h" // for cFluidSimulator::CanWashAway()
#include "../Simulator/FireSimulator.h"
#include "../World.h"
+#include "inifile/iniFile.h"
@@ -484,8 +485,6 @@ int cFinishGenSingleTopBlock::GetNumToGen(const cChunkDef::BiomeMap & a_BiomeMap
void cFinishGenSingleTopBlock::GenFinish(cChunkDesc & a_ChunkDesc)
{
- // Add Lilypads on top of water surface in Swampland
-
int NumToGen = GetNumToGen(a_ChunkDesc.GetBiomeMap());
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
@@ -555,7 +554,10 @@ void cFinishGenBottomLava::GenFinish(cChunkDesc & a_ChunkDesc)
////////////////////////////////////////////////////////////////////////////////
// cFinishGenPreSimulator:
-cFinishGenPreSimulator::cFinishGenPreSimulator(void)
+cFinishGenPreSimulator::cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava) :
+ m_PreSimulateFallingBlocks(a_PreSimulateFallingBlocks),
+ m_PreSimulateWater(a_PreSimulateWater),
+ m_PreSimulateLava(a_PreSimulateLava)
{
// Nothing needed yet
}
@@ -566,9 +568,20 @@ cFinishGenPreSimulator::cFinishGenPreSimulator(void)
void cFinishGenPreSimulator::GenFinish(cChunkDesc & a_ChunkDesc)
{
- CollapseSandGravel(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
- StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
- StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
+ if (m_PreSimulateFallingBlocks)
+ {
+ CollapseSandGravel(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap());
+ }
+
+ if (m_PreSimulateWater)
+ {
+ StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_WATER, E_BLOCK_STATIONARY_WATER);
+ }
+
+ if (m_PreSimulateLava)
+ {
+ StationarizeFluid(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetHeightMap(), E_BLOCK_LAVA, E_BLOCK_STATIONARY_LAVA);
+ }
// TODO: other operations
}
diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h
index ed32768b3..4a08d70c8 100644
--- a/src/Generating/FinishGen.h
+++ b/src/Generating/FinishGen.h
@@ -163,7 +163,7 @@ public:
m_Amount(a_Amount)
{
// Initialize all the block types.
- for (int idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx)
+ for (size_t idx = 0; idx < ARRAYCOUNT(m_IsAllowedBelow); ++idx)
{
m_IsAllowedBelow[idx] = false;
}
@@ -175,7 +175,7 @@ public:
}
// Initialize all the biome types.
- for (int idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx)
+ for (size_t idx = 0; idx < ARRAYCOUNT(m_IsBiomeAllowed); ++idx)
{
m_IsBiomeAllowed[idx] = false;
}
@@ -240,9 +240,14 @@ class cFinishGenPreSimulator :
public cFinishGen
{
public:
- cFinishGenPreSimulator(void);
+ cFinishGenPreSimulator(bool a_PreSimulateFallingBlocks, bool a_PreSimulateWater, bool a_PreSimulateLava);
protected:
+
+ bool m_PreSimulateFallingBlocks;
+ bool m_PreSimulateWater;
+ bool m_PreSimulateLava;
+
// Drops hanging sand and gravel down to the ground, recalculates heightmap
void CollapseSandGravel(
cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
diff --git a/src/Generating/HeiGen.cpp b/src/Generating/HeiGen.cpp
index 870ceef7f..79d529a6a 100644
--- a/src/Generating/HeiGen.cpp
+++ b/src/Generating/HeiGen.cpp
@@ -239,7 +239,13 @@ bool cHeiGenCache::GetHeightAt(int a_ChunkX, int a_ChunkZ, int a_RelX, int a_Rel
cHeiGenClassic::cHeiGenClassic(int a_Seed) :
m_Seed(a_Seed),
- m_Noise(a_Seed)
+ m_Noise(a_Seed),
+ m_HeightFreq1(1.0f),
+ m_HeightAmp1(1.0f),
+ m_HeightFreq2(0.5f),
+ m_HeightAmp2(0.5f),
+ m_HeightFreq3(0.1f),
+ m_HeightAmp3(0.1f)
{
}
@@ -432,7 +438,7 @@ const cHeiGenBiomal::sGenParam cHeiGenBiomal::m_GenParam[256] =
/* biExtremeHillsM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 131
/* biFlowerForest */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 132
/* biTaigaM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 133
- /* biSwamplandM */ { 0.1f, 2.0f, 0.05f, 12.0f, 0.01f, 10.0f, 40}, // 134
+ /* biSwamplandM */ { 1.0f, 3.0f, 1.10f, 7.0f, 0.01f, 0.01f, 60}, // 134
// Biomes 135 .. 139 unused, 5 empty placeholders here:
{}, {}, {}, {}, {}, // 135 .. 139
diff --git a/src/Generating/Noise3DGenerator.cpp b/src/Generating/Noise3DGenerator.cpp
index b879349ee..c3ca30384 100644
--- a/src/Generating/Noise3DGenerator.cpp
+++ b/src/Generating/Noise3DGenerator.cpp
@@ -236,7 +236,7 @@ void cNoise3DGenerator::GenerateNoiseArray(int a_ChunkX, int a_ChunkZ, NOISE_DAT
m_Cubic.Generate2D(Height, DIM_X, DIM_Z, StartX / 25, EndX / 25, StartZ / 25, EndZ / 25);
for (size_t i = 0; i < ARRAYCOUNT(Height); i++)
{
- Height[i] = abs(Height[i]) * m_HeightAmplification + 1;
+ Height[i] = std::abs(Height[i]) * m_HeightAmplification + 1;
}
// Modify the noise by height data:
@@ -395,7 +395,7 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ)
for (int x = 0; x < 17; x += UPSCALE_X)
{
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX;
- NOISE_DATATYPE val = abs(m_Noise1.CubicNoise2D(NoiseX / 5, NoiseZ / 5)) * m_HeightAmplification + 1;
+ NOISE_DATATYPE val = std::abs(m_Noise1.CubicNoise2D(NoiseX / 5, NoiseZ / 5)) * m_HeightAmplification + 1;
Height[x + 17 * z] = val * val * val;
}
}
@@ -412,11 +412,12 @@ void cNoise3DComposable::GenerateNoiseArrayIfNeeded(int a_ChunkX, int a_ChunkZ)
for (int x = 0; x < 17; x += UPSCALE_X)
{
NOISE_DATATYPE NoiseX = ((NOISE_DATATYPE)(a_ChunkX * cChunkDef::Width + x)) / m_FrequencyX;
- CurFloor[x + 17 * z] =
+ CurFloor[x + 17 * z] = (
m_Noise1.CubicNoise3D(NoiseX, NoiseY, NoiseZ) * (NOISE_DATATYPE)0.5 +
m_Noise2.CubicNoise3D(NoiseX / 2, NoiseY / 2, NoiseZ / 2) +
m_Noise3.CubicNoise3D(NoiseX / 4, NoiseY / 4, NoiseZ / 4) * 2 +
- AddHeight / Height[x + 17 * z];
+ AddHeight / Height[x + 17 * z]
+ );
}
}
// Linear-interpolate this XZ floor:
diff --git a/src/Generating/RoughRavines.cpp b/src/Generating/RoughRavines.cpp
index badc7768e..2ee3704b3 100644
--- a/src/Generating/RoughRavines.cpp
+++ b/src/Generating/RoughRavines.cpp
@@ -201,29 +201,11 @@ protected:
{
continue;
}
- switch (a_ChunkDesc.GetBlockType(x, y, z))
+
+ if (cBlockInfo::CanBeTerraformed(a_ChunkDesc.GetBlockType(x, y, z)))
{
- // Only carve out these specific block types
- case E_BLOCK_DIRT:
- case E_BLOCK_GRASS:
- case E_BLOCK_STONE:
- case E_BLOCK_COBBLESTONE:
- case E_BLOCK_GRAVEL:
- case E_BLOCK_SAND:
- case E_BLOCK_SANDSTONE:
- case E_BLOCK_NETHERRACK:
- case E_BLOCK_COAL_ORE:
- case E_BLOCK_IRON_ORE:
- case E_BLOCK_GOLD_ORE:
- case E_BLOCK_DIAMOND_ORE:
- case E_BLOCK_REDSTONE_ORE:
- case E_BLOCK_REDSTONE_ORE_GLOWING:
- {
- a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR);
- break;
- }
- default: break;
- } // switch (BlockType)
+ a_ChunkDesc.SetBlockType(x, y, z, E_BLOCK_AIR);
+ }
} // for y
} // for x, z - a_BlockTypes
} // for itr - m_Points[]
diff --git a/src/Generating/StructGen.cpp b/src/Generating/StructGen.cpp
index 054eec345..c23a72621 100644
--- a/src/Generating/StructGen.cpp
+++ b/src/Generating/StructGen.cpp
@@ -13,45 +13,6 @@
////////////////////////////////////////////////////////////////////////////////
-// cStructGenOreNests configuration:
-
-const int MAX_HEIGHT_COAL = 127;
-const int NUM_NESTS_COAL = 50;
-const int NEST_SIZE_COAL = 10;
-
-const int MAX_HEIGHT_IRON = 64;
-const int NUM_NESTS_IRON = 14;
-const int NEST_SIZE_IRON = 6;
-
-const int MAX_HEIGHT_REDSTONE = 16;
-const int NUM_NESTS_REDSTONE = 4;
-const int NEST_SIZE_REDSTONE = 6;
-
-const int MAX_HEIGHT_GOLD = 32;
-const int NUM_NESTS_GOLD = 2;
-const int NEST_SIZE_GOLD = 6;
-
-const int MAX_HEIGHT_DIAMOND = 15;
-const int NUM_NESTS_DIAMOND = 1;
-const int NEST_SIZE_DIAMOND = 4;
-
-const int MAX_HEIGHT_LAPIS = 30;
-const int NUM_NESTS_LAPIS = 2;
-const int NEST_SIZE_LAPIS = 5;
-
-const int MAX_HEIGHT_DIRT = 127;
-const int NUM_NESTS_DIRT = 20;
-const int NEST_SIZE_DIRT = 32;
-
-const int MAX_HEIGHT_GRAVEL = 70;
-const int NUM_NESTS_GRAVEL = 15;
-const int NEST_SIZE_GRAVEL = 32;
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////
// cStructGenTrees:
void cStructGenTrees::GenFinish(cChunkDesc & a_ChunkDesc)
@@ -311,21 +272,23 @@ void cStructGenOreNests::GenFinish(cChunkDesc & a_ChunkDesc)
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes();
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_COAL_ORE, MAX_HEIGHT_COAL, NUM_NESTS_COAL, NEST_SIZE_COAL, BlockTypes, 1);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_IRON_ORE, MAX_HEIGHT_IRON, NUM_NESTS_IRON, NEST_SIZE_IRON, BlockTypes, 2);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_REDSTONE_ORE, MAX_HEIGHT_REDSTONE, NUM_NESTS_REDSTONE, NEST_SIZE_REDSTONE, BlockTypes, 3);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_GOLD_ORE, MAX_HEIGHT_GOLD, NUM_NESTS_GOLD, NEST_SIZE_GOLD, BlockTypes, 4);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_DIAMOND_ORE, MAX_HEIGHT_DIAMOND, NUM_NESTS_DIAMOND, NEST_SIZE_DIAMOND, BlockTypes, 5);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_LAPIS_ORE, MAX_HEIGHT_LAPIS, NUM_NESTS_LAPIS, NEST_SIZE_LAPIS, BlockTypes, 6);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_DIRT, MAX_HEIGHT_DIRT, NUM_NESTS_DIRT, NEST_SIZE_DIRT, BlockTypes, 10);
- GenerateOre(ChunkX, ChunkZ, E_BLOCK_GRAVEL, MAX_HEIGHT_GRAVEL, NUM_NESTS_GRAVEL, NEST_SIZE_GRAVEL, BlockTypes, 11);
+ cChunkDesc::BlockNibbleBytes & BlockMetas = a_ChunkDesc.GetBlockMetasUncompressed();
+
+ int seq = 1;
+
+ // Generate the ores from the ore list.
+ for (OreList::const_iterator itr = m_OreList.begin(); itr != m_OreList.end(); ++itr)
+ {
+ GenerateOre(ChunkX, ChunkZ, itr->BlockType, itr->BlockMeta, itr->MaxHeight, itr->NumNests, itr->NestSize, BlockTypes, BlockMetas, seq);
+ seq++;
+ }
}
-void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, int a_Seq)
+void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, NIBBLETYPE a_BlockMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc::BlockNibbleBytes & a_BlockMetas, int a_Seq)
{
// This function generates several "nests" of ore, each nest consisting of number of ore blocks relatively adjacent to each other.
// It does so by making a random XYZ walk and adding ore along the way in cuboids of different (random) sizes
@@ -376,9 +339,10 @@ void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_Ore
}
int Index = cChunkDef::MakeIndexNoCheck(BlockX, BlockY, BlockZ);
- if (a_BlockTypes[Index] == E_BLOCK_STONE)
+ if (a_BlockTypes[Index] == m_ToReplace)
{
a_BlockTypes[Index] = a_OreType;
+ a_BlockMetas[Index] = a_BlockMeta;
}
Num++;
} // for z
@@ -585,10 +549,10 @@ void cStructGenDirectOverhangs::GenFinish(cChunkDesc & a_ChunkDesc)
// First update the high floor:
for (int z = 0; z <= 16 / INTERPOL_Z; z++) for (int x = 0; x <= 16 / INTERPOL_X; x++)
{
- FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] =
+ FloorHi[INTERPOL_X * x + 17 * INTERPOL_Z * z] = (
m_Noise1.IntNoise3DInt(BaseX + INTERPOL_X * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) *
- m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) /
- 256;
+ m_Noise2.IntNoise3DInt(BaseX + INTERPOL_Z * x, Segment + SEGMENT_HEIGHT, BaseZ + INTERPOL_Z * z) / 256
+ );
} // for x, z - FloorLo[]
LinearUpscale2DArrayInPlace<17, 17, INTERPOL_X, INTERPOL_Z>(FloorHi);
diff --git a/src/Generating/StructGen.h b/src/Generating/StructGen.h
index 9176bc192..96aa3e437 100644
--- a/src/Generating/StructGen.h
+++ b/src/Generating/StructGen.h
@@ -76,16 +76,44 @@ class cStructGenOreNests :
public cFinishGen
{
public:
- cStructGenOreNests(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {}
-
+ struct OreInfo
+ {
+ BLOCKTYPE BlockType; // The type of the nest.
+ NIBBLETYPE BlockMeta; // The block meta
+ int MaxHeight; // The highest possible a nest can occur
+ int NumNests; // How many nests per chunk
+ int NestSize; // The amount of blocks a nest can have.
+
+ OreInfo() :
+ BlockType(0),
+ BlockMeta(0),
+ MaxHeight(0),
+ NumNests(0),
+ NestSize(0)
+ {
+ }
+ };
+
+ typedef std::vector<OreInfo> OreList;
+
+ cStructGenOreNests(int a_Seed, OreList a_OreList, BLOCKTYPE a_ToReplace) :
+ m_Noise(a_Seed),
+ m_Seed(a_Seed),
+ m_OreList(a_OreList),
+ m_ToReplace(a_ToReplace)
+ {}
+
protected:
- cNoise m_Noise;
- int m_Seed;
+ cNoise m_Noise;
+ int m_Seed;
+
+ OreList m_OreList; // A list of possible ores.
+ BLOCKTYPE m_ToReplace;
// cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
- void GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, int a_Seq);
+ void GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_OreType, NIBBLETYPE a_BlockMeta, int a_MaxHeight, int a_NumNests, int a_NestSize, cChunkDef::BlockTypes & a_BlockTypes, cChunkDesc::BlockNibbleBytes & a_BlockMetas, int a_Seq);
} ;
diff --git a/src/Generating/Trees.cpp b/src/Generating/Trees.cpp
index c40322630..7fd6d6f07 100644
--- a/src/Generating/Trees.cpp
+++ b/src/Generating/Trees.cpp
@@ -181,6 +181,7 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
return;
}
+ case biSwamplandM:
case biSwampland:
{
// Swamp trees:
@@ -218,14 +219,11 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
return;
}
- case biRoofedForest:
case biColdTaiga:
case biColdTaigaHills:
case biMegaTaiga:
case biMegaTaigaHills:
case biExtremeHillsPlus:
- case biSavanna:
- case biSavannaPlateau:
case biMesa:
case biMesaPlateauF:
case biMesaPlateau:
@@ -234,17 +232,13 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
case biExtremeHillsM:
case biFlowerForest:
case biTaigaM:
- case biSwamplandM:
case biIcePlainsSpikes:
case biJungleM:
case biJungleEdgeM:
- case biRoofedForestM:
case biColdTaigaM:
case biMegaSpruceTaiga:
case biMegaSpruceTaigaHills:
case biExtremeHillsPlusM:
- case biSavannaM:
- case biSavannaPlateauM:
case biMesaBryce:
case biMesaPlateauFM:
case biMesaPlateauM:
@@ -253,6 +247,22 @@ void GetTreeImageByBiome(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_No
GetBirchTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
return;
}
+
+ case biSavanna:
+ case biSavannaPlateau:
+ case biSavannaM:
+ case biSavannaPlateauM:
+ {
+ GetAcaciaTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
+ return;
+ }
+
+ case biRoofedForest:
+ case biRoofedForestM:
+ {
+ GetDarkoakTreeImage(a_BlockX, a_BlockY, a_BlockZ, a_Noise, a_Seq, a_LogBlocks, a_OtherBlocks);
+ return;
+ }
case biDesert:
case biDesertHills:
@@ -398,7 +408,72 @@ void GetBirchTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Nois
void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
{
- // TODO
+ // Calculate a base height
+ int Height = 2 + (a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) / 11 % 3);
+
+ // Create the trunk
+ for (int i = 0; i < Height; i++)
+ {
+ a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD));
+ }
+
+ // Array with possible directions for a branch to go to.
+ const Vector3i AvailableDirections[] =
+ {
+ { -1, 1, 0 }, { 0, 1, -1 },
+ { -1, 1, 1 }, { -1, 1, -1 },
+ { 1, 1, 1 }, { 1, 1, -1 },
+ { 1, 1, 0 }, { 0, 1, 1 },
+ };
+
+ // Set the starting point of the branch
+ Vector3i BranchPos = Vector3i(a_BlockX, a_BlockY + Height - 1, a_BlockZ);
+
+ // Get a direction for the trunk to go to.
+ Vector3i BranchDirection = AvailableDirections[a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 8];
+
+ // Calculate a height for the branch between 1 and 3
+ int BranchHeight = a_Noise.IntNoise3DInt(a_BlockX, a_BlockY, a_BlockZ) % 3 + 1;
+
+ // Place the logs of the branch.
+ for (int i = 0; i < BranchHeight; i++)
+ {
+ BranchPos = BranchPos + BranchDirection;
+ a_LogBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y, BranchPos.z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD));
+ }
+
+ // Add the leaves to the top of the branch
+ PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ a_OtherBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD));
+
+ // Choose if we have to add another branch
+ bool TwoTop = (a_Noise.IntNoise3D(a_BlockX, a_BlockY, a_BlockZ) < 0 ? true : false);
+ if (!TwoTop)
+ {
+ return;
+ }
+
+ // Reset the starting point of the branch
+ BranchPos = Vector3i(a_BlockX, a_BlockY + Height - 1, a_BlockZ);
+
+ // Invert the direction of the previous branch.
+ BranchDirection = Vector3d(-BranchDirection.x, 1, -BranchDirection.z);
+
+ // Calculate a new height for the second branch
+ BranchHeight = a_Noise.IntNoise3DInt(a_BlockX * a_Seq, a_BlockY * a_Seq * 10, a_BlockZ * a_Seq) % 3 + 1;
+
+ // Place the logs in the same way as the first branch
+ for (int i = 0; i < BranchHeight; i++)
+ {
+ BranchPos = BranchPos + BranchDirection;
+ a_LogBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y, BranchPos.z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_ACACIA_WOOD));
+ }
+
+ // And add the leaves ontop of the second branch
+ PushCoordBlocks(BranchPos.x, BranchPos.y, BranchPos.z, a_OtherBlocks, BigO2, ARRAYCOUNT(BigO2), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ PushCoordBlocks(BranchPos.x, BranchPos.y + 1, BranchPos.z, a_OtherBlocks, BigO1, ARRAYCOUNT(BigO1), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD);
+ a_OtherBlocks.push_back(sSetBlock(BranchPos.x, BranchPos.y + 1, BranchPos.z, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_ACACIA_WOOD));
}
@@ -407,7 +482,60 @@ void GetAcaciaTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noi
void GetDarkoakTreeImage(int a_BlockX, int a_BlockY, int a_BlockZ, cNoise & a_Noise, int a_Seq, sSetBlockVector & a_LogBlocks, sSetBlockVector & a_OtherBlocks)
{
- // TODO
+ // Pick a height
+ int Height = 5 + (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY, a_BlockZ + 32 * a_Seq) / 11) % 4;
+
+ // Create the trunk
+ for (int i = 0; i < Height; i++)
+ {
+ a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ a_LogBlocks.push_back(sSetBlock(a_BlockX, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ a_LogBlocks.push_back(sSetBlock(a_BlockX + 1, a_BlockY + i, a_BlockZ + 1, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ }
+
+ // Create branches
+ for (int i = 0; i < 3; i++)
+ {
+ int x = (a_Noise.IntNoise3DInt(a_BlockX + 32 * a_Seq, a_BlockY * i, a_BlockZ + 32 * a_Seq) % 3) - 1;
+ int z = (a_Noise.IntNoise3DInt(a_BlockX - 32 * a_Seq, a_BlockY * i, a_BlockZ - 32 * a_Seq) % 3) - 1;
+
+ // The branches would end up in the trunk.
+ if ((x >= a_BlockX) && (x <= a_BlockX + 1) && (z >= a_BlockZ) && (z <= a_BlockZ + 1))
+ {
+ NOISE_DATATYPE Val1 = a_Noise.IntNoise2D(x, z);
+ if (Val1 < 0)
+ {
+ x = a_BlockX + ((Val1 < -0.5) ? -1 : 3);
+ }
+ else
+ {
+ z = a_BlockZ + ((Val1 < 0.5) ? -1 : 3);
+ }
+ }
+
+ int y = Height - (a_Noise.IntNoise3DInt(a_BlockX + x, a_BlockY * i, a_BlockZ - z) % (Height - (Height / 4)));
+
+ for (int Y = y; Y < Height; Y++)
+ {
+ a_LogBlocks.push_back(sSetBlock(a_BlockX + x, a_BlockY + Y, a_BlockZ + z, E_BLOCK_NEW_LOG, E_META_NEW_LOG_DARK_OAK_WOOD));
+ }
+ }
+
+ int hei = a_BlockY + Height - 2;
+
+ // The lower two leaves layers are BigO4 with log in the middle and possibly corners:
+ for (int i = 0; i < 2; i++)
+ {
+ PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO4, ARRAYCOUNT(BigO4), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ hei++;
+ } // for i < 2
+
+ // The top leaves layer is a BigO3 with leaves in the middle and possibly corners:
+ PushCoordBlocks(a_BlockX, hei, a_BlockZ, a_OtherBlocks, BigO3, ARRAYCOUNT(BigO3), E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ PushCornerBlocks(a_BlockX, hei, a_BlockZ, a_Seq, a_Noise, 0x5fffffff, a_OtherBlocks, 3, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD);
+ a_OtherBlocks.push_back(sSetBlock(a_BlockX, hei, a_BlockZ, E_BLOCK_NEW_LEAVES, E_META_NEW_LEAVES_DARK_OAK_WOOD));
}
diff --git a/src/Generating/Trees.h b/src/Generating/Trees.h
index 1f6ac4dff..c9eb7de80 100644
--- a/src/Generating/Trees.h
+++ b/src/Generating/Trees.h
@@ -28,6 +28,7 @@ logs can overwrite others(leaves), but others shouldn't overwrite logs. This is
#define CASE_TREE_ALLOWED_BLOCKS \
case E_BLOCK_AIR: \
case E_BLOCK_LEAVES: \
+ case E_BLOCK_NEW_LEAVES: \
case E_BLOCK_SNOW: \
case E_BLOCK_TALL_GRASS: \
case E_BLOCK_DEAD_BUSH: \
@@ -40,6 +41,7 @@ logs can overwrite others(leaves), but others shouldn't overwrite logs. This is
/* case E_BLOCK_LEAVES: LEAVES are a special case, they can be overwritten only by log. Handled in cChunkMap::ReplaceTreeBlocks(). */ \
case E_BLOCK_SNOW: \
case E_BLOCK_TALL_GRASS: \
+ case E_BLOCK_BIG_FLOWER: \
case E_BLOCK_DEAD_BUSH: \
case E_BLOCK_SAPLING: \
case E_BLOCK_VINES
diff --git a/src/Generating/VillageGen.cpp b/src/Generating/VillageGen.cpp
index cade923c9..a7f66b75e 100644
--- a/src/Generating/VillageGen.cpp
+++ b/src/Generating/VillageGen.cpp
@@ -168,7 +168,7 @@ protected:
/** The density for this village. Used to refrain from populating all house connectors. Range [0, 100] */
int m_Density;
- /** Borders of the vilalge - no item may reach out of this cuboid. */
+ /** Borders of the village - no item may reach out of this cuboid. */
cCuboid m_Borders;
/** Prefabs to use for buildings */