diff --git a/core/interfaces/IRootConsoleMenu.h b/core/interfaces/IRootConsoleMenu.h index 2344ae0e..fc389b5a 100644 --- a/core/interfaces/IRootConsoleMenu.h +++ b/core/interfaces/IRootConsoleMenu.h @@ -4,6 +4,8 @@ /** * @brief Note: This interface is not exposed. * The reason should be obvious: we do not want users touching the "root" console menu. + * If we exposed this, every little plugin would be dropping down a silly set of user commands, + * whereas this menu is explicitly provided for stuff that only Core itself is capable of managing. */ namespace SourceMod @@ -18,7 +20,7 @@ namespace SourceMod }; /** - * @brief Manages the root console menu. + * @brief Manages the root console menu - the "sm" command for servers. */ class IRootConsole { diff --git a/core/systems/ExtensionSys.cpp b/core/systems/ExtensionSys.cpp index ae223b57..ccd33c69 100644 --- a/core/systems/ExtensionSys.cpp +++ b/core/systems/ExtensionSys.cpp @@ -4,6 +4,7 @@ #include "CLogger.h" #include "sourcemm_api.h" #include "PluginSys.h" +#include "sm_srvcmds.h" CExtensionManager g_Extensions; IdentityType_t g_ExtType; @@ -209,10 +210,12 @@ void CExtensionManager::OnSourceModAllInitialized() { g_ExtType = g_ShareSys.CreateIdentType("EXTENSION"); g_PluginSys.AddPluginsListener(this); + g_RootMenu.AddRootConsoleCommand("exts", "Manage extensions", this); } void CExtensionManager::OnSourceModShutdown() { + g_RootMenu.RemoveRootConsoleCommand("exts", this); g_PluginSys.RemovePluginsListener(this); g_ShareSys.DestroyIdentType(g_ExtType); } @@ -418,3 +421,113 @@ bool CExtensionManager::UnloadExtension(IExtension *_pExt) return true; } + +void CExtensionManager::OnRootConsoleCommand(const char *cmd, unsigned int argcount) +{ + if (argcount >= 3) + { + const char *cmd = g_RootMenu.GetArgument(2); + if (strcmp(cmd, "list") == 0) + { + List::iterator iter; + CExtension *pExt; + unsigned int num = 1; + switch (m_Libs.size()) + { + case 1: + { + g_RootMenu.ConsolePrint("[SM] Displaying 1 extension:"); + break; + } + case 0: + { + g_RootMenu.ConsolePrint("[SM] No extensions are loaded."); + break; + } + default: + { + g_RootMenu.ConsolePrint("[SM] Displaying %d extensions:", m_Libs.size()); + break; + } + } + for (iter=m_Libs.begin(); iter!=m_Libs.end(); iter++,num++) + { + pExt = (*iter); + if (pExt->IsLoaded()) + { + IExtensionInterface *pAPI = pExt->GetAPI(); + const char *name = pAPI->GetExtensionName(); + const char *version = pAPI->GetExtensionVerString(); + const char *descr = pAPI->GetExtensionDescription(); + g_RootMenu.ConsolePrint("[%02d] %s (%s): %s", num, name, version, descr); + } else { + g_RootMenu.ConsolePrint("[%02d] file \"%s\": %s", num, pExt->GetFilename(), pExt->m_Error.c_str()); + } + } + return; + } else if (strcmp(cmd, "info") == 0) { + if (argcount < 4) + { + g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>"); + return; + } + + const char *sId = g_RootMenu.GetArgument(3); + unsigned int id = atoi(sId); + if (id <= 0) + { + g_RootMenu.ConsolePrint("[SM] Usage: sm info <#>"); + return; + } + + if (m_Libs.size() == 0) + { + g_RootMenu.ConsolePrint("[SM] No extensions are loaded."); + return; + } + + if (id > m_Libs.size()) + { + g_RootMenu.ConsolePrint("[SM] No extension was found with id %d.", id); + return; + } + + List::iterator iter = m_Libs.begin(); + CExtension *pExt = NULL; + while (iter != m_Libs.end()) + { + if (--id == 0) + { + pExt = (*iter); + break; + } + iter++; + } + /* This should never happen */ + if (!pExt) + { + g_RootMenu.ConsolePrint("[SM] No extension was found with id %d.", id); + return; + } + + if (!pExt->IsLoaded()) + { + g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename()); + g_RootMenu.ConsolePrint(" Loaded: No (%s)", pExt->m_Error.c_str()); + } else { + IExtensionInterface *pAPI = pExt->GetAPI(); + g_RootMenu.ConsolePrint(" File: %s", pExt->GetFilename()); + g_RootMenu.ConsolePrint(" Loaded: Yes (version %s)", pAPI->GetExtensionVerString()); + g_RootMenu.ConsolePrint(" Name: %s (%s)", pAPI->GetExtensionName(), pAPI->GetExtensionDescription()); + g_RootMenu.ConsolePrint(" Author: %s (%s)", pAPI->GetExtensionAuthor(), pAPI->GetExtensionURL()); + g_RootMenu.ConsolePrint(" Binary info: API version %d (compiled %s)", pAPI->GetExtensionVersion(), pAPI->GetExtensionDateString()); + g_RootMenu.ConsolePrint(" Metamod enabled: %s", pAPI->IsMetamodExtension() ? "yes" : "no"); + } + return; + } + } + + g_RootMenu.ConsolePrint("SourceMod Extensions Menu:"); + g_RootMenu.DrawGenericOption("info", "Extra extension information"); + g_RootMenu.DrawGenericOption("list", "List extensions"); +} diff --git a/core/systems/ExtensionSys.h b/core/systems/ExtensionSys.h index 2e946406..b56da392 100644 --- a/core/systems/ExtensionSys.h +++ b/core/systems/ExtensionSys.h @@ -9,6 +9,7 @@ #include "ShareSys.h" #include #include +#include using namespace SourceMod; using namespace SourceHook; @@ -48,7 +49,8 @@ private: class CExtensionManager : public IExtensionManager, public SMGlobalClass, - IPluginsListener + public IPluginsListener, + public IRootConsoleCommand { public: //SMGlobalClass void OnSourceModAllInitialized(); @@ -63,6 +65,8 @@ public: //IExtensionManager IExtension *FindExtensionByName(const char *ext); public: //IPluginsListener void OnPluginDestroyed(IPlugin *plugin); +public: //IRootConsoleCommand + void OnRootConsoleCommand(const char *cmd, unsigned int argcount); public: IExtension *LoadAutoExtension(const char *path); void BindDependency(IExtension *pOwner, IfaceInfo *pInfo); diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index c5db626e..dc43ca22 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -1422,7 +1422,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc } else if (strcmp(cmd, "load") == 0) { if (argcount < 4) { - g_RootMenu.ConsolePrint("Usage: sm plugins load "); + g_RootMenu.ConsolePrint("[SM] Usage: sm plugins load "); return; } @@ -1441,7 +1441,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc } else if (strcmp(cmd, "unload") == 0) { if (argcount < 4) { - g_RootMenu.ConsolePrint("Usage: sm plugins unload <#>"); + g_RootMenu.ConsolePrint("[SM] Usage: sm plugins unload <#>"); return; } @@ -1449,7 +1449,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc int num = atoi(g_RootMenu.GetArgument(3)); if (num < 1 || num > (int)GetPluginCount()) { - g_RootMenu.ConsolePrint("Plugin index %d not found.", num); + g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", num); return; } @@ -1464,9 +1464,9 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc if (UnloadPlugin(pl)) { - g_RootMenu.ConsolePrint("Plugin %s unloaded successfully.", name); + g_RootMenu.ConsolePrint("[SM] Plugin %s unloaded successfully.", name); } else { - g_RootMenu.ConsolePrint("Failed to unload plugin %s.", name); + g_RootMenu.ConsolePrint("[SM] Failed to unload plugin %s.", name); } iter->Release(); @@ -1474,7 +1474,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc } else if (strcmp(cmd, "info") == 0) { if (argcount < 4) { - g_RootMenu.ConsolePrint("Usage: sm plugins info <#>"); + g_RootMenu.ConsolePrint("[SM] Usage: sm plugins info <#>"); return; } @@ -1482,7 +1482,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc int num = atoi(g_RootMenu.GetArgument(3)); if (num < 1 || num > (int)GetPluginCount()) { - g_RootMenu.ConsolePrint("Plugin index not found."); + g_RootMenu.ConsolePrint("[SM] Plugin index not found."); return; } @@ -1524,14 +1524,14 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc } else if (strcmp(cmd, "debug") == 0) { if (argcount < 5) { - g_RootMenu.ConsolePrint("Usage: sm plugins debug <#> [on|off]"); + g_RootMenu.ConsolePrint("[SM] Usage: sm plugins debug <#> [on|off]"); return; } int num = atoi(g_RootMenu.GetArgument(3)); if (num < 1 || num > (int)GetPluginCount()) { - g_RootMenu.ConsolePrint("Plugin index not found."); + g_RootMenu.ConsolePrint("[SM] Plugin index not found."); return; } @@ -1539,7 +1539,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc const char *mode = g_RootMenu.GetArgument(4); if ((res=strcmp("on", mode)) && strcmp("off", mode)) { - g_RootMenu.ConsolePrint("The only possible options are \"on\" and \"off.\""); + g_RootMenu.ConsolePrint("[SM] The only possible options are \"on\" and \"off.\""); return; } @@ -1564,7 +1564,7 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc char error[256]; if (pl->ToggleDebugMode(debug, error, sizeof(error))) { - g_RootMenu.ConsolePrint("Successfully toggled debug mode on plugin %s.", pl->GetFilename()); + g_RootMenu.ConsolePrint("[SM] Successfully toggled debug mode on plugin %s.", pl->GetFilename()); return; } else { g_RootMenu.ConsolePrint("[SM] Could not toggle debug mode on plugin %s.", pl->GetFilename());