1
0

Generate cacti and sugarcane with different heights (#4137)

When generating foliage, create cacti with height in the interval [1; MaxCactusHeight] and sugarcane with height in [1; MaxSugarcaneHeight] (with MaxCactusHeight and MaxSugarcaneHeight declared in world.ini)

Fixes #4135
This commit is contained in:
Cocosushi6 2018-05-03 20:25:08 +02:00 committed by peterbell10
parent a4dbb5c582
commit fbf5cf7aa6
4 changed files with 101 additions and 33 deletions

View File

@ -13,6 +13,7 @@ beeduck
bibo38 bibo38
birkett (Anthony Birkett) birkett (Anthony Birkett)
Bond_009 Bond_009
Cocosushi6
derouinw derouinw
Diusrex Diusrex
Duralex Duralex

View File

@ -525,7 +525,9 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
} }
else if (NoCaseCompare(finisher, "SprinkleFoliage") == 0) else if (NoCaseCompare(finisher, "SprinkleFoliage") == 0)
{ {
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSprinkleFoliage(Seed))); int MaxCactusHeight = a_IniFile.GetValueI("Plants", "MaxCactusHeight", 3);
int MaxSugarcaneHeight = a_IniFile.GetValueI("Plants", "MaxSugarcaneHeight", 3);
m_FinishGens.push_back(std::make_shared<cFinishGenSprinkleFoliage>(Seed, MaxCactusHeight, MaxSugarcaneHeight));
} }
else if (NoCaseCompare(finisher, "TallGrass") == 0) else if (NoCaseCompare(finisher, "TallGrass") == 0)
{ {

View File

@ -671,24 +671,66 @@ void cFinishGenVines::GenFinish(cChunkDesc & a_ChunkDesc)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// cFinishGenSprinkleFoliage: // cFinishGenSprinkleFoliage:
bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ) bool cFinishGenSprinkleFoliage::TryAddCactus(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ)
{ {
if (!IsDesertVariant(a_ChunkDesc.GetBiome(a_RelX, a_RelZ)))
{
return false;
}
int CactusHeight = 1 + (m_Noise.IntNoise2DInt(a_RelX, a_RelZ) % m_MaxCactusHeight);
// We'll be doing comparison with blocks above, so the coords should be 1 block away from chunk top
if (a_RelY + CactusHeight >= cChunkDef::Height - 1)
{
CactusHeight = cChunkDef::Height - a_RelY - 1;
}
// We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges: // We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges:
if ( if (
(a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) || (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) ||
(a_RelY < 1) || (a_RelY >= cChunkDef::Height - 2) || (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1)
(a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1)
) )
{ {
return false; return false;
} }
// Only allow dirt, grass or sand below sugarcane: for (int i = 0; i < CactusHeight; i++)
{
const bool cactusExists = i != 0;
const int y = a_RelY + 1;
if (
cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX + 1, y, a_RelZ)) ||
cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX - 1, y, a_RelZ)) ||
cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX, y, a_RelZ + 1)) ||
cBlockInfo::IsSolid(a_ChunkDesc.GetBlockType(a_RelX, y, a_RelZ - 1))
)
{
return cactusExists;
}
// All conditions are met, we can place a cactus here
a_ChunkDesc.SetBlockType(a_RelX, ++a_RelY, a_RelZ, E_BLOCK_CACTUS);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// cFinishGenSprinkleFoliage:
bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ)
{
int SugarcaneHeight = 1 + (m_Noise.IntNoise2DInt(a_RelX, a_RelZ) % m_MaxSugarcaneHeight);
// Only allow dirt, grass, sand and sugarcane below sugarcane:
switch (a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ)) switch (a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ))
{ {
case E_BLOCK_DIRT: case E_BLOCK_DIRT:
case E_BLOCK_GRASS: case E_BLOCK_GRASS:
case E_BLOCK_SAND: case E_BLOCK_SAND:
case E_BLOCK_SUGARCANE:
{ {
break; break;
} }
@ -698,19 +740,39 @@ bool cFinishGenSprinkleFoliage::TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_
} }
} }
// Water is required next to the block below the sugarcane: // We'll be doing comparison with blocks above, so the coords should be 1 block away from chunk top
if (a_RelY + SugarcaneHeight >= cChunkDef::Height - 1)
{
SugarcaneHeight = cChunkDef::Height - a_RelY - 1;
}
// We'll be doing comparison to neighbors, so require the coords to be 1 block away from the chunk edges:
if ( if (
!IsWater(a_ChunkDesc.GetBlockType(a_RelX - 1, a_RelY, a_RelZ)) && (a_RelX < 1) || (a_RelX >= cChunkDef::Width - 1) ||
!IsWater(a_ChunkDesc.GetBlockType(a_RelX + 1, a_RelY, a_RelZ)) && (a_RelZ < 1) || (a_RelZ >= cChunkDef::Width - 1)
!IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ - 1)) &&
!IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ + 1))
) )
{ {
return false; return false;
} }
// All conditions met, place a sugarcane here: // Water is required next to the block below the sugarcane (if the block below isn't sugarcane already)
a_ChunkDesc.SetBlockType(a_RelX, a_RelY + 1, a_RelZ, E_BLOCK_SUGARCANE); if (
!IsWater(a_ChunkDesc.GetBlockType(a_RelX - 1, a_RelY, a_RelZ)) &&
!IsWater(a_ChunkDesc.GetBlockType(a_RelX + 1, a_RelY, a_RelZ)) &&
!IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ - 1)) &&
!IsWater(a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ + 1)) &&
a_ChunkDesc.GetBlockType(a_RelX, a_RelY, a_RelZ) != E_BLOCK_SUGARCANE
)
{
return false;
}
for (int i = 0; i < SugarcaneHeight; i++)
{
// All conditions met, place a sugarcane here
a_ChunkDesc.SetBlockType(a_RelX, ++a_RelY, a_RelZ, E_BLOCK_SUGARCANE);
}
return true; return true;
} }
@ -778,7 +840,7 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
} }
else if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) else if (TryAddSugarcane(a_ChunkDesc, x, Top, z))
{ {
++Top; // Checks and block placing are handled in the TryAddSugarcane method
} }
else if ((val1 > 0.5) && (val2 < -0.5)) else if ((val1 > 0.5) && (val2 < -0.5))
{ {
@ -789,29 +851,22 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
case E_BLOCK_SAND: case E_BLOCK_SAND:
{ {
int y = Top + 1; if (val1 + val2 > 0.5f)
if (
(x > 0) && (x < cChunkDef::Width - 1) &&
(z > 0) && (z < cChunkDef::Width - 1) &&
(val1 + val2 > 0.5f) &&
(a_ChunkDesc.GetBlockType(x + 1, y, z) == E_BLOCK_AIR) &&
(a_ChunkDesc.GetBlockType(x - 1, y, z) == E_BLOCK_AIR) &&
(a_ChunkDesc.GetBlockType(x, y, z + 1) == E_BLOCK_AIR) &&
(a_ChunkDesc.GetBlockType(x, y, z - 1) == E_BLOCK_AIR) &&
IsDesertVariant(a_ChunkDesc.GetBiome(x, z))
)
{ {
a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_CACTUS); if (!TryAddCactus(a_ChunkDesc, x, Top, z))
{
TryAddSugarcane(a_ChunkDesc, x, Top, z);
}
} }
else if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) else
{ {
++Top; TryAddSugarcane(a_ChunkDesc, x, Top, z);
} }
break; break;
} }
} // switch (TopBlock) } // switch (TopBlock)
a_ChunkDesc.SetHeight(x, z, Top); a_ChunkDesc.SetHeight(x, z, Top);
} // for y } // for x
} // for z } // for z
} }

