summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ClientHandle.cpp87
-rw-r--r--src/ClientHandle.h72
2 files changed, 123 insertions, 36 deletions
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 84286fc41..3711262b6 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -542,19 +542,23 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString & a_Message)
{
- if (a_Channel == "MC|AdvCdm") // Command block, set text, Client -> Server
+ if (a_Channel == "MC|AdvCdm")
{
- const char* Data = a_Message.c_str();
- HandleCommandBlockMessage(Data, a_Message.size());
- return;
+ // Command block, set text, Client -> Server
+ HandleCommandBlockMessage(a_Message.c_str(), a_Message.size());
}
- else if (a_Channel == "MC|Brand") // Client <-> Server branding exchange
+ else if (a_Channel == "MC|Brand")
{
- // We are custom,
- // We are awesome,
- // We are MCServer.
+ // Client <-> Server branding exchange
SendPluginMessage("MC|Brand", "MCServer");
- return;
+ }
+ else if (a_Channel == "REGISTER")
+ {
+ RegisterPluginChannels(BreakApartPluginChannels(a_Message));
+ }
+ else if (a_Channel == "UNREGISTER")
+ {
+ UnregisterPluginChannels(BreakApartPluginChannels(a_Message));
}
cPluginManager::Get()->CallHookPluginMessage(*this, a_Channel, a_Message);
@@ -564,7 +568,61 @@ void cClientHandle::HandlePluginMessage(const AString & a_Channel, const AString
-void cClientHandle::HandleCommandBlockMessage(const char* a_Data, unsigned int a_Length)
+AStringVector cClientHandle::BreakApartPluginChannels(const AString & a_PluginChannels)
+{
+ // Break the string on each NUL character.
+ // Note that StringSplit() doesn't work on this because NUL is a special char - string terminator
+ size_t len = a_PluginChannels.size();
+ size_t first = 0;
+ AStringVector res;
+ for (size_t i = 0; i < len; i++)
+ {
+ if (a_PluginChannels[i] != 0)
+ {
+ continue;
+ }
+ if (i > first)
+ {
+ res.push_back(a_PluginChannels.substr(first, i - first));
+ }
+ first = i + 1;
+ } // for i - a_PluginChannels[]
+ if (first < len)
+ {
+ res.push_back(a_PluginChannels.substr(first, len - first));
+ }
+ return res;
+}
+
+
+
+
+
+void cClientHandle::RegisterPluginChannels(const AStringVector & a_ChannelList)
+{
+ for (AStringVector::const_iterator itr = a_ChannelList.begin(), end = a_ChannelList.end(); itr != end; ++itr)
+ {
+ m_PluginChannels.insert(*itr);
+ } // for itr - a_ChannelList[]
+}
+
+
+
+
+
+void cClientHandle::UnregisterPluginChannels(const AStringVector & a_ChannelList)
+{
+ for (AStringVector::const_iterator itr = a_ChannelList.begin(), end = a_ChannelList.end(); itr != end; ++itr)
+ {
+ m_PluginChannels.erase(*itr);
+ } // for itr - a_ChannelList[]
+}
+
+
+
+
+
+void cClientHandle::HandleCommandBlockMessage(const char * a_Data, unsigned int a_Length)
{
if (a_Length < 14)
{
@@ -2463,6 +2521,15 @@ void cClientHandle::SetViewDistance(int a_ViewDistance)
+bool cClientHandle::HasPluginChannel(const AString & a_PluginChannel)
+{
+ return (m_PluginChannels.find(a_PluginChannel) != m_PluginChannels.end());
+}
+
+
+
+
+
bool cClientHandle::WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
{
if (m_State >= csDestroying)
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index aefca7233..e0447d3f7 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -72,10 +72,10 @@ public:
inline bool IsLoggedIn(void) const { return (m_State >= csAuthenticating); }
- /// Called while the client is being ticked from the world via its cPlayer object
+ /** Called while the client is being ticked from the world via its cPlayer object */
void Tick(float a_Dt);
- /// Called while the client is being ticked from the cServer object
+ /** Called while the client is being ticked from the cServer object */
void ServerTick(float a_Dt);
void Destroy(void);
@@ -150,23 +150,28 @@ public:
void SendWindowOpen (const cWindow & a_Window);
void SendWindowProperty (const cWindow & a_Window, int a_Property, int a_Value);
- const AString & GetUsername(void) const; // tolua_export
- void SetUsername( const AString & a_Username ); // tolua_export
+ // tolua_begin
+ const AString & GetUsername(void) const;
+ void SetUsername( const AString & a_Username );
- inline short GetPing(void) const { return m_Ping; } // tolua_export
+ inline short GetPing(void) const { return m_Ping; }
- void SetViewDistance(int a_ViewDistance); // tolua_export
- int GetViewDistance(void) const { return m_ViewDistance; } // tolua_export
+ void SetViewDistance(int a_ViewDistance);
+ int GetViewDistance(void) const { return m_ViewDistance; }
- void SetLocale(AString & a_Locale) { m_Locale = a_Locale; } // tolua_export
- AString GetLocale(void) const { return m_Locale; } // tolua_export
+ void SetLocale(AString & a_Locale) { m_Locale = a_Locale; }
+ AString GetLocale(void) const { return m_Locale; }
- int GetUniqueID() const { return m_UniqueID; } // tolua_export
+ int GetUniqueID(void) const { return m_UniqueID; }
- /// Returns true if the client wants the chunk specified to be sent (in m_ChunksToSend)
+ bool HasPluginChannel(const AString & a_PluginChannel);
+
+ // tolua_end
+
+ /** Returns true if the client wants the chunk specified to be sent (in m_ChunksToSend) */
bool WantsSendChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
- /// Adds the chunk specified to the list of chunks wanted for sending (m_ChunksToSend)
+ /** Adds the chunk specified to the list of chunks wanted for sending (m_ChunksToSend) */
void AddWantedChunk(int a_ChunkX, int a_ChunkZ);
// Calls that cProtocol descendants use to report state:
@@ -217,14 +222,17 @@ public:
void SendData(const char * a_Data, int a_Size);
- /// Called when the player moves into a different world; queues sreaming the new chunks
+ /** Called when the player moves into a different world; queues sreaming the new chunks */
void MoveToWorld(cWorld & a_World, bool a_SendRespawnPacket);
- /// Handles the block placing packet when it is a real block placement (not block-using, item-using or eating)
+ /** Handles the block placing packet when it is a real block placement (not block-using, item-using or eating) */
void HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler);
private:
+ /** The type used for storing the names of registered plugin channels. */
+ typedef std::set<AString> cChannels;
+
int m_ViewDistance; // Number of chunks the player can see in each direction; 4 is the minimum ( http://wiki.vg/Protocol_FAQ#.E2.80.A6all_connecting_clients_spasm_and_jerk_uncontrollably.21 )
static const int GENERATEDISTANCE = 2; // Server generates this many chunks AHEAD of player sight. 2 is the minimum, since foliage is generated 1 step behind chunk terrain generation
@@ -257,7 +265,7 @@ private:
int m_LastStreamedChunkX;
int m_LastStreamedChunkZ;
- /// Seconds since the last packet data was received (updated in Tick(), reset in DataReceived())
+ /** Seconds since the last packet data was received (updated in Tick(), reset in DataReceived()) */
float m_TimeSinceLastPacket;
short m_Ping;
@@ -279,7 +287,7 @@ private:
int m_LastDigBlockY;
int m_LastDigBlockZ;
- /// Used while csDestroyedWaiting for counting the ticks until the connection is closed
+ /** Used while csDestroyedWaiting for counting the ticks until the connection is closed */
int m_TicksSinceDestruction;
enum eState
@@ -299,10 +307,10 @@ private:
eState m_State;
- /// m_State needs to be locked in the Destroy() function so that the destruction code doesn't run twice on two different threads
+ /** m_State needs to be locked in the Destroy() function so that the destruction code doesn't run twice on two different threads */
cCriticalSection m_CSDestroyingState;
- /// If set to true during csDownloadingWorld, the tick thread calls CheckIfWorldDownloaded()
+ /** If set to true during csDownloadingWorld, the tick thread calls CheckIfWorldDownloaded() */
bool m_ShouldCheckDownloaded;
/** Number of explosions sent this tick */
@@ -311,27 +319,39 @@ private:
static int s_ClientCount;
int m_UniqueID;
- /// Set to true when the chunk where the player is is sent to the client. Used for spawning the player
+ /** Set to true when the chunk where the player is is sent to the client. Used for spawning the player */
bool m_HasSentPlayerChunk;
- /// Client Settings
+ /** Client Settings */
AString m_Locale;
+
+ /** The plugin channels that the client has registered. */
+ cChannels m_PluginChannels;
- /// Returns true if the rate block interactions is within a reasonable limit (bot protection)
+ /** Returns true if the rate block interactions is within a reasonable limit (bot protection) */
bool CheckBlockInteractionsRate(void);
- /// Adds a single chunk to be streamed to the client; used by StreamChunks()
+ /** Adds a single chunk to be streamed to the client; used by StreamChunks() */
void StreamChunk(int a_ChunkX, int a_ChunkZ);
- /// Handles the DIG_STARTED dig packet:
+ /** Handles the DIG_STARTED dig packet: */
void HandleBlockDigStarted (int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta);
- /// Handles the DIG_FINISHED dig packet:
+ /** Handles the DIG_FINISHED dig packet: */
void HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta);
- /// Handles the "MC|AdvCdm" plugin message
- void HandleCommandBlockMessage(const char* a_Data, unsigned int a_Length);
+ /** Converts the protocol-formatted channel list (NUL-separated) into a proper string vector. */
+ AStringVector BreakApartPluginChannels(const AString & a_PluginChannels);
+
+ /** Adds all of the channels to the list of current plugin channels. Handles duplicates gracefully. */
+ void RegisterPluginChannels(const AStringVector & a_ChannelList);
+
+ /** Removes all of the channels from the list of current plugin channels. Ignores channels that are not found. */
+ void UnregisterPluginChannels(const AStringVector & a_ChannelList);
+
+ /** Handles the "MC|AdvCdm" plugin message */
+ void HandleCommandBlockMessage(const char * a_Data, unsigned int a_Length);
// cSocketThreads::cCallback overrides:
virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client