summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-03-19 09:32:02 +0100
committermadmaxoft@gmail.com <madmaxoft@gmail.com@0a769ca7-a7f5-676a-18bf-c427514a06d6>2013-03-19 09:32:02 +0100
commitb4697ab9dbece2afc8d4edbd86678fa8735578b9 (patch)
treec39af3d9dbb0f6323fb05820d2d29ff0ed3b18ea
parentTrees: fixed a glitch in large jungle trees' leaves (1 column was missing) (diff)
downloadcuberite-b4697ab9dbece2afc8d4edbd86678fa8735578b9.tar
cuberite-b4697ab9dbece2afc8d4edbd86678fa8735578b9.tar.gz
cuberite-b4697ab9dbece2afc8d4edbd86678fa8735578b9.tar.bz2
cuberite-b4697ab9dbece2afc8d4edbd86678fa8735578b9.tar.lz
cuberite-b4697ab9dbece2afc8d4edbd86678fa8735578b9.tar.xz
cuberite-b4697ab9dbece2afc8d4edbd86678fa8735578b9.tar.zst
cuberite-b4697ab9dbece2afc8d4edbd86678fa8735578b9.zip
-rw-r--r--source/BlockArea.cpp79
-rw-r--r--source/BlockArea.h21
-rw-r--r--source/Generating/ChunkDesc.cpp93
-rw-r--r--source/Generating/ChunkDesc.h15
-rw-r--r--source/Generating/ChunkGenerator.cpp5
-rw-r--r--source/Generating/CompoGen.cpp12
-rw-r--r--source/Generating/ComposableGenerator.cpp22
-rw-r--r--source/Generating/FinishGen.cpp15
-rw-r--r--source/Generating/FinishGen.h6
-rw-r--r--source/Generating/StructGen.cpp201
-rw-r--r--source/Generating/StructGen.h26
11 files changed, 324 insertions, 171 deletions
diff --git a/source/BlockArea.cpp b/source/BlockArea.cpp
index 66994f613..61abae716 100644
--- a/source/BlockArea.cpp
+++ b/source/BlockArea.cpp
@@ -92,6 +92,70 @@ static void MergeCombinatorImprint(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, N
+/// Combinator used for cBlockArea::msLake merging
+static void MergeCombinatorLake(BLOCKTYPE & a_DstType, BLOCKTYPE a_SrcType, NIBBLETYPE & a_DstMeta, NIBBLETYPE a_SrcMeta)
+{
+ // Sponge is the NOP block
+ if (a_SrcType == E_BLOCK_SPONGE)
+ {
+ return;
+ }
+
+ // Air is always hollowed out
+ if (a_SrcType == E_BLOCK_AIR)
+ {
+ a_DstType = E_BLOCK_AIR;
+ a_DstMeta = 0;
+ return;
+ }
+
+ // Water and lava are never overwritten
+ switch (a_DstType)
+ {
+ case E_BLOCK_WATER:
+ case E_BLOCK_STATIONARY_WATER:
+ case E_BLOCK_LAVA:
+ case E_BLOCK_STATIONARY_LAVA:
+ {
+ return;
+ }
+ }
+
+ // Water and lava always overwrite
+ switch (a_SrcType)
+ {
+ case E_BLOCK_WATER:
+ case E_BLOCK_STATIONARY_WATER:
+ case E_BLOCK_LAVA:
+ case E_BLOCK_STATIONARY_LAVA:
+ {
+ a_DstType = a_SrcType;
+ a_DstMeta = a_DstMeta;
+ return;
+ }
+ }
+
+ if (a_SrcType == E_BLOCK_STONE)
+ {
+ switch (a_DstType)
+ {
+ case E_BLOCK_DIRT:
+ case E_BLOCK_GRASS:
+ case E_BLOCK_MYCELIUM:
+ {
+ a_DstType = E_BLOCK_STONE;
+ a_DstMeta = 0;
+ return;
+ }
+ }
+ }
+ // Everything else is left as it is
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cBlockArea:
@@ -611,6 +675,21 @@ void cBlockArea::Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_R
break;
} // case msImprint
+ case msLake:
+ {
+ InternalMergeBlocks(
+ m_BlockTypes, a_Src.GetBlockTypes(),
+ DstMetas, SrcMetas,
+ SizeX, SizeY, SizeZ,
+ SrcOffX, SrcOffY, SrcOffZ,
+ DstOffX, DstOffY, DstOffZ,
+ a_Src.GetSizeX(), a_Src.GetSizeY(), a_Src.GetSizeZ(),
+ m_SizeX, m_SizeY, m_SizeZ,
+ MergeCombinatorLake
+ );
+ break;
+ } // case msLake
+
default:
{
LOGWARNING("Unknown block area merge strategy: %d", a_Strategy);
diff --git a/source/BlockArea.h b/source/BlockArea.h
index 653e52a70..94ad67e7f 100644
--- a/source/BlockArea.h
+++ b/source/BlockArea.h
@@ -49,6 +49,7 @@ public:
msOverwrite,
msFillAir,
msImprint,
+ msLake,
} ;
cBlockArea(void);
@@ -107,11 +108,29 @@ public:
| A | air | air | A | A |
| air | B | B | B | B |
| A | B | B | A | B |
-
+
So to sum up:
- msOverwrite completely overwrites all blocks with the Src's blocks
- msFillAir overwrites only those blocks that were air
- msImprint overwrites with only those blocks that are non-air
+
+ Special strategies:
+ msLake (evaluate top-down, first match wins):
+ | area block | |
+ | this | Src | result |
+ +----------+--------+--------+
+ | A | sponge | A | Sponge is the NOP block
+ | * | air | air | Air always gets hollowed out, even under the oceans
+ | water | * | water | Water is never overwritten
+ | lava | * | lava | Lava is never overwritten
+ | * | water | water | Water always overwrites anything
+ | * | lava | lava | Lava always overwrites anything
+ | dirt | stone | stone | Stone overwrites dirt
+ | grass | stone | stone | ... and grass
+ | mycelium | stone | stone | ... and mycelium
+ | A | stone | A | ... but nothing else
+ | A | * | A | Everything else is left as it is
+
*/
void Merge(const cBlockArea & a_Src, int a_RelX, int a_RelY, int a_RelZ, eMergeStrategy a_Strategy);
diff --git a/source/Generating/ChunkDesc.cpp b/source/Generating/ChunkDesc.cpp
index 9a2f2eff5..21ebf90ec 100644
--- a/source/Generating/ChunkDesc.cpp
+++ b/source/Generating/ChunkDesc.cpp
@@ -20,8 +20,11 @@ cChunkDesc::cChunkDesc(int a_ChunkX, int a_ChunkZ) :
m_bUseDefaultStructures(true),
m_bUseDefaultFinish(true)
{
+ m_BlockArea.Create(cChunkDef::Width, cChunkDef::Height, cChunkDef::Width);
+ /*
memset(m_BlockTypes, 0, sizeof(cChunkDef::BlockTypes));
memset(m_BlockMeta, 0, sizeof(cChunkDef::BlockNibbles));
+ */
memset(m_BiomeMap, 0, sizeof(cChunkDef::BiomeMap));
memset(m_HeightMap, 0, sizeof(cChunkDef::HeightMap));
}
@@ -51,9 +54,7 @@ void cChunkDesc::SetChunkCoords(int a_ChunkX, int a_ChunkZ)
void cChunkDesc::FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
- const NIBBLETYPE CompressedMeta = a_BlockMeta | (a_BlockMeta << 4);
- memset(m_BlockTypes, a_BlockType, sizeof(cChunkDef::BlockTypes));
- memset(m_BlockMeta, CompressedMeta, sizeof(cChunkDef::BlockNibbles));
+ m_BlockArea.Fill(cBlockArea::baTypes | cBlockArea::baMetas, a_BlockType, a_BlockMeta);
}
@@ -62,9 +63,7 @@ void cChunkDesc::FillBlocks(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
void cChunkDesc::SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
- int Index = cChunkDef::MakeIndex(a_RelX, a_RelY, a_RelZ);
- cChunkDef::SetBlock(m_BlockTypes, Index, a_BlockType);
- cChunkDef::SetNibble(m_BlockMeta, Index, a_BlockMeta);
+ m_BlockArea.SetRelBlockTypeMeta(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
}
@@ -73,9 +72,7 @@ void cChunkDesc::SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
void cChunkDesc::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta)
{
- int Index = cChunkDef::MakeIndex(a_RelX, a_RelY, a_RelZ);
- a_BlockType = cChunkDef::GetBlock(m_BlockTypes, Index);
- a_BlockMeta = cChunkDef::GetNibble(m_BlockMeta, Index);
+ m_BlockArea.GetRelBlockTypeMeta(a_RelX, a_RelY, a_RelZ, a_BlockType, a_BlockMeta);
}
@@ -84,7 +81,7 @@ void cChunkDesc::GetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE
void cChunkDesc::SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
{
- cChunkDef::SetBlock(m_BlockTypes, a_RelX, a_RelY, a_RelZ, a_BlockType);
+ cChunkDef::SetBlock(m_BlockArea.GetBlockTypes(), a_RelX, a_RelY, a_RelZ, a_BlockType);
}
@@ -93,7 +90,7 @@ void cChunkDesc::SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_Bl
BLOCKTYPE cChunkDesc::GetBlockType(int a_RelX, int a_RelY, int a_RelZ)
{
- return cChunkDef::GetBlock(m_BlockTypes, a_RelX, a_RelY, a_RelZ);
+ return cChunkDef::GetBlock(m_BlockArea.GetBlockTypes(), a_RelX, a_RelY, a_RelZ);
}
@@ -102,7 +99,7 @@ BLOCKTYPE cChunkDesc::GetBlockType(int a_RelX, int a_RelY, int a_RelZ)
NIBBLETYPE cChunkDesc::GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ)
{
- return cChunkDef::GetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ);
+ return m_BlockArea.GetRelBlockMeta(a_RelX, a_RelY, a_RelZ);
}
@@ -111,7 +108,7 @@ NIBBLETYPE cChunkDesc::GetBlockMeta(int a_RelX, int a_RelY, int a_RelZ)
void cChunkDesc::SetBlockMeta(int a_RelX, int a_RelY, int a_RelZ, NIBBLETYPE a_BlockMeta)
{
- cChunkDef::SetNibble(m_BlockMeta, a_RelX, a_RelY, a_RelZ, a_BlockMeta);
+ m_BlockArea.SetRelBlockMeta(a_RelX, a_RelY, a_RelZ, a_BlockMeta);
}
@@ -242,62 +239,9 @@ bool cChunkDesc::IsUsingDefaultFinish(void) const
-void cChunkDesc::WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ)
+void cChunkDesc::WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy)
{
- if (!a_BlockArea.HasBlockTypes() && !a_BlockArea.HasBlockMetas())
- {
- LOGWARNING("Request was made to write a block area without BlockTypes nor BlockMetas into cChunkDesc. Ignoring.");
- return;
- }
- int BAOffX = std::max(0, -a_RelX); // Offset in BA where to start reading
- int CDOffX = std::max(0, a_RelX); // Offset in CD where to start writing
- int SizeX = std::min(a_BlockArea.GetSizeX() - BAOffX, cChunkDef::Width - CDOffX); // Number of slices to write
- int BAOffY = std::max(0, -a_RelY); // Offset in BA where to start reading
- int CDOffY = std::max(0, a_RelY); // Offset in CD where to start writing
- int SizeY = std::min(a_BlockArea.GetSizeY() - BAOffY, cChunkDef::Height - CDOffY); // Number of layers to write
- int BAOffZ = std::max(0, -a_RelZ); // Offset in BA where to start reading
- int CDOffZ = std::max(0, a_RelZ); // Offset in CD where to start writing
- int SizeZ = std::min(a_BlockArea.GetSizeZ() - BAOffZ, cChunkDef::Width - CDOffZ); // Number of slices to write
-
- if (a_BlockArea.HasBlockTypes())
- {
- for (int y = 0; y < SizeY; y++)
- {
- int BAY = BAOffY + y;
- int CDY = CDOffY + y;
- for (int z = 0; z < SizeZ; z++)
- {
- int BAZ = BAOffZ + z;
- int CDZ = CDOffZ + z;
- for (int x = 0; x < SizeX; x++)
- {
- int BAX = BAOffX + x;
- int CDX = CDOffX + x;
- cChunkDef::SetBlock(m_BlockTypes, CDX, CDY, CDZ, a_BlockArea.GetRelBlockType(BAX, BAY, BAZ));
- } // for x
- } // for z
- } // for y
- } // HasBlockTypes()
-
- if (a_BlockArea.HasBlockMetas())
- {
- for (int y = 0; y < SizeY; y++)
- {
- int BAY = BAOffY + y;
- int CDY = CDOffY + y;
- for (int z = 0; z < SizeZ; z++)
- {
- int BAZ = BAOffZ + z;
- int CDZ = CDOffZ + z;
- for (int x = 0; x < SizeX; x++)
- {
- int BAX = BAOffX + x;
- int CDX = CDOffX + x;
- cChunkDef::SetNibble(m_BlockMeta, CDX, CDY, CDZ, a_BlockArea.GetRelBlockMeta(BAX, BAY, BAZ));
- } // for x
- } // for z
- } // for y
- } // HasBlockMetas()
+ m_BlockArea.Merge(a_BlockArea, a_RelX, a_RelY, a_RelZ, a_MergeStrategy);
}
@@ -437,3 +381,16 @@ HEIGHTTYPE cChunkDesc::GetMaxHeight(void) const
+
+void cChunkDesc::CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas)
+{
+ const NIBBLETYPE * AreaMetas = m_BlockArea.GetBlockMetas();
+ for (int i = 0; i < ARRAYCOUNT(a_DestMetas); i++)
+ {
+ a_DestMetas[i] = AreaMetas[2 * i] | (AreaMetas[2 * i + 1] << 4);
+ }
+}
+
+
+
+
diff --git a/source/Generating/ChunkDesc.h b/source/Generating/ChunkDesc.h
index 7df7a1d35..226d22429 100644
--- a/source/Generating/ChunkDesc.h
+++ b/source/Generating/ChunkDesc.h
@@ -10,6 +10,7 @@
#pragma once
#include "../ChunkDef.h"
+#include "../BlockArea.h"
@@ -67,7 +68,7 @@ public:
bool IsUsingDefaultFinish(void) const;
/// Writes the block area into the chunk, with its origin set at the specified relative coords. Area's data overwrite everything in the chunk.
- void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ);
+ void WriteBlockArea(const cBlockArea & a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy = cBlockArea::msOverwrite);
/// Reads an area from the chunk into a cBlockArea
void ReadBlockArea(cBlockArea & a_Dest, int a_MinRelX, int a_MaxRelX, int a_MinRelY, int a_MaxRelY, int a_MinRelZ, int a_MaxRelZ);
@@ -80,24 +81,26 @@ public:
// Accessors used by cChunkGenerator::Generator descendants:
inline cChunkDef::BiomeMap & GetBiomeMap (void) { return m_BiomeMap; }
- inline cChunkDef::BlockTypes & GetBlockTypes (void) { return m_BlockTypes; }
- inline cChunkDef::BlockNibbles & GetBlockMetas (void) { return m_BlockMeta; }
+ 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; }
+ /// Compresses the metas from the BlockArea format (1 meta per byte) into regular format (2 metas per byte)
+ void CompressBlockMetas(cChunkDef::BlockNibbles & a_DestMetas);
+
private:
int m_ChunkX;
int m_ChunkZ;
cChunkDef::BiomeMap m_BiomeMap;
- cChunkDef::BlockTypes m_BlockTypes;
- cChunkDef::BlockNibbles m_BlockMeta;
+ cBlockArea m_BlockArea;
cChunkDef::HeightMap m_HeightMap;
cEntityList m_Entities; // Individual entities are NOT owned by this object!
cBlockEntityList m_BlockEntities; // Individual block entities are NOT owned by this object!
-
bool m_bUseDefaultBiomes;
bool m_bUseDefaultHeight;
bool m_bUseDefaultComposition;
diff --git a/source/Generating/ChunkGenerator.cpp b/source/Generating/ChunkGenerator.cpp
index f235215da..b3c25cf46 100644
--- a/source/Generating/ChunkGenerator.cpp
+++ b/source/Generating/ChunkGenerator.cpp
@@ -271,9 +271,12 @@ 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);
+ cChunkDef::BlockNibbles BlockMetas;
+ ChunkDesc.CompressBlockMetas(BlockMetas);
+
m_World->SetChunkData(
a_ChunkX, a_ChunkY, a_ChunkZ,
- ChunkDesc.GetBlockTypes(), ChunkDesc.GetBlockMetas(),
+ ChunkDesc.GetBlockTypes(), BlockMetas,
NULL, NULL, // We don't have lighting, chunk will be lighted when needed
&ChunkDesc.GetHeightMap(), &ChunkDesc.GetBiomeMap(),
ChunkDesc.GetEntities(), ChunkDesc.GetBlockEntities(),
diff --git a/source/Generating/CompoGen.cpp b/source/Generating/CompoGen.cpp
index 34a83bd52..2e0ec5d18 100644
--- a/source/Generating/CompoGen.cpp
+++ b/source/Generating/CompoGen.cpp
@@ -20,8 +20,7 @@
void cCompoGenSameBlock::ComposeTerrain(cChunkDesc & a_ChunkDesc)
{
- memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes()));
- memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
+ a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
for (int z = 0; z < cChunkDef::Width; z++)
{
for (int x = 0; x < cChunkDef::Width; x++)
@@ -80,8 +79,7 @@ void cCompoGenDebugBiomes::ComposeTerrain(cChunkDesc & a_ChunkDesc)
E_BLOCK_BEDROCK,
} ;
- memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes()));
- memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
+ a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
for (int z = 0; z < cChunkDef::Width; z++)
{
@@ -134,8 +132,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc)
- bedrock at the bottom
*/
- memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes()));
- memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
+ a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
// The patterns to use for different situations, must be same length!
const BLOCKTYPE PatternGround[] = {m_BlockTop, m_BlockMiddle, m_BlockMiddle, m_BlockMiddle} ;
@@ -191,8 +188,7 @@ void cCompoGenClassic::ComposeTerrain(cChunkDesc & a_ChunkDesc)
void cCompoGenBiomal::ComposeTerrain(cChunkDesc & a_ChunkDesc)
{
- memset(a_ChunkDesc.GetBlockTypes(), E_BLOCK_AIR, sizeof(a_ChunkDesc.GetBlockTypes()));
- memset(a_ChunkDesc.GetBlockMetas(), 0, sizeof(a_ChunkDesc.GetBlockMetas()));
+ a_ChunkDesc.FillBlocks(E_BLOCK_AIR, 0);
int ChunkX = a_ChunkDesc.GetChunkX();
int ChunkZ = a_ChunkDesc.GetChunkZ();
diff --git a/source/Generating/ComposableGenerator.cpp b/source/Generating/ComposableGenerator.cpp
index b88fb90c7..e349d73f7 100644
--- a/source/Generating/ComposableGenerator.cpp
+++ b/source/Generating/ComposableGenerator.cpp
@@ -94,21 +94,14 @@ void cComposableGenerator::GenerateBiomes(int a_ChunkX, int a_ChunkZ, cChunkDef:
void cComposableGenerator::DoGenerate(int a_ChunkX, int a_ChunkZ, cChunkDesc & a_ChunkDesc)
{
- cChunkDef::BiomeMap & BiomeMap = a_ChunkDesc.GetBiomeMap();
- cChunkDef::BlockTypes & BlockTypes = a_ChunkDesc.GetBlockTypes();
- cChunkDef::BlockNibbles & BlockMeta = a_ChunkDesc.GetBlockMetas();
- cChunkDef::HeightMap & HeightMap = a_ChunkDesc.GetHeightMap();
- cEntityList & Entities = a_ChunkDesc.GetEntities();
- cBlockEntityList & BlockEntities = a_ChunkDesc.GetBlockEntities();
-
if (a_ChunkDesc.IsUsingDefaultBiomes())
{
- m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, BiomeMap);
+ m_BiomeGen->GenBiomes(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetBiomeMap());
}
if (a_ChunkDesc.IsUsingDefaultHeight())
{
- m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap);
+ m_HeightGen->GenHeightMap(a_ChunkX, a_ChunkZ, a_ChunkDesc.GetHeightMap());
}
if (a_ChunkDesc.IsUsingDefaultComposition())
@@ -336,13 +329,18 @@ void cComposableGenerator::InitStructureGens(cIniFile & a_IniFile)
{
m_StructureGens.push_back(new cStructGenRavines(Seed, 128));
}
- //*
- // TODO: Not implemented yet; need a name
else if (NoCaseCompare(*itr, "wormnestcaves") == 0)
{
m_StructureGens.push_back(new cStructGenWormNestCaves(Seed));
}
- //*/
+ else if (NoCaseCompare(*itr, "waterlakes") == 0)
+ {
+ m_StructureGens.push_back(new cStructGenLakes(Seed * 3 + 652, E_BLOCK_STATIONARY_WATER, *m_HeightGen));
+ }
+ else if (NoCaseCompare(*itr, "lavalakes") == 0)
+ {
+ m_StructureGens.push_back(new cStructGenLakes(Seed * 5 + 16873, E_BLOCK_STATIONARY_LAVA, *m_HeightGen));
+ }
else
{
LOGWARNING("Unknown structure generator: \"%s\". Ignoring.", itr->c_str());
diff --git a/source/Generating/FinishGen.cpp b/source/Generating/FinishGen.cpp
index 6a7d53b14..df9b2f265 100644
--- a/source/Generating/FinishGen.cpp
+++ b/source/Generating/FinishGen.cpp
@@ -598,7 +598,7 @@ void cFinishGenFluidSprings::GenFinish(cChunkDesc & a_ChunkDesc)
case E_BLOCK_NETHERRACK:
case E_BLOCK_STONE:
{
- if (TryPlaceSpring(a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetBlockMetas(), x, y, z))
+ if (TryPlaceSpring(a_ChunkDesc, x, y, z))
{
// Succeeded, bail out
return;
@@ -614,15 +614,11 @@ void cFinishGenFluidSprings::GenFinish(cChunkDesc & a_ChunkDesc)
-bool cFinishGenFluidSprings::TryPlaceSpring(
- cChunkDef::BlockTypes & a_BlockTypes,
- cChunkDef::BlockNibbles & a_BlockMetas,
- int x, int y, int z
-)
+bool cFinishGenFluidSprings::TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z)
{
// In order to place a spring, it needs exactly one of the XZ neighbors or a below neighbor to be air
// Also, its neighbor on top of it must be non-air
- if (cChunkDef::GetBlock(a_BlockTypes, x, y + 1, z) == E_BLOCK_AIR)
+ if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR)
{
return false;
}
@@ -641,7 +637,7 @@ bool cFinishGenFluidSprings::TryPlaceSpring(
int NumAirNeighbors = 0;
for (int i = 0; i < ARRAYCOUNT(Coords); i++)
{
- switch (cChunkDef::GetBlock(a_BlockTypes, x + Coords[i].x, y + Coords[i].y, z + Coords[i].z))
+ switch (a_ChunkDesc.GetBlockType(x + Coords[i].x, y + Coords[i].y, z + Coords[i].z))
{
case E_BLOCK_AIR:
{
@@ -659,8 +655,7 @@ bool cFinishGenFluidSprings::TryPlaceSpring(
}
// Has exactly one air neighbor, place a spring:
- cChunkDef::SetBlock(a_BlockTypes, x, y, z, m_Fluid);
- cChunkDef::SetNibble(a_BlockMetas, x, y, z, 0);
+ a_ChunkDesc.SetBlockTypeMeta(x, y, z, m_Fluid, 0);
return true;
}
diff --git a/source/Generating/FinishGen.h b/source/Generating/FinishGen.h
index b4bf67022..ed7df5909 100644
--- a/source/Generating/FinishGen.h
+++ b/source/Generating/FinishGen.h
@@ -177,11 +177,7 @@ protected:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
/// Tries to place a spring at the specified coords, checks neighbors. Returns true if successful
- bool TryPlaceSpring(
- cChunkDef::BlockTypes & a_BlockTypes,
- cChunkDef::BlockNibbles & a_BlockMetas,
- int x, int y, int z
- );
+ bool TryPlaceSpring(cChunkDesc & a_ChunkDesc, int x, int y, int z);
} ;
diff --git a/source/Generating/StructGen.cpp b/source/Generating/StructGen.cpp
index 6d139da2a..6c5bf6491 100644
--- a/source/Generating/StructGen.cpp
+++ b/source/Generating/StructGen.cpp
@@ -5,6 +5,7 @@
#include "StructGen.h"
#include "../BlockID.h"
#include "Trees.h"
+#include "../BlockArea.h"
@@ -85,18 +86,11 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
{
int BaseZ = ChunkZ + z - 1;
- cChunkDef::BlockTypes * BlT;
- cChunkDef::BlockNibbles * BlM;
- cChunkDef::HeightMap * Hei;
- cChunkDef::BiomeMap * Bio;
-
+ cChunkDesc * Dest;
if ((x != 1) || (z != 1))
{
- BlT = &(WorkerDesc.GetBlockTypes());
- BlM = &(WorkerDesc.GetBlockMetas());
- Hei = &(WorkerDesc.GetHeightMap());
- Bio = &(WorkerDesc.GetBiomeMap());
+ Dest = &WorkerDesc;
WorkerDesc.SetChunkCoords(BaseX, BaseZ);
m_BiomeGen->GenBiomes (BaseX, BaseZ, WorkerDesc.GetBiomeMap());
@@ -106,26 +100,23 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
}
else
{
- BlT = &(a_ChunkDesc.GetBlockTypes());
- BlM = &(a_ChunkDesc.GetBlockMetas());
- Hei = &(a_ChunkDesc.GetHeightMap());
- Bio = &(a_ChunkDesc.GetBiomeMap());
+ Dest = &a_ChunkDesc;
}
- int NumTrees = GetNumTrees(BaseX, BaseZ, *Bio);
+ int NumTrees = GetNumTrees(BaseX, BaseZ, Dest->GetBiomeMap());
sSetBlockVector OutsideLogs, OutsideOther;
for (int i = 0; i < NumTrees; i++)
{
- GenerateSingleTree(BaseX, BaseZ, i, *BlT, *BlM, *Hei, *Bio, OutsideLogs, OutsideOther);
+ GenerateSingleTree(BaseX, BaseZ, i, *Dest, OutsideLogs, OutsideOther);
}
sSetBlockVector IgnoredOverflow;
IgnoredOverflow.reserve(OutsideOther.size());
- ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetBlockMetas(), OutsideOther, IgnoredOverflow);
+ ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideOther, IgnoredOverflow);
IgnoredOverflow.clear();
IgnoredOverflow.reserve(OutsideLogs.size());
- ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc.GetBlockTypes(), a_ChunkDesc.GetBlockMetas(), OutsideLogs, IgnoredOverflow);
+ ApplyTreeImage(ChunkX, ChunkZ, a_ChunkDesc, OutsideLogs, IgnoredOverflow);
} // for z
} // for x
@@ -136,9 +127,9 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
{
for (int y = cChunkDef::Height - 1; y >= 0; y--)
{
- if (cChunkDef::GetBlock(a_ChunkDesc.GetBlockTypes(), x, y, z) != E_BLOCK_AIR)
+ if (a_ChunkDesc.GetBlockType(x, y, z) != E_BLOCK_AIR)
{
- cChunkDef::SetHeight(a_ChunkDesc.GetHeightMap(), x, z, y);
+ a_ChunkDesc.SetHeight(x, z, y);
break;
}
} // for y
@@ -152,10 +143,7 @@ void cStructGenTrees::GenStructures(cChunkDesc & a_ChunkDesc)
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,
+ cChunkDesc & a_ChunkDesc,
sSetBlockVector & a_OutsideLogs,
sSetBlockVector & a_OutsideOther
)
@@ -163,7 +151,7 @@ void cStructGenTrees::GenerateSingleTree(
int x = (m_Noise.IntNoise3DInt(a_ChunkX + a_ChunkZ, a_ChunkZ, a_Seq) / 19) % cChunkDef::Width;
int z = (m_Noise.IntNoise3DInt(a_ChunkX - a_ChunkZ, a_Seq, a_ChunkZ) / 19) % cChunkDef::Width;
- int Height = cChunkDef::GetHeight(a_Height, x, z);
+ int Height = a_ChunkDesc.GetHeight(x, z);
if ((Height <= 0) || (Height > 240))
{
@@ -171,7 +159,7 @@ void cStructGenTrees::GenerateSingleTree(
}
// Check the block underneath the tree:
- BLOCKTYPE TopBlock = cChunkDef::GetBlock(a_BlockTypes, x, Height, z);
+ BLOCKTYPE TopBlock = a_ChunkDesc.GetBlockType(x, Height, z);
if ((TopBlock != E_BLOCK_DIRT) && (TopBlock != E_BLOCK_GRASS) && (TopBlock != E_BLOCK_FARMLAND))
{
return;
@@ -181,7 +169,7 @@ void cStructGenTrees::GenerateSingleTree(
GetTreeImageByBiome(
a_ChunkX * cChunkDef::Width + x, Height + 1, a_ChunkZ * cChunkDef::Width + z,
m_Noise, a_Seq,
- cChunkDef::GetBiome(a_Biomes, x, z),
+ a_ChunkDesc.GetBiome(x, z),
TreeLogs, TreeOther
);
@@ -194,7 +182,7 @@ void cStructGenTrees::GenerateSingleTree(
continue;
}
- BLOCKTYPE Block = cChunkDef::GetBlock(a_BlockTypes, itr->x, itr->y, itr->z);
+ BLOCKTYPE Block = a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z);
switch (Block)
{
CASE_TREE_ALLOWED_BLOCKS:
@@ -209,8 +197,8 @@ void cStructGenTrees::GenerateSingleTree(
}
}
- ApplyTreeImage(a_ChunkX, a_ChunkZ, a_BlockTypes, a_BlockMetas, TreeOther, a_OutsideOther);
- ApplyTreeImage(a_ChunkX, a_ChunkZ, a_BlockTypes, a_BlockMetas, TreeLogs, a_OutsideLogs);
+ ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeOther, a_OutsideOther);
+ ApplyTreeImage(a_ChunkX, a_ChunkZ, a_ChunkDesc, TreeLogs, a_OutsideLogs);
}
@@ -219,19 +207,18 @@ void cStructGenTrees::GenerateSingleTree(
void cStructGenTrees::ApplyTreeImage(
int a_ChunkX, int a_ChunkZ,
- cChunkDef::BlockTypes & a_BlockTypes,
- cChunkDef::BlockNibbles & a_BlockMetas,
+ cChunkDesc & a_ChunkDesc,
const sSetBlockVector & a_Image,
sSetBlockVector & a_Overflow
)
{
// Put the generated image into a_BlockTypes, push things outside this chunk into a_Blocks
- for (sSetBlockVector::const_iterator itr = a_Image.begin(); itr != a_Image.end(); ++itr)
+ for (sSetBlockVector::const_iterator itr = a_Image.begin(), end = a_Image.end(); itr != 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))
+ // Inside this chunk, integrate into a_ChunkDesc:
+ switch (a_ChunkDesc.GetBlockType(itr->x, itr->y, itr->z))
{
case E_BLOCK_LEAVES:
{
@@ -243,8 +230,7 @@ void cStructGenTrees::ApplyTreeImage(
}
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);
+ a_ChunkDesc.SetBlockTypeMeta(itr->x, itr->y, itr->z, itr->BlockType, itr->BlockMeta);
break;
}
@@ -271,22 +257,22 @@ int cStructGenTrees::GetNumTrees(
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])
+ switch (cChunkDef::GetBiome(a_Biomes, x, 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 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;
+ case biJungleHills: Add = 90; break;
}
NumTrees += Add;
}
@@ -403,3 +389,118 @@ void cStructGenOreNests::GenerateOre(int a_ChunkX, int a_ChunkZ, BLOCKTYPE a_Ore
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cStructGenLakes:
+
+void cStructGenLakes::GenStructures(cChunkDesc & a_ChunkDesc)
+{
+ int ChunkX = a_ChunkDesc.GetChunkX();
+ int ChunkZ = a_ChunkDesc.GetChunkZ();
+
+ for (int z = -1; z < 2; z++) for (int x = -1; x < 2; x++)
+ {
+ cBlockArea Lake;
+ CreateLakeImage(ChunkX + x, ChunkZ + z, Lake);
+
+ int OfsX = Lake.GetOriginX() + x * cChunkDef::Width;
+ int OfsZ = Lake.GetOriginZ() + z * cChunkDef::Width;
+
+ // Merge the lake into the current data
+ a_ChunkDesc.WriteBlockArea(Lake, OfsX, Lake.GetOriginY(), OfsZ, cBlockArea::msLake);
+ } // for x, z - neighbor chunks
+}
+
+
+
+
+
+void cStructGenLakes::CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake)
+{
+ a_Lake.Create(16, 8, 16);
+ a_Lake.Fill(cBlockArea::baTypes, E_BLOCK_SPONGE); // Sponge is the NOP blocktype for lake merging strategy
+
+ // Find the maximum height in this chunk:
+ cChunkDef::HeightMap HeightMap;
+ m_HeiGen.GenHeightMap(a_ChunkX, a_ChunkZ, HeightMap);
+ HEIGHTTYPE MaxHeight = HeightMap[0];
+ for (int i = 1; i < ARRAYCOUNT(HeightMap); i++)
+ {
+ if (HeightMap[i] > MaxHeight)
+ {
+ MaxHeight = HeightMap[i];
+ }
+ }
+
+ // Make a random position in the chunk by using a random 16 block XZ offset and random height up to chunk's max height
+ int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 128, a_ChunkZ) / 11;
+ // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range
+ int OffsetX = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8;
+ Rnd >>= 12;
+ // Random offset [-8 .. 8], with higher probability around 0; add up four three-bit-wide randoms [0 .. 28], divide and subtract to get range
+ int OffsetZ = 4 * ((Rnd & 0x07) + ((Rnd & 0x38) >> 3) + ((Rnd & 0x1c0) >> 6) + ((Rnd & 0xe00) >> 9)) / 7 - 8;
+ Rnd = m_Noise.IntNoise3DInt(a_ChunkX, 512, a_ChunkZ) / 13;
+ // Random height [0 .. MaxHeight] with preference to center heights
+ int HeightY = (((Rnd & 0x1ff) % (MaxHeight + 1)) + (((Rnd >> 9) & 0x1ff) % (MaxHeight + 1))) / 2;
+ a_Lake.SetOrigin(OffsetX, HeightY, OffsetZ);
+
+ // Hollow out a few bubbles inside the blockarea:
+ int NumBubbles = 4 + ((Rnd >> 18) & 0x03); // 4 .. 7 bubbles
+ BLOCKTYPE * BlockTypes = a_Lake.GetBlockTypes();
+ for (int i = 0; i < NumBubbles; i++)
+ {
+ int Rnd = m_Noise.IntNoise3DInt(a_ChunkX, i, a_ChunkZ) / 13;
+ const int BubbleR = 2 + (Rnd & 0x03); // 2 .. 5
+ const int Range = 16 - 2 * BubbleR;
+ const int BubbleX = BubbleR + (Rnd % Range);
+ Rnd >>= 4;
+ const int BubbleY = 4 + (Rnd & 0x01); // 4 .. 5
+ Rnd >>= 1;
+ const int BubbleZ = BubbleR + (Rnd % Range);
+ Rnd >>= 4;
+ const int HalfR = BubbleR / 2; // 1 .. 2
+ const int RSquared = BubbleR * BubbleR;
+ for (int y = -HalfR; y <= HalfR; y++)
+ {
+ // BubbleY + y is in the [0, 7] bounds
+ int DistY = 4 * y * y / 3;
+ int IdxY = (BubbleY + y) * 16 * 16;
+ for (int z = -BubbleR; z <= BubbleR; z++)
+ {
+ int DistYZ = DistY + z * z;
+ if (DistYZ >= RSquared)
+ {
+ continue;
+ }
+ int IdxYZ = BubbleX + IdxY + (BubbleZ + z) * 16;
+ for (int x = -BubbleR; x <= BubbleR; x++)
+ {
+ if (x * x + DistYZ < RSquared)
+ {
+ BlockTypes[x + IdxYZ] = E_BLOCK_AIR;
+ }
+ } // for x
+ } // for z
+ } // for y
+ } // for i - bubbles
+
+ // Turn air in the bottom half into liquid:
+ for (int y = 0; y < 4; y++)
+ {
+ for (int z = 0; z < 16; z++) for (int x = 0; x < 16; x++)
+ {
+ if (BlockTypes[x + z * 16 + y * 16 * 16] == E_BLOCK_AIR)
+ {
+ BlockTypes[x + z * 16 + y * 16 * 16] = m_Fluid;
+ }
+ } // for z, x
+ } // for y
+
+ // TODO: Turn sponge next to lava into stone
+
+ // a_Lake.SaveToSchematicFile(Printf("Lake_%d_%d.schematic", a_ChunkX, a_ChunkZ));
+}
+
+
+
+
diff --git a/source/Generating/StructGen.h b/source/Generating/StructGen.h
index c627499e2..ffb62e327 100644
--- a/source/Generating/StructGen.h
+++ b/source/Generating/StructGen.h
@@ -46,10 +46,7 @@ protected:
*/
void 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,
+ cChunkDesc & a_ChunkDesc,
sSetBlockVector & a_OutsideLogs,
sSetBlockVector & a_OutsideOther
) ;
@@ -57,8 +54,7 @@ protected:
/// Applies an image into chunk blockdata; all blocks outside the chunk will be appended to a_Overflow
void ApplyTreeImage(
int a_ChunkX, int a_ChunkZ,
- cChunkDef::BlockTypes & a_BlockTypes,
- cChunkDef::BlockNibbles & a_BlockMetas,
+ cChunkDesc & a_ChunkDesc,
const sSetBlockVector & a_Image,
sSetBlockVector & a_Overflow
);
@@ -100,15 +96,25 @@ class cStructGenLakes :
public cStructureGen
{
public:
- cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid) : m_Noise(a_Seed), m_Seed(a_Seed), m_Fluid(a_Fluid) {}
+ cStructGenLakes(int a_Seed, BLOCKTYPE a_Fluid, cTerrainHeightGen & a_HeiGen) :
+ m_Noise(a_Seed),
+ m_Seed(a_Seed),
+ m_Fluid(a_Fluid),
+ m_HeiGen(a_HeiGen)
+ {
+ }
protected:
- cNoise m_Noise;
- int m_Seed;
- BLOCKTYPE m_Fluid;
+ cNoise m_Noise;
+ int m_Seed;
+ BLOCKTYPE m_Fluid;
+ cTerrainHeightGen & m_HeiGen;
// cStructureGen override:
virtual void GenStructures(cChunkDesc & a_ChunkDesc) override;
+
+ /// Creates a lake image for the specified chunk into a_Lake
+ void CreateLakeImage(int a_ChunkX, int a_ChunkZ, cBlockArea & a_Lake);
} ;