2014-05-07 05:01:30 -04:00
// PrefabPiecePool.cpp
// Implements the cPrefabPiecePool class that represents a cPiecePool descendant that uses cPrefab instances as the pieces
# include "Globals.h"
# include "PrefabPiecePool.h"
2015-06-17 09:22:43 -04:00
# include "../Bindings/LuaState.h"
# include "WorldStorage/SchematicFileSerializer.h"
2015-11-11 04:32:42 -05:00
# include "VerticalStrategy.h"
# include "../StringCompression.h"
2015-06-17 09:22:43 -04:00
// Conditionally log a warning
# define CONDWARNING(ShouldLog, ...) \
if ( ShouldLog ) \
{ \
LOGWARNING ( __VA_ARGS__ ) ; \
}
/** Returns the map of string => eMergeStrategy used when translating cubeset file merge strategies. */
static std : : map < AString , cBlockArea : : eMergeStrategy > & GetMergeStrategyMap ( void )
{
static std : : map < AString , cBlockArea : : eMergeStrategy > msmap ;
if ( msmap . empty ( ) )
{
// This is the first use, initialize the map:
msmap [ " msOverwrite " ] = cBlockArea : : msOverwrite ;
msmap [ " msFillAir " ] = cBlockArea : : msFillAir ;
msmap [ " msImprint " ] = cBlockArea : : msImprint ;
msmap [ " msLake " ] = cBlockArea : : msLake ;
msmap [ " msSpongePrint " ] = cBlockArea : : msSpongePrint ;
msmap [ " msDifference " ] = cBlockArea : : msDifference ;
msmap [ " msSimpleCompare " ] = cBlockArea : : msSimpleCompare ;
msmap [ " msMask " ] = cBlockArea : : msMask ;
}
return msmap ;
}
////////////////////////////////////////////////////////////////////////////////
// cPrefabPiecePool:
cPrefabPiecePool : : cPrefabPiecePool ( void )
{
}
2014-05-07 05:01:30 -04:00
cPrefabPiecePool : : cPrefabPiecePool (
const cPrefab : : sDef * a_PieceDefs , size_t a_NumPieceDefs ,
2015-11-11 04:32:42 -05:00
const cPrefab : : sDef * a_StartingPieceDefs , size_t a_NumStartingPieceDefs ,
int a_DefaultStartingPieceHeight
2014-05-07 05:01:30 -04:00
)
{
AddPieceDefs ( a_PieceDefs , a_NumPieceDefs ) ;
2014-10-20 16:55:07 -04:00
if ( a_StartingPieceDefs ! = nullptr )
2014-05-07 05:01:30 -04:00
{
2015-11-11 04:32:42 -05:00
AddStartingPieceDefs ( a_StartingPieceDefs , a_NumStartingPieceDefs , a_DefaultStartingPieceHeight ) ;
2014-05-07 05:01:30 -04:00
}
}
2015-06-17 09:22:43 -04:00
cPrefabPiecePool : : cPrefabPiecePool ( const AString & a_FileName , bool a_LogWarnings )
{
LoadFromFile ( a_FileName , a_LogWarnings ) ;
}
2014-05-28 10:33:10 -04:00
cPrefabPiecePool : : ~ cPrefabPiecePool ( )
{
Clear ( ) ;
}
void cPrefabPiecePool : : Clear ( void )
{
m_PiecesByConnector . clear ( ) ;
for ( cPieces : : iterator itr = m_AllPieces . begin ( ) , end = m_AllPieces . end ( ) ; itr ! = end ; + + itr )
{
delete * itr ;
}
m_AllPieces . clear ( ) ;
for ( cPieces : : iterator itr = m_StartingPieces . begin ( ) , end = m_StartingPieces . end ( ) ; itr ! = end ; + + itr )
{
delete * itr ;
}
m_StartingPieces . clear ( ) ;
}
2014-05-07 05:01:30 -04:00
void cPrefabPiecePool : : AddPieceDefs ( const cPrefab : : sDef * a_PieceDefs , size_t a_NumPieceDefs )
{
2014-10-20 16:55:07 -04:00
ASSERT ( a_PieceDefs ! = nullptr ) ;
2014-05-07 05:01:30 -04:00
for ( size_t i = 0 ; i < a_NumPieceDefs ; i + + )
{
cPrefab * Prefab = new cPrefab ( a_PieceDefs [ i ] ) ;
m_AllPieces . push_back ( Prefab ) ;
AddToPerConnectorMap ( Prefab ) ;
}
}
2015-11-11 04:32:42 -05:00
void cPrefabPiecePool : : AddStartingPieceDefs (
const cPrefab : : sDef * a_StartingPieceDefs ,
size_t a_NumStartingPieceDefs ,
int a_DefaultPieceHeight
)
2014-05-07 05:01:30 -04:00
{
2014-10-20 16:55:07 -04:00
ASSERT ( a_StartingPieceDefs ! = nullptr ) ;
2015-11-11 04:32:42 -05:00
auto verticalStrategy = CreateVerticalStrategyFromString ( Printf ( " Fixed|%d " , a_DefaultPieceHeight ) , false ) ;
2014-05-07 05:01:30 -04:00
for ( size_t i = 0 ; i < a_NumStartingPieceDefs ; i + + )
{
cPrefab * Prefab = new cPrefab ( a_StartingPieceDefs [ i ] ) ;
2015-11-11 04:32:42 -05:00
if ( a_DefaultPieceHeight > = 0 )
{
Prefab - > SetVerticalStrategy ( verticalStrategy ) ;
}
2014-05-07 05:01:30 -04:00
m_StartingPieces . push_back ( Prefab ) ;
}
}
2015-06-17 09:22:43 -04:00
bool cPrefabPiecePool : : LoadFromFile ( const AString & a_FileName , bool a_LogWarnings )
{
2015-11-11 04:32:42 -05:00
// Read the file into a string buffer, load from string:
auto contents = cFile : : ReadWholeFile ( a_FileName ) ;
if ( contents . empty ( ) )
2015-06-17 09:22:43 -04:00
{
2015-11-11 04:32:42 -05:00
CONDWARNING ( a_LogWarnings , " Cannot read data from file %s " , a_FileName . c_str ( ) ) ;
2015-06-17 09:22:43 -04:00
return false ;
}
2015-11-11 04:32:42 -05:00
return LoadFromString ( contents , a_FileName , a_LogWarnings ) ;
}
bool cPrefabPiecePool : : LoadFromString ( const AString & a_Contents , const AString & a_FileName , bool a_LogWarnings )
{
// If the contents start with GZip signature, ungzip and retry:
if ( a_Contents . substr ( 0 , 3 ) = = " \x1f \x8b \x08 " )
{
AString Uncompressed ;
auto res = UncompressStringGZIP ( a_Contents . data ( ) , a_Contents . size ( ) , Uncompressed ) ;
if ( res = = Z_OK )
{
return LoadFromString ( Uncompressed , a_FileName , a_LogWarnings ) ;
}
else
{
CONDWARNING ( a_LogWarnings , " Failed to decompress Gzip data in file %s: %d " , a_FileName . c_str ( ) , res ) ;
return false ;
}
}
2015-06-17 09:22:43 -04:00
2015-11-27 03:29:13 -05:00
// Search the first 8 KiB of the file for the format auto-detection string:
auto Header = a_Contents . substr ( 0 , 8192 ) ;
2015-06-17 09:22:43 -04:00
if ( Header . find ( " CubesetFormatVersion = " ) ! = AString : : npos )
{
2015-11-11 04:32:42 -05:00
return LoadFromCubeset ( a_Contents , a_FileName , a_LogWarnings ) ;
2015-06-17 09:22:43 -04:00
}
2015-06-18 17:30:41 -04:00
CONDWARNING ( a_LogWarnings , " Cannot load prefabs from file %s, unknown file format " , a_FileName . c_str ( ) ) ;
2015-06-17 09:22:43 -04:00
return false ;
}
2015-11-11 04:32:42 -05:00
bool cPrefabPiecePool : : LoadFromCubeset ( const AString & a_Contents , const AString & a_FileName , bool a_LogWarnings )
2015-06-17 09:22:43 -04:00
{
// Load the file in the Lua interpreter:
cLuaState Lua ( Printf ( " LoadablePiecePool %s " , a_FileName . c_str ( ) ) ) ;
Lua . Create ( ) ;
2015-11-11 04:32:42 -05:00
if ( ! Lua . LoadString ( a_Contents , a_FileName , a_LogWarnings ) )
2015-06-17 09:22:43 -04:00
{
// Reason for failure has already been logged in LoadFile()
return false ;
}
// Check the version:
int Version = 0 ;
if ( ! Lua . GetNamedGlobal ( " Cubeset.Metadata.CubesetFormatVersion " , Version ) )
{
CONDWARNING ( a_LogWarnings , " Cannot load cubeset %s, it doesn't contain version information. " , a_FileName . c_str ( ) ) ;
return false ;
}
// Load the data, using the correct version loader:
if ( Version = = 1 )
{
2015-11-11 04:32:42 -05:00
return LoadFromCubesetVer1 ( a_FileName , Lua , a_LogWarnings ) ;
2015-06-17 09:22:43 -04:00
}
// Unknown version:
CONDWARNING ( a_LogWarnings , " Cannot load cubeset %s, version (%d) not supported. " , a_FileName . c_str ( ) , Version ) ;
return false ;
}
2014-05-07 05:01:30 -04:00
void cPrefabPiecePool : : AddToPerConnectorMap ( cPrefab * a_Prefab )
{
2015-05-24 07:56:56 -04:00
cPiece : : cConnectors Connectors = ( static_cast < const cPiece * > ( a_Prefab ) ) - > GetConnectors ( ) ;
2014-05-07 05:01:30 -04:00
for ( cPiece : : cConnectors : : const_iterator itr = Connectors . begin ( ) , end = Connectors . end ( ) ; itr ! = end ; + + itr )
{
m_PiecesByConnector [ itr - > m_Type ] . push_back ( a_Prefab ) ;
}
}
2015-06-17 09:22:43 -04:00
2015-11-11 04:32:42 -05:00
bool cPrefabPiecePool : : LoadFromCubesetVer1 ( const AString & a_FileName , cLuaState & a_LuaState , bool a_LogWarnings )
2015-06-17 09:22:43 -04:00
{
2015-11-11 04:32:42 -05:00
// Load the metadata and apply the known ones:
ReadPoolMetadataCubesetVer1 ( a_FileName , a_LuaState , a_LogWarnings ) ;
ApplyBaseMetadataCubesetVer1 ( a_FileName , a_LogWarnings ) ;
2015-06-20 09:37:41 -04:00
2015-06-17 09:22:43 -04:00
// Push the Cubeset.Pieces global value on the stack:
2015-11-11 04:32:42 -05:00
auto pieces = a_LuaState . WalkToNamedGlobal ( " Cubeset.Pieces " ) ;
2015-06-17 09:22:43 -04:00
if ( ! pieces . IsValid ( ) | | ! lua_istable ( a_LuaState , - 1 ) )
{
CONDWARNING ( a_LogWarnings , " The cubeset file %s doesn't contain any pieces " , a_FileName . c_str ( ) ) ;
return false ;
}
// Iterate over all items in the Cubeset.Pieces value:
int idx = 1 ;
bool res = true ;
while ( true )
{
lua_pushinteger ( a_LuaState , idx ) ; // stk: [Pieces] [idx]
lua_gettable ( a_LuaState , - 2 ) ; // stk: [Pieces] [PieceItem]
if ( ! lua_istable ( a_LuaState , - 1 ) )
{
// The PieceItem is not present, we've iterated over all items
lua_pop ( a_LuaState , 1 ) ; // stk: [Pieces]
break ;
}
if ( ! LoadCubesetPieceVer1 ( a_FileName , a_LuaState , idx , a_LogWarnings ) )
{
res = false ;
}
lua_pop ( a_LuaState , 1 ) ; // stk: [Pieces]
idx + = 1 ;
}
return res ;
}
bool cPrefabPiecePool : : LoadCubesetPieceVer1 ( const AString & a_FileName , cLuaState & a_LuaState , int a_PieceIndex , bool a_LogWarnings )
{
ASSERT ( lua_istable ( a_LuaState , - 1 ) ) ;
// The piece name is optional, but useful for debugging messages:
AString PieceName ;
if ( ! a_LuaState . GetNamedValue ( " OriginData.ExportName " , PieceName ) )
{
Printf ( PieceName , " Piece #%d " , a_PieceIndex ) ;
}
// Read the hitbox dimensions:
cCuboid Hitbox ;
if (
! a_LuaState . GetNamedValue ( " Hitbox.MinX " , Hitbox . p1 . x ) | |
! a_LuaState . GetNamedValue ( " Hitbox.MinY " , Hitbox . p1 . y ) | |
! a_LuaState . GetNamedValue ( " Hitbox.MinZ " , Hitbox . p1 . z ) | |
! a_LuaState . GetNamedValue ( " Hitbox.MaxX " , Hitbox . p2 . x ) | |
! a_LuaState . GetNamedValue ( " Hitbox.MaxY " , Hitbox . p2 . y ) | |
! a_LuaState . GetNamedValue ( " Hitbox.MaxZ " , Hitbox . p2 . z )
)
{
CONDWARNING ( a_LogWarnings , " Cannot load piece %s from file %s, it's missing hitbox information " , PieceName . c_str ( ) , a_FileName . c_str ( ) ) ;
return false ;
}
// Load the prefab data:
auto prefab = LoadPrefabFromCubesetVer1 ( a_FileName , a_LuaState , PieceName , a_LogWarnings ) ;
if ( prefab = = nullptr )
{
return false ;
}
2015-10-05 15:15:08 -04:00
prefab - > SetHitBox ( Hitbox ) ;
2015-06-17 09:22:43 -04:00
// Read the connectors
if ( ! ReadConnectorsCubesetVer1 ( a_FileName , a_LuaState , PieceName , prefab . get ( ) , a_LogWarnings ) )
{
return false ;
}
// Read the allowed rotations. It is an optional metadata value, default to 0:
int AllowedRotations = 0 ;
a_LuaState . GetNamedValue ( " Metadata.AllowedRotations " , AllowedRotations ) ;
prefab - > SetAllowedRotations ( AllowedRotations ) ;
2015-11-11 04:32:42 -05:00
// Read the relevant metadata for the piece:
if ( ! ReadPieceMetadataCubesetVer1 ( a_FileName , a_LuaState , PieceName , prefab . get ( ) , a_LogWarnings ) )
2015-06-17 09:22:43 -04:00
{
return false ;
}
2015-11-11 04:32:42 -05:00
// If the piece is a starting piece, check that it has a vertical strategy:
2015-06-17 09:22:43 -04:00
int IsStartingPiece = 0 ;
a_LuaState . GetNamedValue ( " Metadata.IsStarting " , IsStartingPiece ) ;
if ( IsStartingPiece ! = 0 )
2015-11-11 04:32:42 -05:00
{
if ( prefab - > GetVerticalStrategy ( ) = = nullptr )
{
CONDWARNING ( a_LogWarnings , " Starting prefab %s in file %s doesn't have its VerticalStrategy set. Setting to Fixed|150. " ,
PieceName . c_str ( ) , a_FileName . c_str ( )
) ;
VERIFY ( prefab - > SetVerticalStrategyFromString ( " Fixed|150 " , false ) ) ;
}
}
// Add the prefab into the list of pieces:
if ( IsStartingPiece ! = 0 )
2015-06-17 09:22:43 -04:00
{
m_StartingPieces . push_back ( prefab . release ( ) ) ;
}
else
{
auto p = prefab . release ( ) ;
m_AllPieces . push_back ( p ) ;
AddToPerConnectorMap ( p ) ;
}
2015-11-11 04:32:42 -05:00
2015-06-17 09:22:43 -04:00
return true ;
}
UniquePtr < cPrefab > cPrefabPiecePool : : LoadPrefabFromCubesetVer1 (
const AString & a_FileName ,
cLuaState & a_LuaState ,
const AString & a_PieceName ,
bool a_LogWarnings
)
{
// First try loading a referenced schematic file, if any:
AString SchematicFileName ;
if ( a_LuaState . GetNamedValue ( " SchematicFileName " , SchematicFileName ) )
{
auto PathEnd = a_FileName . find_last_of ( " / \\ " ) ; // Find the last path separator
if ( PathEnd ! = AString : : npos )
{
SchematicFileName = a_FileName . substr ( 0 , PathEnd ) + SchematicFileName ;
}
cBlockArea area ;
if ( ! cSchematicFileSerializer : : LoadFromSchematicFile ( area , SchematicFileName ) )
{
CONDWARNING ( a_LogWarnings , " Cannot load schematic file \" %s \" for piece %s in cubeset %s. " ,
SchematicFileName . c_str ( ) , a_PieceName . c_str ( ) , a_FileName . c_str ( )
) ;
return nullptr ;
}
return cpp14 : : make_unique < cPrefab > ( area ) ;
} // if (SchematicFileName)
// There's no referenced schematic file, load from BlockDefinitions / BlockData.
// Get references to the data and the table.concat function:
cLuaState : : cRef TableConcat , BlockDefinitions , BlockData ;
if (
! a_LuaState . GetNamedGlobal ( " table.concat " , TableConcat ) | |
! a_LuaState . GetNamedValue ( " BlockDefinitions " , BlockDefinitions ) | |
! a_LuaState . GetNamedValue ( " BlockData " , BlockData )
)
{
CONDWARNING ( a_LogWarnings , " Cannot parse block data for piece %s in cubeset %s " , a_PieceName . c_str ( ) , a_FileName . c_str ( ) ) ;
return nullptr ;
}
// Call table.concat() on the BlockDefinitions:
AString BlockDefStr ;
if ( ! a_LuaState . Call ( TableConcat , BlockDefinitions , " \n " , cLuaState : : Return , BlockDefStr ) )
{
CONDWARNING ( a_LogWarnings , " Cannot concat block definitions for piece %s in cubeset %s " , a_PieceName . c_str ( ) , a_FileName . c_str ( ) ) ;
return nullptr ;
}
// Call table.concat() on the BlockData:
AString BlockDataStr ;
if ( ! a_LuaState . Call ( TableConcat , BlockData , " " , cLuaState : : Return , BlockDataStr ) )
{
CONDWARNING ( a_LogWarnings , " Cannot concat block data for piece %s in cubeset %s " , a_PieceName . c_str ( ) , a_FileName . c_str ( ) ) ;
return nullptr ;
}
// Read the size:
int SizeX = 0 , SizeY = 0 , SizeZ = 0 ;
if (
! a_LuaState . GetNamedValue ( " Size.x " , SizeX ) | |
! a_LuaState . GetNamedValue ( " Size.y " , SizeY ) | |
! a_LuaState . GetNamedValue ( " Size.z " , SizeZ )
)
{
CONDWARNING ( a_LogWarnings , " Cannot load piece %s from file %s, its size information is missing " , a_PieceName . c_str ( ) , a_FileName . c_str ( ) ) ;
return nullptr ;
}
// Check that the size matches the data length:
if ( static_cast < size_t > ( SizeX * SizeY * SizeZ ) ! = BlockDataStr . size ( ) )
{
CONDWARNING ( a_LogWarnings , " Cannot create piece %s from file %s, its size (%d) doesn't match the blockdata length (%u) " ,
a_PieceName . c_str ( ) , a_FileName . c_str ( ) ,
SizeX * SizeY * SizeZ , static_cast < unsigned > ( BlockDataStr . size ( ) )
) ;
return nullptr ;
}
return cpp14 : : make_unique < cPrefab > ( BlockDefStr , BlockDataStr , SizeX , SizeY , SizeZ ) ;
}
bool cPrefabPiecePool : : ReadConnectorsCubesetVer1 (
const AString & a_FileName ,
cLuaState & a_LuaState ,
const AString & a_PieceName ,
cPrefab * a_Prefab ,
bool a_LogWarnings
)
{
// Get the Connectors subtable:
auto conns = a_LuaState . WalkToValue ( " Connectors " ) ;
if ( ! conns . IsValid ( ) )
{
CONDWARNING ( a_LogWarnings , " Cannot load piece %s from file %s, it has no connectors definition. " , a_PieceName . c_str ( ) , a_FileName . c_str ( ) ) ;
return false ;
}
// Iterate over all items in the Connectors table:
int idx = 1 ;
bool res = true ;
while ( true )
{
lua_pushinteger ( a_LuaState , idx ) ; // stk: [Connectors] [idx]
lua_gettable ( a_LuaState , - 2 ) ; // stk: [Connectors] [conn]
if ( ! lua_istable ( a_LuaState , - 1 ) )
{
// The connector is not present, we've iterated over all items
lua_pop ( a_LuaState , 1 ) ; // stk: [Connectors]
break ;
}
int Type = 0 , RelX = 0 , RelY = 0 , RelZ = 0 ;
eBlockFace Direction = BLOCK_FACE_NONE ;
if (
! a_LuaState . GetNamedValue ( " Type " , Type ) | |
! a_LuaState . GetNamedValue ( " RelX " , RelX ) | |
! a_LuaState . GetNamedValue ( " RelY " , RelY ) | |
! a_LuaState . GetNamedValue ( " RelZ " , RelZ ) | |
! a_LuaState . GetNamedValue ( " Direction " , Direction )
)
{
CONDWARNING ( a_LogWarnings , " Piece %s in file %s has a malformed Connector at index %d. Skipping the connector. " , a_PieceName . c_str ( ) , a_FileName . c_str ( ) , idx ) ;
res = false ;
continue ;
}
a_Prefab - > AddConnector ( RelX , RelY , RelZ , Direction , Type ) ;
lua_pop ( a_LuaState , 1 ) ; // stk: [Connectors]
idx + = 1 ;
}
return res ;
}
2015-11-11 04:32:42 -05:00
bool cPrefabPiecePool : : ReadPieceMetadataCubesetVer1 (
2015-06-17 09:22:43 -04:00
const AString & a_FileName ,
cLuaState & a_LuaState ,
const AString & a_PieceName ,
cPrefab * a_Prefab ,
bool a_LogWarnings
)
{
// Push the Metadata table on top of the Lua stack:
auto md = a_LuaState . WalkToValue ( " Metadata " ) ;
if ( ! md . IsValid ( ) )
{
return false ;
}
// Get the values:
int AddWeightIfSame = 0 , DefaultWeight = 100 , MoveToGround = 0 , ShouldExpandFloor = 0 ;
2015-11-11 04:32:42 -05:00
AString DepthWeight , MergeStrategy , VerticalLimit , VerticalStrategy ;
2015-06-17 09:22:43 -04:00
a_LuaState . GetNamedValue ( " AddWeightIfSame " , AddWeightIfSame ) ;
a_LuaState . GetNamedValue ( " DefaultWeight " , DefaultWeight ) ;
a_LuaState . GetNamedValue ( " DepthWeight " , DepthWeight ) ;
a_LuaState . GetNamedValue ( " MergeStrategy " , MergeStrategy ) ;
a_LuaState . GetNamedValue ( " MoveToGround " , MoveToGround ) ;
a_LuaState . GetNamedValue ( " ShouldExpandFloor " , ShouldExpandFloor ) ;
2015-11-11 04:32:42 -05:00
a_LuaState . GetNamedValue ( " VerticalLimit " , VerticalLimit ) ;
a_LuaState . GetNamedValue ( " VerticalStrategy " , VerticalStrategy ) ;
2015-06-17 09:22:43 -04:00
// Apply the values:
a_Prefab - > SetAddWeightIfSame ( AddWeightIfSame ) ;
a_Prefab - > SetDefaultWeight ( DefaultWeight ) ;
a_Prefab - > ParseDepthWeight ( DepthWeight . c_str ( ) ) ;
auto msmap = GetMergeStrategyMap ( ) ;
auto strategy = msmap . find ( MergeStrategy ) ;
if ( strategy = = msmap . end ( ) )
{
CONDWARNING ( a_LogWarnings , " Unknown merge strategy ( \" %s \" ) specified for piece %s in file %s. Using msSpongePrint instead. " ,
MergeStrategy . c_str ( ) , a_PieceName . c_str ( ) , a_FileName . c_str ( )
) ;
a_Prefab - > SetMergeStrategy ( cBlockArea : : msSpongePrint ) ;
}
2015-06-20 09:37:41 -04:00
else
{
a_Prefab - > SetMergeStrategy ( strategy - > second ) ;
}
2015-06-17 09:22:43 -04:00
a_Prefab - > SetMoveToGround ( MoveToGround ! = 0 ) ;
a_Prefab - > SetExtendFloor ( ShouldExpandFloor ! = 0 ) ;
2015-11-11 04:32:42 -05:00
if ( ! VerticalLimit . empty ( ) )
{
if ( ! a_Prefab - > SetVerticalLimitFromString ( VerticalLimit , a_LogWarnings ) )
{
CONDWARNING ( a_LogWarnings , " Unknown VerticalLimit ( \" %s \" ) specified for piece %s in file %s. Using no limit instead. " ,
VerticalLimit . c_str ( ) , a_PieceName . c_str ( ) , a_FileName . c_str ( )
) ;
}
}
a_Prefab - > SetVerticalStrategyFromString ( VerticalStrategy , a_LogWarnings ) ;
2015-06-17 09:22:43 -04:00
return true ;
}
2015-11-11 04:32:42 -05:00
void cPrefabPiecePool : : ApplyBaseMetadataCubesetVer1 (
2015-06-20 09:37:41 -04:00
const AString & a_FileName ,
bool a_LogWarnings
)
{
// Set the metadata values to defaults:
m_MinDensity = 100 ;
m_MaxDensity = 100 ;
m_VillageRoadBlockType = E_BLOCK_GRAVEL ;
m_VillageRoadBlockMeta = 0 ;
m_VillageWaterRoadBlockType = E_BLOCK_PLANKS ;
m_VillageWaterRoadBlockMeta = 0 ;
// Read the metadata values:
2015-11-11 04:32:42 -05:00
m_IntendedUse = GetMetadata ( " IntendedUse " ) ;
GetStringMapInteger ( m_Metadata , " MaxDensity " , m_MaxDensity ) ;
GetStringMapInteger ( m_Metadata , " MinDensity " , m_MinDensity ) ;
GetStringMapInteger ( m_Metadata , " VillageRoadBlockType " , m_VillageRoadBlockType ) ;
GetStringMapInteger ( m_Metadata , " VillageRoadBlockMeta " , m_VillageRoadBlockMeta ) ;
GetStringMapInteger ( m_Metadata , " VillageWaterRoadBlockType " , m_VillageWaterRoadBlockType ) ;
GetStringMapInteger ( m_Metadata , " VillageWaterRoadBlockMeta " , m_VillageWaterRoadBlockMeta ) ;
// Read the allowed biomes:
AString allowedBiomes = GetMetadata ( " AllowedBiomes " ) ;
if ( allowedBiomes . empty ( ) )
{
// All biomes are allowed:
for ( int b = biFirstBiome ; b < = biMaxBiome ; b + + )
{
m_AllowedBiomes . insert ( static_cast < EMCSBiome > ( b ) ) ;
}
for ( int b = biFirstVariantBiome ; b < = biMaxVariantBiome ; b + + )
{
m_AllowedBiomes . insert ( static_cast < EMCSBiome > ( b ) ) ;
}
}
else
2015-06-20 09:37:41 -04:00
{
auto biomes = StringSplitAndTrim ( allowedBiomes , " , " ) ;
for ( const auto & biome : biomes )
{
EMCSBiome b = StringToBiome ( biome ) ;
if ( b = = biInvalidBiome )
{
CONDWARNING ( a_LogWarnings , " Invalid biome ( \" %s \" ) specified in AllowedBiomes in cubeset file %s. Skipping the biome. " ,
biome . c_str ( ) , a_FileName . c_str ( )
) ;
continue ;
}
m_AllowedBiomes . insert ( b ) ;
}
}
2015-11-11 04:32:42 -05:00
}
bool cPrefabPiecePool : : ReadPoolMetadataCubesetVer1 (
const AString & a_FileName ,
cLuaState & a_LuaState ,
bool a_LogWarnings
)
{
// Push the Cubeset.Metadata table on top of the Lua stack:
auto gp = a_LuaState . WalkToNamedGlobal ( " Cubeset.Metadata " ) ;
if ( ! gp . IsValid ( ) )
2015-06-20 09:37:41 -04:00
{
2015-11-11 04:32:42 -05:00
return true ;
}
// Iterate over elements in the table, put them into the m_GeneratorParams map:
lua_pushnil ( a_LuaState ) ; // Table is at index -2, starting key (nil) at index -1
while ( lua_next ( a_LuaState , - 2 ) ! = 0 )
{
// Table at index -3, key at index -2, value at index -1
AString key , val ;
a_LuaState . GetStackValues ( - 2 , key , val ) ;
m_Metadata [ key ] = val ;
lua_pop ( a_LuaState , 1 ) ; // Table at index -2, key at index -1
}
return true ;
}
AString cPrefabPiecePool : : GetMetadata ( const AString & a_ParamName ) const
{
auto itr = m_Metadata . find ( a_ParamName ) ;
if ( itr = = m_Metadata . end ( ) )
{
return AString ( ) ;
}
return itr - > second ;
}
void cPrefabPiecePool : : AssignGens ( int a_Seed , cBiomeGenPtr & a_BiomeGen , cTerrainHeightGenPtr & a_HeightGen , int a_SeaLevel )
{
// Assign the generator linkage to all starting pieces' VerticalStrategies:
for ( auto & piece : m_StartingPieces )
{
auto verticalStrategy = piece - > GetVerticalStrategy ( ) ;
if ( verticalStrategy ! = nullptr )
2015-06-20 09:37:41 -04:00
{
2015-11-11 04:32:42 -05:00
verticalStrategy - > AssignGens ( a_Seed , a_BiomeGen , a_HeightGen , a_SeaLevel ) ;
2015-06-20 09:37:41 -04:00
}
2015-11-11 04:32:42 -05:00
} // for piece - m_StartingPieces[]
// Assign the generator linkage to all pieces' VerticalLimits:
for ( auto & piece : m_AllPieces )
{
auto verticalLimit = piece - > GetVerticalLimit ( ) ;
if ( verticalLimit ! = nullptr )
2015-06-20 09:37:41 -04:00
{
2015-11-11 04:32:42 -05:00
verticalLimit - > AssignGens ( a_Seed , a_BiomeGen , a_HeightGen , a_SeaLevel ) ;
2015-06-20 09:37:41 -04:00
}
2015-11-11 04:32:42 -05:00
} // for piece - m_AllPieces[]
2015-06-20 09:37:41 -04:00
}
2014-05-07 05:01:30 -04:00
cPieces cPrefabPiecePool : : GetPiecesWithConnector ( int a_ConnectorType )
{
return m_PiecesByConnector [ a_ConnectorType ] ;
}
cPieces cPrefabPiecePool : : GetStartingPieces ( void )
{
if ( m_StartingPieces . empty ( ) )
{
return m_AllPieces ;
}
else
{
return m_StartingPieces ;
}
}
int cPrefabPiecePool : : GetPieceWeight ( const cPlacedPiece & a_PlacedPiece , const cPiece : : cConnector & a_ExistingConnector , const cPiece & a_NewPiece )
{
2015-11-11 04:32:42 -05:00
return ( reinterpret_cast < const cPrefab & > ( a_NewPiece ) ) . GetPieceWeight ( a_PlacedPiece , a_ExistingConnector ) ;
2014-05-07 05:01:30 -04:00
}
2014-05-27 16:05:50 -04:00
int cPrefabPiecePool : : GetStartingPieceWeight ( const cPiece & a_NewPiece )
{
2015-11-11 04:32:42 -05:00
return ( reinterpret_cast < const cPrefab & > ( a_NewPiece ) ) . GetDefaultWeight ( ) ;
2014-05-27 16:05:50 -04:00
}
2014-05-07 05:01:30 -04:00
void cPrefabPiecePool : : PiecePlaced ( const cPiece & a_Piece )
{
// Do nothing
UNUSED ( a_Piece ) ;
}
void cPrefabPiecePool : : Reset ( void )
{
// Do nothing
}