Cuberite
A lightweight, fast and extensible game server for Minecraft
SinglePieceStructuresGen.cpp
Go to the documentation of this file.
1 
3 
4 #include "PrefabStructure.h"
5 #include "../IniFile.h"
6 #include "../Item.h"
7 
8 
10 // cSinglePieceStructuresGen::cGen
11 
13  public cGridStructGen
14 {
16 public:
17  cGen(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_SeaLevel, const AString & a_Name):
18  Super(a_Seed),
19  m_BiomeGen(a_BiomeGen),
20  m_HeightGen(a_HeightGen),
21  m_SeaLevel(a_SeaLevel),
22  m_Name(a_Name)
23  {
24  }
25 
26 
27 
30  bool LoadFromFile(const AString & a_FileName)
31  {
33 
34  // Load the piecepool from the file, log any warnings:
35  if (!m_PiecePool.LoadFromFile(a_FileName, true))
36  {
37  return false;
38  }
39  if (NoCaseCompare(m_PiecePool.GetIntendedUse(), "SinglePieceStructures") != 0)
40  {
41  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.",
42  a_FileName.c_str(), m_PiecePool.GetIntendedUse().c_str()
43  );
44  }
46 
47  // Apply generator params from the piecepool (in the metadata) into the generator:
48  auto & generatorParams = m_PiecePool.GetAllMetadata();
49  SetGeneratorParams(generatorParams);
50 
51  return true;
52  }
53 
54 
55 
56 
57  // cGridStructGen override
58  virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override
59  {
60  // Generate the biomes for the chunk surrounding the origin:
61  int ChunkX, ChunkZ;
62  cChunkDef::BlockToChunk(a_OriginX, a_OriginZ, ChunkX, ChunkZ);
63  cChunkDef::BiomeMap Biomes;
64  m_BiomeGen.GenBiomes({ChunkX, ChunkZ}, Biomes);
65 
66  // Checks if the biome at the origin position is allowed
67  auto Relative = cChunkDef::AbsoluteToRelative(Vector3i(a_OriginX, 1, a_OriginZ), {ChunkX, ChunkZ});
68  if (!m_PiecePool.IsBiomeAllowed(Biomes[Relative.x + cChunkDef::Width * Relative.z]))
69  {
70  return cStructurePtr();
71  }
72  cPlacedPieces OutPiece;
73  OutPiece.push_back(GetPiece(a_OriginX, a_OriginZ));
74  return std::make_shared<cPrefabStructure>(a_GridX, a_GridZ, a_OriginX, a_OriginZ, std::move(OutPiece), m_HeightGen);
75  }
76 
77 
78 
79 
81  cPlacedPiecePtr GetPiece(int a_BlockX, int a_BlockZ)
82  {
83  int rnd = m_Noise.IntNoise2DInt(a_BlockX, a_BlockZ) / 7;
84 
85  // Choose a random one of the starting pieces:
86  cPieces StartingPieces = m_PiecePool.GetStartingPieces();
87  int Total = 0;
88  for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
89  {
90  Total += m_PiecePool.GetStartingPieceWeight(**itr);
91  }
92  cPiece * StartingPiece;
93  if (Total > 0)
94  {
95  int Chosen = rnd % Total;
96  StartingPiece = StartingPieces.front();
97  for (cPieces::const_iterator itr = StartingPieces.begin(), end = StartingPieces.end(); itr != end; ++itr)
98  {
99  Chosen -= m_PiecePool.GetStartingPieceWeight(**itr);
100  if (Chosen <= 0)
101  {
102  StartingPiece = *itr;
103  break;
104  }
105  }
106  }
107  else
108  {
109  // All pieces returned zero weight, but we need one to start. Choose with equal chance:
110  StartingPiece = StartingPieces[static_cast<size_t>(rnd) % StartingPieces.size()];
111  }
112  rnd = rnd >> 16;
113 
114  // Choose a random supported rotation:
115  int Rotations[4] = {0};
116  int NumRotations = 1;
117  for (size_t i = 1; i < ARRAYCOUNT(Rotations); i++)
118  {
119  if (StartingPiece->CanRotateCCW(static_cast<int>(i)))
120  {
121  Rotations[NumRotations] = static_cast<int>(i);
122  NumRotations += 1;
123  }
124  }
125  int Rotation = Rotations[rnd % NumRotations];
126  int BlockY = StartingPiece->GetStartingPieceHeight(a_BlockX, a_BlockZ);
127  ASSERT(BlockY >= 0); // The vertical strategy should have been provided and should give valid coords
128 
129  cPlacedPiece * Piece = new cPlacedPiece(nullptr, *StartingPiece, Vector3i(a_BlockX, BlockY, a_BlockZ), Rotation);
130  return cPlacedPiecePtr(Piece);
131  }
132 
133 protected:
136 
139 
142 
145 
148 };
149 
150 
152 // cSinglePieceStructuresGen
153 
155  m_Seed(a_Seed)
156 {
157 }
158 
159 
160 
161 
162 
163 bool cSinglePieceStructuresGen::Initialize(const AString & a_Prefabs, int a_SeaLevel, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen)
164 {
165  // Load each piecepool:
166  auto Structures = StringSplitAndTrim(a_Prefabs, "|");
167  for (const auto & S: Structures)
168  {
169  auto FileName = fmt::format(FMT_STRING("Prefabs{0}SinglePieceStructures{0}{1}.cubeset"), cFile::PathSeparator(), S);
170  if (!cFile::IsFile(FileName))
171  {
172  FileName.append(".gz");
173  if (!cFile::IsFile(FileName))
174  {
175  LOGWARNING("Cannot load SinglePieceStructure cubeset file %s", FileName);
176  continue;
177  }
178  }
179 
180  auto Gen = std::make_shared<cGen>(m_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel, S);
181  if (Gen->LoadFromFile(FileName))
182  {
183  m_Gens.push_back(Gen);
184  }
185  }
186 
187  // Report a warning if no generators available:
188  if (m_Gens.empty())
189  {
190  LOGWARNING("The PieceStructures generator was asked to generate \"%s\", but none of the prefabs are valid.", a_Prefabs);
191  return false;
192  }
193  return true;
194 }
195 
196 
197 
198 
199 
201 {
202  for (auto & Gen: m_Gens)
203  {
204  Gen->GenFinish(a_Chunk);
205  }
206 }
std::vector< cPiece * > cPieces
Definition: PiecePool.h:262
std::unique_ptr< cPlacedPiece > cPlacedPiecePtr
Definition: PiecePool.h:369
std::vector< cPlacedPiecePtr > cPlacedPieces
Definition: PiecePool.h:370
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:231
#define ASSERT(x)
Definition: Globals.h:276
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
AStringVector StringSplitAndTrim(const AString &str, const AString &delim)
Split the string at any of the listed delimiters and trim each value.
int NoCaseCompare(const AString &s1, const AString &s2)
Case-insensitive string comparison.
std::string AString
Definition: StringUtils.h:11
Vector3< int > Vector3i
Definition: Vector3.h:487
unsigned char Rotation(const BlockState Block)
static void BlockToChunk(int a_X, int a_Z, int &a_ChunkX, int &a_ChunkZ)
Converts absolute block coords to chunk coords:
Definition: ChunkDef.h:210
static void AbsoluteToRelative(int &a_X, int &a_Y, int &a_Z, int &a_ChunkX, int &a_ChunkZ)
Converts absolute block coords into relative (chunk + block) coords:
Definition: ChunkDef.h:147
static const int Width
Definition: ChunkDef.h:124
EMCSBiome BiomeMap[Width *Width]
The type used for any biomemap operations and storage inside Cuberite, using Cuberite biomes (need no...
Definition: ChunkDef.h:137
The interface that a biome generator must implement A biome generator takes chunk coords on input and...
virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap &a_BiomeMap)=0
Generates biomes for the given chunk.
The interface that is used to query terrain height from the shape generator.
Generates structures in a semi-random grid.
Definition: GridStructGen.h:46
std::shared_ptr< cStructure > cStructurePtr
Definition: GridStructGen.h:77
cGridStructGen(int a_Seed, int a_GridSizeX, int a_GridSizeZ, int a_MaxOffsetX, int a_MaxOffsetZ, int a_MaxStructureSizeX, int a_MaxStructureSizeZ, size_t a_MaxCacheSize)
int m_Seed
Seed for generating grid offsets and also available for descendants.
void SetGeneratorParams(const AStringMap &a_GeneratorParams)
Sets the generator params based on the dictionary passed in.
cNoise m_Noise
The noise used for generating grid offsets.
Represents a single piece.
Definition: PiecePool.h:21
virtual bool CanRotateCCW(int a_NumRotations) const =0
Returns true if the piece can be rotated CCW the specific number of 90-degree turns.
int GetStartingPieceHeight(int a_BlockX, int a_BlockZ)
Returns the height, based on m_VerticalStrategy, for this piece when used as the starting piece.
Definition: PiecePool.h:204
Represents a single piece that has been placed to specific coords in the world.
Definition: PiecePool.h:328
void Clear(void)
Removes and frees all pieces from this pool.
virtual int GetStartingPieceWeight(const cPiece &a_NewPiece) override
Returns the relative weight with which the a_NewPiece is to be selected for placing as the first piec...
bool IsBiomeAllowed(EMCSBiome a_Biome) const
Returns true if a_Biome is among the accepted biomes in the m_AcceptedBiomes metadata member.
virtual cPieces GetStartingPieces(void) override
Returns the pieces that should be used as the starting point.
bool LoadFromFile(const AString &a_FileName, bool a_LogWarnings)
Loads the pieces from the specified file.
const AStringMap & GetAllMetadata(void) const
void AssignGens(int a_Seed, cBiomeGen &a_BiomeGen, cTerrainHeightGen &a_HeightGen, int a_SeaLevel)
Called when the piece pool is assigned to a generator, so that the individual starting pieces' vertic...
const AString & GetIntendedUse(void) const
cPrefabPiecePool m_PiecePool
All available prefabs.
int m_SeaLevel
The world's sea level, if available.
cBiomeGen & m_BiomeGen
The underlying biome generator that defines whether the structure is created or not.
AString m_Name
The name that is used for reporting.
cGen(int a_Seed, cBiomeGen &a_BiomeGen, cTerrainHeightGen &a_HeightGen, int a_SeaLevel, const AString &a_Name)
bool LoadFromFile(const AString &a_FileName)
Loads the piecepool from a file.
cTerrainHeightGen & m_HeightGen
The underlying height generator, used to position the prefabs crossing chunk borders if they are set ...
virtual cStructurePtr CreateStructure(int a_GridX, int a_GridZ, int a_OriginX, int a_OriginZ) override
Create a new structure at the specified gridpoint.
cPlacedPiecePtr GetPiece(int a_BlockX, int a_BlockZ)
Determines which piece to place from the piece pool.
virtual void GenFinish(cChunkDesc &a_ChunkDesc) override
bool Initialize(const AString &a_Prefabs, int a_SeaLevel, cBiomeGen &a_BiomeGen, cTerrainHeightGen &a_HeightGen)
Initializes the generator based on the specified prefab sets.
cGenPtrs m_Gens
The individual structure generators, one per piecepool.
int m_Seed
The seed for the random number generator.
int IntNoise2DInt(int a_X, int a_Y) const
Definition: Noise.h:243
static char PathSeparator()
Definition: File.h:42
static bool IsFile(const AString &a_Path)
Returns true if the specified path is a regular file.
Definition: File.cpp:425