summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities')
-rw-r--r--src/Entities/Player.cpp96
-rw-r--r--src/Entities/Player.h19
2 files changed, 115 insertions, 0 deletions
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 15920d6cf..1d5cc6554 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Player.h"
+#include <unordered_map>
#include "../ChatColor.h"
#include "../Server.h"
#include "../UI/Window.h"
@@ -19,6 +20,10 @@
#include "../WorldStorage/StatSerializer.h"
#include "../CompositeChat.h"
+#include "../Blocks/BlockHandler.h"
+#include "../Blocks/BlockSlab.h"
+#include "../Blocks/ChunkInterface.h"
+
#include "../IniFile.h"
#include "json/json.h"
@@ -2168,6 +2173,97 @@ void cPlayer::LoadRank(void)
+bool cPlayer::PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
+{
+ sSetBlockVector blk{{a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta}};
+ return PlaceBlocks(blk);
+}
+
+
+
+
+
+void cPlayer::SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Range)
+{
+ // Collect the coords of all the blocks to send:
+ sSetBlockVector blks;
+ for (int y = a_BlockY - a_Range + 1; y < a_BlockY + a_Range; y++)
+ {
+ for (int z = a_BlockZ - a_Range + 1; z < a_BlockZ + a_Range; z++)
+ {
+ for (int x = a_BlockX - a_Range + 1; x < a_BlockX + a_Range; x++)
+ {
+ blks.emplace_back(x, y, z, E_BLOCK_AIR, 0); // Use fake blocktype, it will get set later on.
+ };
+ };
+ } // for y
+
+ // Get the values of all the blocks:
+ if (!m_World->GetBlocks(blks, false))
+ {
+ LOGD("%s: Cannot query all blocks, not sending an update", __FUNCTION__);
+ return;
+ }
+
+ // Divide the block changes by their respective chunks:
+ std::unordered_map<cChunkCoords, sSetBlockVector, cChunkCoordsHash> Changes;
+ for (const auto & blk: blks)
+ {
+ Changes[cChunkCoords(blk.m_ChunkX, blk.m_ChunkZ)].push_back(blk);
+ } // for blk - blks[]
+ blks.clear();
+
+ // Send the blocks for each affected chunk:
+ for (auto itr = Changes.cbegin(), end = Changes.cend(); itr != end; ++itr)
+ {
+ m_ClientHandle->SendBlockChanges(itr->first.m_ChunkX, itr->first.m_ChunkZ, itr->second);
+ }
+}
+
+
+
+
+
+bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
+{
+ // Call the "placing" hooks; if any fail, abort:
+ cPluginManager * pm = cPluginManager::Get();
+ for (auto blk: a_Blocks)
+ {
+ if (pm->CallHookPlayerPlacingBlock(*this, blk))
+ {
+ // Abort - re-send all the current blocks in the a_Blocks' coords to the client:
+ for (auto blk2: a_Blocks)
+ {
+ m_World->SendBlockTo(blk2.GetX(), blk2.GetY(), blk2.GetZ(), this);
+ }
+ return false;
+ }
+ } // for blk - a_Blocks[]
+
+ // Set the blocks:
+ m_World->SetBlocks(a_Blocks);
+
+ // Notify the blockhandlers:
+ cChunkInterface ChunkInterface(m_World->GetChunkMap());
+ for (auto blk: a_Blocks)
+ {
+ cBlockHandler * newBlock = BlockHandler(blk.m_BlockType);
+ newBlock->OnPlacedByPlayer(ChunkInterface, *m_World, this, blk);
+ }
+
+ // Call the "placed" hooks:
+ for (auto blk: a_Blocks)
+ {
+ pm->CallHookPlayerPlacedBlock(*this, blk);
+ }
+ return true;
+}
+
+
+
+
+
void cPlayer::Detach()
{
super::Detach();
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index c643aaa8e..b94d2659e 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -440,8 +440,27 @@ public:
Loads the m_Rank, m_Permissions, m_MsgPrefix, m_MsgSuffix and m_MsgNameColorCode members. */
void LoadRank(void);
+ /** Calls the block-placement hook and places the block in the world, unless refused by the hook.
+ If the hook prevents the placement, sends the current block at the specified coords back to the client.
+ Assumes that the block is in a currently loaded chunk.
+ Returns true if the block is successfully placed. */
+ bool PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
+
+ /** Sends the block in the specified range around the specified coord to the client
+ as a block change packet.
+ The blocks in range (a_BlockX - a_Range, a_BlockX + a_Range) are sent (NY-metric). */
+ void SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Range = 1);
+
// tolua_end
+ /** Calls the block placement hooks and places the blocks in the world.
+ First the "placing" hooks for all the blocks are called, then the blocks are placed, and finally
+ the "placed" hooks are called.
+ If the any of the "placing" hooks aborts, none of the blocks are placed and the function returns false.
+ Returns true if all the blocks are placed.
+ Assumes that all the blocks are in currently loaded chunks. */
+ bool PlaceBlocks(const sSetBlockVector & a_Blocks);
+
// cEntity overrides:
virtual bool IsCrouched (void) const { return m_IsCrouched; }
virtual bool IsSprinting(void) const { return m_IsSprinting; }