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
# include "../Stopwatch.h"
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
2017-02-26 16:49:23 -05:00
cGen ( int a_Seed , cBiomeGenPtr a_BiomeGen , cTerrainHeightGenPtr a_HeightGen , int a_SeaLevel , const AString & a_Name ) :
Super ( a_Seed ) ,
2020-05-14 18:15:35 -04:00
m_BiomeGen ( std : : move ( a_BiomeGen ) ) ,
m_HeightGen ( std : : move ( 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:
auto & generatorParams = m_PiecePool . GetAllMetadata ( ) ;
SetGeneratorParams ( generatorParams ) ;
m_MaxDepth = GetStringMapInteger < int > ( generatorParams , " MaxDepth " , m_MaxDepth ) ;
return true ;
}
// cGridStructGen overrides:
virtual cStructurePtr CreateStructure ( int a_GridX , int a_GridZ , int a_OriginX , int a_OriginZ ) override
{
cStopwatch sw ( Printf ( " CreateStructure for %s at <%d, %d> " , m_Name . c_str ( ) , a_GridX , a_GridZ ) ) ;
cPlacedPieces outPieces ;
cPieceGeneratorBFSTree pg ( m_PiecePool , m_Seed ) ;
pg . 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 ) ;
}
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 */
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 ;
/** 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 )
{
}
2020-05-14 18:15:35 -04:00
bool cPieceStructuresGen : : Initialize ( const AString & a_Prefabs , int a_SeaLevel , const cBiomeGenPtr & a_BiomeGen , const cTerrainHeightGenPtr & a_HeightGen )
2015-11-11 04:32:42 -05:00
{
// Load each piecepool:
auto structures = StringSplitAndTrim ( a_Prefabs , " | " ) ;
for ( const auto & s : structures )
{
2018-01-03 12:41:16 -05:00
auto fileName = Printf ( " Prefabs%cPieceStructures%c%s.cubeset " , cFile : : PathSeparator ( ) , cFile : : PathSeparator ( ) , s . c_str ( ) ) ;
2015-11-11 04:32:42 -05:00
if ( ! cFile : : IsFile ( fileName ) )
{
fileName . append ( " .gz " ) ;
if ( ! cFile : : IsFile ( fileName ) )
{
LOGWARNING ( " Cannot load PieceStructures 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 ( ) )
{
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 )
{
for ( auto & gen : m_Gens )
{
gen - > GenFinish ( a_Chunk ) ;
}
}