From 58def8f7df8a01fe5a194cad9f47f1c96033c687 Mon Sep 17 00:00:00 2001 From: mBornand <63592189+mBornand@users.noreply.github.com> Date: Sat, 14 Nov 2020 13:24:31 +0100 Subject: [PATCH] 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 --- src/Generating/ComposableGenerator.cpp | 3 +- src/Generating/FinishGen.cpp | 223 +++++++++++++++++-------- src/Generating/FinishGen.h | 36 +--- src/WorldStorage/WSSAnvil.cpp | 0 4 files changed, 162 insertions(+), 100 deletions(-) mode change 100755 => 100644 src/WorldStorage/WSSAnvil.cpp diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 7c891f5fa..8b7d998d0 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -228,7 +228,8 @@ void cComposableGenerator::InitializeGeneratorDefaults(cIniFile & a_IniFile, eDi "DeadBushes, " "NaturalPatches, " "PreSimulator, " - "Animals" + "Animals, " + "OverworldClumpFlowers" ); break; } // dimOverworld diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 78b28bff5..5f8099922 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -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; 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 Rnd = m_Noise.IntNoise2DInt(ChunkX + ChunkZ + i, ChunkX - ChunkZ - i) / 59; + int x = a_CenterX + (((Rnd % 59) % 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); - 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; } - a_ChunkDesc.SetBlockTypeMeta(x, Top + 1, z, a_BlockType, a_BlockMeta); - if (a_IsDoubleTall) + auto GroundBlockType = a_ChunkDesc.GetBlockType(x, Top, z); + 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.SetHeight(x, z, static_cast(Top + 2)); - } - else - { - a_ChunkDesc.SetHeight(x, z, static_cast(Top + 1)); + 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, E_META_BIG_FLOWER_TOP); + a_ChunkDesc.SetHeight(x, z, static_cast(Top + 2)); + } + else + { + a_ChunkDesc.SetHeight(x, z, static_cast(Top + 1)); + } } } @@ -278,9 +287,10 @@ void cFinishGenClumpTopBlock::TryPlaceFoliageClump(cChunkDesc & a_ChunkDesc, int void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClumpInfo, std::vector & a_Output) { // Initialize the vector for all biomes. - for (int i = static_cast(a_Output.size()); i < static_cast(biMaxVariantBiome); i++) + for (int i = static_cast(a_Output.size()); i <= static_cast(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, "="); @@ -297,15 +307,18 @@ void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClum for (const auto & RawBiomeInfo : Biomes) { - AStringVector BiomeInfo = StringSplitAndTrim(RawBiomeInfo, ","); - AString BiomeName = BiomeInfo[0]; - EMCSBiome Biome = StringToBiome(BiomeName); + const AStringVector BiomeInfo = StringSplitAndTrim(RawBiomeInfo, ","); + const AString & BiomeName = BiomeInfo[0]; + const EMCSBiome Biome = StringToBiome(BiomeName); if (Biome == biInvalidBiome) { LOGWARNING("Biome \"%s\" is invalid.", BiomeName.c_str()); continue; } + // The index of Biome in the output vector. + const size_t BiomeIndex = static_cast(Biome); + if (BiomeInfo.size() == 2) { // 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()); continue; } - a_Output[static_cast(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. - a_Output[static_cast(Biome)].m_MaxNumClumpsPerChunk = std::max(MinNumClump, a_Output[static_cast(Biome)].m_MaxNumClumpsPerChunk); + a_Output[BiomeIndex].m_MaxNumClumpsPerChunk = std::max(MinNumClump, a_Output[BiomeIndex].m_MaxNumClumpsPerChunk); } else if (BiomeInfo.size() == 3) { @@ -330,22 +343,24 @@ void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClum continue; } - a_Output[static_cast(Biome)].m_MaxNumClumpsPerChunk = MaxNumClumps + 1; - a_Output[static_cast(Biome)].m_MinNumClumpsPerChunk = MinNumClumps; + a_Output[BiomeIndex].m_MaxNumClumpsPerChunk = MaxNumClumps + 1; + a_Output[BiomeIndex].m_MinNumClumpsPerChunk = MinNumClumps; } // TODO: Make the weight configurable. for (const auto & BlockName : Blocks) { - cItem Block = cItem(); - if (!StringToItem(BlockName, Block) && IsValidBlock(Block.m_ItemType)) + cItem Block; + if (!StringToItem(BlockName, Block) || !IsValidBlock(Block.m_ItemType)) { LOGWARNING("Block \"%s\" is invalid", BlockName.c_str()); continue; } - FoliageInfo info = FoliageInfo(static_cast(Block.m_ItemType), static_cast(Block.m_ItemDamage), 100); - a_Output[static_cast(Biome)].m_Blocks.push_back(info); + // Construct the FoliageInfo: + a_Output[BiomeIndex].m_Blocks.emplace_back( + static_cast(Block.m_ItemType), static_cast(Block.m_ItemDamage), 100 + ); } } } @@ -354,12 +369,9 @@ void cFinishGenClumpTopBlock::ParseConfigurationString(const AString & a_RawClum -std::vector cFinishGenClumpTopBlock::ParseIniFile(cIniFile & a_IniFile, AString a_ClumpPrefix) +std::vector cFinishGenClumpTopBlock::ParseIniFile(cIniFile & a_IniFile, const AString & a_ClumpPrefix) { - // Also check dashes in case we will get more configuration options with the same prefix. - a_ClumpPrefix += "-"; - - std::vector foliage; + std::vector Foliage; int NumGeneratorValues = a_IniFile.GetNumValues("Generator"); int GeneratorKeyId = a_IniFile.FindKey("Generator"); for (int i = 0; i < NumGeneratorValues; i++) @@ -368,20 +380,22 @@ std::vector cFinishGenClumpTopBlock::ParseIn if (ValueName.substr(0, a_ClumpPrefix.size()) == a_ClumpPrefix) { 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 + "-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); + 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; 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 + "-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 + "-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; 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))) { // If double long grass we have to choose what type we should use: 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; - 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(y + 1)); + NIBBLETYPE Meta = (m_Noise.IntNoise2DInt(xx * 100, zz * 100) / 7 % 100) > 25 ? + E_META_BIG_FLOWER_DOUBLE_TALL_GRASS : E_META_BIG_FLOWER_LARGE_FERN; + + 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(y + 1)); + } } } 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 @@ -816,34 +924,13 @@ void cFinishGenSprinkleFoliage::GenFinish(cChunkDesc & a_ChunkDesc) { case E_BLOCK_GRASS: { - float val3 = m_Noise.CubicNoise2D(xx * 0.01f + 10, zz * 0.01f + 10); - 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)) + if (TryAddSugarcane(a_ChunkDesc, x, Top, z)) { // Checks and block placing are handled in the TryAddSugarcane method } 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(val3 * 8) % 4); } break; diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index c12bc2392..d6458e4fc 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -123,7 +123,7 @@ public: static void ParseConfigurationString(const AString & a_String, std::vector & a_Output); /** Parses an inifile in search for all clumps */ - static std::vector ParseIniFile(cIniFile & a_IniFile, AString a_ClumpPrefix); + static std::vector ParseIniFile(cIniFile & a_IniFile, const AString & a_ClumpPrefix); protected: cNoise m_Noise; @@ -132,7 +132,7 @@ protected: /** The maximum number of foliage per clump */ 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; /** The maximum range a foliage can be placed from the center of the clump */ @@ -181,35 +181,9 @@ protected: // cFinishGen override: virtual void GenFinish(cChunkDesc & a_ChunkDesc) override; - int 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; - } - } - } + static bool CanFernGrow(EMCSBiome a_Biome); + static bool CanLargeFernGrow(EMCSBiome a_Biome); + static int GetBiomeDensity(EMCSBiome a_Biome); }; diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp old mode 100755 new mode 100644