summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Blocks/BlockHandler.cpp37
-rw-r--r--src/Blocks/BlockHandler.h6
-rw-r--r--src/ClientHandle.cpp10
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);