From 08825fdf0d2feb47cca1ae5e4aaa501422802431 Mon Sep 17 00:00:00 2001 From: Chuvi Date: Fri, 10 Mar 2017 01:15:08 +0300 Subject: [PATCH] Add tab completion support in launcher. (#393) Add tab completion support in launcher. --- rehlds/common/textconsole.cpp | 52 ++++++++++++++++++++++-------- rehlds/dedicated/src/dedicated.h | 5 ++- rehlds/dedicated/src/precompiled.h | 6 ++++ rehlds/dedicated/src/sys_ded.cpp | 21 +++++++++++- rehlds/public/rehlds/rehlds_api.h | 4 ++- rehlds/rehlds/rehlds_api_impl.cpp | 26 ++++++++++++++- 6 files changed, 97 insertions(+), 17 deletions(-) diff --git a/rehlds/common/textconsole.cpp b/rehlds/common/textconsole.cpp index a0b8238..8af181c 100644 --- a/rehlds/common/textconsole.cpp +++ b/rehlds/common/textconsole.cpp @@ -130,13 +130,22 @@ void CTextConsole::ReceiveBackspace() void CTextConsole::ReceiveTab() { +#ifndef LAUNCHER_FIXES if (!m_System) return; - +#else + if (!rehldsFuncs || !m_nConsoleTextLen) + { + return; + } +#endif ObjectList matches; m_szConsoleText[ m_nConsoleTextLen ] = '\0'; +#ifndef LAUNCHER_FIXES m_System->GetCommandMatches(m_szConsoleText, &matches); - +#else + rehldsFuncs->GetCommandMatches(m_szConsoleText, &matches); +#endif if (matches.IsEmpty()) return; @@ -159,15 +168,26 @@ void CTextConsole::ReceiveTab() else { int nLongestCmd = 0; + int nSmallestCmd = 0; int nCurrentColumn; int nTotalColumns; - + char szCommonCmd[256];//Should be enough. + char szFormatCmd[256]; + char *pszSmallestCmd; char *pszCurrentCmd = (char *)matches.GetFirst(); + nSmallestCmd = strlen(pszCurrentCmd); + pszSmallestCmd = pszCurrentCmd; while (pszCurrentCmd) { if ((int)strlen(pszCurrentCmd) > nLongestCmd) + { nLongestCmd = strlen(pszCurrentCmd); - + } + if ((int)strlen(pszCurrentCmd) < nSmallestCmd) + { + nSmallestCmd = strlen(pszCurrentCmd); + pszSmallestCmd = pszCurrentCmd; + } pszCurrentCmd = (char *)matches.GetNext(); } @@ -175,13 +195,11 @@ void CTextConsole::ReceiveTab() nCurrentColumn = 0; Echo("\n"); - + Q_strcpy(szCommonCmd, pszSmallestCmd); // Would be nice if these were sorted, but not that big a deal pszCurrentCmd = (char *)matches.GetFirst(); - while (pszCurrentCmd) { - char szFormatCmd[256]; if (++nCurrentColumn > nTotalColumns) { Echo("\n"); @@ -190,17 +208,25 @@ void CTextConsole::ReceiveTab() _snprintf(szFormatCmd, sizeof(szFormatCmd), "%-*s ", nLongestCmd, pszCurrentCmd); Echo(szFormatCmd); - + for (char *pCur = pszCurrentCmd, *pCommon = szCommonCmd; (*pCur&&*pCommon); pCur++, pCommon++) + { + if (*pCur != *pCommon) + { + *pCommon = 0; + break; + } + } pszCurrentCmd = (char *)matches.GetNext(); } Echo("\n"); - Echo(m_szConsoleText); + if (Q_strcmp(szCommonCmd, m_szConsoleText)) + { + Q_strcpy(m_szConsoleText, szCommonCmd); + m_nConsoleTextLen = Q_strlen(szCommonCmd); + } - // TODO: - // Tack on 'common' chars in all the matches, i.e. if I typed 'con' and all the - // matches begin with 'connect_' then print the matches but also complete the - // command up to that point at least. + Echo(m_szConsoleText); } m_nCursorPosition = m_nConsoleTextLen; diff --git a/rehlds/dedicated/src/dedicated.h b/rehlds/dedicated/src/dedicated.h index 37067f5..6e18558 100644 --- a/rehlds/dedicated/src/dedicated.h +++ b/rehlds/dedicated/src/dedicated.h @@ -9,5 +9,8 @@ typedef void (*SleepType)(int msec); extern bool g_bVGui; extern IDedicatedServerAPI *engineAPI; - +#ifdef LAUNCHER_FIXES +extern IRehldsApi *rehldsApi; +extern const RehldsFuncs_t* rehldsFuncs; +#endif #endif // DEDICATED_H diff --git a/rehlds/dedicated/src/precompiled.h b/rehlds/dedicated/src/precompiled.h index 6484ade..91e53c0 100644 --- a/rehlds/dedicated/src/precompiled.h +++ b/rehlds/dedicated/src/precompiled.h @@ -12,6 +12,12 @@ #include "idedicatedexports.h" #include "icommandline.h" +#ifdef LAUNCHER_FIXES +struct DLL_FUNCTIONS; +#include "cvardef.h" +#include "rehlds_api.h" +#endif + #include "sys_ded.h" #include "icommandline.h" #include "textconsole.h" diff --git a/rehlds/dedicated/src/sys_ded.cpp b/rehlds/dedicated/src/sys_ded.cpp index 71745c4..5b97a7b 100644 --- a/rehlds/dedicated/src/sys_ded.cpp +++ b/rehlds/dedicated/src/sys_ded.cpp @@ -8,6 +8,10 @@ bool gbAppHasBeenTerminated = false; CSysModule *g_pEngineModule = nullptr; IDedicatedServerAPI *engineAPI = nullptr; +#ifdef LAUNCHER_FIXES +IRehldsApi *rehldsApi = nullptr; +const RehldsFuncs_t* rehldsFuncs = nullptr; +#endif IFileSystem *g_pFileSystemInterface = nullptr; CSysModule *g_pFileSystemModule = nullptr; @@ -92,8 +96,23 @@ int RunServer() RunVGUIFrame(); if (engineFactory) + { engineAPI = (IDedicatedServerAPI *)engineFactory(VENGINE_HLDS_API_VERSION, NULL); - +#ifdef LAUNCHER_FIXES + rehldsApi = (IRehldsApi *)engineFactory(VREHLDS_HLDS_API_VERSION, NULL); + if (rehldsApi) + { + if (rehldsApi->GetMajorVersion() != REHLDS_API_VERSION_MAJOR || rehldsApi->GetMinorVersion() < REHLDS_API_VERSION_MINOR) + { + rehldsApi = nullptr; + } + else + { + rehldsFuncs = rehldsApi->GetFuncs(); + } + } +#endif + } RunVGUIFrame(); if (!engineAPI) return -1; diff --git a/rehlds/public/rehlds/rehlds_api.h b/rehlds/public/rehlds/rehlds_api.h index 2009ae3..a51d81c 100644 --- a/rehlds/public/rehlds/rehlds_api.h +++ b/rehlds/public/rehlds/rehlds_api.h @@ -33,9 +33,10 @@ #include "FlightRecorder.h" #include "interface.h" #include "model.h" +#include "ObjectList.h" #define REHLDS_API_VERSION_MAJOR 3 -#define REHLDS_API_VERSION_MINOR 1 +#define REHLDS_API_VERSION_MINOR 2 //Steam_NotifyClientConnect hook typedef IHookChain IRehldsHook_Steam_NotifyClientConnect; @@ -283,6 +284,7 @@ struct RehldsFuncs_t { void(*SV_UpdateUserInfo)(IGameClient *pGameClient); bool(*StripUnprintableAndSpace)(char *pch); void(*Cmd_RemoveCmd)(const char *cmd_name); + void(*GetCommandMatches)(const char *string, ObjectList *pMatchList); }; class IRehldsApi { diff --git a/rehlds/rehlds/rehlds_api_impl.cpp b/rehlds/rehlds/rehlds_api_impl.cpp index 6f5e538..ee32549 100644 --- a/rehlds/rehlds/rehlds_api_impl.cpp +++ b/rehlds/rehlds/rehlds_api_impl.cpp @@ -158,6 +158,29 @@ void EXT_FUNC Rehlds_RegisterPluginApi(const char *name, void *impl) { api->impl = impl; } +void EXT_FUNC GetCommandMatches_api(const char *string, ObjectList *pMatchList) +{ + if (!string || !string[0]) + { + return; + } + auto TextLen = Q_strlen(string); + for (auto EngCmd = Cmd_GetFirstCmd(); EngCmd; EngCmd = EngCmd->next) + { + if (!Q_strnicmp(EngCmd->name, string, TextLen)) + { + pMatchList->Add((void*)(EngCmd->name)); + } + } + for (auto EngCvar = GetCvarVars_api(); EngCvar; EngCvar = EngCvar->next) + { + if (!Q_strnicmp(EngCvar->name, string, TextLen)) + { + pMatchList->Add((void*)(EngCvar->name)); + } + } +} + CRehldsServerStatic g_RehldsServerStatic; CRehldsServerData g_RehldsServerData; CRehldsHookchains g_RehldsHookchains; @@ -211,7 +234,8 @@ RehldsFuncs_t g_RehldsApiFuncs = &SV_EmitSound2_api, &SV_UpdateUserInfo_api, &StripUnprintableAndSpace_api, - &Cmd_RemoveCmd + &Cmd_RemoveCmd, + &GetCommandMatches_api }; bool EXT_FUNC SV_EmitSound2_internal(edict_t *entity, IGameClient *pReceiver, int channel, const char *sample, float volume, float attenuation, int flags, int pitch, int emitFlags, const float *pOrigin)