From 6b70574da96208a9bf855d0db983d27972ad9281 Mon Sep 17 00:00:00 2001 From: Mattes D Date: Mon, 21 Nov 2016 17:12:01 +0100 Subject: Prefabs: Implemented support for ExpandFloorStrategy. --- src/Generating/Prefab.cpp | 116 ++++++++++++++++++++++++++----------- src/Generating/Prefab.h | 26 +++++---- src/Generating/PrefabPiecePool.cpp | 54 +++++++++++++---- 3 files changed, 142 insertions(+), 54 deletions(-) (limited to 'src/Generating') diff --git a/src/Generating/Prefab.cpp b/src/Generating/Prefab.cpp index 6805167a9..9af01d6a4 100644 --- a/src/Generating/Prefab.cpp +++ b/src/Generating/Prefab.cpp @@ -97,8 +97,8 @@ static const cPrefab::sDef g_TestPrefabDef = // Merge strategy: cBlockArea::msImprint, - // ShouldExtendFloor: - false, + // ExtendFloorStrategy: + cPrefab::efsNone, // DefaultWeight: 10, @@ -128,7 +128,7 @@ cPrefab::cPrefab(const cPrefab::sDef & a_Def) : ), m_AllowedRotations(a_Def.m_AllowedRotations), m_MergeStrategy(a_Def.m_MergeStrategy), - m_ShouldExtendFloor(a_Def.m_ShouldExtendFloor), + m_ExtendFloorStrategy(a_Def.m_ExtendFloorStrategy), m_DefaultWeight(a_Def.m_DefaultWeight), m_AddWeightIfSame(a_Def.m_AddWeightIfSame), m_MoveToGround(a_Def.m_MoveToGround) @@ -151,7 +151,7 @@ cPrefab::cPrefab(const cBlockArea & a_Image, int a_AllowedRotations) : m_Size(a_Image.GetSize()), m_AllowedRotations(a_AllowedRotations), m_MergeStrategy(cBlockArea::msOverwrite), - m_ShouldExtendFloor(false), + m_ExtendFloorStrategy(efsNone), m_DefaultWeight(1), m_AddWeightIfSame(0), m_MoveToGround(false) @@ -170,7 +170,7 @@ cPrefab::cPrefab(const cBlockArea & a_Image) : m_Size(a_Image.GetSize()), m_AllowedRotations(0), m_MergeStrategy(cBlockArea::msOverwrite), - m_ShouldExtendFloor(false), + m_ExtendFloorStrategy(efsNone), m_DefaultWeight(1), m_AddWeightIfSame(0), m_MoveToGround(false) @@ -188,7 +188,7 @@ cPrefab::cPrefab(const AString & a_BlockDefinitions, const AString & a_BlockData m_Size(a_SizeX, a_SizeY, a_SizeZ), m_AllowedRotations(0), m_MergeStrategy(cBlockArea::msOverwrite), - m_ShouldExtendFloor(false), + m_ExtendFloorStrategy(efsNone), m_DefaultWeight(1), m_AddWeightIfSame(0), m_MoveToGround(false) @@ -264,46 +264,94 @@ void cPrefab::Draw(cChunkDesc & a_Dest, const Vector3i & a_Placement, int a_NumR a_Dest.WriteBlockArea(Image, 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 (m_ShouldExtendFloor) + switch (m_ExtendFloorStrategy) { - int MaxX = Image.GetSizeX(); - int MaxZ = Image.GetSizeZ(); - for (int z = 0; z < MaxZ; z++) + case efsNone: break; // Nothing needed + case efsRepeatBottomTillNonAir: { - int RelZ = Placement.z + z; - if ((RelZ < 0) || (RelZ >= cChunkDef::Width)) - { - // Z coord outside the chunk - continue; - } - for (int x = 0; x < MaxX; x++) + int MaxX = Image.GetSizeX(); + int MaxZ = Image.GetSizeZ(); + for (int z = 0; z < MaxZ; z++) { - int RelX = Placement.x + x; - if ((RelX < 0) || (RelX >= cChunkDef::Width)) + int RelZ = Placement.z + z; + if ((RelZ < 0) || (RelZ >= cChunkDef::Width)) { - // X coord outside the chunk + // Z coord outside the chunk continue; } - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta); - if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE)) + for (int x = 0; x < MaxX; x++) + { + int RelX = Placement.x + x; + if ((RelX < 0) || (RelX >= cChunkDef::Width)) + { + // X coord outside the chunk + continue; + } + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta); + if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE)) + { + // Do not expand air nor sponge blocks + continue; + } + for (int y = Placement.y - 1; y >= 0; y--) + { + BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ); + if (ExistingBlock != E_BLOCK_AIR) + { + // End the expansion for this column, reached the end + break; + } + a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta); + } // for y + } // for x + } // for z + break; + } // efsRepeatBottomTillNonAir + + case efsRepeatBottomTillSolid: + { + int MaxX = Image.GetSizeX(); + int MaxZ = Image.GetSizeZ(); + for (int z = 0; z < MaxZ; z++) + { + int RelZ = Placement.z + z; + if ((RelZ < 0) || (RelZ >= cChunkDef::Width)) { - // Do not expand air nor sponge blocks + // Z coord outside the chunk continue; } - for (int y = Placement.y - 1; y >= 0; y--) + for (int x = 0; x < MaxX; x++) { - BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ); - if (ExistingBlock != E_BLOCK_AIR) + int RelX = Placement.x + x; + if ((RelX < 0) || (RelX >= cChunkDef::Width)) { - // End the expansion for this column, reached the end - break; + // X coord outside the chunk + continue; } - a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta); - } // for y - } // for x - } // for z + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + Image.GetRelBlockTypeMeta(x, 0, z, BlockType, BlockMeta); + if ((BlockType == E_BLOCK_AIR) || (BlockType == E_BLOCK_SPONGE)) + { + // Do not expand air nor sponge blocks + continue; + } + for (int y = Placement.y - 1; y >= 0; y--) + { + BLOCKTYPE ExistingBlock = a_Dest.GetBlockType(RelX, y, RelZ); + if (cBlockInfo::IsSolid(ExistingBlock)) + { + // End the expansion for this column, reached the end + break; + } + a_Dest.SetBlockTypeMeta(RelX, y, RelZ, BlockType, BlockMeta); + } // for y + } // for x + } // for z + break; + } // efsRepeatBottomTillSolid } } diff --git a/src/Generating/Prefab.h b/src/Generating/Prefab.h index 5f937260d..bb961f2b3 100644 --- a/src/Generating/Prefab.h +++ b/src/Generating/Prefab.h @@ -32,6 +32,14 @@ class cPrefab : public cPiece { public: + /** How to handle the space between the prefab bottom and the terrain top. */ + enum eExtendFloorStrategy + { + efsNone, ///< No processing, the prefab is left "floating in the air" + efsRepeatBottomTillNonAir, ///< Repeat the bottom-most block down until the first non-air block + efsRepeatBottomTillSolid, ///< Repeat the bottom-most block down until the first solid block; non-solids are overwritten + }; + struct sDef { int m_SizeX; @@ -62,10 +70,9 @@ public: /** The merge strategy to use while drawing the prefab. */ cBlockArea::eMergeStrategy m_MergeStrategy; - /** If set to true, the prefab will extend its lowermost blocks until a solid block is found, - thus creating a foundation for the prefab. This is used for houses to be "on the ground", as well as - nether fortresses not to float. */ - bool m_ShouldExtendFloor; + /** How the prefab should handle not being on top of the ground. + This is used for houses to be "on the ground", as well as nether fortresses not to float. */ + eExtendFloorStrategy m_ExtendFloorStrategy; /** Chance of this piece being used, if no other modifier is active. */ int m_DefaultWeight; @@ -143,8 +150,8 @@ public: /** Sets the flag whether the prefab should be moved to ground level before being drawn. */ void SetMoveToGround(bool a_MoveToGround) { m_MoveToGround = a_MoveToGround; } - /** Sets the flag whether the lowest layer of the prefab should be repeated downwards until it hits a solid block. */ - void SetExtendFloor(bool a_ShouldExtendFloor) { m_ShouldExtendFloor = a_ShouldExtendFloor; } + /** Sets the strategy to use between the bottom of the prefab and the terrain top. */ + void SetExtendFloorStrategy(eExtendFloorStrategy a_Strategy) { m_ExtendFloorStrategy = a_Strategy; } /** Sets the internal hitbox to the specified value. */ void SetHitBox(const cCuboid & a_HitBox) { m_HitBox = a_HitBox; } @@ -183,10 +190,9 @@ protected: /** The merge strategy to use when drawing the prefab into a block area */ cBlockArea::eMergeStrategy m_MergeStrategy; - /** If set to true, the prefab will extend its lowermost blocks until a solid block is found, - thus creating a foundation for the prefab. This is used for houses to be "on the ground", as well as - nether fortresses not to float. */ - bool m_ShouldExtendFloor; + /** How the prefab should handle not being on top of the ground. + This is used for houses to be "on the ground", as well as nether fortresses not to float. */ + eExtendFloorStrategy m_ExtendFloorStrategy; /** Chance of this piece being used, if no other modifier is active. */ int m_DefaultWeight; diff --git a/src/Generating/PrefabPiecePool.cpp b/src/Generating/PrefabPiecePool.cpp index 417f8ce7e..d6c2c8819 100644 --- a/src/Generating/PrefabPiecePool.cpp +++ b/src/Generating/PrefabPiecePool.cpp @@ -526,16 +526,15 @@ bool cPrefabPiecePool::ReadPieceMetadataCubesetVer1( } // Get the values: - int AddWeightIfSame = 0, DefaultWeight = 100, MoveToGround = 0, ShouldExpandFloor = 0; + int AddWeightIfSame = 0, DefaultWeight = 100, MoveToGround = 0; AString DepthWeight, MergeStrategy, VerticalLimit, VerticalStrategy; - 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); - a_LuaState.GetNamedValue("VerticalLimit", VerticalLimit); - a_LuaState.GetNamedValue("VerticalStrategy", VerticalStrategy); + 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("VerticalLimit", VerticalLimit); + a_LuaState.GetNamedValue("VerticalStrategy", VerticalStrategy); // Apply the values: a_Prefab->SetAddWeightIfSame(AddWeightIfSame); @@ -555,7 +554,42 @@ bool cPrefabPiecePool::ReadPieceMetadataCubesetVer1( a_Prefab->SetMergeStrategy(strategy->second); } a_Prefab->SetMoveToGround(MoveToGround != 0); - a_Prefab->SetExtendFloor(ShouldExpandFloor != 0); + + AString ExpandFloorStrategyStr; + if (!a_LuaState.GetNamedValue("ExpandFloorStrategy", ExpandFloorStrategyStr)) + { + // Check the older variant for ExpandFloorStrategy, ShouldExpandFloor: + int ShouldExpandFloor; + if (a_LuaState.GetNamedValue("ShouldExpandFloor", ShouldExpandFloor)) + { + LOG("Piece \"%s\" in file \"%s\" is using the old \"ShouldExpandFloor\" attribute. Use the new \"ExpandFloorStrategy\" attribute instead for more options.", + a_PieceName.c_str(), a_FileName.c_str() + ); + a_Prefab->SetExtendFloorStrategy((ShouldExpandFloor != 0) ? cPrefab::efsRepeatBottomTillNonAir : cPrefab::efsNone); + } + } + else + { + auto lcExpandFloorStrategyStr = StrToLower(ExpandFloorStrategyStr); + if (lcExpandFloorStrategyStr == "repeatbottomtillnonair") + { + a_Prefab->SetExtendFloorStrategy(cPrefab::efsRepeatBottomTillNonAir); + } + else if (lcExpandFloorStrategyStr == "repeatbottomtillsolid") + { + a_Prefab->SetExtendFloorStrategy(cPrefab::efsRepeatBottomTillSolid); + } + else + { + if (lcExpandFloorStrategyStr != "none") + { + LOGWARNING("Piece \"%s\" in file \"%s\" is using an unknown \"ExpandFloorStrategy\" attribute value: \"%s\"", + a_PieceName.c_str(), a_FileName.c_str(), ExpandFloorStrategyStr.c_str() + ); + } + a_Prefab->SetExtendFloorStrategy(cPrefab::efsNone); + } + } if (!VerticalLimit.empty()) { if (!a_Prefab->SetVerticalLimitFromString(VerticalLimit, a_LogWarnings)) -- cgit v1.2.3