2015-11-11 04:32:42 -05:00
// PieceStructuresGen.cpp
// Declares the cPieceStructuresGen class representing the PieceStructures finisher generator
# include "Globals.h"
# include "PieceStructuresGen.h"
# include "PrefabStructure.h"
2017-02-26 16:49:23 -05:00
# include "PieceGeneratorBFSTree.h"
2018-08-28 20:51:25 -04:00
# include "../IniFile.h"
2015-11-11 04:32:42 -05:00
2017-02-26 16:49:23 -05:00
class cPieceStructuresGen : : cGen :
public cGridStructGen
{
2020-04-13 12:38:06 -04:00
using Super = cGridStructGen ;
2017-02-26 16:49:23 -05:00
public :
2020-04-13 12:38:06 -04:00
2021-03-08 11:39:43 -05:00
cGen ( int a_Seed , cBiomeGen & a_BiomeGen , cTerrainHeightGen & a_HeightGen , int a_SeaLevel , const AString & a_Name ) :
2017-02-26 16:49:23 -05:00
Super ( a_Seed ) ,
2021-03-08 11:39:43 -05:00
m_BiomeGen ( a_BiomeGen ) ,
m_HeightGen ( a_HeightGen ) ,
2017-02-26 16:49:23 -05:00
m_SeaLevel ( a_SeaLevel ) ,
m_Name ( a_Name ) ,
m_MaxDepth ( 5 )
{
}
/** Loads the piecepool from a file.
Returns true on success , logs warning and returns false on failure . */
bool LoadFromFile ( const AString & a_FileName )
{
// Load the piecepool from the file, log any warnings:
if ( ! m_PiecePool . LoadFromFile ( a_FileName , true ) )
{
return false ;
}
if ( NoCaseCompare ( m_PiecePool . GetIntendedUse ( ) , " PieceStructures " ) ! = 0 )
{
LOGWARNING ( " PieceStructures generator: File %s is intended for use in \" %s \" , rather than 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:
2020-10-12 08:35:14 -04:00
auto & GeneratorParams = m_PiecePool . GetAllMetadata ( ) ;
SetGeneratorParams ( GeneratorParams ) ;
m_MaxDepth = GetStringMapInteger < int > ( GeneratorParams , " MaxDepth " , m_MaxDepth ) ;
2017-02-26 16:49:23 -05:00
return true ;
}
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure ( int a_GridX , int a_GridZ , int a_OriginX , int a_OriginZ ) override
{
2020-10-12 08:35:14 -04:00
cPlacedPieces OutPieces ;
cPieceGeneratorBFSTree PieceTree ( m_PiecePool , m_Seed ) ;
PieceTree . PlacePieces ( a_OriginX , a_OriginZ , m_MaxDepth , OutPieces ) ;
return std : : make_shared < cPrefabStructure > ( a_GridX , a_GridZ , a_OriginX , a_OriginZ , std : : move ( OutPieces ) , m_HeightGen ) ;
2017-02-26 16:49:23 -05:00
}
protected :
/** The type used for storing a connection from one piece to another, while building the piece tree. */
struct cConnection
{
cPiece * m_Piece ; // The piece being connected
cPiece : : cConnector m_Connector ; // The piece's connector being used (relative non-rotated coords)
int m_NumCCWRotations ; // Number of rotations necessary to match the two connectors
int m_Weight ; // Relative chance that this connection will be chosen
cConnection ( cPiece & a_Piece , cPiece : : cConnector & a_Connector , int a_NumCCWRotations , int a_Weight ) ;
} ;
typedef std : : vector < cConnection > cConnections ;
/** The type used for storing a pool of connectors that will be attempted to expand by another piece. */
struct cFreeConnector
{
cPlacedPiece * m_Piece ;
cPiece : : cConnector m_Connector ;
cFreeConnector ( cPlacedPiece * a_Piece , const cPiece : : cConnector & a_Connector ) ;
} ;
typedef std : : vector < cFreeConnector > cFreeConnectors ;
/** The underlying biome generator that defines whether the structure is created or not */
2021-03-08 11:39:43 -05:00
cBiomeGen & m_BiomeGen ;
2017-02-26 16:49:23 -05:00
/** The underlying height generator, used to position the prefabs crossing chunk borders if they are set to FitGround. */
2021-03-08 11:39:43 -05:00
cTerrainHeightGen & m_HeightGen ;
2017-02-26 16:49:23 -05:00
/** 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 ;
/** Maximum depth of the generated piece tree. */
int m_MaxDepth ;
} ;
////////////////////////////////////////////////////////////////////////////////
// cPieceStructuresGen:
2015-11-11 04:32:42 -05:00
cPieceStructuresGen : : cPieceStructuresGen ( int a_Seed ) :
m_Seed ( a_Seed )
{
}
2021-03-08 11:39:43 -05:00
bool cPieceStructuresGen : : Initialize ( const AString & a_Prefabs , int a_SeaLevel , cBiomeGen & a_BiomeGen , cTerrainHeightGen & a_HeightGen )
2015-11-11 04:32:42 -05:00
{
// Load each piecepool:
2020-10-12 08:35:14 -04:00
auto Structures = StringSplitAndTrim ( a_Prefabs , " | " ) ;
for ( const auto & Structure : Structures )
2015-11-11 04:32:42 -05:00
{
2020-10-12 08:35:14 -04:00
auto FileName = Printf ( " Prefabs%cPieceStructures%c%s.cubeset " , cFile : : PathSeparator ( ) , cFile : : PathSeparator ( ) , Structure . c_str ( ) ) ;
if ( ! cFile : : IsFile ( FileName ) )
2015-11-11 04:32:42 -05:00
{
2020-10-12 08:35:14 -04:00
FileName . append ( " .gz " ) ;
if ( ! cFile : : IsFile ( FileName ) )
2015-11-11 04:32:42 -05:00
{
2020-10-12 08:35:14 -04:00
LOGWARNING ( " Cannot load PieceStructures cubeset file %s " , FileName . c_str ( ) ) ;
2015-11-11 04:32:42 -05:00
continue ;
}
}
2020-10-12 08:35:14 -04:00
auto Gen = std : : make_shared < cGen > ( m_Seed , a_BiomeGen , a_HeightGen , a_SeaLevel , Structure ) ;
if ( Gen - > LoadFromFile ( FileName ) )
2015-11-11 04:32:42 -05:00
{
2020-10-12 08:35:14 -04:00
m_Gens . push_back ( Gen ) ;
2015-11-11 04:32:42 -05:00
}
}
// Report a warning if no generators available:
if ( m_Gens . empty ( ) )
{
2015-12-15 12:04:40 -05:00
LOGWARNING ( " The PieceStructures generator was asked to generate \" %s \" , but none of the prefabs are valid. " , a_Prefabs . c_str ( ) ) ;
2015-11-11 04:32:42 -05:00
return false ;
}
return true ;
}
void cPieceStructuresGen : : GenFinish ( cChunkDesc & a_Chunk )
{
2020-10-12 08:35:14 -04:00
for ( auto & Gen : m_Gens )
2015-11-11 04:32:42 -05:00
{
2020-10-12 08:35:14 -04:00
Gen - > GenFinish ( a_Chunk ) ;
2015-11-11 04:32:42 -05:00
}
}