From a62b2b1be2103d7de2fd66c7304b7473e369be3c Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Wed, 5 May 2021 14:25:10 +0100 Subject: Move item placement into item handlers (#5184) * Move item placement into item handlers + Add appropriate CanBeAt checks in cPlayer::PlaceBlocks, into which all placement handlers call. * Partly addresses #5157 * Fixes #4878 * Fixes #2919 * Fixes #4629 * Fixes #4239 * Fixes #4849 Co-authored-by: changyong guo Co-authored-by: Xotheus Co-authored-by: Krist Pregracke * Review fixes * Update APIDesc.lua * Rename Co-authored-by: changyong guo Co-authored-by: Xotheus Co-authored-by: Krist Pregracke --- src/Blocks/BlockRail.h | 237 ++++++++++++++++++++----------------------------- 1 file changed, 96 insertions(+), 141 deletions(-) (limited to 'src/Blocks/BlockRail.h') diff --git a/src/Blocks/BlockRail.h b/src/Blocks/BlockRail.h index 7c147d48a..d822e728f 100644 --- a/src/Blocks/BlockRail.h +++ b/src/Blocks/BlockRail.h @@ -25,141 +25,8 @@ public: using Super::Super; -private: - - 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 - ) const override - { - a_BlockType = m_BlockType; - a_BlockMeta = FindMeta(a_ChunkInterface, a_PlacedBlockPos); - return a_Player.GetWorld()->DoWithChunkAt(a_PlacedBlockPos, - [this, a_PlacedBlockPos, &a_ChunkInterface](cChunk & a_Chunk) - { - auto RelPos = cChunkDef::AbsoluteToRelative(a_PlacedBlockPos); - return CanBeAt(a_ChunkInterface, RelPos, a_Chunk); - } - ); - } - - - - - - virtual void OnPlaced( - cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, - Vector3i a_BlockPos, - BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta - ) const override - { - Super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_BlockType, a_BlockMeta); - - // Alert diagonal rails: - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); - } - - - - - - virtual void OnBroken( - cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, - Vector3i a_BlockPos, - BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, - const cEntity * a_Digger - ) const override - { - Super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta, a_Digger); - - // Alert diagonal rails: - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); - NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); - } - - - - - virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override - { - const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); - const auto NewMeta = FindMeta(a_ChunkInterface, a_BlockPos); - if ((Meta != NewMeta) && IsUnstable(a_ChunkInterface, a_BlockPos)) - { - a_ChunkInterface.FastSetBlock(a_BlockPos, m_BlockType, (m_BlockType == E_BLOCK_RAIL) ? NewMeta : NewMeta | (Meta & 0x08)); - } - - Super::OnNeighborChanged(a_ChunkInterface, a_BlockPos, a_WhichNeighbor); - } - - - - - - virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, const Vector3i a_RelPos, const cChunk & a_Chunk) const override - { - if (a_RelPos.y <= 0) - { - return false; - } - if (!cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_RelPos.addedY(-1)))) - { - return false; - } - - NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelPos); - switch (Meta) - { - case E_META_RAIL_ASCEND_XP: - case E_META_RAIL_ASCEND_XM: - case E_META_RAIL_ASCEND_ZM: - case E_META_RAIL_ASCEND_ZP: - { - // Mapping between the meta and the neighbors that need checking - Meta -= E_META_RAIL_ASCEND_XP; // Base index at zero - static const Vector3i Coords[] = - { - { 1, 0, 0}, // east, XP - {-1, 0, 0}, // west, XM - { 0, 0, -1}, // north, ZM - { 0, 0, 1}, // south, ZP - } ; - BLOCKTYPE BlockType; - NIBBLETYPE BlockMeta; - if (!a_Chunk.UnboundedRelGetBlock(a_RelPos + Coords[Meta], BlockType, BlockMeta)) - { - // Too close to the edge, cannot simulate - return true; - } - return cBlockInfo::FullyOccupiesVoxel(BlockType); - } - } - return true; - } - - - - - - NIBBLETYPE FindMeta(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos) const + static NIBBLETYPE FindMeta(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, BLOCKTYPE a_RailType) { NIBBLETYPE Meta = 0; char RailsCnt = 0; @@ -234,19 +101,21 @@ private: } if (RailsCnt > 1) { - if (Neighbors[3] && Neighbors[0] && CanThisRailCurve()) + const bool CanCurve = a_RailType == E_BLOCK_RAIL; + + if (Neighbors[3] && Neighbors[0] && CanCurve) { return E_META_RAIL_CURVED_ZP_XP; } - else if (Neighbors[3] && Neighbors[1] && CanThisRailCurve()) + else if (Neighbors[3] && Neighbors[1] && CanCurve) { return E_META_RAIL_CURVED_ZP_XM; } - else if (Neighbors[2] && Neighbors[0] && CanThisRailCurve()) + else if (Neighbors[2] && Neighbors[0] && CanCurve) { return E_META_RAIL_CURVED_ZM_XP; } - else if (Neighbors[2] && Neighbors[1] && CanThisRailCurve()) + else if (Neighbors[2] && Neighbors[1] && CanCurve) { return E_META_RAIL_CURVED_ZM_XM; } @@ -275,7 +144,7 @@ private: return E_META_RAIL_ZM_ZP; } - if (CanThisRailCurve()) + if (CanCurve) { ASSERT(!"Weird neighbor count"); } @@ -283,10 +152,42 @@ private: return Meta; } +private: - bool CanThisRailCurve(void) const + virtual bool CanBeAt(const cChunk & a_Chunk, const Vector3i a_Position, NIBBLETYPE a_Meta) const override { - return m_BlockType == E_BLOCK_RAIL; + if ((a_Position.y <= 0) || !cBlockInfo::FullyOccupiesVoxel(a_Chunk.GetBlock(a_Position.addedY(-1)))) + { + return false; + } + + switch (a_Meta) + { + case E_META_RAIL_ASCEND_XP: + case E_META_RAIL_ASCEND_XM: + case E_META_RAIL_ASCEND_ZM: + case E_META_RAIL_ASCEND_ZP: + { + // Mapping between the meta and the neighbors that need checking + a_Meta -= E_META_RAIL_ASCEND_XP; // Base index at zero + static const Vector3i Coords[] = + { + { 1, 0, 0}, // east, XP + {-1, 0, 0}, // west, XM + { 0, 0, -1}, // north, ZM + { 0, 0, 1}, // south, ZP + } ; + BLOCKTYPE BlockType; + NIBBLETYPE BlockMeta; + if (!a_Chunk.UnboundedRelGetBlock(a_Position + Coords[a_Meta], BlockType, BlockMeta)) + { + // Too close to the edge, cannot simulate + return true; + } + return cBlockInfo::FullyOccupiesVoxel(BlockType); + } + } + return true; } @@ -521,6 +422,60 @@ private: } + virtual void OnBroken( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + Vector3i a_BlockPos, + BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, + const cEntity * a_Digger + ) const override + { + Super::OnBroken(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_OldBlockType, a_OldBlockMeta, a_Digger); + + // Alert diagonal rails: + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); + } + + + virtual void OnNeighborChanged(cChunkInterface & a_ChunkInterface, Vector3i a_BlockPos, eBlockFace a_WhichNeighbor) const override + { + const auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos); + const auto NewMeta = FindMeta(a_ChunkInterface, a_BlockPos, m_BlockType); + if ((Meta != NewMeta) && IsUnstable(a_ChunkInterface, a_BlockPos)) + { + a_ChunkInterface.FastSetBlock(a_BlockPos, m_BlockType, (m_BlockType == E_BLOCK_RAIL) ? NewMeta : NewMeta | (Meta & 0x08)); + } + + Super::OnNeighborChanged(a_ChunkInterface, a_BlockPos, a_WhichNeighbor); + } + + + virtual void OnPlaced( + cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, + Vector3i a_BlockPos, + BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta + ) const override + { + Super::OnPlaced(a_ChunkInterface, a_WorldInterface, a_BlockPos, a_BlockType, a_BlockMeta); + + // Alert diagonal rails: + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, 1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, +1, -1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i(-1, -1, 0), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, 1), BLOCK_FACE_NONE); + NeighborChanged(a_ChunkInterface, a_BlockPos + Vector3i( 0, -1, -1), BLOCK_FACE_NONE); + } + + virtual NIBBLETYPE MetaRotateCCW(NIBBLETYPE a_Meta) const override { // Bit 0x08 is a flag when a_Meta is in the range 0x00--0x05 and 0x0A--0x0F. -- cgit v1.2.3