rewrote console command implementation internally
admin commands on the way but still not done removed weird restriction --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40519
This commit is contained in:
parent
49d96d4322
commit
6b28bec27f
@ -13,6 +13,7 @@
|
||||
|
||||
#include "CConCmdManager.h"
|
||||
#include "sm_srvcmds.h"
|
||||
#include "AdminCache.h"
|
||||
#include "sm_stringutil.h"
|
||||
|
||||
CConCmdManager g_ConCmds;
|
||||
@ -23,19 +24,22 @@ SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int
|
||||
struct PlCmdInfo
|
||||
{
|
||||
ConCmdInfo *pInfo;
|
||||
CmdHook *pHook;
|
||||
CmdType type;
|
||||
};
|
||||
|
||||
typedef List<PlCmdInfo> CmdList;
|
||||
void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info);
|
||||
|
||||
CConCmdManager::CConCmdManager()
|
||||
CConCmdManager::CConCmdManager() : m_Strings(1024)
|
||||
{
|
||||
m_pCmds = sm_trie_create();
|
||||
m_pCmdGrps = sm_trie_create();
|
||||
}
|
||||
|
||||
CConCmdManager::~CConCmdManager()
|
||||
{
|
||||
sm_trie_destroy(m_pCmds);
|
||||
sm_trie_destroy(m_pCmdGrps);
|
||||
}
|
||||
|
||||
void CConCmdManager::OnSourceModAllInitialized()
|
||||
@ -53,9 +57,23 @@ void CConCmdManager::OnSourceModShutdown()
|
||||
g_PluginSys.RemovePluginsListener(this);
|
||||
}
|
||||
|
||||
void CConCmdManager::OnPluginLoaded(IPlugin *plugin)
|
||||
void CConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext)
|
||||
{
|
||||
/* Nothing yet... */
|
||||
List<CmdHook *>::iterator iter = cmdlist.begin();
|
||||
CmdHook *pHook;
|
||||
|
||||
while (iter != cmdlist.end())
|
||||
{
|
||||
pHook = (*iter);
|
||||
if (pHook->pf->GetParentContext() == pContext)
|
||||
{
|
||||
delete pHook->pAdmin;
|
||||
delete pHook;
|
||||
iter = cmdlist.erase(iter);
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
||||
@ -64,36 +82,41 @@ void CConCmdManager::OnPluginDestroyed(IPlugin *plugin)
|
||||
List<ConCmdInfo *> removed;
|
||||
if (plugin->GetProperty("CommandList", (void **)&pList, true))
|
||||
{
|
||||
IPluginContext *pContext = plugin->GetBaseContext();
|
||||
CmdList::iterator iter;
|
||||
/* First pass!
|
||||
* Only bother if there's an actual command list on this plugin...
|
||||
*/
|
||||
for (iter=pList->begin();
|
||||
iter!=pList->end();
|
||||
iter++)
|
||||
iter!=pList->end();
|
||||
iter++)
|
||||
{
|
||||
PlCmdInfo &cmd = (*iter);
|
||||
if (cmd.type == Cmd_Server
|
||||
|| cmd.type == Cmd_Console)
|
||||
ConCmdInfo *pInfo = cmd.pInfo;
|
||||
|
||||
/* Has this chain already been fully cleaned/removed? */
|
||||
if (removed.find(pInfo) != removed.end())
|
||||
{
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove any hooks from us on this command */
|
||||
RemoveConCmds(pInfo->conhooks, pContext);
|
||||
RemoveConCmds(pInfo->srvhooks, pContext);
|
||||
|
||||
/* See if there are still hooks */
|
||||
if (pInfo->srvhooks.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pInfo->conhooks.size())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove the command, it should be safe now */
|
||||
RemoveConCmd(pInfo);
|
||||
removed.push_back(pInfo);
|
||||
}
|
||||
delete pList;
|
||||
}
|
||||
@ -118,15 +141,32 @@ ResultType CConCmdManager::DispatchClientCommand(int client, ResultType type)
|
||||
if (sm_trie_retrieve(m_pCmds, cmd, (void **)&pInfo))
|
||||
{
|
||||
cell_t result = type;
|
||||
if (pInfo->conhooks && pInfo->conhooks->GetFunctionCount())
|
||||
cell_t tempres = result;
|
||||
List<CmdHook *>::iterator iter;
|
||||
CmdHook *pHook;
|
||||
for (iter=pInfo->conhooks.begin();
|
||||
iter!=pInfo->conhooks.end();
|
||||
iter++)
|
||||
{
|
||||
pInfo->conhooks->PushCell(client);
|
||||
pInfo->conhooks->PushCell(args);
|
||||
pInfo->conhooks->Execute(&result);
|
||||
}
|
||||
if (result >= Pl_Stop)
|
||||
{
|
||||
return Pl_Stop;
|
||||
pHook = (*iter);
|
||||
if (pHook->pAdmin
|
||||
&& pHook->pAdmin->eflags)
|
||||
{
|
||||
/* :TODO: admin calculations */
|
||||
}
|
||||
pHook->pf->PushCell(client);
|
||||
pHook->pf->PushCell(args);
|
||||
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
||||
{
|
||||
if (tempres > result)
|
||||
{
|
||||
result = tempres;
|
||||
}
|
||||
if (result == Pl_Stop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
type = (ResultType)result;
|
||||
}
|
||||
@ -153,12 +193,30 @@ void CConCmdManager::InternalDispatch()
|
||||
cell_t result = Pl_Continue;
|
||||
int args = engine->Cmd_Argc() - 1;
|
||||
|
||||
if (m_CmdClient == 0)
|
||||
List<CmdHook *>::iterator iter;
|
||||
CmdHook *pHook;
|
||||
|
||||
/* Execute server-only commands if viable */
|
||||
if (m_CmdClient == 0 && pInfo->srvhooks.size())
|
||||
{
|
||||
if (pInfo->srvhooks && pInfo->srvhooks->GetFunctionCount())
|
||||
cell_t tempres = result;
|
||||
for (iter=pInfo->srvhooks.begin();
|
||||
iter!=pInfo->srvhooks.end();
|
||||
iter++)
|
||||
{
|
||||
pInfo->srvhooks->PushCell(args);
|
||||
pInfo->srvhooks->Execute(&result);
|
||||
pHook = (*iter);
|
||||
pHook->pf->PushCell(args);
|
||||
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE)
|
||||
{
|
||||
if (tempres > result)
|
||||
{
|
||||
result = tempres;
|
||||
}
|
||||
if (result == Pl_Stop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if there's an early stop */
|
||||
@ -172,12 +230,35 @@ void CConCmdManager::InternalDispatch()
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute console command hooks */
|
||||
if (pInfo->conhooks && pInfo->conhooks->GetFunctionCount())
|
||||
/* Execute console commands */
|
||||
if (pInfo->conhooks.size())
|
||||
{
|
||||
pInfo->conhooks->PushCell(m_CmdClient);
|
||||
pInfo->conhooks->PushCell(args);
|
||||
pInfo->conhooks->Execute(&result);
|
||||
cell_t tempres = result;
|
||||
for (iter=pInfo->conhooks.begin();
|
||||
iter!=pInfo->conhooks.end();
|
||||
iter++)
|
||||
{
|
||||
pHook = (*iter);
|
||||
if (m_CmdClient
|
||||
&& pHook->pAdmin
|
||||
&& pHook->pAdmin->eflags)
|
||||
{
|
||||
/* :TODO: check admin stuff */
|
||||
}
|
||||
pHook->pf->PushCell(m_CmdClient);
|
||||
pHook->pf->PushCell(args);
|
||||
if (pHook->pf->Execute(&tempres) != SP_ERROR_NONE)
|
||||
{
|
||||
if (tempres > result)
|
||||
{
|
||||
result = tempres;
|
||||
}
|
||||
if (result == Pl_Stop)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result >= Pl_Handled)
|
||||
@ -190,19 +271,25 @@ void CConCmdManager::InternalDispatch()
|
||||
}
|
||||
}
|
||||
|
||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args)
|
||||
{
|
||||
return Pl_Continue;
|
||||
}
|
||||
|
||||
void CConCmdManager::AddConsoleCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *description,
|
||||
int flags)
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
CmdHook *pHook = new CmdHook();
|
||||
|
||||
if (!pInfo->conhooks)
|
||||
pHook->pf = pFunction;
|
||||
if (description && description[0])
|
||||
{
|
||||
pInfo->conhooks = g_Forwards.CreateForwardEx(NULL, ET_Hook, 2, NULL, Param_Cell, Param_Cell);
|
||||
pHook->helptext.assign(description);
|
||||
}
|
||||
|
||||
pInfo->conhooks->AddFunction(pFunction);
|
||||
pInfo->conhooks.push_back(pHook);
|
||||
|
||||
/* Add to the plugin */
|
||||
CmdList *pList;
|
||||
@ -215,7 +302,79 @@ void CConCmdManager::AddConsoleCommand(IPluginFunction *pFunction,
|
||||
PlCmdInfo info;
|
||||
info.pInfo = pInfo;
|
||||
info.type = Cmd_Console;
|
||||
pList->push_back(info);
|
||||
info.pHook = pHook;
|
||||
AddToPlCmdList(pList, info);
|
||||
}
|
||||
|
||||
bool CConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *group,
|
||||
int adminflags,
|
||||
const char *description,
|
||||
int flags)
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
|
||||
CmdHook *pHook = new CmdHook();
|
||||
AdminCmdInfo *pAdmin = new AdminCmdInfo();
|
||||
|
||||
pHook->pf = pFunction;
|
||||
if (description && description[0])
|
||||
{
|
||||
pHook->helptext.assign(description);
|
||||
}
|
||||
pHook->pAdmin = pAdmin;
|
||||
|
||||
void *object;
|
||||
int grpid;
|
||||
if (!sm_trie_retrieve(m_pCmdGrps, group, (void **)&object))
|
||||
{
|
||||
grpid = m_Strings.AddString(group);
|
||||
sm_trie_insert(m_pCmdGrps, group, (void *)grpid);
|
||||
} else {
|
||||
grpid = (int)object;
|
||||
}
|
||||
|
||||
pAdmin->cmdGrpId = grpid;
|
||||
pAdmin->flags = flags;
|
||||
|
||||
/* First get the command group override, if any */
|
||||
bool override = g_Admins.GetCommandOverride(group,
|
||||
Override_CommandGroup,
|
||||
&(pAdmin->eflags));
|
||||
|
||||
/* Next get the command override, if any */
|
||||
if (g_Admins.GetCommandOverride(name,
|
||||
Override_Command,
|
||||
&(pAdmin->eflags)))
|
||||
{
|
||||
override = true;
|
||||
}
|
||||
|
||||
/* Assign normal flags if there were no overrides */
|
||||
if (!override)
|
||||
{
|
||||
pAdmin->eflags = pAdmin->flags;
|
||||
}
|
||||
|
||||
/* Finally, add the hook */
|
||||
pInfo->conhooks.push_back(pHook);
|
||||
|
||||
/* Now 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_Admin;
|
||||
info.pHook = pHook;
|
||||
AddToPlCmdList(pList, info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CConCmdManager::AddServerCommand(IPluginFunction *pFunction,
|
||||
@ -225,13 +384,15 @@ void CConCmdManager::AddServerCommand(IPluginFunction *pFunction,
|
||||
|
||||
{
|
||||
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
|
||||
CmdHook *pHook = new CmdHook();
|
||||
|
||||
if (!pInfo->srvhooks)
|
||||
pHook->pf = pFunction;
|
||||
if (description && description[0])
|
||||
{
|
||||
pInfo->srvhooks = g_Forwards.CreateForwardEx(NULL, ET_Hook, 1, NULL, Param_Cell);
|
||||
pHook->helptext.assign(description);
|
||||
}
|
||||
|
||||
pInfo->srvhooks->AddFunction(pFunction);
|
||||
pInfo->srvhooks.push_back(pHook);
|
||||
|
||||
/* Add to the plugin */
|
||||
CmdList *pList;
|
||||
@ -244,7 +405,36 @@ void CConCmdManager::AddServerCommand(IPluginFunction *pFunction,
|
||||
PlCmdInfo info;
|
||||
info.pInfo = pInfo;
|
||||
info.type = Cmd_Server;
|
||||
pList->push_back(info);
|
||||
info.pHook = pHook;
|
||||
AddToPlCmdList(pList, info);
|
||||
}
|
||||
|
||||
void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info)
|
||||
{
|
||||
CmdList::iterator iter = pList->begin();
|
||||
bool inserted = false;
|
||||
const char *orig = NULL;
|
||||
|
||||
orig = info.pInfo->pCmd->GetName();
|
||||
|
||||
/* Insert this into the help list, SORTED alphabetically. */
|
||||
while (iter != pList->end())
|
||||
{
|
||||
PlCmdInfo &obj = (*iter);
|
||||
const char *cmd = obj.pInfo->pCmd->GetName();
|
||||
if (strcmp(orig, cmd) < 0)
|
||||
{
|
||||
pList->insert(iter, info);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
if (!inserted)
|
||||
{
|
||||
pList->push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
void CConCmdManager::AddToCmdList(ConCmdInfo *info)
|
||||
@ -305,12 +495,8 @@ void CConCmdManager::RemoveConCmd(ConCmdInfo *info)
|
||||
|
||||
/* Remove from list */
|
||||
m_CmdList.remove(info);
|
||||
|
||||
/* Free forwards */
|
||||
if (info->srvhooks)
|
||||
{
|
||||
g_Forwards.ReleaseForward(info->srvhooks);
|
||||
}
|
||||
|
||||
delete info;
|
||||
}
|
||||
|
||||
ConCmdInfo *CConCmdManager::AddOrFindCommand(const char *name, const char *description, int flags)
|
||||
@ -400,11 +586,16 @@ void CConCmdManager::OnRootConsoleCommand(const char *command, unsigned int argc
|
||||
type = "server";
|
||||
} else if (cmd.type == Cmd_Console) {
|
||||
type = "console";
|
||||
} else if (cmd.type == Cmd_Client) {
|
||||
type = "client";
|
||||
} else if (cmd.type == Cmd_Admin) {
|
||||
type = "admin";
|
||||
}
|
||||
name = cmd.pInfo->pCmd->GetName();
|
||||
help = cmd.pInfo->pCmd->GetHelpText();
|
||||
if (cmd.pHook->helptext.size())
|
||||
{
|
||||
help = cmd.pHook->helptext.c_str();
|
||||
} else {
|
||||
help = cmd.pInfo->pCmd->GetHelpText();
|
||||
}
|
||||
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,11 @@
|
||||
#include "sourcemm_api.h"
|
||||
#include "ForwardSys.h"
|
||||
#include "sm_trie.h"
|
||||
#include "sm_memtable.h"
|
||||
#include <sh_list.h>
|
||||
#include <sh_string.h>
|
||||
#include <IRootConsoleMenu.h>
|
||||
#include <IAdminSystem.h>
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
@ -28,7 +31,32 @@ enum CmdType
|
||||
{
|
||||
Cmd_Server,
|
||||
Cmd_Console,
|
||||
Cmd_Client
|
||||
Cmd_Admin,
|
||||
};
|
||||
|
||||
struct AdminCmdInfo
|
||||
{
|
||||
AdminCmdInfo()
|
||||
{
|
||||
cmdGrpId = -1;
|
||||
flags = 0;
|
||||
eflags = 0;
|
||||
}
|
||||
int cmdGrpId; /* index into cmdgroup string table */
|
||||
FlagBits flags; /* default flags */
|
||||
FlagBits eflags; /* effective flags */
|
||||
};
|
||||
|
||||
struct CmdHook
|
||||
{
|
||||
CmdHook()
|
||||
{
|
||||
pf = NULL;
|
||||
pAdmin = NULL;
|
||||
}
|
||||
IPluginFunction *pf; /* function hook */
|
||||
String helptext; /* help text */
|
||||
AdminCmdInfo *pAdmin; /* admin requirements, if any */
|
||||
};
|
||||
|
||||
struct ConCmdInfo
|
||||
@ -37,13 +65,11 @@ 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 */
|
||||
List<CmdHook *> srvhooks; /**< Hooks as a server command */
|
||||
List<CmdHook *> conhooks; /**< Hooks as a console command */
|
||||
};
|
||||
|
||||
class CConCmdManager :
|
||||
@ -59,24 +85,33 @@ public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IPluginsListener
|
||||
void OnPluginLoaded(IPlugin *plugin);
|
||||
void OnPluginDestroyed(IPlugin *plugin);
|
||||
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);
|
||||
bool AddAdminCommand(IPluginFunction *pFunction,
|
||||
const char *name,
|
||||
const char *group,
|
||||
int adminflags,
|
||||
const char *description,
|
||||
int flags);
|
||||
ResultType DispatchClientCommand(int client, ResultType type);
|
||||
private:
|
||||
void InternalDispatch();
|
||||
ResultType RunAdminCommand(ConCmdInfo *pInfo, int client, int args);
|
||||
ConCmdInfo *AddOrFindCommand(const char *name, const char *description, int flags);
|
||||
void SetCommandClient(int client);
|
||||
void AddToCmdList(ConCmdInfo *info);
|
||||
void RemoveConCmd(ConCmdInfo *info);
|
||||
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
|
||||
private:
|
||||
Trie *m_pCmds;
|
||||
List<ConCmdInfo *> m_CmdList;
|
||||
int m_CmdClient;
|
||||
Trie *m_pCmds; /* command lookup */
|
||||
Trie *m_pCmdGrps; /* command group lookup */
|
||||
List<ConCmdInfo *> m_CmdList; /* command list, currently unused */
|
||||
int m_CmdClient; /* current client */
|
||||
BaseStringTable m_Strings; /* string table */
|
||||
};
|
||||
|
||||
extern CConCmdManager g_ConCmds;
|
||||
|
@ -115,7 +115,7 @@ native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:descripti
|
||||
#if 0
|
||||
/**
|
||||
* Creates a console command as an administrative command. If the command does not exist,
|
||||
* it is created. This command cannot be used to create duplicate admin commands.
|
||||
* it is created.
|
||||
*
|
||||
* @param cmd String containing command to register.
|
||||
* @param callback A function to use as a callback for when the command is invoked.
|
||||
@ -125,7 +125,6 @@ native RegConsoleCmd(const String:cmd[], ConCmd:callback, const String:descripti
|
||||
* @param description Optional description to use for help.
|
||||
* @param flags Optional console flags.
|
||||
* @noreturn
|
||||
* @error If this command has already been registered as an admin command.
|
||||
*/
|
||||
native RegAdminCmd(const String:cmd[],
|
||||
ConCmd:callback,
|
||||
|
Loading…
Reference in New Issue
Block a user