cPieceModifier interface and cPieceModifierRandomizeBlocks class (#5122)
This commit is contained in:
parent
d78bcac150
commit
befe132861
@ -18,6 +18,7 @@ target_sources(
|
|||||||
MineShafts.cpp
|
MineShafts.cpp
|
||||||
Noise3DGenerator.cpp
|
Noise3DGenerator.cpp
|
||||||
PieceGeneratorBFSTree.cpp
|
PieceGeneratorBFSTree.cpp
|
||||||
|
PieceModifier.cpp
|
||||||
PiecePool.cpp
|
PiecePool.cpp
|
||||||
PieceStructuresGen.cpp
|
PieceStructuresGen.cpp
|
||||||
Prefab.cpp
|
Prefab.cpp
|
||||||
@ -52,6 +53,7 @@ target_sources(
|
|||||||
MineShafts.h
|
MineShafts.h
|
||||||
Noise3DGenerator.h
|
Noise3DGenerator.h
|
||||||
PieceGeneratorBFSTree.h
|
PieceGeneratorBFSTree.h
|
||||||
|
PieceModifier.h
|
||||||
PiecePool.h
|
PiecePool.h
|
||||||
PieceStructuresGen.h
|
PieceStructuresGen.h
|
||||||
Prefab.h
|
Prefab.h
|
||||||
|
402
src/Generating/PieceModifier.cpp
Normal file
402
src/Generating/PieceModifier.cpp
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
|
||||||
|
// PieceModifier.cpp
|
||||||
|
|
||||||
|
// Implements the various classes descending from cPiece::cPieceModifier
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "PieceModifier.h"
|
||||||
|
#include "../Noise/Noise.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Constant that is added to seed
|
||||||
|
static const int SEED_OFFSET = 135 * 13;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Emit a warning if the first param is true
|
||||||
|
#define CONDWARNING(ShouldLog, Fmt, ...) \
|
||||||
|
do { \
|
||||||
|
if (ShouldLog) \
|
||||||
|
{ \
|
||||||
|
LOGWARNING(Fmt, __VA_ARGS__); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/** A modifier which is pseudo-randomly replacing blocks to other types and metas. */
|
||||||
|
class cPieceModifierRandomizeBlocks:
|
||||||
|
public cPiece::cPieceModifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cPieceModifierRandomizeBlocks(void) :
|
||||||
|
m_Seed()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) override
|
||||||
|
{
|
||||||
|
m_AllWeights = 0;
|
||||||
|
AString Params = a_Params;
|
||||||
|
|
||||||
|
|
||||||
|
/** BlocksToReplace parsing */
|
||||||
|
auto idxPipe = Params.find('|');
|
||||||
|
if (idxPipe != AString::npos)
|
||||||
|
{
|
||||||
|
AString blocksToReplaceStr = Params.substr(0, idxPipe);
|
||||||
|
auto blocksToReplace = StringSplitAndTrim(blocksToReplaceStr, ",");
|
||||||
|
for (size_t i = 0; i < blocksToReplace.size(); i++)
|
||||||
|
{
|
||||||
|
BLOCKTYPE blockType = static_cast<BLOCKTYPE>(BlockStringToType(blocksToReplace[i]));
|
||||||
|
if ((blockType == E_BLOCK_AIR) && !NoCaseCompare(blocksToReplace[i], "Air"))
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "Cannot parse block type from string \"%s\"!", blocksToReplace[i].c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_BlocksToReplace[blockType] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Params = Params.substr(idxPipe + 1, Params.length() - 1);
|
||||||
|
}
|
||||||
|
if (m_BlocksToReplace.size() == 0)
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "You must specify at least one block to replace%s!", "");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Meta params parsing */
|
||||||
|
auto idxSqBracketStart = Params.find('[');
|
||||||
|
auto idxSqBracketStartLast = Params.find_last_of('[');
|
||||||
|
|
||||||
|
bool isMultiMeta = false;
|
||||||
|
if ((idxSqBracketStart != idxSqBracketStartLast) && (idxSqBracketStartLast != Params.length() - 1))
|
||||||
|
{
|
||||||
|
// Meta per block type
|
||||||
|
isMultiMeta = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto idxSqBracketEnd = Params.find(']');
|
||||||
|
if ((idxSqBracketEnd == Params.length() - 1) && (idxSqBracketStart != AString::npos))
|
||||||
|
{
|
||||||
|
AString metaParamsStr = Params.substr(idxSqBracketStart + 1, Params.length() - idxSqBracketStart - 2);
|
||||||
|
std::array<int, 4> metaParamsInt;
|
||||||
|
if (!ParseMeta(metaParamsStr, metaParamsInt, a_LogWarnings))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_MinMeta = metaParamsInt[0];
|
||||||
|
m_MaxMeta = metaParamsInt[1];
|
||||||
|
m_MinNoiseMeta = metaParamsInt[2];
|
||||||
|
m_MaxNoiseMeta = metaParamsInt[3];
|
||||||
|
|
||||||
|
Params = Params.substr(0, idxSqBracketStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// BlocksToRandomize parsing
|
||||||
|
auto BlocksToRandomize = StringSplitAndTrim(Params, ";");
|
||||||
|
for (size_t i = 0; i < BlocksToRandomize.size(); i++)
|
||||||
|
{
|
||||||
|
AString block = BlocksToRandomize[i];
|
||||||
|
|
||||||
|
cRandomizedBlock Block{};
|
||||||
|
|
||||||
|
if (isMultiMeta)
|
||||||
|
{
|
||||||
|
auto sqBrStart = block.find('[');
|
||||||
|
if (sqBrStart != AString::npos)
|
||||||
|
{
|
||||||
|
auto sqBrEnd = block.find(']');
|
||||||
|
if (sqBrEnd != block.size() - 1)
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "If present, block meta params must be at the end of block to randomize definition \"%s\"!", block.c_str());
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
AString metaParamsStr = block.substr(sqBrStart + 1, block.size() - sqBrStart - 2);
|
||||||
|
|
||||||
|
std::array<int, 4> metaParamsInt;
|
||||||
|
if (!ParseMeta(metaParamsStr, metaParamsInt, a_LogWarnings))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block.m_MinMeta = metaParamsInt[0];
|
||||||
|
Block.m_MaxMeta = metaParamsInt[1];
|
||||||
|
Block.m_MinNoiseMeta = metaParamsInt[2];
|
||||||
|
Block.m_MaxNoiseMeta = metaParamsInt[3];
|
||||||
|
|
||||||
|
block = block.substr(0, sqBrStart);
|
||||||
|
|
||||||
|
}
|
||||||
|
// No meta randomization for this block
|
||||||
|
}
|
||||||
|
|
||||||
|
auto BlockParams = StringSplitAndTrim(block, ",");
|
||||||
|
if (BlockParams.size() < 2)
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "Block weight is required param \"%s\"!", BlockParams[0].c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BLOCKTYPE BlockType = static_cast<BLOCKTYPE>(BlockStringToType(BlockParams[0]));
|
||||||
|
int BlockWeight = 0;
|
||||||
|
if ((BlockType != E_BLOCK_AIR) && !NoCaseCompare(BlockParams[0], "Air"))
|
||||||
|
{
|
||||||
|
// Failed to parse block type
|
||||||
|
CONDWARNING(
|
||||||
|
a_LogWarnings, "Cannot parse block type from string \"%s\"!",
|
||||||
|
BlockParams[0].c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringToInteger(BlockParams[1], BlockWeight))
|
||||||
|
{
|
||||||
|
// Failed to parse the crop weight:
|
||||||
|
CONDWARNING(
|
||||||
|
a_LogWarnings,
|
||||||
|
"Cannot parse block weight from string \"%s\"!",
|
||||||
|
BlockParams[1].c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Block.m_Type = BlockType;
|
||||||
|
Block.m_Weight = BlockWeight;
|
||||||
|
m_AllWeights += BlockWeight;
|
||||||
|
|
||||||
|
m_BlocksToRandomize.push_back(Block);
|
||||||
|
}
|
||||||
|
if (m_BlocksToRandomize.size() == 0)
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "You must specify at least one block to randomize%s!", "");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool ParseMeta(const AString & a_Meta, std::array<int, 4> & a_ParsedMeta, bool a_LogWarnings)
|
||||||
|
{
|
||||||
|
auto MetaParams = StringSplitAndTrim(a_Meta, ",");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MetaParams.size(); i++)
|
||||||
|
{
|
||||||
|
int Value;
|
||||||
|
if (!StringToInteger(MetaParams[i], Value))
|
||||||
|
{
|
||||||
|
// Failed to parse meta parameter from string:
|
||||||
|
CONDWARNING(a_LogWarnings, "Cannot parse meta param from string \"%s\", meta: %s!", MetaParams[i].c_str(), a_Meta.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > 3)
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "Unsupported meta param \"%d\"!", Value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_ParsedMeta[i] = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MetaParams.size() == 1)
|
||||||
|
{
|
||||||
|
// Noise is not used for meta
|
||||||
|
a_ParsedMeta[1] = a_ParsedMeta[0];
|
||||||
|
}
|
||||||
|
else if (MetaParams.size() == 2)
|
||||||
|
{
|
||||||
|
// Noise range is same as meta range
|
||||||
|
a_ParsedMeta[2] = a_ParsedMeta[0];
|
||||||
|
a_ParsedMeta[3] = a_ParsedMeta[1];
|
||||||
|
}
|
||||||
|
else if (MetaParams.size() == 3)
|
||||||
|
{
|
||||||
|
a_ParsedMeta[3] = a_ParsedMeta[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual void Modify(cBlockArea & a_Image, const Vector3i a_PiecePos, const int a_PieceRot) override
|
||||||
|
{
|
||||||
|
cNoise Noise(m_Seed);
|
||||||
|
cNoise PieceNoise(Noise.IntNoise3DInt(a_PiecePos));
|
||||||
|
|
||||||
|
size_t NumBlocks = a_Image.GetBlockCount();
|
||||||
|
BLOCKTYPE * BlockTypes = a_Image.GetBlockTypes();
|
||||||
|
BLOCKTYPE * BlockMetas = a_Image.GetBlockMetas();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NumBlocks; i++)
|
||||||
|
{
|
||||||
|
if (m_BlocksToReplace.count(BlockTypes[i]))
|
||||||
|
{
|
||||||
|
float BlockRnd = PieceNoise.IntNoise2DInRange(a_PieceRot, static_cast<int>(i), 0, m_AllWeights);
|
||||||
|
|
||||||
|
int weightDelta = 0;
|
||||||
|
for (auto & blockToRnd : m_BlocksToRandomize)
|
||||||
|
{
|
||||||
|
weightDelta += blockToRnd.m_Weight;
|
||||||
|
if (BlockRnd <= weightDelta)
|
||||||
|
{
|
||||||
|
BlockTypes[i] = blockToRnd.m_Type;
|
||||||
|
|
||||||
|
// Per block meta params
|
||||||
|
if (blockToRnd.m_MinMeta < blockToRnd.m_MaxMeta)
|
||||||
|
{
|
||||||
|
int BlockMetaRnd = std::clamp(static_cast<int>(PieceNoise.IntNoise2DInRange(a_PieceRot*2, static_cast<int>(i), blockToRnd.m_MinNoiseMeta, blockToRnd.m_MaxNoiseMeta)), blockToRnd.m_MinMeta, blockToRnd.m_MaxMeta);
|
||||||
|
BlockMetas[i] = static_cast<NIBBLETYPE>(BlockMetaRnd);
|
||||||
|
}
|
||||||
|
else if ((blockToRnd.m_MaxMeta > -1) && (blockToRnd.m_MaxMeta == blockToRnd.m_MinMeta))
|
||||||
|
{
|
||||||
|
// Change meta if at least minimum meta was specified
|
||||||
|
BlockMetas[i] = static_cast<NIBBLETYPE>(blockToRnd.m_MaxMeta);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All blocks meta params
|
||||||
|
if (m_MaxMeta > m_MinMeta)
|
||||||
|
{
|
||||||
|
int BlockMetaRnd = std::clamp(static_cast<int>(PieceNoise.IntNoise2DInRange(a_PieceRot*2, static_cast<int>(i), m_MinNoiseMeta, m_MaxNoiseMeta)), m_MinMeta, m_MaxMeta);
|
||||||
|
BlockMetas[i] = static_cast<NIBBLETYPE>(BlockMetaRnd);
|
||||||
|
}
|
||||||
|
else if ((m_MaxMeta > -1) && (m_MaxMeta == m_MinMeta))
|
||||||
|
{
|
||||||
|
// Change meta if at least minimum meta was specified
|
||||||
|
BlockMetas[i] = static_cast<NIBBLETYPE>(m_MaxMeta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // for i - BlockTypes[]
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void AssignSeed(int a_Seed) override
|
||||||
|
{
|
||||||
|
m_Seed = a_Seed + SEED_OFFSET;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
int m_Seed;
|
||||||
|
int m_AllWeights = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/** Block types of a blocks which are being replaced by this strategy */
|
||||||
|
std::map<BLOCKTYPE, int> m_BlocksToReplace;
|
||||||
|
|
||||||
|
/** Randomized blocks with their weights and meta params */
|
||||||
|
cRandomizedBlocks m_BlocksToRandomize;
|
||||||
|
|
||||||
|
/** Minimum meta to randomize */
|
||||||
|
int m_MinMeta = 0;
|
||||||
|
|
||||||
|
/** Maximum meta to randomize */
|
||||||
|
int m_MaxMeta = -1;
|
||||||
|
|
||||||
|
/** Maximum meta in noise range */
|
||||||
|
int m_MaxNoiseMeta = 0;
|
||||||
|
|
||||||
|
/** Minimum meta in noise range */
|
||||||
|
int m_MinNoiseMeta = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// CreatePieceModifierFromString:
|
||||||
|
|
||||||
|
bool CreatePieceModifierFromString(const AString & a_Definition, std::shared_ptr<cPiece::cPieceModifiers> & a_Modifiers, bool a_LogWarnings)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto idxCurlyStart = a_Definition.find('{');
|
||||||
|
auto idxCurlyFirstEnd = a_Definition.find('}');
|
||||||
|
if ((idxCurlyStart == AString::npos) && (idxCurlyFirstEnd == AString::npos))
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "Piece metadata \"Modifiers\" needs at least one valid modifier definition \"%s\"!", a_Definition.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto modifiersStr = StringSplitAndTrim(a_Definition, "{");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < modifiersStr.size(); i++)
|
||||||
|
{
|
||||||
|
AString modifierStr = TrimString(modifiersStr[i]);
|
||||||
|
|
||||||
|
if (modifierStr.size() == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto idxCurlyEnd = modifierStr.find('}');
|
||||||
|
if (idxCurlyEnd == AString::npos)
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "Modifier definition must end with curly bracket \"%s\"!!", modifierStr.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
modifierStr = modifierStr.substr(0, idxCurlyEnd);
|
||||||
|
|
||||||
|
// Break apart the modifier class, the first parameter before the first pipe char:
|
||||||
|
auto idxPipe = modifierStr.find('|');
|
||||||
|
if (idxPipe == AString::npos)
|
||||||
|
{
|
||||||
|
idxPipe = modifierStr.length();
|
||||||
|
}
|
||||||
|
AString ModifierClass = modifierStr.substr(0, idxPipe);
|
||||||
|
|
||||||
|
// Create a modifier class based on the class string:
|
||||||
|
cPiece::cPieceModifierPtr Modifier;
|
||||||
|
if (NoCaseCompare(ModifierClass, "RandomizeBlocks") == 0)
|
||||||
|
{
|
||||||
|
Modifier = std::make_shared<cPieceModifierRandomizeBlocks>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Modifier == nullptr)
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "Unknown modifier class \"%s\" %s!", ModifierClass.c_str(), modifierStr.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the modifier's parameters:
|
||||||
|
AString Params;
|
||||||
|
if (idxPipe < modifierStr.length())
|
||||||
|
{
|
||||||
|
Params = modifierStr.substr(idxPipe + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Modifier->InitializeFromString(Params, a_LogWarnings))
|
||||||
|
{
|
||||||
|
CONDWARNING(a_LogWarnings, "InitializeFromString error \"%s\" -- %!", Params.c_str(), modifierStr.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
a_Modifiers->push_back(Modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
45
src/Generating/PieceModifier.h
Normal file
45
src/Generating/PieceModifier.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
// PieceModifier.h
|
||||||
|
|
||||||
|
// Declares the public interface for cPiece's cPieceModifier implementations
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PiecePool.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool CreatePieceModifierFromString(const AString & a_Definition, std::shared_ptr<cPiece::cPieceModifiers> & a_Modifiers, bool a_LogWarnings);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Used to store block type, meta, weight and some more params */
|
||||||
|
class cRandomizedBlock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BLOCKTYPE m_Type;
|
||||||
|
|
||||||
|
int m_Weight;
|
||||||
|
|
||||||
|
/** Minimum meta to randomize */
|
||||||
|
int m_MinMeta = 0;
|
||||||
|
|
||||||
|
/** Maximum meta to randomize */
|
||||||
|
int m_MaxMeta = -1;
|
||||||
|
|
||||||
|
/** Maximum meta in noise range */
|
||||||
|
int m_MaxNoiseMeta = 0;
|
||||||
|
|
||||||
|
/** Minimum meta in noise range */
|
||||||
|
int m_MinNoiseMeta = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<cRandomizedBlock> cRandomizedBlocks;
|
@ -8,6 +8,7 @@
|
|||||||
#include "PiecePool.h"
|
#include "PiecePool.h"
|
||||||
#include "VerticalStrategy.h"
|
#include "VerticalStrategy.h"
|
||||||
#include "VerticalLimit.h"
|
#include "VerticalLimit.h"
|
||||||
|
#include "PieceModifier.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -46,6 +47,29 @@ bool cPiece::SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogW
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPiece::SetPieceModifiersFromString(const AString & a_Definition, bool a_LogWarnings)
|
||||||
|
{
|
||||||
|
auto modifiers = std::make_shared<cPieceModifiers>();
|
||||||
|
if (!CreatePieceModifierFromString(a_Definition, modifiers, a_LogWarnings))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cPieceModifiers Modifiers;
|
||||||
|
for (size_t i = 0; i < modifiers->size(); i++)
|
||||||
|
{
|
||||||
|
Modifiers.push_back(std::move(modifiers->at(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Modifiers = Modifiers;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const
|
Vector3i cPiece::RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const
|
||||||
{
|
{
|
||||||
Vector3i Size = GetSize();
|
Vector3i Size = GetSize();
|
||||||
|
@ -148,12 +148,41 @@ public:
|
|||||||
typedef std::shared_ptr<cVerticalLimit> cVerticalLimitPtr;
|
typedef std::shared_ptr<cVerticalLimit> cVerticalLimitPtr;
|
||||||
|
|
||||||
|
|
||||||
|
/** Base class (interface) for piece modifiers. */
|
||||||
|
class cPieceModifier
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Force a virtual destructor in descendants
|
||||||
|
virtual ~cPieceModifier() {}
|
||||||
|
|
||||||
|
/** Initializes the modifier's parameters from the string
|
||||||
|
representation. a_Params is the string containing only the parameters
|
||||||
|
If a_LogWarnings is true, logs any problems to the console.
|
||||||
|
Returns true if successful, false if the string parsing failed.
|
||||||
|
Used when loading the modifier from a file. */
|
||||||
|
virtual bool InitializeFromString(const AString & a_Params, bool a_LogWarnings) = 0;
|
||||||
|
|
||||||
|
/** Called prior to writing piece to a chunk, so that modifiers can modify blocks in the blockarea */
|
||||||
|
virtual void Modify(cBlockArea & a_Image, const Vector3i a_PiecePos, const int a_PieceNumRotations) = 0;
|
||||||
|
|
||||||
|
/** Called when the piece pool is assigned to a generator,
|
||||||
|
so that the modifiers can access world seed. */
|
||||||
|
virtual void AssignSeed(int a_Seed) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::shared_ptr<cPieceModifier> cPieceModifierPtr;
|
||||||
|
|
||||||
|
typedef std::vector<cPieceModifierPtr> cPieceModifiers;
|
||||||
|
|
||||||
/** The strategy used for vertical placement of this piece when it is used as a starting piece. */
|
/** The strategy used for vertical placement of this piece when it is used as a starting piece. */
|
||||||
cVerticalStrategyPtr m_VerticalStrategy;
|
cVerticalStrategyPtr m_VerticalStrategy;
|
||||||
|
|
||||||
/** The checker that verifies each placement's vertical position. */
|
/** The checker that verifies each placement's vertical position. */
|
||||||
cVerticalLimitPtr m_VerticalLimit;
|
cVerticalLimitPtr m_VerticalLimit;
|
||||||
|
|
||||||
|
/** The modifiers which are modifying piece's blocks. */
|
||||||
|
cPieceModifiers m_Modifiers;
|
||||||
|
|
||||||
/** Returns all of the available connectors that the piece has.
|
/** Returns all of the available connectors that the piece has.
|
||||||
Each connector has a (relative) position in the piece, and a type associated with it. */
|
Each connector has a (relative) position in the piece, and a type associated with it. */
|
||||||
@ -196,6 +225,11 @@ public:
|
|||||||
return m_VerticalLimit;
|
return m_VerticalLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cPieceModifiers GetModifiers(void) const
|
||||||
|
{
|
||||||
|
return m_Modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
/** Sets the vertical strategy based on the description in the string.
|
/** Sets the vertical strategy based on the description in the string.
|
||||||
If a_LogWarnings is true, logs the parsing problems into the server console.
|
If a_LogWarnings is true, logs the parsing problems into the server console.
|
||||||
Returns true if successful, false if strategy parsing failed (no strategy assigned). */
|
Returns true if successful, false if strategy parsing failed (no strategy assigned). */
|
||||||
@ -206,6 +240,12 @@ public:
|
|||||||
If a_LogWarnings is true, any problem is reported into the server console. */
|
If a_LogWarnings is true, any problem is reported into the server console. */
|
||||||
bool SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings);
|
bool SetVerticalLimitFromString(const AString & a_LimitDesc, bool a_LogWarnings);
|
||||||
|
|
||||||
|
/** Sets the modifiers with their params in the string.
|
||||||
|
If a_LogWarnings is true, logs the parsing problems into the server console.
|
||||||
|
Returns true if successful, false if strategy parsing failed (no strategy
|
||||||
|
assigned). */
|
||||||
|
bool SetPieceModifiersFromString(const AString & a_Definition, bool a_LogWarnings);
|
||||||
|
|
||||||
/** Returns a copy of the a_Pos after rotating the piece the specified number of CCW rotations. */
|
/** Returns a copy of the a_Pos after rotating the piece the specified number of CCW rotations. */
|
||||||
Vector3i RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const;
|
Vector3i RotatePos(const Vector3i & a_Pos, int a_NumCCWRotations) const;
|
||||||
|
|
||||||
|
@ -157,8 +157,24 @@ void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumR
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the image:
|
if (m_Modifiers.size() == 0)
|
||||||
a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
|
{
|
||||||
|
// Write the image:
|
||||||
|
a_Dest.WriteBlockArea(Image, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cBlockArea RandomizedImage;
|
||||||
|
Image.CopyTo(RandomizedImage);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_Modifiers.size(); i++)
|
||||||
|
{
|
||||||
|
m_Modifiers[i]->Modify(RandomizedImage, a_Placement, a_NumRotations);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the modified image:
|
||||||
|
a_Dest.WriteBlockArea(RandomizedImage, Placement.x, Placement.y, Placement.z, m_MergeStrategy);
|
||||||
|
}
|
||||||
|
|
||||||
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)
|
// If requested, draw the floor (from the bottom of the prefab down to the nearest non-air)
|
||||||
switch (m_ExtendFloorStrategy)
|
switch (m_ExtendFloorStrategy)
|
||||||
|
@ -615,6 +615,12 @@ bool cPrefabPiecePool::ReadPieceMetadataCubesetVer1(
|
|||||||
}
|
}
|
||||||
a_Prefab->SetVerticalStrategyFromString(VerticalStrategy, a_LogWarnings);
|
a_Prefab->SetVerticalStrategyFromString(VerticalStrategy, a_LogWarnings);
|
||||||
|
|
||||||
|
AString ModifiersStr;
|
||||||
|
if (a_LuaState.GetNamedValue("Modifiers", ModifiersStr))
|
||||||
|
{
|
||||||
|
a_Prefab->SetPieceModifiersFromString(ModifiersStr, a_LogWarnings);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,6 +750,14 @@ void cPrefabPiecePool::AssignGens(int a_Seed, cBiomeGen & a_BiomeGen, cTerrainHe
|
|||||||
{
|
{
|
||||||
verticalLimit->AssignGens(a_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel);
|
verticalLimit->AssignGens(a_Seed, a_BiomeGen, a_HeightGen, a_SeaLevel);
|
||||||
}
|
}
|
||||||
|
auto modifiers = piece->GetModifiers();
|
||||||
|
if (modifiers.size() > 0)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < modifiers.size(); i++)
|
||||||
|
{
|
||||||
|
modifiers[i]->AssignSeed(a_Seed);
|
||||||
|
}
|
||||||
|
}
|
||||||
} // for piece - m_AllPieces[]
|
} // for piece - m_AllPieces[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ set (GENERATING_SRCS
|
|||||||
${PROJECT_SOURCE_DIR}/src/Generating/MineShafts.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/MineShafts.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/Noise3DGenerator.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/Noise3DGenerator.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PieceGeneratorBFSTree.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceGeneratorBFSTree.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PieceStructuresGen.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceStructuresGen.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.cpp
|
||||||
@ -119,6 +120,7 @@ set (GENERATING_HDRS
|
|||||||
${PROJECT_SOURCE_DIR}/src/Generating/MineShafts.h
|
${PROJECT_SOURCE_DIR}/src/Generating/MineShafts.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/Noise3DGenerator.h
|
${PROJECT_SOURCE_DIR}/src/Generating/Noise3DGenerator.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PieceGeneratorBFSTree.h
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceGeneratorBFSTree.h
|
||||||
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h
|
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PieceStructuresGen.h
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceStructuresGen.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h
|
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h
|
||||||
|
@ -14,6 +14,7 @@ set (SHARED_SRCS
|
|||||||
${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.cpp
|
${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.cpp
|
||||||
|
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.cpp
|
${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.cpp
|
||||||
@ -45,6 +46,7 @@ set (SHARED_HDRS
|
|||||||
${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.h
|
${PROJECT_SOURCE_DIR}/src/Bindings/LuaState.h
|
||||||
|
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.h
|
${PROJECT_SOURCE_DIR}/src/Generating/ChunkDesc.h
|
||||||
|
${PROJECT_SOURCE_DIR}/src/Generating/PieceModifier.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h
|
${PROJECT_SOURCE_DIR}/src/Generating/PiecePool.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h
|
${PROJECT_SOURCE_DIR}/src/Generating/Prefab.h
|
||||||
${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.h
|
${PROJECT_SOURCE_DIR}/src/Generating/PrefabPiecePool.h
|
||||||
|
@ -297,3 +297,12 @@ bool cUUID::FromString(const AString &)
|
|||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int BlockStringToType(const AString &)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user