diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp index 3e27280ce..fa8db8f93 100644 --- a/src/Generating/ComposableGenerator.cpp +++ b/src/Generating/ComposableGenerator.cpp @@ -332,7 +332,11 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) } else if (NoCaseCompare(*itr, "DirtPockets") == 0) { - m_FinishGens.push_back(std::make_shared(Seed + 1, cFinishGenOrePockets::DefaultNaturalPatches())); + auto gen = std::make_shared(Seed + 1, cFinishGenOrePockets::DefaultNaturalPatches()); + if (gen->Initialize(a_IniFile, "DirtPockets")) + { + m_FinishGens.push_back(gen); + } } else if (NoCaseCompare(*itr, "DistortedMembraneOverhangs") == 0) { @@ -425,7 +429,7 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile) else if (NoCaseCompare(*itr, "OrePockets") == 0) { auto gen = std::make_shared(Seed + 2, cFinishGenOrePockets::DefaultOverworldOres()); - if (gen->Initialize(a_IniFile)) + if (gen->Initialize(a_IniFile, "OrePockets")) { m_FinishGens.push_back(gen); } diff --git a/src/Generating/FinishGen.cpp b/src/Generating/FinishGen.cpp index 8066a497e..6e833ad6d 100644 --- a/src/Generating/FinishGen.cpp +++ b/src/Generating/FinishGen.cpp @@ -1441,13 +1441,11 @@ const cFinishGenOres::OreInfos & cFinishGenOres::DefaultOverworldOres(void) const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNetherOres(void) { - static OreInfos res; - if (res.empty()) + static OreInfos res { - // Hasn't been initialized yet, emplace the defaults: - // OreType, OreMeta, MaxHeight, NumNests, NestSize - res.emplace_back(E_BLOCK_NETHER_QUARTZ_ORE, 0, 127, 20, 8); - } + // OreType, OreMeta, MaxHeight, NumNests, NestSize + {E_BLOCK_NETHER_QUARTZ_ORE, 0, 127, 20, 8}, + }; return res; } @@ -1457,17 +1455,15 @@ const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNetherOres(void) const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNaturalPatches(void) { - static OreInfos res; - if (res.empty()) + static OreInfos res { - // Hasn't been initialized yet, emplace the defaults: - // OreType, OreMeta, MaxHeight, NumNests, NestSize - res.emplace_back(E_BLOCK_DIRT, 0, 127, 20, 32); - res.emplace_back(E_BLOCK_GRAVEL, 0, 127, 10, 32); - res.emplace_back(E_BLOCK_STONE, E_META_STONE_GRANITE, 127, 20, 32); - res.emplace_back(E_BLOCK_STONE, E_META_STONE_DIORITE, 127, 20, 32); - res.emplace_back(E_BLOCK_STONE, E_META_STONE_ANDESITE, 127, 20, 32); - } + // OreType, OreMeta, MaxHeight, NumNests, NestSize + {E_BLOCK_DIRT, 0, 127, 20, 32}, + {E_BLOCK_GRAVEL, 0, 127, 10, 32}, + {E_BLOCK_STONE, E_META_STONE_GRANITE, 127, 20, 32}, + {E_BLOCK_STONE, E_META_STONE_DIORITE, 127, 20, 32}, + {E_BLOCK_STONE, E_META_STONE_ANDESITE, 127, 20, 32}, + }; return res; } @@ -1475,6 +1471,80 @@ const cFinishGenOres::OreInfos & cFinishGenOres::DefaultNaturalPatches(void) +cFinishGenOres::OreInfos cFinishGenOres::OreInfosFromString(const AString & a_OreInfosString) +{ + // The string is expected to be formatted as " | | | ..." + // Each OreInfo is expected to be formatted as " : : : : " + + OreInfos res; + auto ores = StringSplitAndTrim(a_OreInfosString, "|"); + for (const auto & ore: ores) + { + auto parts = StringSplitAndTrim(ore, ":"); + if (parts.size() != 5) + { + LOGWARNING("Cannot parse ore information from string, not enough OreInfo members (exp 5, got %d). Offending item: \"%s\".", + static_cast(parts.size()), ore.c_str() + ); + continue; + } + auto oreType = BlockStringToType(parts[0]); + if (oreType < 0) + { + LOGWARNING("Cannot parse ore information from string, invalid OreType: \"%s\".", parts[0].c_str()); + continue; + } + NIBBLETYPE oreMeta; + int maxHeight, numNests, nestSize; + if ( + !StringToInteger(parts[1], oreMeta) || + !StringToInteger(parts[2], maxHeight) || + !StringToInteger(parts[3], numNests) || + !StringToInteger(parts[4], nestSize) + ) + { + LOGWARNING("Cannot parse ore information from string, invalid number in OreInfo \"%s\".", ore.c_str()); + continue; + } + res.emplace_back(oreType, oreMeta, maxHeight, numNests, nestSize); + } // for i - split[] + return res; +} + + + + + +AString cFinishGenOres::OreInfosToString(const cFinishGenOres::OreInfos & a_OreInfos) +{ + AString res; + for (const auto & ore: a_OreInfos) + { + if (!res.empty()) + { + res.append(" | "); + } + AppendPrintf(res, "%s:%d:%d:%d:%d", + ItemTypeToString(ore.m_BlockType).c_str(), ore.m_BlockMeta, + ore.m_MaxHeight, ore.m_NumNests, ore.m_NestSize + ); + } // for ore - a_OreInfos[] + return res; +} + + + + + +void cFinishGenOres::SetSeed(int a_Seed) +{ + m_Noise.SetSeed(a_Seed); +} + + + + + //////////////////////////////////////////////////////////////////////////////// // cFinishGenOreNests: @@ -1576,9 +1646,25 @@ void cFinishGenOreNests::GenerateOre( //////////////////////////////////////////////////////////////////////////////// // cFinishGenOrePockets: -bool cFinishGenOrePockets::Initialize(cIniFile & a_IniFile) +bool cFinishGenOrePockets::Initialize(cIniFile & a_IniFile, const AString & a_GenName) { - // TODO + // Read the OreInfos configuration: + auto valueName = a_GenName + "_blocks"; + auto pocketCfg = a_IniFile.GetValue("Generator", valueName, ""); + if (pocketCfg.empty()) + { + // There's no config currently stored in the INI file. Store the defaults as the config: + a_IniFile.SetValue("Generator", valueName, OreInfosToString(m_OreInfos)); + } + else + { + m_OreInfos = OreInfosFromString(pocketCfg); + } + + // Read the optional seed configuration (but do not store the default): + valueName = a_GenName + "_seed"; + SetSeed(a_IniFile.GetValueI("Generator", valueName, m_Noise.GetSeed())); + return true; } diff --git a/src/Generating/FinishGen.h b/src/Generating/FinishGen.h index 4541887ec..464ed209f 100644 --- a/src/Generating/FinishGen.h +++ b/src/Generating/FinishGen.h @@ -440,7 +440,6 @@ public: cFinishGenOres(int a_Seed, const OreInfos & a_OreInfos): m_Noise(a_Seed), - m_Seed(a_Seed), m_OreInfos(a_OreInfos) { } @@ -457,13 +456,23 @@ public: /** Returns a vector of OreInfo structures describing the default Overworld non-ore pockets (dirt, diorite etc), usable in the constructor. */ static const OreInfos & DefaultNaturalPatches(void); + /** Parses the parameter string into OreInfos array. + See OreInfosToString() for the complementary function. + Used for loading configuration from INI files. */ + static OreInfos OreInfosFromString(const AString & a_OreInfosString); + + /** Returns a string that represents the OreInfos given as the parameter. + See OreInfosFromString() for the complementary function. + Used for storing defaults in the INI file. */ + static AString OreInfosToString(const OreInfos & a_OreInfos); + + /** (Re-)sets the seed used by the internal generating mechanisms. */ + void SetSeed(int a_Seed); + protected: /** The noise used for generating. */ cNoise m_Noise; - /** The seed for the generating noise. */ - int m_Seed; - /** All the ores enabled in this generator. */ OreInfos m_OreInfos; @@ -520,8 +529,9 @@ public: {} /** Reads the configuration from the specified INI file. + a_GenName is the name of the generator (this class may be used for OrePockets and DirtPockets, each has a different default). Returns true on success, false and logs errors to console on failure. */ - bool Initialize(cIniFile & a_IniFile); + bool Initialize(cIniFile & a_IniFile, const AString & a_GenName); protected: diff --git a/src/Noise/Noise.h b/src/Noise/Noise.h index b08b96e24..4c99cee5b 100644 --- a/src/Noise/Noise.h +++ b/src/Noise/Noise.h @@ -49,6 +49,7 @@ public: NOISE_DATATYPE CubicNoise3D (NOISE_DATATYPE a_X, NOISE_DATATYPE a_Y, NOISE_DATATYPE a_Z) const; void SetSeed(int a_Seed) { m_Seed = a_Seed; } + int GetSeed(void) const { return m_Seed; } inline static NOISE_DATATYPE CubicInterpolate (NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_C, NOISE_DATATYPE a_D, NOISE_DATATYPE a_Pct); inline static NOISE_DATATYPE CosineInterpolate(NOISE_DATATYPE a_A, NOISE_DATATYPE a_B, NOISE_DATATYPE a_Pct);