diff --git a/source/Protocol125.cpp b/source/Protocol125.cpp index 4f162dab6..7047f1f30 100644 --- a/source/Protocol125.cpp +++ b/source/Protocol125.cpp @@ -974,10 +974,9 @@ int cProtocol125::ParseHandshake(void) LOGD("HANDSHAKE %s", Username.c_str()); - if (cRoot::Get()->GetDefaultWorld()->GetNumPlayers() >= cRoot::Get()->GetDefaultWorld()->GetMaxPlayers()) + if (!m_Client->HandleHandshake( m_Username )) { - m_Client->Kick("The server is currently full :(-- Try again later"); - return PARSE_OK; + return PARSE_OK; // Player is not allowed into the server } SendHandshake(cRoot::Get()->GetServer()->GetServerID()); diff --git a/source/Protocol132.cpp b/source/Protocol132.cpp index 2765b66b2..d7cd70723 100644 --- a/source/Protocol132.cpp +++ b/source/Protocol132.cpp @@ -332,6 +332,11 @@ int cProtocol132::ParseHandshake(void) HANDLE_PACKET_READ(ReadBEInt, int, ServerPort); m_Username = Username; + if (!m_Client->HandleHandshake( m_Username )) + { + return PARSE_OK; // Player is not allowed into the server + } + // Send a 0xFD Encryption Key Request http://wiki.vg/Protocol#0xFD AString key; CryptoPP::StringSink sink(key); // GCC won't allow inline instantiation in the following line, damned temporary refs diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index 06325785e..c62be45ac 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -918,6 +918,23 @@ void cClientHandle::HandleKeepAlive(int a_KeepAliveID) +bool cClientHandle::HandleHandshake(const AString & a_Username) +{ + if (!cRoot::Get()->GetPluginManager()->CallHookHandshake(this, a_Username)) + { + if (cRoot::Get()->GetDefaultWorld()->GetNumPlayers() >= cRoot::Get()->GetDefaultWorld()->GetMaxPlayers()) + { + Kick("The server is currently full :(-- Try again later"); + return false; + } + } + return true; +} + + + + + void cClientHandle::SendData(const char * a_Data, int a_Size) { { diff --git a/source/cClientHandle.h b/source/cClientHandle.h index ab4e3e64c..f5028b0aa 100644 --- a/source/cClientHandle.h +++ b/source/cClientHandle.h @@ -162,6 +162,7 @@ public: void HandleRespawn (void); void HandleDisconnect (const AString & a_Reason); void HandleKeepAlive (int a_KeepAliveID); + bool HandleHandshake (const AString & a_Username); /** Called when the protocol has finished logging the user in. Return true to allow the user in; false to kick them. diff --git a/source/cPlugin.cpp b/source/cPlugin.cpp index 5fb8057a3..ce66a9655 100644 --- a/source/cPlugin.cpp +++ b/source/cPlugin.cpp @@ -283,6 +283,17 @@ bool cPlugin::OnWeatherChanged(cWorld * a_World) +bool cPlugin::OnHandshake(cClientHandle * a_Client, const AString & a_Username) +{ + UNUSED(a_Client); + UNUSED(a_Username); + return false; +} + + + + + void cPlugin::AddCommand(const AString & a_Command, const AString & a_Description, const AString & a_Permission) { CommandStruct Command; diff --git a/source/cPlugin.h b/source/cPlugin.h index 14a415fdb..c9367051a 100644 --- a/source/cPlugin.h +++ b/source/cPlugin.h @@ -61,6 +61,7 @@ public: virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player); virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player); virtual bool OnWeatherChanged (cWorld * a_World); + virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username); // Accessors const AString & GetName() const { return m_Name; } diff --git a/source/cPluginManager.cpp b/source/cPluginManager.cpp index 13a67ee28..8f52839c8 100644 --- a/source/cPluginManager.cpp +++ b/source/cPluginManager.cpp @@ -627,6 +627,26 @@ bool cPluginManager::CallHookUpdatedSign(cWorld * a_World, int a_BlockX, int a_B +bool cPluginManager::CallHookHandshake(cClientHandle * a_ClientHandle, const AString & a_Username) +{ + HookMap::iterator Plugins = m_Hooks.find(HOOK_HANDSHAKE); + if (Plugins == m_Hooks.end()) + { + return false; + } + for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) + { + if ((*itr)->OnHandshake(a_ClientHandle, a_Username)) + { + return true; + } + } + return false; +} + + + + cPlugin* cPluginManager::GetPlugin( const AString & a_Plugin ) const { diff --git a/source/cPluginManager.h b/source/cPluginManager.h index 578e84013..ea02bff19 100644 --- a/source/cPluginManager.h +++ b/source/cPluginManager.h @@ -115,6 +115,7 @@ public: //tolua_export bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player); bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player); bool CallHookWeatherChanged (cWorld * a_World); + bool CallHookHandshake (cClientHandle * a_ClientHandle, const AString & a_Username); void RemoveHooks( cPlugin* a_Plugin ); void RemovePlugin( cPlugin* a_Plugin, bool a_bDelete = false ); //tolua_export diff --git a/source/cPlugin_NewLua.cpp b/source/cPlugin_NewLua.cpp index dea74540b..1b9e8cdbb 100644 --- a/source/cPlugin_NewLua.cpp +++ b/source/cPlugin_NewLua.cpp @@ -640,6 +640,30 @@ bool cPlugin_NewLua::OnUpdatedSign( +bool cPlugin_NewLua::OnHandshake(cClientHandle * a_Client, const AString & a_Username) +{ + cCSLock Lock(m_CriticalSection); + if (!PushFunction("OnHandshake")) + { + return false; + } + + tolua_pushusertype(m_LuaState, a_Client, "cClientHandle"); + tolua_pushstring (m_LuaState, a_Username.c_str()); + + if (!CallFunction(2, 1, "OnHandshake")) + { + return false; + } + + bool bRetVal = (tolua_toboolean( m_LuaState, -1, 0) > 0); + return bRetVal; +} + + + + + cPlugin_NewLua * cPlugin_NewLua::CreateWebPlugin(lua_State * a_LuaState) { LOGWARN("WARNING: Using deprecated function CreateWebPlugin()! A Lua plugin is a WebPlugin by itself now. (plugin \"%s\" in folder \"%s\")", diff --git a/source/cPlugin_NewLua.h b/source/cPlugin_NewLua.h index 5114889e9..01fefde0a 100644 --- a/source/cPlugin_NewLua.h +++ b/source/cPlugin_NewLua.h @@ -34,17 +34,18 @@ public: //tolua_export virtual bool OnCollectPickup (cPlayer * a_Player, cPickup * a_Pickup) override; virtual bool OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) override; - virtual bool OnKilled (cPawn* a_Killed, cEntity* a_Killer ) override; + virtual bool OnKilled (cPawn * a_Killed, cEntity* a_Killer ) override; virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override; - virtual bool OnPlayerJoin (cPlayer* a_Player ) override; - virtual void OnPlayerMove (cPlayer* a_Player ) override; - virtual void OnPlayerSpawn (cPlayer* a_Player ) override; + virtual bool OnPlayerJoin (cPlayer * a_Player ) override; + virtual void OnPlayerMove (cPlayer * a_Player ) override; + virtual void OnPlayerSpawn (cPlayer * a_Player ) override; virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; - virtual void OnTakeDamage (cPawn* a_Pawn, TakeDamageInfo* a_TakeDamageInfo ) override; + virtual void OnTakeDamage (cPawn * a_Pawn, TakeDamageInfo * a_TakeDamageInfo ) override; virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override; virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override; virtual bool OnWeatherChanged (cWorld * a_World) override; + virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) override; const AString & GetDirectory(void) const {return m_Directory; }