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/Entities/Player.cpp | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'src/Entities/Player.cpp') diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 08adb1096..235433cf8 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -2391,10 +2391,9 @@ void cPlayer::LoadRank(void) -bool cPlayer::PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) +bool cPlayer::PlaceBlock(const Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) { - sSetBlockVector blk{{a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta}}; - return PlaceBlocks(blk); + return PlaceBlocks({ { a_Position, a_BlockType, a_BlockMeta } }); } @@ -2442,7 +2441,7 @@ void cPlayer::SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_R -bool cPlayer::DoesPlacingBlocksIntersectEntity(const sSetBlockVector & a_Blocks) +bool cPlayer::DoesPlacingBlocksIntersectEntity(const std::initializer_list a_Blocks) const { // Compute the bounding box for each block to be placed std::vector PlacementBoxes; @@ -2516,44 +2515,52 @@ const cUUID & cPlayer::GetUUID(void) const -bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks) +bool cPlayer::PlaceBlocks(const std::initializer_list a_Blocks) { if (DoesPlacingBlocksIntersectEntity(a_Blocks)) { // Abort - re-send all the current blocks in the a_Blocks' coords to the client: - for (auto blk2: a_Blocks) + for (const auto & ResendBlock : a_Blocks) { - m_World->SendBlockTo(blk2.GetX(), blk2.GetY(), blk2.GetZ(), *this); + m_World->SendBlockTo(ResendBlock.GetX(), ResendBlock.GetY(), ResendBlock.GetZ(), *this); } return false; } - // Call the "placing" hooks; if any fail, abort: cPluginManager * pm = cPluginManager::Get(); - for (auto blk: a_Blocks) + + // Check the blocks CanBeAt, and call the "placing" hooks; if any fail, abort: + for (const auto & Block : a_Blocks) { - if (pm->CallHookPlayerPlacingBlock(*this, blk)) + if ( + !m_World->DoWithChunkAt(Block.GetAbsolutePos(), [&Block](cChunk & a_Chunk) + { + return cBlockHandler::For(Block.m_BlockType).CanBeAt(a_Chunk, Block.GetRelativePos(), Block.m_BlockMeta); + }) + ) + { + return false; + } + + if (pm->CallHookPlayerPlacingBlock(*this, Block)) { // Abort - re-send all the current blocks in the a_Blocks' coords to the client: - for (auto blk2: a_Blocks) + for (const auto & ResendBlock : a_Blocks) { - m_World->SendBlockTo(blk2.GetX(), blk2.GetY(), blk2.GetZ(), *this); + m_World->SendBlockTo(ResendBlock.GetX(), ResendBlock.GetY(), ResendBlock.GetZ(), *this); } return false; } - } // for blk - a_Blocks[] + } cChunkInterface ChunkInterface(m_World->GetChunkMap()); - for (auto blk: a_Blocks) + for (const auto & Block : a_Blocks) { // Set the blocks: - m_World->PlaceBlock(blk.GetAbsolutePos(), blk.m_BlockType, blk.m_BlockMeta); - - // Notify the blockhandlers: - cBlockHandler::For(blk.m_BlockType).OnPlacedByPlayer(ChunkInterface, *m_World, *this, blk); + m_World->PlaceBlock(Block.GetAbsolutePos(), Block.m_BlockType, Block.m_BlockMeta); // Call the "placed" hooks: - pm->CallHookPlayerPlacedBlock(*this, blk); + pm->CallHookPlayerPlacedBlock(*this, Block); } return true; -- cgit v1.2.3