summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Generating/CMakeLists.txt2
-rw-r--r--src/Generating/ComposableGenerator.cpp16
-rw-r--r--src/Generating/SinglePieceStructuresGen.cpp205
-rw-r--r--src/Generating/SinglePieceStructuresGen.h52
4 files changed, 275 insertions, 0 deletions
diff --git a/src/Generating/CMakeLists.txt b/src/Generating/CMakeLists.txt
index d6f0ce2fb..bf539d6c2 100644
--- a/src/Generating/CMakeLists.txt
+++ b/src/Generating/CMakeLists.txt
@@ -24,6 +24,7 @@ target_sources(
PrefabStructure.cpp
Ravines.cpp
RoughRavines.cpp
+ SinglePieceStructuresGen.cpp
StructGen.cpp
Trees.cpp
TwoHeights.cpp
@@ -58,6 +59,7 @@ target_sources(
Ravines.h
RoughRavines.h
ShapeGen.cpp
+ SinglePieceStructuresGen.h
StructGen.h
Trees.h
TwoHeights.h
diff --git a/src/Generating/ComposableGenerator.cpp b/src/Generating/ComposableGenerator.cpp
index 5dd54a497..7c891f5fa 100644
--- a/src/Generating/ComposableGenerator.cpp
+++ b/src/Generating/ComposableGenerator.cpp
@@ -27,6 +27,7 @@
#include "Noise3DGenerator.h"
#include "Ravines.h"
#include "RoughRavines.h"
+#include "SinglePieceStructuresGen.h"
#include "VillageGen.h"
#include "PieceStructuresGen.h"
@@ -217,6 +218,7 @@ void cComposableGenerator::InitializeGeneratorDefaults(cIniFile & a_IniFile, eDi
"Mineshafts, "
"Trees, "
"Villages, "
+ "SinglePieceStructures: JungleTemple|WitchHut|DesertPyramid|DesertWell, "
"TallGrass, "
"SprinkleFoliage, "
"Ice, "
@@ -606,6 +608,20 @@ void cComposableGenerator::InitFinishGens(cIniFile & a_IniFile)
GridSize, MaxOffset
)));
}
+ else if (NoCaseCompare(finisher, "SinglePieceStructures") == 0)
+ {
+ if (split.size() < 2)
+ {
+ LOGWARNING("The SinglePieceStructures generator needs the structures to use. Example: \"SinglePieceStructures: DesertPyramid\".");
+ continue;
+ }
+
+ auto Gen = std::make_shared<cSinglePieceStructuresGen>(m_Seed);
+ if (Gen->Initialize(split[1], seaLevel, m_BiomeGen, m_CompositedHeightCache))
+ {
+ m_FinishGens.push_back(Gen);
+ }
+ }
else if (NoCaseCompare(finisher, "SoulsandRims") == 0)
{
m_FinishGens.push_back(cFinishGenPtr(new cFinishGenSoulsandRims(m_Seed)));
diff --git a/src/Generating/SinglePieceStructuresGen.cpp b/src/Generating/SinglePieceStructuresGen.cpp
new file mode 100644
index 000000000..bd079d762
--- /dev/null
+++ b/src/Generating/SinglePieceStructuresGen.cpp
@@ -0,0 +1,205 @@
+
+#include "SinglePieceStructuresGen.h"
+
+#include "PrefabStructure.h"
+#include "../IniFile.h"
+#include "../Item.h"
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cSinglePieceStructuresGen::cGen
+
+class cSinglePieceStructuresGen::cGen :
+ public cGridStructGen
+{
+ using Super = cGridStructGen;
+public:
+ cGen(int a_Seed, cBiomeGenPtr a_BiomeGen, cTerrainHeightGenPtr a_HeightGen, int a_SeaLevel, const AString & a_Name):
+ Super(a_Seed),
+ m_BiomeGen(std::move(a_BiomeGen)),
+ m_HeightGen(std::move(a_HeightGen)),
+ m_SeaLevel(a_SeaLevel),
+ m_Name(a_Name)
+ {
+ }
+
+
+
+ /** Loads the piecepool from a file.
+ Returns true on success, logs warning and returns false on failure. */
+ bool LoadFromFile(const AString & a_FileName)
+ {
+ m_PiecePool.Clear();
+
+ // Load the piecepool from the file, log any warnings:
+ if (!m_PiecePool.LoadFromFile(a_FileName, true))
+ {
+ return false;
+ }
+ if (NoCaseCompare(m_PiecePool.GetIntendedUse(), "SinglePieceStructures") != 0)
+ {
+ LOGWARNING("SinglePieceStructures generator: File %s is intended for use in \"%s\", rather than single piece structures. Loading the file, but the generator may behave unexpectedly.",
+ a_FileName.c_str(), m_PiecePool.GetIntendedUse().c_str()
+ );
+ }
+ m_PiecePool.AssignGens(m_Seed, m_BiomeGen, m_HeightGen, m_SeaLevel);
+
+ // Apply generator params from the piecepool (in the metadata) into the generator:
+ auto & generatorParams = m_PiecePool.GetAllMetadata();
+ SetGeneratorParams(generatorParams);
+
+ return true;
+ }
+
+
+
+
+ // cGridStructGen override
+ virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override
+ {
+ // Generate the biomes for the chunk surrounding the origin:
+ int ChunkX, ChunkZ;
+ cChunkDef::BlockToChunk(a_OriginX, a_OriginZ, ChunkX, ChunkZ);
+ cChunkDef::BiomeMap Biomes;
+ m_BiomeGen->GenBiomes({ChunkX, ChunkZ}, Biomes);
+
+ // Checks if the biome at the origin position is allowed
+ if (!m_PiecePool.IsBiomeAllowed(Biomes[ChunkX + cChunkDef::Width * ChunkZ]))
+ {
+ return cStructurePtr();
+ }
+ cPlacedPieces OutPiece;
+ OutPiece.push_back(GetPiece(a_OriginX, a_OriginZ));
+ return std::make_shared<cPrefabStructure>(a_GridX, a_GridZ, a_OriginX, a_OriginZ, std::move(OutPiece), m_HeightGen);
+ }
+
+
+
+
+ /** Determines which piece to place from the piece pool */
+ cPlacedPiecePtr GetPiece(int a_BlockX, int a_BlockZ)
+ {
+ int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7;
+
+ // Choose a random one of the starting pieces:
+ cPieces StartingPieces = m_PiecePool.GetStartingPieces();
+ int Total = 0;
+ for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
+ {
+ Total += m_PiecePool.GetStartingPieceWeight(**itr);
+ }
+ cPiece * StartingPiece;
+ if (Total > 0)
+ {
+ int Chosen = rnd % Total;
+ StartingPiece = StartingPieces.front();
+ for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
+ {
+ Chosen -= m_PiecePool.GetStartingPieceWeight(**itr);
+ if (Chosen <= 0)
+ {
+ StartingPiece = *itr;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // All pieces returned zero weight, but we need one to start. Choose with equal chance:
+ StartingPiece = StartingPieces[static_cast<size_t>(rnd) % StartingPieces.size()];
+ }
+ rnd = rnd >> 16;
+
+ // Choose a random supported rotation:
+ int Rotations[4] = {0};
+ int NumRotations = 1;
+ for (size_t i = 1; i < ARRAYCOUNT(Rotations); i++)
+ {
+ if (StartingPiece->CanRotateCCW(static_cast<int>(i)))
+ {
+ Rotations[NumRotations] = static_cast<int>(i);
+ NumRotations += 1;
+ }
+ }
+ int Rotation = Rotations[rnd % NumRotations];
+ int BlockY = StartingPiece->GetStartingPieceHeight(a_BlockX, a_BlockZ);
+ ASSERT(BlockY >= 0); // The vertical strategy should have been provided and should give valid coords
+
+ cPlacedPiece * Piece = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, BlockY, a_BlockZ), Rotation);
+ return cPlacedPiecePtr(Piece);
+ }
+
+protected:
+ /** The underlying biome generator that defines whether the structure is created or not */
+ cBiomeGenPtr m_BiomeGen;
+
+ /** The underlying height generator, used to position the prefabs crossing chunk borders if they are set to FitGround. */
+ cTerrainHeightGenPtr m_HeightGen;
+
+ /** The world's sea level, if available. Used for some cVerticalStrategy descendants. */
+ int m_SeaLevel;
+
+ /** The name that is used for reporting. */
+ AString m_Name;
+
+ /** All available prefabs. */
+ cPrefabPiecePool m_PiecePool;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cSinglePieceStructuresGen
+
+cSinglePieceStructuresGen::cSinglePieceStructuresGen(int a_Seed) :
+ m_Seed(a_Seed)
+{
+}
+
+
+
+
+
+bool cSinglePieceStructuresGen::Initialize(const AString & a_Prefabs, int a_SeaLevel, const cBiomeGenPtr & a_BiomeGen, const cTerrainHeightGenPtr & a_HeightGen)
+{
+ // Load each piecepool:
+ auto Structures = StringSplitAndTrim(a_Prefabs, "|");
+ for (const auto & S: Structures)
+ {
+ auto FileName = Printf("Prefabs%cSinglePieceStructures%c%s.cubeset", cFile::PathSeparator(), cFile::PathSeparator(), S.c_str());
+ if (!cFile::IsFile(FileName))
+ {
+ FileName.append(".gz");
+ if (!cFile::IsFile(FileName))
+ {
+ LOGWARNING("Cannot load SinglePieceStructure cubeset file %s", FileName.c_str());
+ continue;
+ }
+ }
+
+ auto Gen = std::make_shared<cGen>(m_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel, S);
+ if (Gen->LoadFromFile(FileName))
+ {
+ m_Gens.push_back(Gen);
+ }
+ }
+
+ // Report a warning if no generators available:
+ if (m_Gens.empty())
+ {
+ LOGWARNING("The PieceStructures generator was asked to generate \"%s\", but none of the prefabs are valid.", a_Prefabs.c_str());
+ return false;
+ }
+ return true;
+}
+
+
+
+
+
+void cSinglePieceStructuresGen::GenFinish(cChunkDesc & a_Chunk)
+{
+ for (auto & Gen: m_Gens)
+ {
+ Gen->GenFinish(a_Chunk);
+ }
+}
diff --git a/src/Generating/SinglePieceStructuresGen.h b/src/Generating/SinglePieceStructuresGen.h
new file mode 100644
index 000000000..c14757738
--- /dev/null
+++ b/src/Generating/SinglePieceStructuresGen.h
@@ -0,0 +1,52 @@
+
+// PrefabSingleStructureGen.h
+
+
+/*
+Classes to support the generation of single piece prefab structures
+*/
+
+#pragma once
+
+#include "Globals.h"
+
+#include "ComposableGenerator.h"
+#include "PrefabPiecePool.h"
+
+/** The Single Prefab Structure Generator:
+This uses the cGridStructGen to generate the structures on the map
+This is similar to the Piece Structure Generator but only placing one possible structure
+The Exported cubeset MUST have all possible structures as start structures or the server crashes on generation
+else it isn't accessible from the m_Piecepool. */
+class cSinglePieceStructuresGen :
+ public cFinishGen
+{
+using Super = cFinishGen;
+
+public:
+ cSinglePieceStructuresGen(int a_Seed);
+
+ /** Initializes the generator based on the specified prefab sets.
+ a_Prefabs contains the list of prefab sets that should be activated, "|"-separated.
+ All problems are logged to the console and the generator skips over them.
+ Returns true if at least one prefab set is valid (the generator should be kept). */
+ bool Initialize(const AString & a_Prefabs, int a_SeaLevel, const cBiomeGenPtr & a_BiomeGen, const cTerrainHeightGenPtr & a_HeightGen);
+
+
+ // cFinishGen override:
+ virtual void GenFinish(cChunkDesc & a_ChunkDesc) override;
+
+protected:
+ /** The generator doing the work for a single prefab set.
+ Forward-declared so that its implementation changes don't affect the header. */
+ class cGen;
+
+ typedef std::shared_ptr<cGen> cGenPtr;
+ typedef std::vector<cGenPtr> cGenPtrs;
+
+ /** The individual structure generators, one per piecepool. */
+ cGenPtrs m_Gens;
+
+ /** The seed for the random number generator */
+ int m_Seed;
+};