1
0
Fork 0

Fix flower and foliage generation (#4723)

* fix flower generation
- remove wrong mushroom and flower generation
+ add "tiny" mushrooms in Mushrooms biomes
+ add "tiny" mushrooms in Mega Taiga and variants
+ add tulip generation for plains biomes
* Turn numbers into constants
- Remove duplication of grass generation
- Remove fern in inappropriate biomes
* added roofed forest flowers to ini file
* fixed crash with biMesaPlateuM
+ Use empty()
+ Emplace directly
+ Avoid a string copy in BiomeName
+ Alias BiomeIndex to avoid multiple casts

Co-authored-by: 12xx12 <12xx12100@gmail.com>
Co-authored-by: Tiger Wang <ziwei.tiger@outlook.com>
This commit is contained in:
mBornand 2020-11-14 13:24:31 +01:00 committed by GitHub
parent 283b9d706c
commit 58def8f7df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 162 additions and 100 deletions

View File

@ -228,7 +228,8 @@ void cComposableGenerator::InitializeGeneratorDefaults(cIniFile & a_IniFile, eDi
"DeadBushes, " "DeadBushes, "
"NaturalPatches, " "NaturalPatches, "
"PreSimulator, " "PreSimulator, "
"Animals" "Animals, "
"OverworldClumpFlowers"
); );
break; break;
} // dimOverworld } // dimOverworld

View File

