1.1 --- a/core/CConCmdManager.cpp Fri Feb 16 00:04:14 2007 +0000
1.2 +++ b/core/CConCmdManager.cpp Fri Feb 16 02:17:41 2007 +0000
1.3 @@ -40,6 +40,7 @@
1.4
1.5 void CConCmdManager::OnSourceModShutdown()
1.6 {
1.7 + /* All commands should already be removed by the time we're done */
1.8 SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &CConCmdManager::SetCommandClient, false);
1.9 g_RootMenu.RemoveRootConsoleCommand("cmds", this);
1.10 g_PluginSys.RemovePluginsListener(this);
1.11 @@ -53,6 +54,7 @@
1.12 void CConCmdManager::OnPluginDestroyed(IPlugin *plugin)
1.13 {
1.14 CmdList *pList;
1.15 + List<ConCmdInfo *> removed;
1.16 if (plugin->GetProperty("CommandList", (void **)&pList, true))
1.17 {
1.18 CmdList::iterator iter;
1.19 @@ -65,14 +67,25 @@
1.20 || cmd.type == Cmd_Console)
1.21 {
1.22 ConCmdInfo *pInfo = cmd.pInfo;
1.23 + /* See if this is being removed */
1.24 + if (removed.find(pInfo) != removed.end())
1.25 + {
1.26 + continue;
1.27 + }
1.28 /* See if there are still hooks */
1.29 if (pInfo->srvhooks
1.30 && pInfo->srvhooks->GetFunctionCount())
1.31 {
1.32 continue;
1.33 }
1.34 + if (pInfo->conhooks
1.35 + && pInfo->conhooks->GetFunctionCount())
1.36 + {
1.37 + continue;
1.38 + }
1.39 /* Remove the command */
1.40 RemoveConCmd(pInfo);
1.41 + removed.push_back(pInfo);
1.42 }
1.43 }
1.44 delete pList;
1.45 @@ -89,12 +102,39 @@
1.46 m_CmdClient = client + 1;
1.47 }
1.48
1.49 +ResultType CConCmdManager::DispatchClientCommand(int client, ResultType type)
1.50 +{
1.51 + const char *cmd = engine->Cmd_Argv(0);
1.52 + int args = engine->Cmd_Argc() - 1;
1.53 +
1.54 + ConCmdInfo *pInfo;
1.55 + if (sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
1.56 + {
1.57 + cell_t result = type;
1.58 + if (pInfo->conhooks && pInfo->conhooks->GetFunctionCount())
1.59 + {
1.60 + pInfo->conhooks->PushCell(client);
1.61 + pInfo->conhooks->PushCell(args);
1.62 + pInfo->conhooks->Execute(&result);
1.63 + }
1.64 + if (result >= Pl_Stop)
1.65 + {
1.66 + return Pl_Stop;
1.67 + }
1.68 + type = (ResultType)result;
1.69 + }
1.70 +
1.71 + return type;
1.72 +}
1.73 +
1.74 void CConCmdManager::InternalDispatch()
1.75 {
1.76 - if (m_CmdClient)
1.77 - {
1.78 - return;
1.79 - }
1.80 + /**
1.81 + * Note: Console commands will EITHER go through IServerGameDLL::ClientCommand,
1.82 + * OR this dispatch. They will NEVER go through both.
1.83 + * --
1.84 + * Whether or not it goes through the callback is determined by FCVAR_GAMEDLL
1.85 + */
1.86
1.87 const char *cmd = engine->Cmd_Argv(0);
1.88 ConCmdInfo *pInfo;
1.89 @@ -104,9 +144,33 @@
1.90 }
1.91
1.92 cell_t result = Pl_Continue;
1.93 - if (pInfo->srvhooks)
1.94 + int args = engine->Cmd_Argc() - 1;
1.95 +
1.96 + if (m_CmdClient == 0)
1.97 {
1.98 - pInfo->srvhooks->Execute(&result);
1.99 + if (pInfo->srvhooks && pInfo->srvhooks->GetFunctionCount())
1.100 + {
1.101 + pInfo->srvhooks->PushCell(args);
1.102 + pInfo->srvhooks->Execute(&result);
1.103 + }
1.104 +
1.105 + /* Check if there's an early stop */
1.106 + if (result >= Pl_Stop)
1.107 + {
1.108 + if (!pInfo->sourceMod)
1.109 + {
1.110 + RETURN_META(MRES_SUPERCEDE);
1.111 + }
1.112 + return;
1.113 + }
1.114 + }
1.115 +
1.116 + /* Execute console command hooks */
1.117 + if (pInfo->conhooks && pInfo->conhooks->GetFunctionCount())
1.118 + {
1.119 + pInfo->conhooks->PushCell(m_CmdClient);
1.120 + pInfo->conhooks->PushCell(args);
1.121 + pInfo->conhooks->Execute(&result);
1.122 }
1.123
1.124 if (result >= Pl_Handled)
1.125 @@ -119,6 +183,34 @@
1.126 }
1.127 }
1.128
1.129 +void CConCmdManager::AddConsoleCommand(IPluginFunction *pFunction,
1.130 + const char *name,
1.131 + const char *description,
1.132 + int flags)
1.133 +{
1.134 + ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
1.135 +
1.136 + if (!pInfo->conhooks)
1.137 + {
1.138 + pInfo->conhooks = g_Forwards.CreateForwardEx(NULL, ET_Hook, 2, NULL, Param_Cell, Param_Cell);
1.139 + }
1.140 +
1.141 + pInfo->conhooks->AddFunction(pFunction);
1.142 +
1.143 + /* Add to the plugin */
1.144 + CmdList *pList;
1.145 + IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
1.146 + if (!pPlugin->GetProperty("CommandList", (void **)&pList))
1.147 + {
1.148 + pList = new CmdList();
1.149 + pPlugin->SetProperty("CommandList", pList);
1.150 + }
1.151 + PlCmdInfo info;
1.152 + info.pInfo = pInfo;
1.153 + info.type = Cmd_Console;
1.154 + pList->push_back(info);
1.155 +}
1.156 +
1.157 void CConCmdManager::AddServerCommand(IPluginFunction *pFunction,
1.158 const char *name,
1.159 const char *description,
1.160 @@ -144,7 +236,7 @@
1.161 }
1.162 PlCmdInfo info;
1.163 info.pInfo = pInfo;
1.164 - info.type = Cmd_Console;
1.165 + info.type = Cmd_Server;
1.166 pList->push_back(info);
1.167 }
1.168
1.169 @@ -310,8 +402,7 @@
1.170 }
1.171 name = cmd.pInfo->pCmd->GetName();
1.172 help = cmd.pInfo->pCmd->GetHelpText();
1.173 - g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
1.174 -
1.175 + g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
1.176 }
1.177
1.178 return;
2.1 --- a/core/CConCmdManager.h Fri Feb 16 00:04:14 2007 +0000
2.2 +++ b/core/CConCmdManager.h Fri Feb 16 02:17:41 2007 +0000
2.3 @@ -38,10 +38,12 @@
2.4 sourceMod = false;
2.5 pCmd = NULL;
2.6 srvhooks = NULL;
2.7 + conhooks = NULL;
2.8 }
2.9 bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
2.10 ConCommand *pCmd; /**< Pointer to the command itself */
2.11 IChangeableForward *srvhooks; /**< Hooks on this name as a server command */
2.12 + IChangeableForward *conhooks; /**< Hooks on this name as a console command */
2.13 };
2.14
2.15 class CConCmdManager :
2.16 @@ -63,6 +65,8 @@
2.17 void OnRootConsoleCommand(const char *command, unsigned int argcount);
2.18 public:
2.19 void AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
2.20 + void AddConsoleCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
2.21 + ResultType DispatchClientCommand(int client, ResultType type);
2.22 private:
2.23 void InternalDispatch();
2.24 ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
3.1 --- a/core/CPlayerManager.cpp Fri Feb 16 00:04:14 2007 +0000
3.2 +++ b/core/CPlayerManager.cpp Fri Feb 16 02:17:41 2007 +0000
3.3 @@ -15,6 +15,7 @@
3.4 #include "ForwardSys.h"
3.5 #include "ShareSys.h"
3.6 #include "AdminCache.h"
3.7 +#include "CConCmdManager.h"
3.8
3.9 CPlayerManager g_Players;
3.10
3.11 @@ -51,15 +52,14 @@
3.12
3.13 ParamType p1[] = {Param_Cell, Param_String, Param_Cell};
3.14 ParamType p2[] = {Param_Cell};
3.15 - ParamType p3[] = {Param_Cell, Param_String};
3.16
3.17 m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1);
3.18 m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
3.19 m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
3.20 m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
3.21 - m_clcommand = g_Forwards.CreateForward("OnClientCommand", ET_Hook, 1, p2);
3.22 + m_clcommand = g_Forwards.CreateForward("OnClientCommand", ET_Hook, 2, NULL, Param_Cell, Param_Cell);
3.23 m_clinfochanged = g_Forwards.CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2);
3.24 - m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, p3);
3.25 + m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
3.26 }
3.27
3.28 void CPlayerManager::OnSourceModShutdown()
3.29 @@ -197,6 +197,7 @@
3.30 g_SourceMod.SetAuthChecking(true);
3.31 }
3.32
3.33 + //:todo: this must meta return
3.34 return (res) ? true : false;
3.35 }
3.36
3.37 @@ -328,10 +329,26 @@
3.38
3.39 void CPlayerManager::OnClientCommand(edict_t *pEntity)
3.40 {
3.41 - cell_t res;
3.42 + cell_t res = Pl_Continue;
3.43 + int client = engine->IndexOfEdict(pEntity);
3.44 +
3.45 + int args = engine->Cmd_Argc() - 1;
3.46 +
3.47 + m_clcommand->PushCell(client);
3.48 + m_clcommand->PushCell(args);
3.49 + m_clcommand->Execute(&res, NULL);
3.50
3.51 - m_clcommand->PushCell(engine->IndexOfEdict(pEntity));
3.52 - m_clcommand->Execute(&res, NULL);
3.53 + if (res >= Pl_Stop)
3.54 + {
3.55 + RETURN_META(MRES_SUPERCEDE);
3.56 + }
3.57 +
3.58 + res = g_ConCmds.DispatchClientCommand(client, (ResultType)res);
3.59 +
3.60 + if (res >= Pl_Handled)
3.61 + {
3.62 + RETURN_META(MRES_SUPERCEDE);
3.63 + }
3.64 }
3.65
3.66 void CPlayerManager::OnClientSettingsChanged(edict_t *pEntity)
4.1 --- a/core/smn_console.cpp Fri Feb 16 00:04:14 2007 +0000
4.2 +++ b/core/smn_console.cpp Fri Feb 16 02:17:41 2007 +0000
4.3 @@ -342,6 +342,25 @@
4.4 return 1;
4.5 }
4.6
4.7 +static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
4.8 +{
4.9 + char *name,*help;
4.10 + IPluginFunction *pFunction;
4.11 +
4.12 + pContext->LocalToString(params[1], &name);
4.13 + pContext->LocalToString(params[3], &help);
4.14 + pFunction = pContext->GetFunctionById(params[2]);
4.15 +
4.16 + if (!pFunction)
4.17 + {
4.18 + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
4.19 + }
4.20 +
4.21 + g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]);
4.22 +
4.23 + return 1;
4.24 +}
4.25 +
4.26 REGISTER_NATIVES(convarNatives)
4.27 {
4.28 {"CreateConVar", sm_CreateConVar},
4.29 @@ -363,5 +382,6 @@
4.30 {"GetConVarMax", sm_GetConVarMax},
4.31 {"ResetConVar", sm_ResetConVar},
4.32 {"RegServerCmd", sm_RegServerCmd},
4.33 + {"RegConsoleCmd", sm_RegConsoleCmd},
4.34 {NULL, NULL}
4.35 };
5.1 --- a/plugins/include/console.inc Fri Feb 16 00:04:14 2007 +0000
5.2 +++ b/plugins/include/console.inc Fri Feb 16 02:17:41 2007 +0000
5.3 @@ -79,7 +79,7 @@
5.4 * @return A Result value. Not handling the command
5.5 * means that Source will report it as "not found."
5.6 */
5.7 -functag SrvCmd Action:public();
5.8 +functag SrvCmd Action:public(argCount);
5.9
5.10 /**
5.11 * Creates a server-only console command, or hooks an already existing one.
5.12 @@ -92,7 +92,6 @@
5.13 */
5.14 native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:description[]="", flags=0);
5.15
5.16 -#if 0
5.17 /**
5.18 * Called when a generic console command is invoked.
5.19 *
5.20 @@ -100,7 +99,7 @@
5.21 * @return A Result value. Not handling the command
5.22 * means that Source will report it as "not found."
5.23 */
5.24 -functag ConCmd Action:public(client);
5.25 +functag ConCmd Action:public(client, argCount);
5.26
5.27 /**
5.28 * Creates a console command, or hooks an already existing one.
5.29 @@ -113,6 +112,7 @@
5.30 */
5.31 native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:description[]="", flags=0);
5.32
5.33 +#if 0
5.34 /**
5.35 * Hooks a specific client-only command.
5.36 *
6.1 --- a/plugins/include/sourcemod.inc Fri Feb 16 00:04:14 2007 +0000
6.2 +++ b/plugins/include/sourcemod.inc Fri Feb 16 02:17:41 2007 +0000
6.3 @@ -128,7 +128,7 @@
6.4 * @param client Player index.
6.5 * @noreturn
6.6 */
6.7 -forward OnClientCommand(client);
6.8 +forward OnClientCommand(client, argCount);
6.9
6.10 /**
6.11 * Called whenever the client's settings are changed.