From 00f349c74530e7b66f5988d7e9b1e640c9d81156 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sat, 22 Jul 2023 14:51:15 +0200 Subject: [PATCH] Use ICVar iterator for console partial suggest Added public interface to ICVarIteratorInternal, this class also deals with the deletion of the iterator. This fixes the problem of cvars not showing up that have been registered after 'CModAppSystemGroup::Create()' has been called. Currently, no cvar is registered after it. This will/could change when the plugin system is utilized. Additional changes: - Cvar 'con_suggestion_flags_realtime' has been removed, as we no longer keep an early copy anymore; real time flags are always shows from now on. - Fixed a bug in 'CConsole::FindFromPartial()' where we would return in the loop when 'm_vSuggest.size() >= con_suggestion_limit->GetInt()', instead of breaking out, which skips the element sorting process. --- r5dev/common/global.cpp | 2 -- r5dev/common/global.h | 1 - r5dev/engine/sys_dll.cpp | 6 ---- r5dev/gameui/IConsole.cpp | 38 ++++++++++------------- r5dev/gameui/IConsole.h | 1 - r5dev/public/icvar.h | 63 +++++++++++++++++++++++++++++++++++++++ r5dev/public/tier1/cvar.h | 3 -- r5dev/tier1/cvar.cpp | 22 -------------- 8 files changed, 78 insertions(+), 58 deletions(-) diff --git a/r5dev/common/global.cpp b/r5dev/common/global.cpp index d8f72b7e..6a5c48fc 100644 --- a/r5dev/common/global.cpp +++ b/r5dev/common/global.cpp @@ -202,7 +202,6 @@ ConVar* con_max_history = nullptr; ConVar* con_suggestion_limit = nullptr; ConVar* con_suggestion_showhelptext = nullptr; ConVar* con_suggestion_showflags = nullptr; -ConVar* con_suggestion_flags_realtime = nullptr; ConVar* origin_disconnectWhenOffline = nullptr; @@ -394,7 +393,6 @@ void ConVar_StaticInit(void) con_suggestion_limit = ConVar::StaticCreate("con_suggestion_limit" , "128" , FCVAR_DEVELOPMENTONLY, "Maximum number of suggestions the autocomplete window will show for the console.", true, 0.f, false, 0.f, nullptr, nullptr); con_suggestion_showhelptext = ConVar::StaticCreate("con_suggestion_showhelptext" , "1" , FCVAR_DEVELOPMENTONLY, "Show CommandBase help text in autocomplete window.", false, 0.f, false, 0.f, nullptr, nullptr); con_suggestion_showflags = ConVar::StaticCreate("con_suggestion_showflags" , "1" , FCVAR_DEVELOPMENTONLY, "Show CommandBase flags in autocomplete window.", false, 0.f, false, 0.f, nullptr, nullptr); - con_suggestion_flags_realtime = ConVar::StaticCreate("con_suggestion_flags_realtime", "1" , FCVAR_DEVELOPMENTONLY, "Whether to show compile-time or run-time CommandBase flags.", false, 0.f, false, 0.f, nullptr, nullptr); serverbrowser_hideEmptyServers = ConVar::StaticCreate("serverbrowser_hideEmptyServers", "0", FCVAR_RELEASE, "Hide empty servers in the server browser", false, 0.f, false, 0.f, nullptr, nullptr); serverbrowser_mapFilter = ConVar::StaticCreate("serverbrowser_mapFilter", "0", FCVAR_RELEASE, "Filter servers by map in the server browser", false, 0.f, false, 0.f, nullptr, nullptr); diff --git a/r5dev/common/global.h b/r5dev/common/global.h index c61f16da..401544e8 100644 --- a/r5dev/common/global.h +++ b/r5dev/common/global.h @@ -192,7 +192,6 @@ extern ConVar* con_max_history; extern ConVar* con_suggestion_limit; extern ConVar* con_suggestion_showhelptext; extern ConVar* con_suggestion_showflags; -extern ConVar* con_suggestion_flags_realtime; extern ConVar* origin_disconnectWhenOffline; #endif // !DEDICATED diff --git a/r5dev/engine/sys_dll.cpp b/r5dev/engine/sys_dll.cpp index f1194bc8..0a87ef71 100644 --- a/r5dev/engine/sys_dll.cpp +++ b/r5dev/engine/sys_dll.cpp @@ -126,12 +126,6 @@ bool CModAppSystemGroup::StaticCreate(CModAppSystemGroup* pModAppSystemGroup) g_pEngineTraceClient = g_pFactory->GetFactoryPtr(INTERFACEVERSION_ENGINETRACE_CLIENT, false).RCast(); g_pImGuiConfig->Load(); // Load ImGui configs. - for (auto& map : g_pCVar->DumpToMap()) - { - g_pConsole->m_vsvCommandBases.push_back( - CSuggest(map.first, map.second->GetFlags())); - } - DirectX_Init(); #endif // !DEDICATED diff --git a/r5dev/gameui/IConsole.cpp b/r5dev/gameui/IConsole.cpp index 4799e79b..74669c8c 100644 --- a/r5dev/gameui/IConsole.cpp +++ b/r5dev/gameui/IConsole.cpp @@ -587,27 +587,30 @@ void CConsole::FindFromPartial(void) ClearAutoComplete(); m_bCanAutoComplete = false; - for (const CSuggest& suggest : m_vsvCommandBases) + ICvar::Iterator iter(g_pCVar); + for (iter.SetFirst(); iter.IsValid(); iter.Next()) { if (m_vSuggest.size() >= size_t(con_suggestion_limit->GetInt())) { - return; + break; } - if (!HasPartial(suggest.m_svName, m_szInputBuf)) + + const ConCommandBase* pCommandBase = iter.Get(); + if (pCommandBase->IsFlagSet(FCVAR_HIDDEN)) + { + continue; + } + + const char* pCommandName = pCommandBase->GetName(); + if (!V_stristr(pCommandName, m_szInputBuf)) { continue; } if (std::find(m_vSuggest.begin(), m_vSuggest.end(), - suggest.m_svName) == m_vSuggest.end()) + pCommandName) == m_vSuggest.end()) { - string svValue; int nFlags = FCVAR_NONE; - const ConCommandBase* pCommandBase = g_pCVar->FindCommandBase(suggest.m_svName.c_str()); - - if (!pCommandBase || pCommandBase->IsFlagSet(FCVAR_HIDDEN)) - { - continue; - } + string svValue; if (!pCommandBase->IsCommand()) { @@ -636,18 +639,7 @@ void CConsole::FindFromPartial(void) } } } - if (con_suggestion_showflags->GetBool()) - { - if (con_suggestion_flags_realtime->GetBool()) - { - nFlags = pCommandBase->GetFlags(); - } - else // Display compile-time flags instead. - { - nFlags = suggest.m_nFlags; - } - } - m_vSuggest.push_back(CSuggest(suggest.m_svName + svValue, nFlags)); + m_vSuggest.push_back(CSuggest(pCommandName + svValue, pCommandBase->GetFlags())); } else { break; } } diff --git a/r5dev/gameui/IConsole.h b/r5dev/gameui/IConsole.h index 5d3d4306..e48dba35 100644 --- a/r5dev/gameui/IConsole.h +++ b/r5dev/gameui/IConsole.h @@ -106,7 +106,6 @@ private: public: bool m_bActivate = false; - vector m_vsvCommandBases; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/public/icvar.h b/r5dev/public/icvar.h index 40483c78..76b1bd23 100644 --- a/r5dev/public/icvar.h +++ b/r5dev/public/icvar.h @@ -108,7 +108,40 @@ public: virtual bool HasQueuedMaterialThreadConVarSets() const = 0; virtual int ProcessQueuedMaterialThreadConVarSets() = 0; +protected: class ICVarIteratorInternal; +public: + /// Iteration over all cvars. + /// (THIS IS A SLOW OPERATION AND YOU SHOULD AVOID IT.) + /// usage: + /// { ICVar::Iterator iter(g_pCVar); + /// for ( iter.SetFirst() ; iter.IsValid() ; iter.Next() ) + /// { + /// ConCommandBase *cmd = iter.Get(); + /// } + /// } + /// The Iterator class actually wraps the internal factory methods + /// so you don't need to worry about new/delete -- scope takes care + // of it. + /// We need an iterator like this because we can't simply return a + /// pointer to the internal data type that contains the cvars -- + /// it's a custom, protected class with unusual semantics and is + /// prone to change. + class Iterator + { + public: + inline void SetFirst(void) RESTRICT; + inline void Next(void) RESTRICT; + inline bool IsValid(void) RESTRICT; + inline ConCommandBase* Get(void) RESTRICT; + + inline Iterator(ICvar* icvar); + inline ~Iterator(void); + private: + ICVarIteratorInternal* m_pIter; + }; + protected: + // internals for ICVarIterator class ICVarIteratorInternal { public: @@ -123,4 +156,34 @@ protected: virtual ICVarIteratorInternal* FactoryInternalIterator(void) = 0; }; +inline void ICvar::Iterator::SetFirst(void) RESTRICT +{ + m_pIter->SetFirst(); +} + +inline void ICvar::Iterator::Next(void) RESTRICT +{ + m_pIter->Next(); +} + +inline bool ICvar::Iterator::IsValid(void) RESTRICT +{ + return m_pIter->IsValid(); +} + +inline ConCommandBase* ICvar::Iterator::Get(void) RESTRICT +{ + return m_pIter->Get(); +} + +inline ICvar::Iterator::Iterator(ICvar* icvar) +{ + m_pIter = icvar->FactoryInternalIterator(); +} + +inline ICvar::Iterator::~Iterator(void) +{ + delete m_pIter; +} + #endif // ICVAR_H diff --git a/r5dev/public/tier1/cvar.h b/r5dev/public/tier1/cvar.h index 1e488a1e..79a05bf1 100644 --- a/r5dev/public/tier1/cvar.h +++ b/r5dev/public/tier1/cvar.h @@ -66,9 +66,6 @@ extern CCvarUtilities* cv; class CCvar : public CBaseAppSystem< ICvar > { // Implementation in engine. -public: - unordered_map DumpToMap(void); - protected: enum ConVarSetType_t { diff --git a/r5dev/tier1/cvar.cpp b/r5dev/tier1/cvar.cpp index d3fc6ae1..590adc8e 100644 --- a/r5dev/tier1/cvar.cpp +++ b/r5dev/tier1/cvar.cpp @@ -1061,28 +1061,6 @@ int CCvarUtilities::CvarFindFlagsCompletionCallback(const char* partial, return values; } -//----------------------------------------------------------------------------- -// Purpose: returns all ConVars -//----------------------------------------------------------------------------- -unordered_map CCvar::DumpToMap(void) -{ - stringstream ss; - CCVarIteratorInternal* itint = FactoryInternalIterator(); // Allocate new InternalIterator. - - unordered_map allConVars; - - for (itint->SetFirst(); itint->IsValid(); itint->Next()) // Loop through all instances. - { - ConCommandBase* pCommand = itint->Get(); - const char* pszCommandName = pCommand->m_pszName; - allConVars[pszCommandName] = pCommand; - } - - delete itint; - - return allConVars; -} - /////////////////////////////////////////////////////////////////////////////// CCvar* g_pCVar = nullptr;