diff options
-rw-r--r-- | src/Blocks/BlockHandler.cpp | 37 | ||||
-rw-r--r-- | src/Blocks/BlockHandler.h | 6 | ||||
-rw-r--r-- | src/ClientHandle.cpp | 10 |
3 files changed, 51 insertions, 2 deletions
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp index 60f13a747..7f1d72159 100644 --- a/src/Blocks/BlockHandler.cpp +++ b/src/Blocks/BlockHandler.cpp @@ -500,6 +500,43 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac +bool cBlockHandler::CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) +{ + class cCallback : public cChunkCallback + { + public: + cCallback(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, cBlockHandler * a_BlockHandler) : + m_ChunkInterface(a_ChunkInterface), + m_RelX(a_RelX), + m_RelY(a_RelY), + m_RelZ(a_RelZ), + m_Handler(a_BlockHandler) + { + } + + virtual bool Item(cChunk * a_Chunk) + { + return m_Handler->CanBeAt(m_ChunkInterface, m_RelX, m_RelY, m_RelZ, *a_Chunk); + } + + protected: + cChunkInterface & m_ChunkInterface; + int m_RelX, m_RelY, m_RelZ; + cBlockHandler * m_Handler; + }; + + int ChunkX, ChunkZ; + cChunkDef::AbsoluteToRelative(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ); + cChunkInterface ChunkInterface(a_World->GetChunkMap()); + + cCallback Callback(ChunkInterface, a_BlockX, a_BlockY, a_BlockZ, this); + return a_World->GetChunkMap()->DoWithChunk(ChunkX, ChunkZ, Callback); +} + + + + + bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, const cChunk & a_Chunk) { return true; diff --git a/src/Blocks/BlockHandler.h b/src/Blocks/BlockHandler.h index f2298afb5..6c782da8c 100644 --- a/src/Blocks/BlockHandler.h +++ b/src/Blocks/BlockHandler.h @@ -14,6 +14,7 @@ class cBlockPluginInterface; class cChunkInterface; class cWorldInterface; class cItems; +class cWorld; @@ -83,7 +84,10 @@ public: @param a_DropVerbatim Calls ConvertToVerbatimPickups() instead of its counterpart, meaning the block itself is dropped by default (due to a speical tool or enchantment) */ virtual void DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cEntity * a_Digger, int a_BlockX, int a_BlockY, int a_BlockZ, bool a_CanDrop = true); - + + /** Checks if the block can stay at the specified absolute coords */ + bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ); + /// Checks if the block can stay at the specified relative coords in the chunk virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk); diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index a6cbad32a..aefff9aa7 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1493,6 +1493,15 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e } cBlockHandler * NewBlock = BlockHandler(BlockType); + cChunkInterface ChunkInterface(World->GetChunkMap()); + + if (!NewBlock->CanBeAt(World, a_BlockX, a_BlockY, a_BlockZ)) + { + // Handler refused the placement, send that information back to the client: + World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); + m_Player->GetInventory().SendEquippedSlot(); + return; + } if (cRoot::Get()->GetPluginManager()->CallHookPlayerPlacingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta)) { @@ -1509,7 +1518,6 @@ void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, e m_Player->GetInventory().RemoveOneEquippedItem(); } - cChunkInterface ChunkInterface(World->GetChunkMap()); NewBlock->OnPlacedByPlayer(ChunkInterface, *World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta); AString PlaceSound = cBlockInfo::GetPlaceSound(BlockType); |