summaryrefslogtreecommitdiffstats
path: root/source/StructGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/StructGen.cpp928
1 files changed, 464 insertions, 464 deletions
diff --git a/source/StructGen.cpp b/source/StructGen.cpp
index 5f1d9da74..aa3632204 100644
--- a/source/StructGen.cpp
+++ b/source/StructGen.cpp
@@ -1,464 +1,464 @@
-
-// StructGen.h
-
-#include "Globals.h"
-#include "StructGen.h"
-#include "BlockID.h"
-#include "Trees.h"
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStructGenOreNests configuration:
-
-const int MAX_HEIGHT_COAL = 127;
-const int NUM_NESTS_COAL = 60;
-const int NEST_SIZE_COAL = 10;
-
-const int MAX_HEIGHT_IRON = 70;
-const int NUM_NESTS_IRON = 30;
-const int NEST_SIZE_IRON = 6;
-
-const int MAX_HEIGHT_REDSTONE = 40;
-const int NUM_NESTS_REDSTONE = 10;
-const int NEST_SIZE_REDSTONE = 6;
-
-const int MAX_HEIGHT_GOLD = 35;
-const int NUM_NESTS_GOLD = 6;
-const int NEST_SIZE_GOLD = 6;
-
-const int MAX_HEIGHT_DIAMOND = 16;
-const int NUM_NESTS_DIAMOND = 6;
-const int NEST_SIZE_DIAMOND = 5;
-
-const int MAX_HEIGHT_LAPIS = 30;
-const int NUM_NESTS_LAPIS = 6;
-const int NEST_SIZE_LAPIS = 5;
-
-
-
-
-
-template <typename T> T Clamp(T a_Value, T a_Min, T a_Max)
-{
- return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value);
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStructGenTrees:
-
-void cStructGenTrees::GenStructures(
- int a_ChunkX, int a_ChunkZ,
- cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
- cChunkDef::BlockNibbles & a_BlockMetas, // Block meta to read and change
- cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
- cEntityList & a_Entities, // Entities may be added or deleted
- cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
-)
-{
- cChunkDef::BlockTypes WorkerBlockTypes;
- cChunkDef::BlockNibbles WorkerBlockMeta;
- cChunkDef::HeightMap WorkerHeight;
-
- cEntityList Entities;
- cBlockEntityList BlockEntities;
-
- // Generate trees:
- for (int x = 0; x <= 2; x++)
- {
- int BaseX = a_ChunkX + x - 1;
- for (int z = 0; z <= 2; z++)
- {
- int BaseZ = a_ChunkZ + z - 1;
- sSetBlockVector Outside;
-
- cChunkDef::BlockTypes * BlT;
- cChunkDef::BlockNibbles * BlM;
- cChunkDef::HeightMap * Hei;
-
- cChunkDef::BiomeMap Biomes;
- m_BiomeGen->GenBiomes(BaseX, BaseZ, Biomes);
-
- if ((x != 1) || (z != 1))
- {
- BlT = &WorkerBlockTypes;
- BlM = &WorkerBlockMeta;
- Hei = &WorkerHeight;
-
- m_HeightGen->GenHeightMap (BaseX, BaseZ, *Hei);
- m_CompositionGen->ComposeTerrain(BaseX, BaseZ, *BlT, *BlM, *Hei, Biomes, Entities, BlockEntities);
- // TODO: Free the entity lists
- }
- else
- {
- BlT = &a_BlockTypes;
- BlM = &a_BlockMetas;
- Hei = &a_HeightMap;
- }
-
- int NumTrees = GetNumTrees(BaseX, BaseZ, Biomes);
-
- for (int i = 0; i < NumTrees; i++)
- {
- GenerateSingleTree(BaseX, BaseZ, i, *BlT, *BlM, *Hei, Biomes, Outside);
- }
-
- // Integrate blocks in Outside into chunk:
- for (sSetBlockVector::const_iterator itr = Outside.begin(); itr != Outside.end(); ++itr)
- {
- if ((itr->ChunkX != a_ChunkX) || (itr->ChunkZ != a_ChunkZ))
- {
- continue;
- }
- switch (cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z))
- {
- CASE_TREE_OVERWRITTEN_BLOCKS:
- {
- cChunkDef::SetBlock (a_BlockTypes, itr->x, itr->y, itr->z, itr->BlockType);
- cChunkDef::SetNibble(a_BlockMetas, itr->x, itr->y, itr->z, itr->BlockMeta);
- break;
- }
- } // switch (GetBlock())
- } // for itr - Outside[]
- } // for z
- } // for x
-
- // Update the heightmap:
- for (int x = 0; x < cChunkDef::Width; x++)
- {
- for (int z = 0; z < cChunkDef::Width; z++)
- {
- for (int y = cChunkDef::Height - 1; y >= 0; y--)
- {
- if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) != E_BLOCK_AIR)
- {
- cChunkDef::SetHeight(a_HeightMap, x, z, y);
- break;
- }
- } // for y
- } // for z
- } // for x
-}
-
-
-
-
-
-void cStructGenTrees::GenerateSingleTree(
- int a_ChunkX, int a_ChunkZ, int a_Seq,
- cChunkDef::BlockTypes & a_BlockTypes,
- cChunkDef::BlockNibbles & a_BlockMetas,
- const cChunkDef::HeightMap & a_Height,
- const cChunkDef::BiomeMap & a_Biomes,
- sSetBlockVector & a_Blocks
-)
-{
- int x = m_Noise.IntNoise3DInt(a_ChunkX + a_ChunkZ, a_ChunkZ, a_Seq) % cChunkDef::Width;
- int z = m_Noise.IntNoise3DInt(a_ChunkX - a_ChunkZ, a_Seq, a_ChunkZ) % cChunkDef::Width;
-
- int Height = a_Height[x + cChunkDef::Width * z];
-
- if ((Height <= 0) || (Height > 240))
- {
- return;
- }
-
- // Check the block underneath the tree:
- BLOCKTYPE TopBlock = cChunkDef::GetBlock(a_BlockTypes, x, Height, z);
- if ((TopBlock != E_BLOCK_DIRT) && (TopBlock != E_BLOCK_GRASS) && (TopBlock != E_BLOCK_SOIL))
- {
- return;
- }
-
- sSetBlockVector TreeBlocks;
- GetTreeImageByBiome(a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z, m_Noise, a_Seq, a_Biomes[x + cChunkDef::Width * z], TreeBlocks);
-
- // Check if the generated image fits the terrain:
- for (sSetBlockVector::const_iterator itr = TreeBlocks.begin(); itr != TreeBlocks.end(); ++itr)
- {
- if ((itr->ChunkX != a_ChunkX) || (itr->ChunkZ != a_ChunkZ) || (itr->BlockType != E_BLOCK_LOG))
- {
- // Outside the chunk, or not a log (we don't check non-logs)
- continue;
- }
-
- BLOCKTYPE Block = cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z);
- switch (Block)
- {
- CASE_TREE_ALLOWED_BLOCKS:
- {
- break;
- }
- default:
- {
- // There's something in the way, abort this tree altogether
- return;
- }
- }
- }
-
- // Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks
- for (sSetBlockVector::const_iterator itr = TreeBlocks.begin(); itr != TreeBlocks.end(); ++itr)
- {
- if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ))
- {
- // Inside this chunk, integrate into a_BlockTypes:
- switch (cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z))
- {
- CASE_TREE_OVERWRITTEN_BLOCKS:
- {
- cChunkDef::SetBlock (a_BlockTypes, itr->x, itr->y, itr->z, itr->BlockType);
- cChunkDef::SetNibble(a_BlockMetas, itr->x, itr->y, itr->z, itr->BlockMeta);
- break;
- }
- } // switch (GetBlock())
- continue;
- }
-
- // Outside the chunk, push into a_Blocks; check if already present there:
- bool Found = false;
- for (sSetBlockVector::iterator itrB = a_Blocks.begin(); itrB != a_Blocks.end(); ++itrB)
- {
- if (
- (itr->ChunkX == itrB->ChunkX) &&
- (itr->ChunkZ == itrB->ChunkZ) &&
- (itr->x == itrB->x) &&
- (itr->y == itrB->y) &&
- (itr->z == itrB->z)
- )
- {
- // Same coords already found in a_Blocks, overwrite with wood, if requested:
- if (itr->BlockType == E_BLOCK_LOG)
- {
- itrB->BlockType = itr->BlockType;
- itrB->BlockMeta = itr->BlockMeta;
- }
- Found = true;
- break;
- }
- } // for itrB - a_Blocks[]
- if (!Found)
- {
- a_Blocks.push_back(*itr);
- }
- }
-}
-
-
-
-
-
-int cStructGenTrees::GetNumTrees(
- int a_ChunkX, int a_ChunkZ,
- const cChunkDef::BiomeMap & a_Biomes
-)
-{
- int NumTrees = 0;
- for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++)
- {
- int Add = 0;
- switch (a_Biomes[x + cChunkDef::Width * z])
- {
- case biPlains: Add = 1; break;
- case biExtremeHills: Add = 3; break;
- case biForest: Add = 30; break;
- case biTaiga: Add = 30; break;
- case biSwampland: Add = 8; break;
- case biIcePlains: Add = 1; break;
- case biIceMountains: Add = 1; break;
- case biMushroomIsland: Add = 3; break;
- case biMushroomShore: Add = 3; break;
- case biForestHills: Add = 20; break;
- case biTaigaHills: Add = 20; break;
- case biExtremeHillsEdge: Add = 5; break;
- case biJungle: Add = 120; break;
- case biJungleHills: Add = 90; break;
- }
- NumTrees += Add;
- }
- return NumTrees / 1024;
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStructGenMarbleCaves:
-
-static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise )
-{
- static const float PI_2 = 1.57079633f;
- float oct1 = (a_Noise.CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f )) * 4;
-
- oct1 = oct1 * oct1 * oct1;
- if (oct1 < 0.f) oct1 = PI_2;
- if (oct1 > PI_2) oct1 = PI_2;
-
- return oct1;
-}
-
-
-
-
-
-void cStructGenMarbleCaves::GenStructures(
- int a_ChunkX, int a_ChunkZ,
- cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
- cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change
- cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
- cEntityList & a_Entities, // Entities may be added or deleted
- cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
-)
-{
- cNoise Noise(m_Seed);
- for (int z = 0; z < cChunkDef::Width; z++)
- {
- const float zz = (float)(a_ChunkZ * cChunkDef::Width + z);
- for (int x = 0; x < cChunkDef::Width; x++)
- {
- const float xx = (float)(a_ChunkX * cChunkDef::Width + x);
-
- int Top = cChunkDef::GetHeight(a_HeightMap, x, z);
- for (int y = 1; y < Top; ++y )
- {
- if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) != E_BLOCK_STONE)
- {
- continue;
- }
-
- const float yy = (float)y;
- const float WaveNoise = 1;
- if (cosf(GetMarbleNoise(xx, yy * 0.5f, zz, Noise)) * fabs(cosf(yy * 0.2f + WaveNoise * 2) * 0.75f + WaveNoise) > 0.0005f)
- {
- if (y > 4)
- {
- cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
- }
- else
- {
- cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_STATIONARY_LAVA);
- }
- }
- } // for y
- } // for x
- } // for z
-}
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// cStructGenOreNests:
-
-void cStructGenOreNests::GenStructures(
- int a_ChunkX, int a_ChunkZ,
- cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
- cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change
- cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
- cEntityList & a_Entities, // Entities may be added or deleted
- cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
-)
-{
- GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_COAL_ORE, MAX_HEIGHT_COAL, NUM_NESTS_COAL, NEST_SIZE_COAL, a_BlockTypes, 1);
- GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_IRON_ORE, MAX_HEIGHT_IRON, NUM_NESTS_IRON, NEST_SIZE_IRON, a_BlockTypes, 2);
- GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_REDSTONE_ORE, MAX_HEIGHT_REDSTONE, NUM_NESTS_REDSTONE, NEST_SIZE_REDSTONE, a_BlockTypes, 3);
- GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_GOLD_ORE, MAX_HEIGHT_GOLD, NUM_NESTS_GOLD, NEST_SIZE_GOLD, a_BlockTypes, 4);
- GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_DIAMOND_ORE, MAX_HEIGHT_DIAMOND, NUM_NESTS_DIAMOND, NEST_SIZE_DIAMOND, a_BlockTypes, 5);
- GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_LAPIS_ORE, MAX_HEIGHT_LAPIS, NUM_NESTS_LAPIS, NEST_SIZE_LAPIS, a_BlockTypes, 6);
-}
-
-
-
-
-
-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)
-{
- // 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
- // Only stone gets replaced with ore, all other blocks stay (so the nest can actually be smaller than specified).
-
- for (int i = 0; i < a_NumNests; i++)
- {
- int rnd = m_Noise.IntNoise3DInt(a_ChunkX + i, a_Seq, a_ChunkZ + 64 * i) / 8;
- int BaseX = rnd % cChunkDef::Width;
- rnd /= cChunkDef::Width;
- int BaseZ = rnd % cChunkDef::Width;
- rnd /= cChunkDef::Width;
- int BaseY = rnd % a_MaxHeight;
- rnd /= a_MaxHeight;
- int NestSize = a_NestSize + (rnd % (a_NestSize / 4)); // The actual nest size may be up to 1/4 larger
- int Num = 0;
- while (Num < NestSize)
- {
- // Put a cuboid around [BaseX, BaseY, BaseZ]
- int rnd = m_Noise.IntNoise3DInt(a_ChunkX + 64 * i, 2 * a_Seq + Num, a_ChunkZ + 32 * i) / 8;
- int xsize = rnd % 2;
- int ysize = (rnd / 4) % 2;
- int zsize = (rnd / 16) % 2;
- rnd >>= 8;
- for (int x = xsize; x >= 0; --x)
- {
- int BlockX = BaseX + x;
- if ((BlockX < 0) || (BlockX >= cChunkDef::Width))
- {
- Num++; // So that the cycle finishes even if the base coords wander away from the chunk
- continue;
- }
- for (int y = ysize; y >= 0; --y)
- {
- int BlockY = BaseY + y;
- if ((BlockY < 0) || (BlockY >= cChunkDef::Height))
- {
- Num++; // So that the cycle finishes even if the base coords wander away from the chunk
- continue;
- }
- for (int z = zsize; z >= 0; --z)
- {
- int BlockZ = BaseZ + z;
- if ((BlockZ < 0) || (BlockZ >= cChunkDef::Width))
- {
- Num++; // So that the cycle finishes even if the base coords wander away from the chunk
- continue;
- }
-
- int Index = cChunkDef::MakeIndexNoCheck(BlockX, BlockY, BlockZ);
- if (a_BlockTypes[Index] == E_BLOCK_STONE)
- {
- a_BlockTypes[Index] = a_OreType;
- }
- Num++;
- } // for z
- } // for y
- } // for x
-
- // Move the base to a neighbor voxel
- switch (rnd % 4)
- {
- case 0: BaseX--; break;
- case 1: BaseX++; break;
- }
- switch ((rnd >> 3) % 4)
- {
- case 0: BaseY--; break;
- case 1: BaseY++; break;
- }
- switch ((rnd >> 6) % 4)
- {
- case 0: BaseZ--; break;
- case 1: BaseZ++; break;
- }
- } // while (Num < NumBlocks)
- } // for i - NumNests
-}
-
-
-
-
+
+// StructGen.h
+
+#include "Globals.h"
+#include "StructGen.h"
+#include "BlockID.h"
+#include "Trees.h"
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStructGenOreNests configuration:
+
+const int MAX_HEIGHT_COAL = 127;
+const int NUM_NESTS_COAL = 60;
+const int NEST_SIZE_COAL = 10;
+
+const int MAX_HEIGHT_IRON = 70;
+const int NUM_NESTS_IRON = 30;
+const int NEST_SIZE_IRON = 6;
+
+const int MAX_HEIGHT_REDSTONE = 40;
+const int NUM_NESTS_REDSTONE = 10;
+const int NEST_SIZE_REDSTONE = 6;
+
+const int MAX_HEIGHT_GOLD = 35;
+const int NUM_NESTS_GOLD = 6;
+const int NEST_SIZE_GOLD = 6;
+
+const int MAX_HEIGHT_DIAMOND = 16;
+const int NUM_NESTS_DIAMOND = 6;
+const int NEST_SIZE_DIAMOND = 5;
+
+const int MAX_HEIGHT_LAPIS = 30;
+const int NUM_NESTS_LAPIS = 6;
+const int NEST_SIZE_LAPIS = 5;
+
+
+
+
+
+template <typename T> T Clamp(T a_Value, T a_Min, T a_Max)
+{
+ return (a_Value < a_Min) ? a_Min : ((a_Value > a_Max) ? a_Max : a_Value);
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStructGenTrees:
+
+void cStructGenTrees::GenStructures(
+ int a_ChunkX, int a_ChunkZ,
+ cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
+ cChunkDef::BlockNibbles & a_BlockMetas, // Block meta to read and change
+ cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
+ cEntityList & a_Entities, // Entities may be added or deleted
+ cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
+)
+{
+ cChunkDef::BlockTypes WorkerBlockTypes;
+ cChunkDef::BlockNibbles WorkerBlockMeta;
+ cChunkDef::HeightMap WorkerHeight;
+
+ cEntityList Entities;
+ cBlockEntityList BlockEntities;
+
+ // Generate trees:
+ for (int x = 0; x <= 2; x++)
+ {
+ int BaseX = a_ChunkX + x - 1;
+ for (int z = 0; z <= 2; z++)
+ {
+ int BaseZ = a_ChunkZ + z - 1;
+ sSetBlockVector Outside;
+
+ cChunkDef::BlockTypes * BlT;
+ cChunkDef::BlockNibbles * BlM;
+ cChunkDef::HeightMap * Hei;
+
+ cChunkDef::BiomeMap Biomes;
+ m_BiomeGen->GenBiomes(BaseX, BaseZ, Biomes);
+
+ if ((x != 1) || (z != 1))
+ {
+ BlT = &WorkerBlockTypes;
+ BlM = &WorkerBlockMeta;
+ Hei = &WorkerHeight;
+
+ m_HeightGen->GenHeightMap (BaseX, BaseZ, *Hei);
+ m_CompositionGen->ComposeTerrain(BaseX, BaseZ, *BlT, *BlM, *Hei, Biomes, Entities, BlockEntities);
+ // TODO: Free the entity lists
+ }
+ else
+ {
+ BlT = &a_BlockTypes;
+ BlM = &a_BlockMetas;
+ Hei = &a_HeightMap;
+ }
+
+ int NumTrees = GetNumTrees(BaseX, BaseZ, Biomes);
+
+ for (int i = 0; i < NumTrees; i++)
+ {
+ GenerateSingleTree(BaseX, BaseZ, i, *BlT, *BlM, *Hei, Biomes, Outside);
+ }
+
+ // Integrate blocks in Outside into chunk:
+ for (sSetBlockVector::const_iterator itr = Outside.begin(); itr != Outside.end(); ++itr)
+ {
+ if ((itr->ChunkX != a_ChunkX) || (itr->ChunkZ != a_ChunkZ))
+ {
+ continue;
+ }
+ switch (cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z))
+ {
+ CASE_TREE_OVERWRITTEN_BLOCKS:
+ {
+ cChunkDef::SetBlock (a_BlockTypes, itr->x, itr->y, itr->z, itr->BlockType);
+ cChunkDef::SetNibble(a_BlockMetas, itr->x, itr->y, itr->z, itr->BlockMeta);
+ break;
+ }
+ } // switch (GetBlock())
+ } // for itr - Outside[]
+ } // for z
+ } // for x
+
+ // Update the heightmap:
+ for (int x = 0; x < cChunkDef::Width; x++)
+ {
+ for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ for (int y = cChunkDef::Height - 1; y >= 0; y--)
+ {
+ if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) != E_BLOCK_AIR)
+ {
+ cChunkDef::SetHeight(a_HeightMap, x, z, y);
+ break;
+ }
+ } // for y
+ } // for z
+ } // for x
+}
+
+
+
+
+
+void cStructGenTrees::GenerateSingleTree(
+ int a_ChunkX, int a_ChunkZ, int a_Seq,
+ cChunkDef::BlockTypes & a_BlockTypes,
+ cChunkDef::BlockNibbles & a_BlockMetas,
+ const cChunkDef::HeightMap & a_Height,
+ const cChunkDef::BiomeMap & a_Biomes,
+ sSetBlockVector & a_Blocks
+)
+{
+ int x = m_Noise.IntNoise3DInt(a_ChunkX + a_ChunkZ, a_ChunkZ, a_Seq) % cChunkDef::Width;
+ int z = m_Noise.IntNoise3DInt(a_ChunkX - a_ChunkZ, a_Seq, a_ChunkZ) % cChunkDef::Width;
+
+ int Height = a_Height[x + cChunkDef::Width * z];
+
+ if ((Height <= 0) || (Height > 240))
+ {
+ return;
+ }
+
+ // Check the block underneath the tree:
+ BLOCKTYPE TopBlock = cChunkDef::GetBlock(a_BlockTypes, x, Height, z);
+ if ((TopBlock != E_BLOCK_DIRT) && (TopBlock != E_BLOCK_GRASS) && (TopBlock != E_BLOCK_SOIL))
+ {
+ return;
+ }
+
+ sSetBlockVector TreeBlocks;
+ GetTreeImageByBiome(a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z, m_Noise, a_Seq, a_Biomes[x + cChunkDef::Width * z], TreeBlocks);
+
+ // Check if the generated image fits the terrain:
+ for (sSetBlockVector::const_iterator itr = TreeBlocks.begin(); itr != TreeBlocks.end(); ++itr)
+ {
+ if ((itr->ChunkX != a_ChunkX) || (itr->ChunkZ != a_ChunkZ) || (itr->BlockType != E_BLOCK_LOG))
+ {
+ // Outside the chunk, or not a log (we don't check non-logs)
+ continue;
+ }
+
+ BLOCKTYPE Block = cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z);
+ switch (Block)
+ {
+ CASE_TREE_ALLOWED_BLOCKS:
+ {
+ break;
+ }
+ default:
+ {
+ // There's something in the way, abort this tree altogether
+ return;
+ }
+ }
+ }
+
+ // Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks
+ for (sSetBlockVector::const_iterator itr = TreeBlocks.begin(); itr != TreeBlocks.end(); ++itr)
+ {
+ if ((itr->ChunkX == a_ChunkX) && (itr->ChunkZ == a_ChunkZ))
+ {
+ // Inside this chunk, integrate into a_BlockTypes:
+ switch (cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z))
+ {
+ CASE_TREE_OVERWRITTEN_BLOCKS:
+ {
+ cChunkDef::SetBlock (a_BlockTypes, itr->x, itr->y, itr->z, itr->BlockType);
+ cChunkDef::SetNibble(a_BlockMetas, itr->x, itr->y, itr->z, itr->BlockMeta);
+ break;
+ }
+ } // switch (GetBlock())
+ continue;
+ }
+
+ // Outside the chunk, push into a_Blocks; check if already present there:
+ bool Found = false;
+ for (sSetBlockVector::iterator itrB = a_Blocks.begin(); itrB != a_Blocks.end(); ++itrB)
+ {
+ if (
+ (itr->ChunkX == itrB->ChunkX) &&
+ (itr->ChunkZ == itrB->ChunkZ) &&
+ (itr->x == itrB->x) &&
+ (itr->y == itrB->y) &&
+ (itr->z == itrB->z)
+ )
+ {
+ // Same coords already found in a_Blocks, overwrite with wood, if requested:
+ if (itr->BlockType == E_BLOCK_LOG)
+ {
+ itrB->BlockType = itr->BlockType;
+ itrB->BlockMeta = itr->BlockMeta;
+ }
+ Found = true;
+ break;
+ }
+ } // for itrB - a_Blocks[]
+ if (!Found)
+ {
+ a_Blocks.push_back(*itr);
+ }
+ }
+}
+
+
+
+
+
+int cStructGenTrees::GetNumTrees(
+ int a_ChunkX, int a_ChunkZ,
+ const cChunkDef::BiomeMap & a_Biomes
+)
+{
+ int NumTrees = 0;
+ for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ int Add = 0;
+ switch (a_Biomes[x + cChunkDef::Width * z])
+ {
+ case biPlains: Add = 1; break;
+ case biExtremeHills: Add = 3; break;
+ case biForest: Add = 30; break;
+ case biTaiga: Add = 30; break;
+ case biSwampland: Add = 8; break;
+ case biIcePlains: Add = 1; break;
+ case biIceMountains: Add = 1; break;
+ case biMushroomIsland: Add = 3; break;
+ case biMushroomShore: Add = 3; break;
+ case biForestHills: Add = 20; break;
+ case biTaigaHills: Add = 20; break;
+ case biExtremeHillsEdge: Add = 5; break;
+ case biJungle: Add = 120; break;
+ case biJungleHills: Add = 90; break;
+ }
+ NumTrees += Add;
+ }
+ return NumTrees / 1024;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStructGenMarbleCaves:
+
+static float GetMarbleNoise( float x, float y, float z, cNoise & a_Noise )
+{
+ static const float PI_2 = 1.57079633f;
+ float oct1 = (a_Noise.CubicNoise3D(x * 0.1f, y * 0.1f, z * 0.1f )) * 4;
+
+ oct1 = oct1 * oct1 * oct1;
+ if (oct1 < 0.f) oct1 = PI_2;
+ if (oct1 > PI_2) oct1 = PI_2;
+
+ return oct1;
+}
+
+
+
+
+
+void cStructGenMarbleCaves::GenStructures(
+ int a_ChunkX, int a_ChunkZ,
+ cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
+ cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change
+ cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
+ cEntityList & a_Entities, // Entities may be added or deleted
+ cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
+)
+{
+ cNoise Noise(m_Seed);
+ for (int z = 0; z < cChunkDef::Width; z++)
+ {
+ const float zz = (float)(a_ChunkZ * cChunkDef::Width + z);
+ for (int x = 0; x < cChunkDef::Width; x++)
+ {
+ const float xx = (float)(a_ChunkX * cChunkDef::Width + x);
+
+ int Top = cChunkDef::GetHeight(a_HeightMap, x, z);
+ for (int y = 1; y < Top; ++y )
+ {
+ if (cChunkDef::GetBlock(a_BlockTypes, x, y, z) != E_BLOCK_STONE)
+ {
+ continue;
+ }
+
+ const float yy = (float)y;
+ const float WaveNoise = 1;
+ if (cosf(GetMarbleNoise(xx, yy * 0.5f, zz, Noise)) * fabs(cosf(yy * 0.2f + WaveNoise * 2) * 0.75f + WaveNoise) > 0.0005f)
+ {
+ if (y > 4)
+ {
+ cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_AIR);
+ }
+ else
+ {
+ cChunkDef::SetBlock(a_BlockTypes, x, y, z, E_BLOCK_STATIONARY_LAVA);
+ }
+ }
+ } // for y
+ } // for x
+ } // for z
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStructGenOreNests:
+
+void cStructGenOreNests::GenStructures(
+ int a_ChunkX, int a_ChunkZ,
+ cChunkDef::BlockTypes & a_BlockTypes, // Block types to read and change
+ cChunkDef::BlockNibbles & a_BlockMeta, // Block meta to read and change
+ cChunkDef::HeightMap & a_HeightMap, // Height map to read and change by the current data
+ cEntityList & a_Entities, // Entities may be added or deleted
+ cBlockEntityList & a_BlockEntities // Block entities may be added or deleted
+)
+{
+ GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_COAL_ORE, MAX_HEIGHT_COAL, NUM_NESTS_COAL, NEST_SIZE_COAL, a_BlockTypes, 1);
+ GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_IRON_ORE, MAX_HEIGHT_IRON, NUM_NESTS_IRON, NEST_SIZE_IRON, a_BlockTypes, 2);
+ GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_REDSTONE_ORE, MAX_HEIGHT_REDSTONE, NUM_NESTS_REDSTONE, NEST_SIZE_REDSTONE, a_BlockTypes, 3);
+ GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_GOLD_ORE, MAX_HEIGHT_GOLD, NUM_NESTS_GOLD, NEST_SIZE_GOLD, a_BlockTypes, 4);
+ GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_DIAMOND_ORE, MAX_HEIGHT_DIAMOND, NUM_NESTS_DIAMOND, NEST_SIZE_DIAMOND, a_BlockTypes, 5);
+ GenerateOre(a_ChunkX, a_ChunkZ, E_BLOCK_LAPIS_ORE, MAX_HEIGHT_LAPIS, NUM_NESTS_LAPIS, NEST_SIZE_LAPIS, a_BlockTypes, 6);
+}
+
+
+
+
+
+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)
+{
+ // 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
+ // Only stone gets replaced with ore, all other blocks stay (so the nest can actually be smaller than specified).
+
+ for (int i = 0; i < a_NumNests; i++)
+ {
+ int rnd = m_Noise.IntNoise3DInt(a_ChunkX + i, a_Seq, a_ChunkZ + 64 * i) / 8;
+ int BaseX = rnd % cChunkDef::Width;
+ rnd /= cChunkDef::Width;
+ int BaseZ = rnd % cChunkDef::Width;
+ rnd /= cChunkDef::Width;
+ int BaseY = rnd % a_MaxHeight;
+ rnd /= a_MaxHeight;
+ int NestSize = a_NestSize + (rnd % (a_NestSize / 4)); // The actual nest size may be up to 1/4 larger
+ int Num = 0;
+ while (Num < NestSize)
+ {
+ // Put a cuboid around [BaseX, BaseY, BaseZ]
+ int rnd = m_Noise.IntNoise3DInt(a_ChunkX + 64 * i, 2 * a_Seq + Num, a_ChunkZ + 32 * i) / 8;
+ int xsize = rnd % 2;
+ int ysize = (rnd / 4) % 2;
+ int zsize = (rnd / 16) % 2;
+ rnd >>= 8;
+ for (int x = xsize; x >= 0; --x)
+ {
+ int BlockX = BaseX + x;
+ if ((BlockX < 0) || (BlockX >= cChunkDef::Width))
+ {
+ Num++; // So that the cycle finishes even if the base coords wander away from the chunk
+ continue;
+ }
+ for (int y = ysize; y >= 0; --y)
+ {
+ int BlockY = BaseY + y;
+ if ((BlockY < 0) || (BlockY >= cChunkDef::Height))
+ {
+ Num++; // So that the cycle finishes even if the base coords wander away from the chunk
+ continue;
+ }
+ for (int z = zsize; z >= 0; --z)
+ {
+ int BlockZ = BaseZ + z;
+ if ((BlockZ < 0) || (BlockZ >= cChunkDef::Width))
+ {
+ Num++; // So that the cycle finishes even if the base coords wander away from the chunk
+ continue;
+ }
+
+ int Index = cChunkDef::MakeIndexNoCheck(BlockX, BlockY, BlockZ);
+ if (a_BlockTypes[Index] == E_BLOCK_STONE)
+ {
+ a_BlockTypes[Index] = a_OreType;
+ }
+ Num++;
+ } // for z
+ } // for y
+ } // for x
+
+ // Move the base to a neighbor voxel
+ switch (rnd % 4)
+ {
+ case 0: BaseX--; break;
+ case 1: BaseX++; break;
+ }
+ switch ((rnd >> 3) % 4)
+ {
+ case 0: BaseY--; break;
+ case 1: BaseY++; break;
+ }
+ switch ((rnd >> 6) % 4)
+ {
+ case 0: BaseZ--; break;
+ case 1: BaseZ++; break;
+ }
+ } // while (Num < NumBlocks)
+ } // for i - NumNests
+}
+
+
+
+