#pragma once
#include "BlockHandler.h"
#include "Mixins.h"
class cBlockLadderHandler:
public cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04> >
{
using Super = cClearMetaOnDrop<cMetaRotator<cBlockHandler, 0x07, 0x02, 0x05, 0x03, 0x04>>;
public:
cBlockLadderHandler(BLOCKTYPE a_BlockType):
Super(a_BlockType)
{
}
virtual bool GetPlacementBlockTypeMeta(
cChunkInterface & a_ChunkInterface,
cPlayer & a_Player,
const Vector3i a_PlacedBlockPos,
eBlockFace a_ClickedBlockFace,
const Vector3i a_CursorPos,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
// Try finding a suitable neighbor block face for the ladder; start with the given one.
if (!LadderCanBePlacedAt(a_ChunkInterface, a_PlacedBlockPos, a_ClickedBlockFace))
{
a_ClickedBlockFace = FindSuitableBlockFace(a_ChunkInterface, a_PlacedBlockPos);
if (a_ClickedBlockFace == BLOCK_FACE_NONE)
{
return false;
}
}
a_BlockType = m_BlockType;
a_BlockMeta = BlockFaceToMetaData(a_ClickedBlockFace);
return true;
}
/** Converts the block face of the neighbor to which the ladder is attached to the ladder block's meta. */
static NIBBLETYPE BlockFaceToMetaData(eBlockFace a_NeighborBlockFace)
{
switch (a_NeighborBlockFace)
{
case BLOCK_FACE_ZM: return 0x2;
case BLOCK_FACE_ZP: return 0x3;
case BLOCK_FACE_XM: return 0x4;
case BLOCK_FACE_XP: return 0x5;
case BLOCK_FACE_NONE:
case BLOCK_FACE_YM:
case BLOCK_FACE_YP:
{
return 0x2;
}
}
UNREACHABLE("Unsupported neighbor block face");
}
/** Converts the ladder block's meta to the block face of the neighbor to which the ladder is attached. */
static eBlockFace MetaDataToBlockFace(NIBBLETYPE a_MetaData)
{
switch (a_MetaData)
{
case 0x2: return BLOCK_FACE_ZM;
case 0x3: return BLOCK_FACE_ZP;
case 0x4: return BLOCK_FACE_XM;
case 0x5: return BLOCK_FACE_XP;
default: return BLOCK_FACE_ZM;
}
}
/** Finds a suitable block face value for the Ladder.
The returned value is the block face of the neighbor of the specified block to which a ladder at a_LadderPos can be attached.
Returns BLOCK_FACE_NONE if no valid location is found */
static eBlockFace FindSuitableBlockFace(cChunkInterface & a_ChunkInterface, const Vector3i a_LadderPos)
{
for (int FaceInt = BLOCK_FACE_ZM; FaceInt <= BLOCK_FACE_XP; FaceInt++)
{
eBlockFace Face = static_cast<eBlockFace>(FaceInt);
if (LadderCanBePlacedAt(a_ChunkInterface, a_LadderPos, Face))
{
return Face;
}
}
return BLOCK_FACE_NONE;
}
/** Returns true if the ladder in the specified position will be supported by its neghbor through the specified neighbor's blockface. */
static bool LadderCanBePlacedAt(cChunkInterface & a_ChunkInterface, const Vector3i a_LadderPos, eBlockFace a_NeighborBlockFace)
{
if (
(a_NeighborBlockFace == BLOCK_FACE_NONE) ||
(a_NeighborBlockFace == BLOCK_FACE_BOTTOM) ||
(a_NeighborBlockFace == BLOCK_FACE_TOP)
)
{
return false;
}
auto NeighborPos = AddFaceDirection(a_LadderPos, a_NeighborBlockFace, true);
return cBlockInfo::IsSolid(a_ChunkInterface.GetBlock(NeighborPos));
}
virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) override
{
auto NeighborBlockFace = MetaDataToBlockFace(a_Chunk.GetMeta(a_RelPos));
auto LadderAbsPos = a_Chunk.RelativeToAbsolute(a_RelPos);
return LadderCanBePlacedAt(a_ChunkInterface, LadderAbsPos, NeighborBlockFace);
}
virtual ColourID GetMapBaseColourID(NIBBLETYPE a_Meta) override
{
UNUSED(a_Meta);
return 0;
}
} ;