From a2a9341c24609e45e563427eecc1a927ee2b657a Mon Sep 17 00:00:00 2001 From: Alexander Harkness Date: Thu, 21 Jul 2016 12:00:30 +0100 Subject: Tab completion across worlds (#3270) Fixes #2563. --- src/ClientHandle.cpp | 14 +++++++++++++- src/Root.cpp | 30 ++++++++++++++++++++++++++++++ src/Root.h | 4 ++++ src/Server.cpp | 1 + src/Server.h | 7 +++++++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp index 772d8ad6c..997510684 100644 --- a/src/ClientHandle.cpp +++ b/src/ClientHandle.cpp @@ -1831,12 +1831,24 @@ void cClientHandle::HandleUnmount(void) void cClientHandle::HandleTabCompletion(const AString & a_Text) { AStringVector Results; - m_Player->GetWorld()->TabCompleteUserName(a_Text, Results); + // Get player name completions. + if (cRoot::Get()->GetServer()->ShouldAllowMultiWorldTabCompletion()) + { + Results = cRoot::Get()->GetPlayerTabCompletionMultiWorld(a_Text); + } + else + { + m_Player->GetWorld()->TabCompleteUserName(a_Text, Results); + } + + // Get command completions. cRoot::Get()->GetPluginManager()->TabCompleteCommand(a_Text, Results, m_Player); if (Results.empty()) { return; } + + // Sort and send results. std::sort(Results.begin(), Results.end()); SendTabCompletionResults(Results); } diff --git a/src/Root.cpp b/src/Root.cpp index 1eca73cb2..09c91bc72 100644 --- a/src/Root.cpp +++ b/src/Root.cpp @@ -1006,3 +1006,33 @@ int cRoot::GetFurnaceFuelBurnTime(const cItem & a_Fuel) cFurnaceRecipe * FR = Get()->GetFurnaceRecipe(); return FR->GetBurnTime(a_Fuel); } + + + + + +AStringVector cRoot::GetPlayerTabCompletionMultiWorld(const AString & a_Text) +{ + AStringVector Results; + class cWorldCallback : public cWorldListCallback + { + public: + cWorldCallback(AStringVector & a_Results, const AString & a_Search) : + m_Results(a_Results), + m_Search(a_Search) + { + } + + virtual bool Item(cWorld * a_World) override + { + a_World->TabCompleteUserName(m_Search, m_Results); + return true; + } + private: + AStringVector & m_Results; + const AString & m_Search; + } WC(Results, a_Text); + + Get()->ForEachWorld(WC); + return Results; +} diff --git a/src/Root.h b/src/Root.h index a828dc3fa..722554332 100644 --- a/src/Root.h +++ b/src/Root.h @@ -89,6 +89,10 @@ public: /** Returns the number of ticks for how long the item would fuel a furnace. Returns zero if not a fuel */ static int GetFurnaceFuelBurnTime(const cItem & a_Fuel); // tolua_export + /** Returns the completions for a player name across all worlds. Returns an + empty vector if none are found. */ + AStringVector GetPlayerTabCompletionMultiWorld(const AString & a_Text); + /** The current time where the startup of the server has been completed */ std::chrono::steady_clock::time_point m_StartTime; diff --git a/src/Server.cpp b/src/Server.cpp index 8405109de..ba469bd3e 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -234,6 +234,7 @@ bool cServer::InitServer(cSettingsRepositoryInterface & a_Settings, bool a_Shoul LOGWARNING("WARNING: BungeeCord is allowed and server set to online mode. This is unsafe and will not work properly. Disable either authentication or BungeeCord in settings.ini."); } + m_ShouldAllowMultiWorldTabCompletion = a_Settings.GetValueSetB("Server", "AllowMultiWorldTabCompletion", true); m_ShouldLoadOfflinePlayerData = a_Settings.GetValueSetB("PlayerData", "LoadOfflinePlayerData", false); m_ShouldLoadNamedPlayerData = a_Settings.GetValueSetB("PlayerData", "LoadNamedPlayerData", true); diff --git a/src/Server.h b/src/Server.h index b6c8bfe1f..600e7ca97 100644 --- a/src/Server.h +++ b/src/Server.h @@ -139,6 +139,10 @@ public: it makes the server vulnerable to identity theft through direct connections. */ bool ShouldAllowBungeeCord(void) const { return m_ShouldAllowBungeeCord; } + /** Returns true if usernames should be completed across worlds. This is read + from the settings. */ + bool ShouldAllowMultiWorldTabCompletion(void) const { return m_ShouldAllowMultiWorldTabCompletion; } + private: friend class cRoot; // so cRoot can create and destroy cServer @@ -230,6 +234,9 @@ private: /** True if BungeeCord handshake packets (with player UUID) should be accepted. */ bool m_ShouldAllowBungeeCord; + /** True if usernames should be completed across worlds. */ + bool m_ShouldAllowMultiWorldTabCompletion; + /** The list of ports on which the server should listen for connections. Initialized in InitServer(), used in Start(). */ AStringVector m_Ports; -- cgit v1.2.3