@ -247,25 +247,34 @@ void cFinishGenClumpTopBlock::TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int
int NumBlocks = m_Noise.IntNoise2DInt(a_CenterX + ChunkX * 16, a_CenterZ + ChunkZ * 16) % (MAX_NUM_FOLIAGE - MIN_NUM_FOLIAGE) + MIN_NUM_FOLIAGE + 1; 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++) for (int i = 1; i < NumBlocks; i++)
{ {
int rnd = m_Noise.IntNoise2DInt(ChunkX + ChunkZ + i, ChunkX - ChunkZ - i) / 59; 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 x = a_CenterX + (((Rnd % 59) % RANGE_FROM_CENTER * 2) - RANGE_FROM_CENTER);
int z = a_CenterZ + (((rnd / 256) % RANGE_FROM_CENTER * 2) - RANGE_FROM_CENTER); int z = a_CenterZ + (((Rnd / 97) % RANGE_FROM_CENTER * 2) - RANGE_FROM_CENTER);
int Top = a_ChunkDesc.GetHeight(x, z); int Top = a_ChunkDesc.GetHeight(x, z);
if (a_ChunkDesc.GetBlockType(x, Top, z) != E_BLOCK_GRASS) // Doesn't place if the blocks can't be placed. Checked value also depends on a_IsDoubleTall
if (Top + 1 + (a_IsDoubleTall ? 1 : 0) >= cChunkDef::Height)
{ {
continue; continue;
} }
a_ChunkDesc.SetBlockTypeMeta(x, Top + 1, z, a_BlockType, a_BlockMeta); auto GroundBlockType = a_ChunkDesc.GetBlockType(x, Top, z);
if (a_IsDoubleTall) if (
(GroundBlockType == E_BLOCK_GRASS) || (
(GroundBlockType == E_BLOCK_MYCELIUM) && ((a_BlockType == E_BLOCK_RED_MUSHROOM) || (a_BlockType == E_BLOCK_BROWN_MUSHROOM))
)
)
{ {
a_ChunkDesc.SetBlockTypeMeta(x, Top + 2, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP); a_ChunkDesc.SetBlockTypeMeta(x, Top + 1, z, a_BlockType, a_BlockMeta);
a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(Top + 2)); if (a_IsDoubleTall)
} {
else a_ChunkDesc.SetBlockTypeMeta(x, Top + 2, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
{ a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(Top + 2));
a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(Top + 1)); }
else
{
a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(Top + 1));
}
} }
} }
@ -278,9 +287,10 @@ void cFinishGenClumpTopBlock::TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int
void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClumpInfo, std::vector<BiomeInfo> & a_Output) void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClumpInfo, std::vector<BiomeInfo> & a_Output)
{ {
// Initialize the vector for all biomes. // Initialize the vector for all biomes.
for (int i = static_cast<int>(a_Output.size()); i < static_cast<int>(biMaxVariantBiome); i++) for (int i = static_cast<int>(a_Output.size()); i <= static_cast<int>(biMaxVariantBiome); i++)
{ {
a_Output.push_back(BiomeInfo()); // Push empty BiomeInfo structure to be later directly accessed by index:
a_Output.emplace_back();
} }
AStringVector ClumpInfo = StringSplitAndTrim(a_RawClumpInfo, "="); AStringVector ClumpInfo = StringSplitAndTrim(a_RawClumpInfo, "=");
@ -297,15 +307,18 @@ void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClum
for (const auto & RawBiomeInfo : Biomes) for (const auto & RawBiomeInfo : Biomes)
{ {
AStringVector BiomeInfo = StringSplitAndTrim(RawBiomeInfo, ","); const AStringVector BiomeInfo = StringSplitAndTrim(RawBiomeInfo, ",");
AString BiomeName = BiomeInfo[0]; const AString & BiomeName = BiomeInfo[0];
EMCSBiome Biome = StringToBiome(BiomeName); const EMCSBiome Biome = StringToBiome(BiomeName);
if (Biome == biInvalidBiome) if (Biome == biInvalidBiome)
{ {
LOGWARNING("Biome \"%s\" is invalid.", BiomeName.c_str()); LOGWARNING("Biome \"%s\" is invalid.", BiomeName.c_str());
continue; continue;
} }
// The index of Biome in the output vector.
const size_t BiomeIndex = static_cast<size_t>(Biome);
if (BiomeInfo.size() == 2) if (BiomeInfo.size() == 2)
{ {
// Only the minimum amount of clumps per chunk is changed. // Only the minimum amount of clumps per chunk is changed.
@ -315,10 +328,10 @@ void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClum
LOGWARNING("OverworldClumpFoliage: Invalid data in \"%s\". Second parameter is either not existing or a number", RawBiomeInfo.c_str()); LOGWARNING("OverworldClumpFoliage: Invalid data in \"%s\". Second parameter is either not existing or a number", RawBiomeInfo.c_str());
continue; continue;
} }
a_Output[static_cast<size_t>(Biome)].m_MinNumClumpsPerChunk = MinNumClump; a_Output[BiomeIndex].m_MinNumClumpsPerChunk = MinNumClump;
// In case the minimum number is higher than the current maximum value we change the max to the minimum value. // 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); a_Output[BiomeIndex].m_MaxNumClumpsPerChunk = std::max(MinNumClump, a_Output[BiomeIndex].m_MaxNumClumpsPerChunk);
} }
else if (BiomeInfo.size() == 3) else if (BiomeInfo.size() == 3)
{ {
@ -330,22 +343,24 @@ void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClum
continue; continue;
} }
a_Output[static_cast<size_t>(Biome)].m_MaxNumClumpsPerChunk = MaxNumClumps + 1; a_Output[BiomeIndex].m_MaxNumClumpsPerChunk = MaxNumClumps + 1;
a_Output[static_cast<size_t>(Biome)].m_MinNumClumpsPerChunk = MinNumClumps; a_Output[BiomeIndex].m_MinNumClumpsPerChunk = MinNumClumps;
} }
// TODO: Make the weight configurable. // TODO: Make the weight configurable.
for (const auto & BlockName : Blocks) for (const auto & BlockName : Blocks)
{ {
cItem Block = cItem(); cItem Block;
if (!StringToItem(BlockName, Block) && IsValidBlock(Block.m_ItemType)) if (!StringToItem(BlockName, Block) || !IsValidBlock(Block.m_ItemType))
{ {
LOGWARNING("Block \"%s\" is invalid", BlockName.c_str()); LOGWARNING("Block \"%s\" is invalid", BlockName.c_str());
continue; continue;
} }
FoliageInfo info = FoliageInfo(static_cast<BLOCKTYPE>(Block.m_ItemType), static_cast<NIBBLETYPE>(Block.m_ItemDamage), 100); // Construct the FoliageInfo:
a_Output[static_cast<size_t>(Biome)].m_Blocks.push_back(info); a_Output[BiomeIndex].m_Blocks.emplace_back(
static_cast<BLOCKTYPE>(Block.m_ItemType), static_cast<NIBBLETYPE>(Block.m_ItemDamage), 100
);
} }
} }
} }
@ -354,12 +369,9 @@ void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClum
std::vector<cFinishGenClumpTopBlock::BiomeInfo> cFinishGenClumpTopBlock::ParseIniFile(cIniFile & a_IniFile, AString a_ClumpPrefix) std::vector<cFinishGenClumpTopBlock::BiomeInfo> cFinishGenClumpTopBlock::ParseIniFile(cIniFile & a_IniFile, const AString & a_ClumpPrefix)
{ {
// Also check dashes in case we will get more configuration options with the same prefix. std::vector<cFinishGenClumpTopBlock::BiomeInfo> Foliage;
a_ClumpPrefix += "-";
std::vector<cFinishGenClumpTopBlock::BiomeInfo> foliage;
int NumGeneratorValues = a_IniFile.GetNumValues("Generator"); int NumGeneratorValues = a_IniFile.GetNumValues("Generator");
int GeneratorKeyId = a_IniFile.FindKey("Generator"); int GeneratorKeyId = a_IniFile.FindKey("Generator");
for (int i = 0; i < NumGeneratorValues; i++) for (int i = 0; i < NumGeneratorValues; i++)
@ -368,20 +380,22 @@ std::vector<cFinishGenClumpTopBlock::BiomeInfo> cFinishGenClumpTopBlock::ParseIn
if (ValueName.substr(0, a_ClumpPrefix.size()) == a_ClumpPrefix) if (ValueName.substr(0, a_ClumpPrefix.size()) == a_ClumpPrefix)
{ {
AString RawClump = a_IniFile.GetValue(GeneratorKeyId, i); AString RawClump = a_IniFile.GetValue(GeneratorKeyId, i);
cFinishGenClumpTopBlock::ParseConfigurationString(RawClump, foliage); cFinishGenClumpTopBlock::ParseConfigurationString(RawClump, Foliage);
} }
} }
if (foliage.size() == 0) if (Foliage.empty())
{ {
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 + "-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 + "-2", "Plains, -2, 1; SunflowerPlains = yellowflower; redflower; azurebluet; redtulip; orangetulip; whitetulip; pinktulip; oxeyedaisy"), Foliage);
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-3", "SunflowerPlains, 1, 2 = sunflower"), 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 + "-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); cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-5", "Swampland; SwamplandM = brownmushroom; redmushroom; blueorchid"), Foliage);
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-6", "MushroomIsland; MushroomShore; MegaTaiga; MegaTaigaHills; MegaSpruceTaiga; MegaSpruceTaigaHills = brownmushroom; redmushroom"), Foliage);
cFinishGenClumpTopBlock::ParseConfigurationString(a_IniFile.GetValueSet("Generator", a_ClumpPrefix + "-7", "RoofedForest, 1, 5; RoofedForestM, 1, 5 = rosebush; peony; lilac; grass"), Foliage);
} }
return foliage; return Foliage;
} }
@ -541,21 +555,26 @@ void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc)
int GrassType = m_Noise.IntNoise2DInt(xx * 50, zz * 50) / 7 % 100; int GrassType = m_Noise.IntNoise2DInt(xx * 50, zz * 50) / 7 % 100;
if (GrassType < 60) if (GrassType < 60)
{ {
a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, 1); a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, E_META_TALL_GRASS_GRASS);
} }
else if (GrassType < 90) else if ((GrassType < 90) && CanFernGrow(a_ChunkDesc.GetBiome(x, z)))
{ {
a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, 2); a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_TALL_GRASS, E_META_TALL_GRASS_FERN);
} }
else if (!IsBiomeVeryCold(a_ChunkDesc.GetBiome(x, z))) else if (!IsBiomeVeryCold(a_ChunkDesc.GetBiome(x, z)))
{ {
// If double long grass we have to choose what type we should use: // If double long grass we have to choose what type we should use:
if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR) if (a_ChunkDesc.GetBlockType(x, y + 1, z) == E_BLOCK_AIR)
{ {
NIBBLETYPE Meta = (m_Noise.IntNoise2DInt(xx * 100, zz * 100) / 7 % 100) > 25 ? 2 : 3; NIBBLETYPE Meta = (m_Noise.IntNoise2DInt(xx * 100, zz * 100) / 7 % 100) > 25 ?
a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_BIG_FLOWER, Meta); E_META_BIG_FLOWER_DOUBLE_TALL_GRASS : E_META_BIG_FLOWER_LARGE_FERN;
a_ChunkDesc.SetBlockTypeMeta(x, y + 1, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(y + 1)); if ((Meta != E_META_BIG_FLOWER_LARGE_FERN) || CanLargeFernGrow(a_ChunkDesc.GetBiome(x, z)))
{
a_ChunkDesc.SetBlockTypeMeta(x, y, z, E_BLOCK_BIG_FLOWER, Meta);
a_ChunkDesc.SetBlockTypeMeta(x, y + 1, z, E_BLOCK_BIG_FLOWER, E_META_BIG_FLOWER_TOP);
a_ChunkDesc.SetHeight(x, z, static_cast<HEIGHTTYPE>(y + 1));
}
} }
} }
else else
@ -572,6 +591,95 @@ void cFinishGenTallGrass::GenFinish(cChunkDesc & a_ChunkDesc)
bool cFinishGenTallGrass::CanFernGrow(EMCSBiome a_Biome)
{
switch (a_Biome)
{
case biJungle:
case biJungleEdge:
case biJungleEdgeM:
case biJungleHills:
case biJungleM:
{
return true;
}
default:
{
return CanLargeFernGrow(a_Biome);
}
}
}
bool cFinishGenTallGrass::CanLargeFernGrow(EMCSBiome a_Biome)
{
switch (a_Biome)
{
case biColdTaiga:
case biColdTaigaHills:
case biColdTaigaM:
case biTaiga:
case biTaigaHills:
case biTaigaM:
case biMegaSpruceTaiga:
case biMegaSpruceTaigaHills:
case biMegaTaiga:
case biMegaTaigaHills:
{
return true;
}
default:
{
return false;
}
}
}
int cFinishGenTallGrass::GetBiomeDensity(EMCSBiome a_Biome)
{
switch (a_Biome)
{
case biSavanna:
case biSavannaM:
case biSavannaPlateau:
case biSavannaPlateauM:
case biPlains:
{
return 70;
}
case biExtremeHillsEdge:
case biExtremeHillsPlus:
case biExtremeHills:
case biExtremeHillsPlusM:
case biExtremeHillsM:
case biIceMountains:
{
return 3;
}
default:
{
return 20;
}
}
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// cFinishGenVines // cFinishGenVines
@ -816,34 +924,13 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc)
{ {
case E_BLOCK_GRASS: case E_BLOCK_GRASS:
{ {
float val3 = m_Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10); if (TryAddSugarcane(a_ChunkDesc, x, Top, z))
float val4 = m_Noise.CubicNoise2D(xx * 0.05f + 20, zz * 0.05f + 20);
if (val1 + val2 > 0.2f)
{
a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_YELLOW_FLOWER);
}
else if (val2 + val3 > 0.2f)
{
a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_RED_ROSE);
}
else if (val3 + val4 > 0.2f)
{
a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_RED_MUSHROOM);
}
else if (val1 + val4 > 0.2f)
{
a_ChunkDesc.SetBlockType(x, ++Top, z, E_BLOCK_BROWN_MUSHROOM);
}
else if (val1 + val2 + val3 + val4 < -0.1)
{
a_ChunkDesc.SetBlockTypeMeta(x, ++Top, z, E_BLOCK_TALL_GRASS, E_META_TALL_GRASS_GRASS);
}
else if (TryAddSugarcane(a_ChunkDesc, x, Top, z))
{ {
// Checks and block placing are handled in the TryAddSugarcane method // 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))
{ {
float val3 = m_Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10);
a_ChunkDesc.SetBlockTypeMeta(x, ++Top, z, E_BLOCK_PUMPKIN, static_cast<int>(val3 * 8) % 4); a_ChunkDesc.SetBlockTypeMeta(x, ++Top, z, E_BLOCK_PUMPKIN, static_cast<int>(val3 * 8) % 4);
} }
break; break;

View File

@ -123,7 +123,7 @@ public:
static void ParseConfigurationString(const AString & a_String, std::vector<BiomeInfo> & a_Output); static void ParseConfigurationString(const AString & a_String, std::vector<BiomeInfo> & a_Output);
/** Parses an inifile in search for all clumps */ /** Parses an inifile in search for all clumps */
static std::vector<BiomeInfo> ParseIniFile(cIniFile & a_IniFile, AString a_ClumpPrefix); static std::vector<BiomeInfo> ParseIniFile(cIniFile & a_IniFile, const AString & a_ClumpPrefix);
protected: protected:
cNoise m_Noise; cNoise m_Noise;
@ -132,7 +132,7 @@ protected:
/** The maximum number of foliage per clump */ /** The maximum number of foliage per clump */
const int MAX_NUM_FOLIAGE = 8; const int MAX_NUM_FOLIAGE = 8;
/** The mininum number of foliage per clump */ /** The minimum number of foliage per clump */
const int MIN_NUM_FOLIAGE = 4; const int MIN_NUM_FOLIAGE = 4;
/** The maximum range a foliage can be placed from the center of the clump */ /** The maximum range a foliage can be placed from the center of the clump */
@ -181,35 +181,9 @@ protected:
// cFinishGen override: // cFinishGen override:
virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
int GetBiomeDensity(EMCSBiome a_Biome) static bool CanFernGrow(EMCSBiome a_Biome);
{ static bool CanLargeFernGrow(EMCSBiome a_Biome);
switch (a_Biome) static int GetBiomeDensity(EMCSBiome a_Biome);
{
case biSavanna:
case biSavannaM:
case biSavannaPlateau:
case biSavannaPlateauM:
case biPlains:
{
return 70;
}
case biExtremeHillsEdge:
case biExtremeHillsPlus:
case biExtremeHills:
case biExtremeHillsPlusM:
case biExtremeHillsM:
case biIceMountains:
{
return 3;
}
default:
{
return 20;
}
}
}
}; };

0
src/WorldStorage/WSSAnvil.cpp Executable file → Normal file
View File