11 #include "../WorldStorage/SchematicFileSerializer.h"
13 #include "../BlockInfo.h"
20 m_Size(a_Def.m_SizeX, a_Def.m_SizeY, a_Def.m_SizeZ),
23 {a_Def.m_HitboxMaxX, a_Def.m_HitboxMaxY, a_Def.m_HitboxMaxZ}
25 m_AllowedRotations(a_Def.m_AllowedRotations),
26 m_MergeStrategy(a_Def.m_MergeStrategy),
27 m_ExtendFloorStrategy(a_Def.m_ExtendFloorStrategy),
28 m_DefaultWeight(a_Def.m_DefaultWeight),
29 m_AddWeightIfSame(a_Def.m_AddWeightIfSame),
30 m_MoveToGround(a_Def.m_MoveToGround)
32 m_BlockArea[0].Create(m_Size);
34 ParseCharMap(cm, a_Def.m_CharMap);
35 ParseBlockImage(cm, a_Def.m_Image);
36 ParseConnectors(a_Def.m_Connectors);
37 ParseDepthWeight(a_Def.m_DepthWeight);
39 AddRotatedBlockAreas();
47 m_Size(a_Image.GetSize()),
48 m_AllowedRotations(a_AllowedRotations),
50 m_ExtendFloorStrategy(efsNone),
66 m_Size(a_Image.GetSize()),
67 m_AllowedRotations(0),
69 m_ExtendFloorStrategy(efsNone),
84 m_Size(a_SizeX, a_SizeY, a_SizeZ),
85 m_AllowedRotations(0),
87 m_ExtendFloorStrategy(efsNone),
148 Placement.
Move(-ChunkStartX, 0, -ChunkStartZ);
168 Image.
CopyTo(RandomizedImage);
172 m_Modifiers[i]->Modify(RandomizedImage, a_Placement, a_NumRotations);
187 for (
int z = 0; z < MaxZ; z++)
189 int RelZ = Placement.
z + z;
195 for (
int x = 0; x < MaxX; x++)
197 int RelX = Placement.
x + x;
211 for (
int y = Placement.
y - 1; y >= 0; y--)
230 for (
int z = 0; z < MaxZ; z++)
232 int RelZ = Placement.
z + z;
238 for (
int x = 0; x < MaxX; x++)
240 int RelX = Placement.
x + x;
254 for (
int y = Placement.
y - 1; y >= 0; y--)
279 if (itr->m_Type == a_ConnectorType)
299 const cPiece * ThisPiece =
this;
300 if (ThisPiece == ParentPiece)
322 m_Connectors.emplace_back(a_RelX, a_RelY, a_RelZ, a_Type, a_Direction);
341 ASSERT(a_CharMapDef !=
nullptr);
344 for (
size_t i = 0; i <
ARRAYCOUNT(a_CharMapOut); i++)
346 a_CharMapOut[i].m_BlockType = 0;
347 a_CharMapOut[i].m_BlockMeta = 16;
352 for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr)
355 size_t NumElements = CharDef.size();
356 if ((NumElements < 2) || CharDef[0].empty() || CharDef[1].empty())
358 LOGWARNING(
"Bad prefab CharMap definition line: \"%s\", skipping.", itr->c_str());
361 unsigned char Src =
static_cast<unsigned char>(CharDef[0][0]);
362 ASSERT(a_CharMapOut[Src].m_BlockMeta == 16);
363 a_CharMapOut[Src].m_BlockType =
static_cast<BLOCKTYPE>(atoi(CharDef[1].c_str()));
365 if ((NumElements >= 3) && !CharDef[2].empty())
367 BlockMeta =
static_cast<NIBBLETYPE>(atoi(CharDef[2].c_str()));
368 ASSERT((BlockMeta <= 15));
370 a_CharMapOut[Src].m_BlockMeta = BlockMeta;
381 for (
int y = 0; y <
m_Size.
y; y++)
383 for (
int z = 0; z <
m_Size.
z; z++)
385 const unsigned char * BlockImage =
reinterpret_cast<const unsigned char *
>(a_BlockImage + y *
m_Size.
x *
m_Size.
z + z *
m_Size.
x);
386 for (
int x = 0; x <
m_Size.
x; x++)
388 const sBlockTypeDef & MappedValue = a_CharMap[BlockImage[x]];
402 ASSERT(a_ConnectorsDef !=
nullptr);
405 for (AStringVector::const_iterator itr = Lines.begin(), end = Lines.end(); itr != end; ++itr)
413 if (Defs.size() != 3)
415 LOGWARNING(
"Bad prefab Connector definition line: \"%s\", skipping.", itr->c_str());
419 if (Coords.size() != 3)
421 LOGWARNING(
"Bad prefab Connector coords definition: \"%s\", skipping.", Defs[1].c_str());
429 LOGWARNING(
"Bad prefab Connector direction: \"%s\", skipping.", Defs[2].c_str());
435 atoi(Coords[0].c_str()), atoi(Coords[1].c_str()), atoi(Coords[2].c_str()),
436 atoi(Defs[0].c_str()),
449 if (a_DepthWeightDef ==
nullptr)
458 for (AStringVector::const_iterator itr = Defs.begin(), end = Defs.end(); itr != end; ++itr)
462 if (Components.size() != 2)
464 LOGWARNING(
"Bad prefab DepthWeight record: \"%s\", skipping.", itr->c_str());
469 int Depth = atoi(Components[0].c_str());
470 if ((Depth == 0) && (Components[0] !=
"0"))
472 LOGWARNING(
"Bad prefab DepthWeight record, cannot parse depth \"%s\", skipping.", Components[0].c_str());
477 int Weight = atoi(Components[1].c_str());
478 if ((Weight == 0) && (Components[1] !=
"0"))
480 LOGWARNING(
"Bad prefab DepthWeight record, cannot parse weight \"%s\", skipping.", Components[1].c_str());
525 return (a_NumRotations == 0) || ((
m_AllowedRotations & (1 << ((a_NumRotations + 3) % 4))) != 0);
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
unsigned char BLOCKTYPE
The datatype used by blockdata.
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
void LOGWARNING(std::string_view a_Format, const Args &... args)
AStringVector StringSplitAndTrim(const AString &str, const AString &delim)
Split the string at any of the listed delimiters and trim each value.
std::vector< AString > AStringVector
void Create(int a_SizeX, int a_SizeY, int a_SizeZ, int a_DataTypes=baTypes|baMetas|baBlockEntities)
Creates a new area of the specified size and contents.
void GetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
void SetRelBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
void MirrorYZ(void)
Mirrors the entire area around the YZ plane.
void MirrorXY(void)
Mirrors the entire area around the XY plane.
void CopyFrom(const cBlockArea &a_From)
Copies the contents from the specified BlockArea into this object.
void RotateCW(void)
Rotates the entire area clockwise around the Y axis.
void RotateCCW(void)
Rotates the entire area counter-clockwise around the Y axis.
void CopyTo(cBlockArea &a_Into) const
Copies this object's contents into the specified BlockArea.
static bool IsSolid(BLOCKTYPE Block)
Is this block solid (player cannot walk through)?
void SetBlockTypeMeta(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const
void WriteBlockArea(const cBlockArea &a_BlockArea, int a_RelX, int a_RelY, int a_RelZ, cBlockArea::eMergeStrategy a_MergeStrategy=cBlockArea::msOverwrite)
Writes the block area into the chunk, with its origin set at the specified relative coords.
Represents a single piece.
cPieceModifiers m_Modifiers
The modifiers which are modifying piece's blocks.
std::vector< cConnector > cConnectors
static bool StringToDirection(const AString &a_Value, eDirection &a_Out)
Converts the string representation of a direction into the eDirection enum value.
Represents a single piece that has been placed to specific coords in the world.
const Vector3i & GetCoords(void) const
int GetNumCCWRotations(void) const
const cPiece & GetPiece(void) const
sBlockTypeDef CharMap[256]
Maps letters in the sDef::m_Image onto a sBlockTypeDef block type definition.
virtual Vector3i GetSize(void) const override
Returns the dimensions of this piece.
cDepthWeight m_DepthWeight
Chances of this piece being used, per depth of the generated piece tree.
void ParseCharMap(CharMap &a_CharMapOut, const char *a_CharMapDef)
Parses the CharMap in the definition into a CharMap binary data used for translating the definition i...
int m_AllowedRotations
Bitmask, bit N set -> N rotations CCW supported.
void ParseConnectors(const char *a_ConnectorsDef)
Parses the connectors definition text into m_Connectors member.
void ParseDepthWeight(const char *a_DepthWeightDef)
Parses the per-depth weight into m_DepthWeight member.
void AddConnector(int a_RelX, int a_RelY, int a_RelZ, cPiece::cConnector::eDirection a_Direction, int a_Type)
Adds the specified connector to the list of connectors this piece supports.
cCuboid m_HitBox
The hitbox used for collision-checking between prefabs.
int m_DefaultWeight
Chance of this piece being used, if no other modifier is active.
void SetAllowedRotations(int a_AllowedRotations)
Sets the m_AllowedRotations bitmask and fills the m_BlockArea[] with rotated versions of m_BlockArea[...
Vector3i m_Size
The size of the prefab.
virtual bool CanRotateCCW(int a_NumRotations) const override
Returns true if the piece can be rotated CCW the specific number of 90-degree turns.
void Draw(cChunkDesc &a_Dest, const cPlacedPiece *a_Placement) const
Draws the prefab into the specified chunk, according to the placement stored in the PlacedPiece.
cBlockArea m_BlockArea[4]
The cBlockArea that contains the block definitions for the prefab.
cConnectors m_Connectors
The connectors through which the piece connects to other pieces.
virtual cConnectors GetConnectors(void) const override
Returns all of the available connectors that the piece has.
cPrefab(const sDef &a_Def)
Creates a prefab from the provided definition.
void AddRotatedBlockAreas(void)
Based on the m_AllowedRotations, adds rotated cBlockAreas to the m_BlockArea array.
@ efsRepeatBottomTillSolid
Repeat the bottom-most block down until the first solid block; non-solids are overwritten.
@ efsRepeatBottomTillNonAir
Repeat the bottom-most block down until the first non-air block.
@ efsNone
No processing, the prefab is left "floating in the air".
void SetDefaultWeight(int a_DefaultWeight)
Sets the (unmodified) DefaultWeight property for this piece.
int m_AddWeightIfSame
The weight to add to this piece's base per-depth chance if the previous piece is the same.
cBlockArea::eMergeStrategy m_MergeStrategy
The merge strategy to use when drawing the prefab into a block area.
eExtendFloorStrategy m_ExtendFloorStrategy
How the prefab should handle not being on top of the ground.
virtual cCuboid GetHitBox(void) const override
Returns the "hitbox" of this piece.
void ParseBlockImage(const CharMap &a_CharMap, const char *a_BlockImage)
Parses the Image in the definition into m_BlockArea[0]'s block types and metas, using the specified C...
int GetPieceWeight(const cPlacedPiece &a_PlacedPiece, const cPiece::cConnector &a_ExistingConnector) const
Returns the weight (chance) of this prefab generating as the next piece after the specified placed pi...
bool HasConnectorType(int a_ConnectorType) const
Returns true if the prefab has any connector of the specified type.
int m_HitboxMinX
The hitbox used for collision-checking between prefabs.
Packs complete definition of a single block, for per-letter assignment.
void Move(T a_X, T a_Y, T a_Z)
void Set(T a_x, T a_y, T a_z)