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()
{
/* All commands should already be removed by the time we're done */
SH_REMOVE_HOOK_MEMFUNC(IServerGameClients, SetCommandClient, serverClients, this, &CConCmdManager::SetCommandClient, false);
g_RootMenu.RemoveRootConsoleCommand("cmds", this);
g_PluginSys.RemovePluginsListener(this);
@ -53,6 +54,7 @@ void CConCmdManager::OnPluginLoaded(IPlugin *plugin)
void CConCmdManager::OnPluginDestroyed(IPlugin *plugin)
{
CmdList *pList;
List<ConCmdInfo *> removed;
if (plugin->GetProperty("CommandList", (void **)&pList, true))
{
CmdList::iterator iter;
@ -65,14 +67,25 @@ void CConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|| cmd.type == Cmd_Console)
{
ConCmdInfo *pInfo = cmd.pInfo;
/* See if this is being removed */
if (removed.find(pInfo) != removed.end())
{
continue;
}
/* See if there are still hooks */
if (pInfo->srvhooks
&& pInfo->srvhooks->GetFunctionCount())
{
continue;
}
if (pInfo->conhooks
&& pInfo->conhooks->GetFunctionCount())
{
continue;
}
/* Remove the command */
RemoveConCmd(pInfo);
removed.push_back(pInfo);
}
}
delete pList;
@ -89,12 +102,39 @@ void CConCmdManager::SetCommandClient(int client)
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()
{
if (m_CmdClient)
{
return;
}
/**
* Note: Console commands will EITHER go through IServerGameDLL::ClientCommand,
* 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);
ConCmdInfo *pInfo;
@ -104,11 +144,35 @@ void CConCmdManager::InternalDispatch()
}
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);
}
/* 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 (!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,
const char *name,
const char *description,
@ -144,7 +236,7 @@ void CConCmdManager::AddServerCommand(IPluginFunction *pFunction,
}
PlCmdInfo info;
info.pInfo = pInfo;
info.type = Cmd_Console;
info.type = Cmd_Server;
pList->push_back(info);
}
@ -311,7 +403,6 @@ void CConCmdManager::OnRootConsoleCommand(const char *command, unsigned int argc
name = cmd.pInfo->pCmd->GetName();
help = cmd.pInfo->pCmd->GetHelpText();
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
}
return;

View File

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

View File

@ -15,6 +15,7 @@
#include "ForwardSys.h"
#include "ShareSys.h"
#include "AdminCache.h"
#include "CConCmdManager.h"
CPlayerManager g_Players;
@ -51,15 +52,14 @@ void CPlayerManager::OnSourceModAllInitialized()
ParamType p1[] = {Param_Cell, Param_String, Param_Cell};
ParamType p2[] = {Param_Cell};
ParamType p3[] = {Param_Cell, Param_String};
m_clconnect = g_Forwards.CreateForward("OnClientConnect", ET_Event, 3, p1);
m_clputinserver = g_Forwards.CreateForward("OnClientPutInServer", 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_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_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()
@ -197,6 +197,7 @@ bool CPlayerManager::OnClientConnect(edict_t *pEntity, const char *pszName, cons
g_SourceMod.SetAuthChecking(true);
}
//:todo: this must meta return
return (res) ? true : false;
}
@ -328,10 +329,26 @@ void CPlayerManager::OnClientDisconnect_Post(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);
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)

View File

@ -342,6 +342,25 @@ static cell_t sm_RegServerCmd(IPluginContext *pContext, const cell_t *params)
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)
{
{"CreateConVar", sm_CreateConVar},
@ -363,5 +382,6 @@ REGISTER_NATIVES(convarNatives)
{"GetConVarMax", sm_GetConVarMax},
{"ResetConVar", sm_ResetConVar},
{"RegServerCmd", sm_RegServerCmd},
{"RegConsoleCmd", sm_RegConsoleCmd},
{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
* 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.
@ -92,7 +92,6 @@ functag SrvCmd Action:public();
*/
native RegServerCmd(const String:cmd[], SrvCmd:callback, const String:description[]="", flags=0);
#if 0
/**
* 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
* 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.
@ -113,6 +112,7 @@ functag ConCmd Action:public(client);
*/
native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:description[]="", flags=0);
#if 0
/**
* Hooks a specific client-only command.
*

View File

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