1
0

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 <guo1487@163.com>
Co-authored-by: Xotheus <shady3300@outlook.com>
Co-authored-by: Krist Pregracke <krist@tiger-scm.com>

* Review fixes

* Update APIDesc.lua

* Rename

Co-authored-by: changyong guo <guo1487@163.com>
Co-authored-by: Xotheus <shady3300@outlook.com>
Co-authored-by: Krist Pregracke <krist@tiger-scm.com>
This commit is contained in:
Tiger Wang
2021-05-05 14:25:10 +01:00
committed by GitHub
parent 34bf5c0d9d
commit a62b2b1be2
109 changed files with 2096 additions and 2686 deletions

View File

@@ -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<sSetBlock> a_Blocks) const
{
// Compute the bounding box for each block to be placed
std::vector<cBoundingBox> 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<sSetBlock> 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;