diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index 958c8b49..f2bdcd69 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -31,12 +31,17 @@ struct PlCmdInfo CmdType type; }; typedef List CmdList; + void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info); ConCmdManager::ConCmdManager() : m_Strings(1024) { m_pCmds = sm_trie_create(); m_pCmdGrps = sm_trie_create(); + m_bServerCfgDone = true; + m_pExecCmd = NULL; + m_pServerCfgFile = NULL; + m_pServerCfgFwd = NULL; } ConCmdManager::~ConCmdManager() @@ -50,15 +55,73 @@ void ConCmdManager::OnSourceModAllInitialized() g_PluginSys.AddPluginsListener(this); g_RootMenu.AddRootConsoleCommand("cmds", "List console commands", this); SH_ADD_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &ConCmdManager::SetCommandClient, false); + + ConCommandBase *pCmd = icvar->GetCommands(); + while (pCmd) + { + if (pCmd->IsCommand() + && strcmp(pCmd->GetName(), "exec") == 0) + { + m_pExecCmd = (ConCommand *)pCmd; + break; + } + pCmd = const_cast(pCmd->GetNext()); + } + + if (m_pExecCmd) + { + m_pServerCfgFile = (ConVar *)icvar->FindVar("servercfgfile"); + SH_ADD_HOOK_MEMFUNC(ConCommand, Dispatch, m_pExecCmd, this, &ConCmdManager::OnExecCmd, true); + m_pServerCfgFwd = g_Forwards.CreateForward("OnServerCfg", ET_Ignore, 0, NULL); + } } void ConCmdManager::OnSourceModShutdown() { + if (m_pExecCmd) + { + SH_REMOVE_HOOK_MEMFUNC(ConCommand, Dispatch, m_pExecCmd, this, &ConCmdManager::OnExecCmd, true); + g_Forwards.ReleaseForward(m_pServerCfgFwd); + m_pServerCfgFwd = NULL; + m_pExecCmd = NULL; + } + /* All commands should already be removed by the time we're done */ SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &ConCmdManager::SetCommandClient, false); g_RootMenu.RemoveRootConsoleCommand("cmds", this); } +void ConCmdManager::OnSourceModPluginsLoaded() +{ + m_bServerCfgDone = false; +} + +void ConCmdManager::OnExecCmd() +{ + const char *arg = engine->Cmd_Argv(1); + const char *cfgfile = "server.cfg"; + + if (m_pServerCfgFile) + { + cfgfile = m_pServerCfgFile->GetString(); + } + + if (strcmp(arg, cfgfile) == 0) + { + engine->ServerCommand("sm cmds internal 1\n"); + } +} + +void ConCmdManager::NotifyExecDone(const char *file) +{ + if (file == NULL && !m_bServerCfgDone) + { + /* Server-cfg file */ + m_bServerCfgDone = true; + m_pServerCfgFwd->Execute(NULL); + } +} + void ConCmdManager::RemoveConCmds(List &cmdlist, IPluginContext *pContext) { List::iterator iter = cmdlist.begin(); @@ -732,6 +795,16 @@ void ConCmdManager::OnRootConsoleCommand(const char *command, unsigned int argco if (argcount >= 3) { const char *text = engine->Cmd_Argv(2); + + if (strcmp(text, "internal") == 0) + { + const char *num = engine->Cmd_Argv(3); + if (atoi(num) == 1) + { + g_ConCmds.NotifyExecDone(NULL); + } + } + int id = atoi(text); CPlugin *pPlugin = g_PluginSys.GetPluginByOrder(id); diff --git a/core/ConCmdManager.h b/core/ConCmdManager.h index e14ec711..bc6ccff4 100644 --- a/core/ConCmdManager.h +++ b/core/ConCmdManager.h @@ -84,6 +84,7 @@ public: public: //SMGlobalClass void OnSourceModAllInitialized(); void OnSourceModShutdown(); + void OnSourceModPluginsLoaded(); public: //IPluginsListener void OnPluginDestroyed(IPlugin *plugin); public: //IRootConsoleCommand @@ -99,6 +100,7 @@ public: int flags); ResultType DispatchClientCommand(int client, ResultType type); void UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits); + void NotifyExecDone(const char *file); private: void InternalDispatch(); ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args); @@ -108,12 +110,17 @@ private: void RemoveConCmd(ConCmdInfo *info); void RemoveConCmds(List &cmdlist, IPluginContext *pContext); bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); + void OnExecCmd(); private: Trie *m_pCmds; /* command lookup */ Trie *m_pCmdGrps; /* command group lookup */ List m_CmdList; /* command list */ int m_CmdClient; /* current client */ BaseStringTable m_Strings; /* string table */ + ConVar *m_pServerCfgFile; /* servercfgfile cvar */ + ConCommand *m_pExecCmd; /* "exec" command */ + IForward *m_pServerCfgFwd; /* server config forward */ + bool m_bServerCfgDone; /* marks whether a servercfg was detected */ }; extern ConCmdManager g_ConCmds; diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index cedd2aab..6a7e4eda 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -116,7 +116,7 @@ forward OnGameFrame(); /** * Called when the map is loaded. * - * Note: This used to be OnServerLoad(), which is now deprecated. + * @note This used to be OnServerLoad(), which is now deprecated. * Plugins still using the old forward will work. */ forward OnMapStart(); @@ -126,6 +126,16 @@ forward OnMapStart(); */ forward OnMapEnd(); +/** + * Called when the map has loaded and the servercfgfile has finished + * executing. This is usually 'server.cfg' but most mods allow it to + * be set via 'servercfgfile'. + * + * @note If server.cfg is executed more than once per map, this forward + * will only be called the first time (per map). + */ +forward OnServerCfg(); + /** * Returns the calling plugin's Handle. *