Implemented OverworldClumpFlowers
This commit is contained in:
parent
503a79f19a
commit
ab6e8b790c
@ -438,6 +438,11 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
|
||||
m_FinishGens.push_back(gen);
|
||||
}
|
||||
}
|
||||
else if (NoCaseCompare(finisher, "OverworldClumpFlowers") == 0)
|
||||
{
|
||||
auto flowers = cFinishGenClumpTopBlock::ParseIniFile(a_IniFile, "OverworldClumpFlowers");
|
||||
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenClumpTopBlock(Seed, flowers)));
|
||||
}
|
||||
else if (NoCaseCompare(finisher, "PieceStructures") == 0)
|
||||
{
|
||||
if (split.size() < 2)
|
||||
|
@ -179,6 +179,210 @@ void cFinishGenNetherClumpFoliage::TryPlaceClump(cChunkDesc & a_ChunkDesc, int a
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cFinishGenClumpTopBlock
|
||||
|
||||
void cFinishGenClumpTopBlock::GenFinish(cChunkDesc & a_ChunkDesc)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
|
||||
int NoiseVal = m_Noise.IntNoise2DInt(ChunkX, ChunkZ);
|
||||
EMCSBiome Biome = a_ChunkDesc.GetBiome(cChunkDef::Width / 2, cChunkDef::Width / 2);
|
||||
BiomeInfo info = m_FlowersPerBiome[static_cast<size_t>(Biome)];
|
||||
|
||||
const auto & PossibleBlocks = info.m_Blocks;
|
||||
if (PossibleBlocks.empty())
|
||||
{
|
||||
// No need to go any further. This biome can't generate any blocks.
|
||||
return;
|
||||
}
|
||||
|
||||
int NumClumps = info.m_MaxNumClumpsPerChunk - info.m_MinNumClumpsPerChunk;
|
||||
if (NumClumps == 0)
|
||||
{
|
||||
NumClumps = 1;
|
||||
}
|
||||
|
||||
NumClumps = NoiseVal % NumClumps + info.m_MinNumClumpsPerChunk;
|
||||
for (int i = 0; i < NumClumps; i++)
|
||||
{
|
||||
int Val1 = m_Noise.IntNoise2DInt(ChunkX * ChunkZ * i, ChunkZ + ChunkX + i);
|
||||
int Val2 = m_Noise.IntNoise2DInt(ChunkZ * ChunkX + i, ChunkZ - ChunkX * i);
|
||||
int BlockVal = m_Noise.IntNoise2DInt(Val1, Val2);
|
||||
|
||||
int PosX = Val1 % (cChunkDef::Width - RANGE_FROM_CENTER * 2) + RANGE_FROM_CENTER;
|
||||
int PosZ = Val2 % (cChunkDef::Width - RANGE_FROM_CENTER * 2) + RANGE_FROM_CENTER;
|
||||
|
||||
int TotalWeight = 0;
|
||||
for (const auto & Block : PossibleBlocks)
|
||||
{
|
||||
TotalWeight += Block.m_Weight;
|
||||
}
|
||||
|
||||
// Prevent division by 0
|
||||
TotalWeight = (TotalWeight != 0) ? TotalWeight : 1;
|
||||
int Weight = BlockVal % TotalWeight;
|
||||
for (const auto & Block : PossibleBlocks)
|
||||
{
|
||||
Weight -= Block.m_Weight;
|
||||
if (Weight < 0)
|
||||
{
|
||||
TryPlaceFoliageClump(a_ChunkDesc, PosX, PosZ, Block.m_BlockType, Block.m_BlockMeta, Block.m_BlockType == E_BLOCK_BIG_FLOWER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cFinishGenClumpTopBlock::TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int a_CenterX, int a_CenterZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_IsDoubleTall)
|
||||
{
|
||||
int ChunkX = a_ChunkDesc.GetChunkX();
|
||||
int ChunkZ = a_ChunkDesc.GetChunkZ();
|
||||
|
||||
int NumBlocks = m_Noise.IntNoise2DInt(a_CenterX + ChunkX * 16, a_CenterZ + ChunkZ * 16) % (MAX_NUM_FOLIAGE - MIN_NUM_FOLIAGE) + MIN_NUM_FOLIAGE + 1;
|
||||
for (int i = 1; i < NumBlocks; i++)
|
||||
{
|
||||
int rnd = m_Noise.IntNoise2DInt(ChunkX + ChunkZ + i, ChunkX - ChunkZ - i) / 59;
|
||||
int x = a_CenterX + (((rnd % 256) % RANGE_FROM_CENTER * 2) - RANGE_FROM_CENTER);
|
||||
int z = a_CenterZ + (((rnd / 256) % RANGE_FROM_CENTER * 2) - RANGE_FROM_CENTER);
|
||||
int Top = a_ChunkDesc.GetHeight(x, z);
|
||||
|
||||
if (a_ChunkDesc.GetBlockType(x, Top, z) != E_BLOCK_GRASS)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
a_ChunkDesc.SetBlockTypeMeta(x, Top + 1, z, a_BlockType, a_BlockMeta);
|
||||
if (a_IsDoubleTall)
|
||||
{
|
||||
a_ChunkDesc.SetBlockTypeMeta(x, Top + 2, z, E_BLOCK_BIG_FLOWER, 8);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cFinishGenClumpTopBlock::ParseConfigurationString(AString a_RawClumpInfo, std::vector<BiomeInfo> & a_Output)
|
||||
{
|
||||
// Initialize the vector for all biomes.
|
||||
for (int i = static_cast<int>(a_Output.size()); i < static_cast<int>(biMaxVariantBiome); i++)
|
||||
{
|
||||
a_Output.push_back(BiomeInfo());
|
||||
}
|
||||
|
||||
AStringVector ClumpInfo = StringSplitAndTrim(a_RawClumpInfo, "=");
|
||||
|
||||
// Information about a clump is divided in 2 parts. The biomes they can be in and the blocks that can be placed.
|
||||
if (ClumpInfo.size() != 2)
|
||||
{
|
||||
LOGWARNING("OverworldClumpFoliage: Data missing for \"%s\". Please divide biome and blocks with a semi colon", a_RawClumpInfo.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
AStringVector Biomes = StringSplitAndTrim(ClumpInfo[0], ";");
|
||||
AStringVector Blocks = StringSplitAndTrim(ClumpInfo[1], ";");
|
||||
|
||||
for (const auto & RawBiomeInfo : Biomes)
|
||||
{
|
||||
AStringVector BiomeInfo = StringSplitAndTrim(RawBiomeInfo, ",");
|
||||
AString BiomeName = BiomeInfo[0];
|
||||
EMCSBiome Biome = StringToBiome(BiomeName);
|
||||
if (Biome == biInvalidBiome)
|
||||
{
|
||||
LOGWARNING("Biome \"%s\" is invalid.", BiomeName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (BiomeInfo.size() == 2)
|
||||
{
|
||||
// Only the minimum amount of clumps per chunk is changed.
|
||||
int MinNumClump = 1;
|
||||
if (!StringToInteger(BiomeInfo[1], MinNumClump))
|
||||
{
|
||||
LOGWARNING("OverworldClumpFoliage: Invalid data in \"%s\". Second parameter is either not existing or a number", RawBiomeInfo.c_str());
|
||||
continue;
|
||||
}
|
||||
a_Output[static_cast<size_t>(Biome)].m_MinNumClumpsPerChunk = MinNumClump;
|
||||
|
||||
// In case the minimum number is higher than the current maximum value we change the max to the minimum value.
|
||||
a_Output[static_cast<size_t>(Biome)].m_MaxNumClumpsPerChunk = std::max(MinNumClump, a_Output[static_cast<size_t>(Biome)].m_MaxNumClumpsPerChunk);
|
||||
}
|
||||
else if (BiomeInfo.size() == 3)
|
||||
{
|
||||
// Both the minimum and maximum amount of clumps per chunk is changed.
|
||||
int MinNumClumps = 0, MaxNumClumps = 1;
|
||||
if (!StringToInteger(BiomeInfo[1], MinNumClumps) || !StringToInteger(BiomeInfo[2], MaxNumClumps))
|
||||
{
|
||||
LOGWARNING("Invalid data in \"%s\". Second parameter is either not existing or a number", RawBiomeInfo.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
a_Output[static_cast<size_t>(Biome)].m_MaxNumClumpsPerChunk = MaxNumClumps + 1;
|
||||
a_Output[static_cast<size_t>(Biome)].m_MinNumClumpsPerChunk = MinNumClumps;
|
||||
}
|
||||
|
||||
// TODO: Make the weight configurable.
|
||||
for (const auto & BlockName : Blocks)
|
||||
{
|
||||
cItem Block = cItem();
|
||||
if (!StringToItem(BlockName, Block) && IsValidBlock(Block.m_ItemType))
|
||||
{
|
||||
LOGWARNING("Block \"%s\" is invalid", BlockName.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
FoliageInfo info = FoliageInfo(static_cast<BLOCKTYPE>(Block.m_ItemType), static_cast<NIBBLETYPE>(Block.m_ItemDamage), 100);
|
||||
a_Output[static_cast<size_t>(Biome)].m_Blocks.push_back(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<cFinishGenClumpTopBlock::BiomeInfo> cFinishGenClumpTopBlock::ParseIniFile(cIniFile & a_IniFile, AString a_ClumpPrefix)
|
||||
{
|
||||
// Also check dashes in case we will get more configuration options with the same prefix.
|
||||
a_ClumpPrefix += "-";
|
||||
|
||||
std::vector<cFinishGenClumpTopBlock::BiomeInfo> foliage;
|
||||
int NumGeneratorValues = a_IniFile.GetNumValues("Generator");
|
||||
int GeneratorKeyId = a_IniFile.FindKey("Generator");
|
||||
for (int i = 0; i < NumGeneratorValues; i++)
|
||||
{
|
||||
AString ValueName = a_IniFile.GetValueName("Generator", i);
|
||||
if (ValueName.substr(0, a_ClumpPrefix.size()) == a_ClumpPrefix)
|
||||
{
|
||||
AString RawClump = a_IniFile.GetValue(GeneratorKeyId, i);
|
||||
cFinishGenClumpTopBlock::ParseConfigurationString(RawClump, foliage);
|
||||
}
|
||||
}
|
||||
|
||||
if (foliage.size() == 0)
|
||||
{
|
||||
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-1", "Forest, -2, 2; ForestHills, -3, 2; FlowerForest = yellowflower, redflower, lilac, rosebush"), foliage);
|
||||
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-2", "Plains, -2, 1; SunflowerPlains = yellowflower, redflower, azurebluet, oxeyedaisy"), foliage);
|
||||
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-3", "SunflowerPlains, 1, 2 = sunflower"), foliage);
|
||||
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-4", "FlowerForest, 2, 5 = allium, redtulip, orangetulip, whitetulip, pinktulip, oxeyedaisy"), foliage);
|
||||
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-5", "Swampland, SwamplandM = brownmushroom, redmushroom, blueorchid"), foliage);
|
||||
}
|
||||
|
||||
return foliage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cFinishGenGlowStone:
|
||||
|
||||
|
@ -70,6 +70,80 @@ protected:
|
||||
|
||||
|
||||
|
||||
class cFinishGenClumpTopBlock :
|
||||
public cFinishGen
|
||||
{
|
||||
public:
|
||||
// Contains the meta, type and weight for a clump block
|
||||
struct FoliageInfo
|
||||
{
|
||||
BLOCKTYPE m_BlockType;
|
||||
NIBBLETYPE m_BlockMeta;
|
||||
int m_Weight;
|
||||
|
||||
FoliageInfo(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, int a_Weight) :
|
||||
m_BlockType(a_BlockType),
|
||||
m_BlockMeta(a_BlockMeta),
|
||||
m_Weight(a_Weight)
|
||||
{}
|
||||
};
|
||||
|
||||
// Contains the minimum and maximum amount of clumps for a biome and it's blocks.
|
||||
struct BiomeInfo
|
||||
{
|
||||
int m_MinNumClumpsPerChunk;
|
||||
int m_MaxNumClumpsPerChunk;
|
||||
std::vector<FoliageInfo> m_Blocks;
|
||||
|
||||
BiomeInfo() :
|
||||
m_MinNumClumpsPerChunk(0),
|
||||
m_MaxNumClumpsPerChunk(2),
|
||||
m_Blocks()
|
||||
{}
|
||||
|
||||
BiomeInfo(int a_MinNumClumpsPerChunk, int a_MaxNumClumpsPerChunk, std::vector<FoliageInfo> a_Blocks) :
|
||||
m_MinNumClumpsPerChunk(a_MinNumClumpsPerChunk),
|
||||
m_MaxNumClumpsPerChunk(a_MaxNumClumpsPerChunk),
|
||||
m_Blocks(a_Blocks)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
cFinishGenClumpTopBlock(int a_Seed, std::vector<BiomeInfo> a_BlockList) :
|
||||
m_Noise(a_Seed),
|
||||
m_FlowersPerBiome()
|
||||
{
|
||||
std::swap(a_BlockList, m_FlowersPerBiome);
|
||||
}
|
||||
|
||||
/** Parses a string and puts a vector with a length of biMaxVariantBiome in a_Output.
|
||||
The format of the string is "<Biomes separated with a comma>;<Blocks separated with a comma>". This can also be repeated with a | */
|
||||
static void ParseConfigurationString(AString a_String, std::vector<BiomeInfo> & a_Output);
|
||||
|
||||
/** Parses an inifile in search for all clumps */
|
||||
static std::vector<BiomeInfo> ParseIniFile(cIniFile & a_IniFile, AString a_ClumpPrefix);
|
||||
protected:
|
||||
|
||||
cNoise m_Noise;
|
||||
std::vector<BiomeInfo> m_FlowersPerBiome;
|
||||
|
||||
/** The maximum number of foliage per clump */
|
||||
const int MAX_NUM_FOLIAGE = 8;
|
||||
|
||||
/** The mininum number of foliage per clump */
|
||||
const int MIN_NUM_FOLIAGE = 4;
|
||||
|
||||
/** The maximum range a foliage can be placed from the center of the clump */
|
||||
const int RANGE_FROM_CENTER = 5;
|
||||
|
||||
void TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int a_RelX, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, bool a_IsDoubleTall);
|
||||
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class cFinishGenGlowStone :
|
||||
public cFinishGen
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user