added client-based console commands

extended console command functions to have an argument number
renamed Result to Action

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40506
This commit is contained in:
David Anderson 2007-02-16 02:17:41 +00:00
parent dcb10ee3a2
commit 76903cd919
6 changed files with 150 additions and 18 deletions

View File

@ -40,6 +40,7 @@ void CConCmdManager::OnSourceModAllInitialized()
void CConCmdManager::OnSourceModShutdown() void CConCmdManager::OnSourceModShutdown()
{ {
/* All commands should already be removed by the time we're done */
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &CConCmdManager::SetCommandClient, false); SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &CConCmdManager::SetCommandClient, false);
g_RootMenu.RemoveRootConsoleCommand("cmds", this); g_RootMenu.RemoveRootConsoleCommand("cmds", this);
g_PluginSys.RemovePluginsListener(this); g_PluginSys.RemovePluginsListener(this);
@ -53,6 +54,7 @@ void CConCmdManager::OnPluginLoaded(IPlugin *plugin)
void CConCmdManager::OnPluginDestroyed(IPlugin *plugin) void CConCmdManager::OnPluginDestroyed(IPlugin *plugin)
{ {
CmdList *pList; CmdList *pList;
List<ConCmdInfo *> removed;
if (plugin->GetProperty("CommandList", (void **)&pList, true)) if (plugin->GetProperty("CommandList", (void **)&pList, true))
{ {
CmdList::iterator iter; CmdList::iterator iter;
@ -65,14 +67,25 @@ void CConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|| cmd.type == Cmd_Console) || cmd.type == Cmd_Console)
{ {
ConCmdInfo *pInfo = cmd.pInfo; ConCmdInfo *pInfo = cmd.pInfo;
/* See if this is being removed */
if (removed.find(pInfo) != removed.end())
{
continue;
}
/* See if there are still hooks */ /* See if there are still hooks */
if (pInfo->srvhooks if (pInfo->srvhooks
&& pInfo->srvhooks->GetFunctionCount()) && pInfo->srvhooks->GetFunctionCount())
{ {
continue; continue;
} }
if (pInfo->conhooks
&& pInfo->conhooks->GetFunctionCount())
{
continue;
}
/* Remove the command */ /* Remove the command */
RemoveConCmd(pInfo); RemoveConCmd(pInfo);
removed.push_back(pInfo);
} }
} }
delete pList; delete pList;
@ -89,12 +102,39 @@ void CConCmdManager::SetCommandClient(int client)
m_CmdClient = client + 1; m_CmdClient = client + 1;
} }
ResultType CConCmdManager::DispatchClientCommand(int client, ResultType type)
{
const char *cmd = engine->Cmd_Argv(0);
int args = engine->Cmd_Argc() - 1;
ConCmdInfo *pInfo;
if (sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
{
cell_t result = type;
if (pInfo->conhooks && pInfo->conhooks->GetFunctionCount())
{
pInfo->conhooks->PushCell(client);
pInfo->conhooks->PushCell(args);
pInfo->conhooks->Execute(&result);
}
if (result >= Pl_Stop)
{
return Pl_Stop;
}
type = (ResultType)result;
}
return type;
}
void CConCmdManager::InternalDispatch() void CConCmdManager::InternalDispatch()
{ {
if (m_CmdClient) /**
{ * Note: Console commands will EITHER go through IServerGameDLL::ClientCommand,
return; * OR this dispatch. They will NEVER go through both.
} * --
* Whether or not it goes through the callback is determined by FCVAR_GAMEDLL
*/
const char *cmd = engine->Cmd_Argv(0); const char *cmd = engine->Cmd_Argv(0);
ConCmdInfo *pInfo; ConCmdInfo *pInfo;
@ -104,11 +144,35 @@ void CConCmdManager::InternalDispatch()
} }
cell_t result = Pl_Continue; cell_t result = Pl_Continue;
if (pInfo->srvhooks) int args = engine->Cmd_Argc() - 1;
if (m_CmdClient == 0)
{ {
if (pInfo->srvhooks && pInfo->srvhooks->GetFunctionCount())
{
pInfo->srvhooks->PushCell(args);
pInfo->srvhooks->Execute(&result); pInfo->srvhooks->Execute(&result);
} }
/* Check if there's an early stop */
if (result >= Pl_Stop)
{
if (!pInfo->sourceMod)
{
RETURN_META(MRES_SUPERCEDE);
}
return;
}
}
/* Execute console command hooks */
if (pInfo->conhooks && pInfo->conhooks->GetFunctionCount())
{
pInfo->conhooks->PushCell(m_CmdClient);
pInfo->conhooks->PushCell(args);
pInfo->conhooks->Execute(&result);
}
if (result >= Pl_Handled) if (result >= Pl_Handled)
{ {
if (!pInfo->sourceMod) if (!pInfo->sourceMod)
@ -119,6 +183,34 @@ void CConCmdManager::InternalDispatch()
} }
} }
void CConCmdManager::AddConsoleCommand(IPluginFunction *pFunction,
const char *name,
const char *description,
int flags)
{
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo->conhooks)
{
pInfo->conhooks = g_Forwards.CreateForwardEx(NULL, ET_Hook, 2, NULL, Param_Cell, Param_Cell);
}
pInfo->conhooks->AddFunction(pFunction);
/* Add to the plugin */
CmdList *pList;
IPlugin *pPlugin = g_PluginSys.GetPluginByCtx(pFunction->GetParentContext()->GetContext());
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new CmdList();
pPlugin->SetProperty("CommandList", pList);
}
PlCmdInfo info;
info.pInfo = pInfo;
info.type = Cmd_Console;
pList->push_back(info);
}
void CConCmdManager::AddServerCommand(IPluginFunction *pFunction, void CConCmdManager::AddServerCommand(IPluginFunction *pFunction,
const char *name, const char *name,
const char *description, const char *description,
@ -144,7 +236,7 @@ void CConCmdManager::AddServerCommand(IPluginFunction *pFunction,
} }
PlCmdInfo info; PlCmdInfo info;
info.pInfo = pInfo; info.pInfo = pInfo;
info.type = Cmd_Console; info.type = Cmd_Server;
pList->push_back(info); pList->push_back(info);
} }
@ -311,7 +403,6 @@ void CConCmdManager::OnRootConsoleCommand(const char *command, unsigned int argc
name = cmd.pInfo->pCmd->GetName(); name = cmd.pInfo->pCmd->GetName();
help = cmd.pInfo->pCmd->GetHelpText(); help = cmd.pInfo->pCmd->GetHelpText();
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help); g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
} }
return; return;

View File

@ -38,10 +38,12 @@ struct ConCmdInfo
sourceMod = false; sourceMod = false;
pCmd = NULL; pCmd = NULL;
srvhooks = NULL; srvhooks = NULL;
conhooks = NULL;
} }
bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */ bool sourceMod; /**< Determines whether or not concmd was created by a SourceMod plugin */
ConCommand *pCmd; /**< Pointer to the command itself */ ConCommand *pCmd; /**< Pointer to the command itself */
IChangeableForward *srvhooks; /**< Hooks on this name as a server command */ IChangeableForward *srvhooks; /**< Hooks on this name as a server command */
IChangeableForward *conhooks; /**< Hooks on this name as a console command */
}; };
class CConCmdManager : class CConCmdManager :
@ -63,6 +65,8 @@ public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *command, unsigned int argcount); void OnRootConsoleCommand(const char *command, unsigned int argcount);
public: public:
void AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags); void AddServerCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
void AddConsoleCommand(IPluginFunction *pFunction, const char *name, const char *description, int flags);
ResultType DispatchClientCommand(int client, ResultType type);
private: private:
void InternalDispatch(); void InternalDispatch();
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags); ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);

View File

@ -15,6 +15,7 @@
#include "ForwardSys.h" #include "ForwardSys.h"
#include "ShareSys.h" #include "ShareSys.h"
#include "AdminCache.h" #include "AdminCache.h"
#include "CConCmdManager.h"
CPlayerManager g_Players; CPlayerManager g_Players;
@ -51,15 +52,14 @@ void CPlayerManager::OnSourceModAllInitialized()
ParamType p1[] = {Param_Cell, Param_String, Param_Cell}; ParamType p1[] = {Param_Cell, Param_String, Param_Cell};
ParamType p2[] = {Param_Cell}; ParamType p2[] = {Param_Cell};
ParamType p3[] = {Param_Cell, Param_String};
m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1); m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1);
m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2); m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", ET_Ignore, 1, p2);
m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2); m_cldisconnect = g_Forwards.CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2); m_cldisconnect_post = g_Forwards.CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
m_clcommand = g_Forwards.CreateForward("OnClientCommand", ET_Hook, 1, p2); m_clcommand = g_Forwards.CreateForward("OnClientCommand", ET_Hook, 2, NULL, Param_Cell, Param_Cell);
m_clinfochanged = g_Forwards.CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2); m_clinfochanged = g_Forwards.CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2);
m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, p3); m_clauth = g_Forwards.CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
} }
void CPlayerManager::OnSourceModShutdown() void CPlayerManager::OnSourceModShutdown()
@ -197,6 +197,7 @@ bool CPlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, cons
g_SourceMod.SetAuthChecking(true); g_SourceMod.SetAuthChecking(true);
} }
//:todo: this must meta return
return (res) ? true : false; return (res) ? true : false;
} }
@ -328,10 +329,26 @@ void CPlayerManager::OnClientDisconnect_Post(edict_t *pEntity)
void CPlayerManager::OnClientCommand(edict_t *pEntity) void CPlayerManager::OnClientCommand(edict_t *pEntity)
{ {
cell_t res; cell_t res = Pl_Continue;
int client = engine->IndexOfEdict(pEntity);
m_clcommand->PushCell(engine->IndexOfEdict(pEntity)); int args = engine->Cmd_Argc() - 1;
m_clcommand->PushCell(client);
m_clcommand->PushCell(args);
m_clcommand->Execute(&res, NULL); m_clcommand->Execute(&res, NULL);
if (res >= Pl_Stop)
{
RETURN_META(MRES_SUPERCEDE);
}
res = g_ConCmds.DispatchClientCommand(client, (ResultType)res);
if (res >= Pl_Handled)
{
RETURN_META(MRES_SUPERCEDE);
}
} }
void CPlayerManager::OnClientSettingsChanged(edict_t *pEntity) void CPlayerManager::OnClientSettingsChanged(edict_t *pEntity)

View File

@ -342,6 +342,25 @@ static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
return 1; return 1;
} }
static cell_t sm_RegConsoleCmd(IPluginContext *pContext, const cell_t *params)
{
char *name,*help;
IPluginFunction *pFunction;
pContext->LocalToString(params[1], &name);
pContext->LocalToString(params[3], &help);
pFunction = pContext->GetFunctionById(params[2]);
if (!pFunction)
{
return pContext->ThrowNativeError("Invalid function id (%X)", params[2]);
}
g_ConCmds.AddConsoleCommand(pFunction, name, help, params[4]);
return 1;
}
REGISTER_NATIVES(convarNatives) REGISTER_NATIVES(convarNatives)
{ {
{"CreateConVar", sm_CreateConVar}, {"CreateConVar", sm_CreateConVar},
@ -363,5 +382,6 @@ REGISTER_NATIVES(convarNatives)
{"GetConVarMax", sm_GetConVarMax}, {"GetConVarMax", sm_GetConVarMax},
{"ResetConVar", sm_ResetConVar}, {"ResetConVar", sm_ResetConVar},
{"RegServerCmd", sm_RegServerCmd}, {"RegServerCmd", sm_RegServerCmd},
{"RegConsoleCmd", sm_RegConsoleCmd},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -79,7 +79,7 @@ native PrintToConsole(client, const String:format[], {Handle,Float,String,_}:...
* @return A Result value. Not handling the command * @return A Result value. Not handling the command
* means that Source will report it as "not found." * means that Source will report it as "not found."
*/ */
functag SrvCmd Action:public(); functag SrvCmd Action:public(argCount);
/** /**
* Creates a server-only console command, or hooks an already existing one. * Creates a server-only console command, or hooks an already existing one.
@ -92,7 +92,6 @@ functag SrvCmd Action:public();
*/ */
native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:description[]="", flags=0); native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:description[]="", flags=0);
#if 0
/** /**
* Called when a generic console command is invoked. * Called when a generic console command is invoked.
* *
@ -100,7 +99,7 @@ native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:descriptio
* @return A Result value. Not handling the command * @return A Result value. Not handling the command
* means that Source will report it as "not found." * means that Source will report it as "not found."
*/ */
functag ConCmd Action:public(client); functag ConCmd Action:public(client, argCount);
/** /**
* Creates a console command, or hooks an already existing one. * Creates a console command, or hooks an already existing one.
@ -113,6 +112,7 @@ functag ConCmd Action:public(client);
*/ */
native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:description[]="", flags=0); native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:description[]="", flags=0);
#if 0
/** /**
* Hooks a specific client-only command. * Hooks a specific client-only command.
* *

View File

@ -128,7 +128,7 @@ forward OnClientDisconnect_Post(client);
* @param client Player index. * @param client Player index.
* @noreturn * @noreturn
*/ */
forward OnClientCommand(client); forward OnClientCommand(client, argCount);
/** /**
* Called whenever the client's settings are changed. * Called whenever the client's settings are changed.