View File

@ -260,14 +260,24 @@ class cFinishGenSprinkleFoliage :
public cFinishGen public cFinishGen
{ {
public: public:
cFinishGenSprinkleFoliage(int a_Seed) : m_Noise(a_Seed), m_Seed(a_Seed) {} cFinishGenSprinkleFoliage(int a_Seed, int a_MaxCactusHeight, int a_MaxSugarcaneHeight):
m_Noise(a_Seed),
m_Seed(a_Seed),
m_MaxCactusHeight(a_MaxCactusHeight),
m_MaxSugarcaneHeight(a_MaxSugarcaneHeight)
{
}
protected: protected:
cNoise m_Noise; cNoise m_Noise;
int m_Seed; int m_Seed;
int m_MaxCactusHeight;
int m_MaxSugarcaneHeight;
/** Tries to place sugarcane at the coords specified, returns true if successful */ /** Tries to place sugarcane at the coords specified, returns true if successful, updates the top variable (hence the & a_RefY) */
bool TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelY, int a_RelZ); bool TryAddSugarcane(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ);
/** Tries to place cactus at the coords specified, returns true if successful, updates the top variable (hence the & a_RefY) */
bool TryAddCactus(cChunkDesc & a_ChunkDesc, int a_RelX, HEIGHTTYPE & a_RelY, int a_RelZ);
// Returns true is the specified biome is a desert or its variant // Returns true is the specified biome is a desert or its variant
static bool IsDesertVariant(EMCSBiome a_biome); static bool IsDesertVariant(EMCSBiome a_biome);