summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortycho <tycho@localhost>2015-03-21 18:17:26 +0100
committertycho <tycho@localhost>2015-05-07 04:47:46 +0200
commit448df85e569e85e1b4da4eac685950273f30ae1f (patch)
tree045241fff430ae2ffe0b97d7151e44293ad76467
parentMerge pull request #1946 from SafwatHalaby/lean (diff)
downloadcuberite-448df85e569e85e1b4da4eac685950273f30ae1f.tar
cuberite-448df85e569e85e1b4da4eac685950273f30ae1f.tar.gz
cuberite-448df85e569e85e1b4da4eac685950273f30ae1f.tar.bz2
cuberite-448df85e569e85e1b4da4eac685950273f30ae1f.tar.lz
cuberite-448df85e569e85e1b4da4eac685950273f30ae1f.tar.xz
cuberite-448df85e569e85e1b4da4eac685950273f30ae1f.tar.zst
cuberite-448df85e569e85e1b4da4eac685950273f30ae1f.zip
-rw-r--r--src/Bindings/LuaState.cpp41
-rw-r--r--src/Bindings/LuaState.h6
-rw-r--r--src/Bindings/ManualBindings.cpp58
-rw-r--r--src/Broadcaster.cpp47
-rw-r--r--src/Broadcaster.h20
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Chunk.h6
-rw-r--r--src/ChunkMap.cpp22
-rw-r--r--src/ChunkMap.h3
-rw-r--r--src/ClientHandle.cpp9
-rw-r--r--src/ClientHandle.h2
-rw-r--r--src/Entities/Floater.cpp6
-rw-r--r--src/Mobs/Wolf.cpp5
-rw-r--r--src/Protocol/Protocol.h3
-rw-r--r--src/Protocol/Protocol17x.cpp10
-rw-r--r--src/Protocol/Protocol17x.h1
-rw-r--r--src/Protocol/Protocol18x.cpp44
-rw-r--r--src/Protocol/Protocol18x.h1
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp11
-rw-r--r--src/Protocol/ProtocolRecognizer.h1
-rw-r--r--src/World.cpp24
-rw-r--r--src/World.h7
22 files changed, 310 insertions, 19 deletions
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index ed31e678f..f574dbe26 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -1133,6 +1133,23 @@ void cLuaState::GetStackValue(int a_StackPos, pWorld & a_ReturnedVal)
+void cLuaState::GetStackValue(int a_StackPos, pClientHandle & a_ReturnedVal)
+{
+ if (lua_isnil(m_LuaState, a_StackPos))
+ {
+ a_ReturnedVal = nullptr;
+ return;
+ }
+ tolua_Error err;
+ if (tolua_isusertype(m_LuaState, a_StackPos, "cClientHandle", false, &err))
+ {
+ a_ReturnedVal = *(reinterpret_cast<cClientHandle **>(lua_touserdata(m_LuaState, a_StackPos)));
+ }
+}
+
+
+
+
bool cLuaState::CallFunction(int a_NumResults)
{
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
@@ -1415,6 +1432,30 @@ bool cLuaState::CheckParamEnd(int a_Param)
+bool cLuaState::IsParamUserType(int a_Param, AString a_UserType)
+{
+ ASSERT(IsValid());
+
+ tolua_Error tolua_err;
+ return tolua_isusertype(m_LuaState, a_Param, a_UserType.c_str(), 0, &tolua_err);
+}
+
+
+
+
+
+bool cLuaState::IsParamNumber(int a_Param)
+{
+ ASSERT(IsValid());
+
+ tolua_Error tolua_err;
+ return tolua_isnumber(m_LuaState, a_Param, 0, &tolua_err);
+}
+
+
+
+
+
bool cLuaState::ReportErrors(int a_Status)
{
return ReportErrors(m_LuaState, a_Status);
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index 6bedbf5ec..3f2e828f3 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -76,6 +76,7 @@ typedef cPluginManager * pPluginManager;
typedef cRoot * pRoot;
typedef cScoreboard * pScoreboard;
typedef cWorld * pWorld;
+typedef cClientHandle * pClientHandle;
@@ -254,6 +255,7 @@ public:
void GetStackValue(int a_StackPos, int & a_Value);
void GetStackValue(int a_StackPos, pBlockArea & a_Value);
void GetStackValue(int a_StackPos, pBoundingBox & a_Value);
+ void GetStackValue(int a_StackPos, pClientHandle & a_Value);
void GetStackValue(int a_StackPos, pMapManager & a_Value);
void GetStackValue(int a_StackPos, pPluginManager & a_Value);
void GetStackValue(int a_StackPos, pRoot & a_Value);
@@ -307,6 +309,10 @@ public:
/** Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters) */
bool CheckParamEnd(int a_Param);
+ bool IsParamUserType(int a_Param, AString a_UserType);
+
+ bool IsParamNumber(int a_Param);
+
/** If the status is nonzero, prints the text on the top of Lua stack and returns true */
bool ReportErrors(int status);
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index f25800d5f..2fbff11d3 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -32,9 +32,10 @@
#include "../WorldStorage/SchematicFileSerializer.h"
#include "../CompositeChat.h"
#include "../StringCompression.h"
+#include "../Broadcaster.h"
-
+#include <array>
// Better error reporting for Lua
@@ -2009,6 +2010,60 @@ static int tolua_cPluginManager_FindPlugins(lua_State * tolua_S)
+static int tolua_cWorld_BroadcastParticleEffect(lua_State * tolua_S)
+{
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamString (2) ||
+ !L.CheckParamNumber (3, 10)
+ )
+ {
+ return 0;
+ }
+
+ cPluginLua * Plugin = GetLuaPlugin(tolua_S);
+ if (Plugin == nullptr)
+ {
+ return 0;
+ }
+
+ // Read the params:
+ cWorld * World = nullptr;
+ AString Name;
+ double PosX, PosY, PosZ, OffX, OffY, OffZ;
+ double ParticleData;
+ int ParticleAmmount;
+ L.GetStackValues(1, World, Name, PosX, PosY, PosZ, OffX, OffY, OffZ, ParticleData, ParticleAmmount);
+ if (World == nullptr)
+ {
+ LOGWARNING("World:BroadcastParticleEffect(): invalid world parameter");
+ L.LogStackTrace();
+ return 0;
+ }
+
+ std::array<int, 2> data;
+
+ for (int i = 0; (i < 2) && L.IsParamNumber(11 + i); i++)
+ {
+ L.GetStackValue(11 + i, data[i]);
+ }
+
+ cClientHandle * Exclude = nullptr;
+
+ if (L.IsParamUserType(11, "cClientHandle"))
+ {
+ L.GetStackValue(11, Exclude);
+ }
+ World->GetBroadcaster().BroadcastParticleEffect(Name, Vector3f(PosX, PosY, PosZ), Vector3f(OffX, OffY, OffZ), ParticleData, ParticleAmmount, Exclude);
+
+ return 0;
+}
+
+
+
+
+
static int tolua_cWorld_ChunkStay(lua_State * tolua_S)
{
/* Function signature:
@@ -3792,6 +3847,7 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "cWorld");
+ tolua_function(tolua_S, "BroadcastParticleEffect", tolua_cWorld_BroadcastParticleEffect);
tolua_function(tolua_S, "ChunkStay", tolua_cWorld_ChunkStay);
tolua_function(tolua_S, "DoWithBlockEntityAt", tolua_DoWithXYZ<cWorld, cBlockEntity, &cWorld::DoWithBlockEntityAt>);
tolua_function(tolua_S, "DoWithBeaconAt", tolua_DoWithXYZ<cWorld, cBeaconEntity, &cWorld::DoWithBeaconAt>);
diff --git a/src/Broadcaster.cpp b/src/Broadcaster.cpp
new file mode 100644
index 000000000..7f2b65d09
--- /dev/null
+++ b/src/Broadcaster.cpp
@@ -0,0 +1,47 @@
+
+#include "Globals.h"
+#include "Broadcaster.h"
+#include "World.h"
+#include "Chunk.h"
+
+cBroadcaster::cBroadcaster(cWorld * a_World) :
+ m_World(a_World)
+{
+}
+
+
+void cBroadcaster::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude)
+{
+ m_World->DoWithChunkAt(a_Src,
+ [=](cChunk & a_Chunk) -> bool
+ {
+ for (auto&& client : a_Chunk.GetAllClients())
+ {
+ if (client == a_Exclude)
+ {
+ continue;
+ }
+ client->SendParticleEffect(a_ParticleName, a_Src.x, a_Src.y, a_Src.z, a_Offset.x, a_Offset.y, a_Offset.z, a_ParticleData, a_ParticleAmount);
+ };
+ return true;
+ });
+}
+
+
+void cBroadcaster::BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data, cClientHandle * a_Exclude)
+{
+ m_World->DoWithChunkAt(a_Src,
+ [=](cChunk & a_Chunk) -> bool
+ {
+ for (auto && client : a_Chunk.GetAllClients())
+ {
+ if (client == a_Exclude)
+ {
+ continue;
+ }
+ client->SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount, a_Data);
+ };
+ return true;
+ });
+}
+
diff --git a/src/Broadcaster.h b/src/Broadcaster.h
new file mode 100644
index 000000000..27d35fe4d
--- /dev/null
+++ b/src/Broadcaster.h
@@ -0,0 +1,20 @@
+
+class cWorld;
+
+#include <array>
+
+class cBroadcaster
+{
+
+public:
+
+ cBroadcaster(cWorld * a_World);
+
+ void BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = nullptr);
+
+ void BroadcastParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data, cClientHandle * a_Exclude = nullptr);
+
+private:
+ cWorld * m_World;
+
+};
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e04e6311f..fd28f3787 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -18,6 +18,7 @@ SET (SRCS
BlockArea.cpp
BlockID.cpp
BlockInfo.cpp
+ Broadcaster.cpp
BoundingBox.cpp
ByteBuffer.cpp
ChatColor.cpp
@@ -77,6 +78,7 @@ SET (HDRS
BlockInServerPluginInterface.h
BlockInfo.h
BlockTracer.h
+ Broadcaster.h
BoundingBox.h
BuildInfo.h.cmake
ByteBuffer.h
diff --git a/src/Chunk.h b/src/Chunk.h
index e8c60a74b..58f6ba707 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -439,6 +439,9 @@ public:
as at least one requests is active the chunk will be ticked). */
void SetAlwaysTicked(bool a_AlwaysTicked);
+ // Makes a copy of the list
+ cClientHandleList GetAllClients(void) const {return m_LoadedByClient; }
+
private:
friend class cChunkMap;
@@ -530,9 +533,6 @@ private:
/** Wakes up each simulator for its specific blocks; through all the blocks in the chunk */
void WakeUpSimulators(void);
-
- // Makes a copy of the list
- cClientHandleList GetAllClients(void) const {return m_LoadedByClient; }
/** Sends m_PendingSendBlocks to all clients */
void BroadcastPendingBlockChanges(void);
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index b84b8dc3d..edff6baf1 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -791,6 +791,28 @@ bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callb
}
+bool cChunkMap::DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback)
+{
+ int ChunkX, ChunkZ;
+ cChunkDef::BlockToChunk(a_BlockPos.x, a_BlockPos.z, ChunkX, ChunkZ);
+ struct cCallBackWrapper : cChunkCallback
+ {
+ cCallBackWrapper(std::function<bool(cChunk &)> a_InnerCallback) :
+ m_Callback(a_InnerCallback)
+ {
+ }
+
+ virtual bool Item(cChunk * a_Chunk)
+ {
+ return m_Callback(*a_Chunk);
+ }
+
+ private:
+ std::function<bool(cChunk &)> m_Callback;
+ } callback(a_Callback);
+ return DoWithChunk(ChunkX, ChunkZ, callback);
+}
+
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 0fac79c84..e9f1b94c0 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -104,6 +104,9 @@ public:
/** Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback */
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
+ /** Calls the callback for the chunk at the block position specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback **/
+ bool DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback);
+
/** Wakes up simulators for the specified block */
void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 60a2f8873..b12ab419b 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -2374,6 +2374,15 @@ void cClientHandle::SendParticleEffect(const AString & a_ParticleName, float a_S
+void cClientHandle::SendParticleEffect(const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data)
+{
+ m_Protocol->SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount, a_Data);
+}
+
+
+
+
+
void cClientHandle::SendPickupSpawn(const cPickup & a_Pickup)
{
m_Protocol->SendPickupSpawn(a_Pickup);
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 9e5287985..7992d6bc2 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -22,6 +22,7 @@
#include "ChunkSender.h"
+#include <array>
@@ -177,6 +178,7 @@ public: // tolua_export
void SendMapInfo (int a_ID, unsigned int a_Scale);
void SendPaintingSpawn (const cPainting & a_Painting);
void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount);
+ void SendParticleEffect (const AString & a_ParticleName, const Vector3f a_Src, const Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data);
void SendPickupSpawn (const cPickup & a_Pickup);
void SendPlayerAbilities (void);
void SendPlayerListAddPlayer (const cPlayer & a_Player);
diff --git a/src/Entities/Floater.cpp b/src/Entities/Floater.cpp
index cf8dd6c6f..0c868270d 100644
--- a/src/Entities/Floater.cpp
+++ b/src/Entities/Floater.cpp
@@ -6,7 +6,7 @@
#include "Floater.h"
#include "Player.h"
#include "../ClientHandle.h"
-
+#include "Broadcaster.h"
@@ -145,12 +145,12 @@ void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
LOGD("Started producing particles for floater %i", GetUniqueID());
m_ParticlePos.Set(GetPosX() + (-4 + m_World->GetTickRandomNumber(8)), GetPosY(), GetPosZ() + (-4 + m_World->GetTickRandomNumber(8)));
- m_World->BroadcastParticleEffect("splash", (float) m_ParticlePos.x, (float) m_ParticlePos.y, (float) m_ParticlePos.z, 0, 0, 0, 0, 15);
+ m_World->GetBroadcaster().BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15);
}
else if (m_CountDownTime < 20)
{
m_ParticlePos = (m_ParticlePos + (GetPosition() - m_ParticlePos) / 6);
- m_World->BroadcastParticleEffect("splash", (float) m_ParticlePos.x, (float) m_ParticlePos.y, (float) m_ParticlePos.z, 0, 0, 0, 0, 15);
+ m_World->GetBroadcaster().BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15);
}
m_CountDownTime--;
diff --git a/src/Mobs/Wolf.cpp b/src/Mobs/Wolf.cpp
index c66763f17..3c2ec1520 100644
--- a/src/Mobs/Wolf.cpp
+++ b/src/Mobs/Wolf.cpp
@@ -5,6 +5,7 @@
#include "../World.h"
#include "../Entities/Player.h"
#include "../Items/ItemHandler.h"
+#include "Broadcaster.h"
@@ -83,13 +84,13 @@ void cWolf::OnRightClicked(cPlayer & a_Player)
SetIsTame(true);
SetOwner(a_Player.GetName(), a_Player.GetUUID());
m_World->BroadcastEntityStatus(*this, esWolfTamed);
- m_World->BroadcastParticleEffect("heart", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
+ m_World->GetBroadcaster().BroadcastParticleEffect("heart", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
}
else
{
// Taming failed
m_World->BroadcastEntityStatus(*this, esWolfTaming);
- m_World->BroadcastParticleEffect("smoke", (float) GetPosX(), (float) GetPosY(), (float) GetPosZ(), 0, 0, 0, 0, 5);
+ m_World->GetBroadcaster().BroadcastParticleEffect("smoke", static_cast<Vector3f>(GetPosition()), Vector3f{}, 0, 5);
}
}
}
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index d8399049e..3bca7551b 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -16,6 +16,8 @@
#include "../Map.h"
#include "../ByteBuffer.h"
+#include <array>
+
@@ -98,6 +100,7 @@ public:
virtual void SendPlayerAbilities (void) = 0;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) = 0;
virtual void SendParticleEffect (const AString & a_SoundName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) = 0;
+ virtual void SendParticleEffect (const AString & a_SoundName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) = 0;
virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) = 0;
virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) = 0;
virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) = 0;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 8e7d526ef..57631c37d 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -804,6 +804,16 @@ void cProtocol172::SendParticleEffect(const AString & a_ParticleName, float a_Sr
+void cProtocol172::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data)
+{
+ // 1.72 doesn't support extra data
+ this->SendParticleEffect(a_ParticleName, a_Src.x, a_Src.y, a_Src.z, a_Offset.x, a_Offset.y, a_Offset.z, a_ParticleData, a_ParticleAmount);
+}
+
+
+
+
+
void cProtocol172::SendPlayerListAddPlayer(const cPlayer & a_Player)
{
ASSERT(m_State == 3); // In game mode?
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 1212cc325..773c39f87 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -99,6 +99,7 @@ public:
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override;
+ virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) override;
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override;
virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override;
diff --git a/src/Protocol/Protocol18x.cpp b/src/Protocol/Protocol18x.cpp
index 4429ca683..628d8f528 100644
--- a/src/Protocol/Protocol18x.cpp
+++ b/src/Protocol/Protocol18x.cpp
@@ -802,6 +802,50 @@ void cProtocol180::SendParticleEffect(const AString & a_ParticleName, float a_Sr
+void cProtocol180::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data)
+{
+ ASSERT(m_State == 3); // In game mode?
+ int ParticleID = GetParticleID(a_ParticleName);
+
+ cPacketizer Pkt(*this, 0x2A);
+ Pkt.WriteBEInt32(ParticleID);
+ Pkt.WriteBool(false);
+ Pkt.WriteBEFloat(a_Src.x);
+ Pkt.WriteBEFloat(a_Src.y);
+ Pkt.WriteBEFloat(a_Src.z);
+ Pkt.WriteBEFloat(a_Offset.x);
+ Pkt.WriteBEFloat(a_Offset.y);
+ Pkt.WriteBEFloat(a_Offset.z);
+ Pkt.WriteBEFloat(a_ParticleData);
+ Pkt.WriteBEInt32(a_ParticleAmount);
+ switch (ParticleID)
+ {
+ // iconcrack
+ case 36:
+ {
+ Pkt.WriteVarInt32(static_cast<UInt32>(a_Data[0]));
+ Pkt.WriteVarInt32(static_cast<UInt32>(a_Data[1]));
+ break;
+ }
+ // blockcrack
+ // blockdust
+ case 37:
+ case 38:
+ {
+ Pkt.WriteVarInt32(static_cast<UInt32>(a_Data[0]));
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+}
+
+
+
+
+
void cProtocol180::SendPlayerListAddPlayer(const cPlayer & a_Player)
{
ASSERT(m_State == 3); // In game mode?
diff --git a/src/Protocol/Protocol18x.h b/src/Protocol/Protocol18x.h
index 9aa5ed827..21024d702 100644
--- a/src/Protocol/Protocol18x.h
+++ b/src/Protocol/Protocol18x.h
@@ -97,6 +97,7 @@ public:
virtual void SendPlayerAbilities (void) override;
virtual void SendEntityAnimation (const cEntity & a_Entity, char a_Animation) override;
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override;
+ virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) override;
virtual void SendPlayerListAddPlayer (const cPlayer & a_Player) override;
virtual void SendPlayerListRemovePlayer (const cPlayer & a_Player) override;
virtual void SendPlayerListUpdateGameMode (const cPlayer & a_Player) override;
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 36f8bc791..e7f7a4526 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -439,6 +439,17 @@ void cProtocolRecognizer::SendParticleEffect(const AString & a_ParticleName, flo
+
+void cProtocolRecognizer::SendParticleEffect(const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data)
+{
+ ASSERT(m_Protocol != nullptr);
+ m_Protocol->SendParticleEffect(a_ParticleName, a_Src, a_Offset, a_ParticleData, a_ParticleAmount, a_Data);
+}
+
+
+
+
+
void cProtocolRecognizer::SendPaintingSpawn(const cPainting & a_Painting)
{
m_Protocol->SendPaintingSpawn(a_Painting);
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 13be9478f..6c2185d6d 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -81,6 +81,7 @@ public:
virtual void SendMapDecorators (int a_ID, const cMapDecoratorList & a_Decorators, unsigned int m_Scale) override;
virtual void SendMapInfo (int a_ID, unsigned int a_Scale) override;
virtual void SendParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount) override;
+ virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) override;
virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
virtual void SendPickupSpawn (const cPickup & a_Pickup) override;
virtual void SendPlayerAbilities (void) override;
diff --git a/src/World.cpp b/src/World.cpp
index 87209e4c2..6c2e31965 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -57,7 +57,7 @@
#include <stdlib.h>
#endif
-
+#include "Broadcaster.h"
@@ -1459,6 +1459,15 @@ bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback
+bool cWorld::DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback)
+{
+ return m_ChunkMap->DoWithChunkAt(a_BlockPos, a_Callback);
+}
+
+
+
+
+
void cWorld::GrowTree(int a_X, int a_Y, int a_Z)
{
if (GetBlock(a_X, a_Y, a_Z) == E_BLOCK_SAPLING)
@@ -2241,14 +2250,6 @@ void cWorld::BroadcastEntityAnimation(const cEntity & a_Entity, char a_Animation
-void cWorld::BroadcastParticleEffect(const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude)
-{
- m_ChunkMap->BroadcastParticleEffect(a_ParticleName, a_SrcX, a_SrcY, a_SrcZ, a_OffsetX, a_OffsetY, a_OffsetZ, a_ParticleData, a_ParticleAmount, a_Exclude);
-}
-
-
-
-
void cWorld::BroadcastPlayerListAddPlayer(const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
@@ -3770,5 +3771,10 @@ void cWorld::cChunkGeneratorCallbacks::CallHookChunkGenerated (cChunkDesc & a_Ch
+cBroadcaster cWorld::GetBroadcaster()
+{
+ return cBroadcaster(this);
+}
+
diff --git a/src/World.h b/src/World.h
index 1de241f60..624262cd3 100644
--- a/src/World.h
+++ b/src/World.h
@@ -55,6 +55,7 @@ class cMobHeadEntity;
class cCompositeChat;
class cCuboid;
class cSetChunkData;
+class cBroadcaster;
typedef std::list< cPlayer * > cPlayerList;
@@ -243,7 +244,6 @@ public:
void BroadcastEntityStatus (const cEntity & a_Entity, char a_Status, const cClientHandle * a_Exclude = nullptr);
void BroadcastEntityVelocity (const cEntity & a_Entity, const cClientHandle * a_Exclude = nullptr);
virtual void BroadcastEntityAnimation (const cEntity & a_Entity, char a_Animation, const cClientHandle * a_Exclude = nullptr) override; // tolua_export
- void BroadcastParticleEffect (const AString & a_ParticleName, float a_SrcX, float a_SrcY, float a_SrcZ, float a_OffsetX, float a_OffsetY, float a_OffsetZ, float a_ParticleData, int a_ParticleAmount, cClientHandle * a_Exclude = nullptr); // tolua_export
void BroadcastPlayerListAddPlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr);
void BroadcastPlayerListRemovePlayer (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr);
void BroadcastPlayerListUpdateGameMode (const cPlayer & a_Player, const cClientHandle * a_Exclude = nullptr);
@@ -610,6 +610,9 @@ public:
/** Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback */
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
+ /** Calls the callback for the chunk at the block position specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback **/
+ bool DoWithChunkAt(Vector3i a_BlockPos, std::function<bool(cChunk &)> a_Callback);
+
void GrowTreeImage(const sSetBlockVector & a_Blocks);
// tolua_begin
@@ -828,6 +831,8 @@ public:
This function allows nesting and task-concurrency (multiple separate tasks can request ticking and as long
as at least one requests is active the chunk will be ticked). */
void SetChunkAlwaysTicked(int a_ChunkX, int a_ChunkZ, bool a_AlwaysTicked = true); // tolua_export
+
+ cBroadcaster GetBroadcaster();
private: