Clean up ConCmdManager (bug 5900, r=fyren).

This commit is contained in:
David Anderson 2013-08-31 11:51:23 -07:00
parent 435f2b8e39
commit ba927964c8
4 changed files with 190 additions and 361 deletions

View File

@ -50,15 +50,8 @@ ConCmdManager g_ConCmds;
SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int); SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int);
struct PlCmdInfo typedef ke::LinkedList<CmdHook *> PluginHookList;
{ void RegisterInPlugin(CmdHook *hook);
ConCmdInfo *pInfo;
CmdHook *pHook;
CmdType type;
};
typedef List<PlCmdInfo> CmdList;
void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info);
ConCmdManager::ConCmdManager() : m_Strings(1024) ConCmdManager::ConCmdManager() : m_Strings(1024)
{ {
@ -92,116 +85,56 @@ void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na
if (!m_Cmds.retrieve(name, &pInfo)) if (!m_Cmds.retrieve(name, &pInfo))
return; return;
RemoveConCmds(pInfo->srvhooks); CmdHookList::iterator iter = pInfo->hooks.begin();
RemoveConCmds(pInfo->conhooks); while (iter != pInfo->hooks.end())
{
CmdHook *hook = *iter;
IPluginContext *pContext = hook->pf->GetParentContext();
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
// The list is guaranteed to exist.
PluginHookList *list;
pPlugin->GetProperty("CommandList", (void **)&list, false);
for (PluginHookList::iterator hiter = list->begin(); hiter != list->end(); hiter++)
{
if (*hiter == hook)
{
list->erase(hiter);
break;
}
}
iter = pInfo->hooks.erase(iter);
delete hook;
}
RemoveConCmd(pInfo, name, is_read_safe, false); RemoveConCmd(pInfo, name, is_read_safe, false);
} }
void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist)
{
List<CmdHook *>::iterator iter = cmdlist.begin();
while (iter != cmdlist.end())
{
CmdHook *pHook = (*iter);
IPluginContext *pContext = pHook->pf->GetParentContext();
IPlugin *pPlugin = scripts->FindPluginByContext(pContext->GetContext());
CmdList *pList = NULL;
//gaben
if (!pPlugin->GetProperty("CommandList", (void **)&pList, false) || !pList)
{
continue;
}
CmdList::iterator p_iter = pList->begin();
while (p_iter != pList->end())
{
PlCmdInfo &cmd = (*p_iter);
if (cmd.pHook == pHook)
{
p_iter = pList->erase(p_iter);
}
else
{
p_iter++;
}
}
delete pHook->pAdmin;
delete pHook;
iter = cmdlist.erase(iter);
}
}
void ConCmdManager::RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext)
{
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 ConCmdManager::OnPluginDestroyed(IPlugin *plugin) void ConCmdManager::OnPluginDestroyed(IPlugin *plugin)
{ {
CmdList *pList; PluginHookList *pList;
List<ConCmdInfo *> removed; if (!plugin->GetProperty("CommandList", (void **)&pList, true))
if (plugin->GetProperty("CommandList", (void **)&pList, true)) return;
PluginHookList::iterator iter = pList->begin();
while (iter != pList->end())
{ {
IPluginContext *pContext = plugin->GetBaseContext(); CmdHook *hook = *iter;
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++)
{
PlCmdInfo &cmd = (*iter);
ConCmdInfo *pInfo = cmd.pInfo;
/* Has this chain already been fully cleaned/removed? */ hook->info->hooks.remove(hook);
if (removed.find(pInfo) != removed.end())
{
continue;
}
/* Remove any hooks from us on this command */ if (hook->info->hooks.empty())
RemoveConCmds(pInfo->conhooks, pContext); RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true, true);
RemoveConCmds(pInfo->srvhooks, pContext);
/* See if there are still hooks */ iter = pList->erase(iter);
if (pInfo->srvhooks.size()) delete hook;
{
continue;
}
if (pInfo->conhooks.size())
{
continue;
}
/* Remove the command, it should be safe now */
RemoveConCmd(pInfo, pInfo->pCmd->GetName(), true, true);
removed.push_back(pInfo);
}
delete pList;
} }
delete pList;
} }
#if SOURCE_ENGINE == SE_DOTA #if SOURCE_ENGINE == SE_DOTA
void CommandCallback(const CCommandContext &context, const CCommand &command) void CommandCallback(const CCommandContext &context, const CCommand &command)
{ {
@ -261,44 +194,34 @@ ResultType ConCmdManager::DispatchClientCommand(int client, const char *cmd, int
} }
cell_t result = type; cell_t result = type;
cell_t tempres = result; for (CmdHookList::iterator iter = pInfo->hooks.begin(); iter != pInfo->hooks.end(); iter++)
List<CmdHook *>::iterator iter;
CmdHook *pHook;
for (iter=pInfo->conhooks.begin();
iter!=pInfo->conhooks.end();
iter++)
{ {
pHook = (*iter); CmdHook *hook = *iter;
if (!pHook->pf->IsRunnable())
{ if (hook->type == CmdHook::Server || !hook->pf->IsRunnable())
continue; continue;
}
if (pHook->pAdmin && !CheckAccess(client, cmd, pHook->pAdmin)) if (hook->admin && !CheckAccess(client, cmd, hook->admin))
{ {
if (result < Pl_Handled) if (result < Pl_Handled)
{
result = Pl_Handled; result = Pl_Handled;
}
continue; continue;
} }
pHook->pf->PushCell(client);
pHook->pf->PushCell(args); hook->pf->PushCell(client);
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE) hook->pf->PushCell(args);
cell_t tempres = result;
if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
{ {
if (tempres > result) if (tempres > result)
{
result = tempres; result = tempres;
}
if (result == Pl_Stop) if (result == Pl_Stop)
{
break; break;
}
} }
} }
type = (ResultType)result; return (ResultType)result;
return type;
} }
void ConCmdManager::InternalDispatch(const CCommand &command) void ConCmdManager::InternalDispatch(const CCommand &command)
@ -309,9 +232,7 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
{ {
CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
if (!pPlayer || !pPlayer->IsConnected()) if (!pPlayer || !pPlayer->IsConnected())
{
return; return;
}
} }
/** /**
@ -343,109 +264,61 @@ void ConCmdManager::InternalDispatch(const CCommand &command)
* "nicer" when we expose explicit say hooks. * "nicer" when we expose explicit say hooks.
*/ */
if (g_ChatTriggers.WasFloodedMessage()) if (g_ChatTriggers.WasFloodedMessage())
{
return; return;
}
cell_t result = Pl_Continue; cell_t result = Pl_Continue;
int args = command.ArgC() - 1; int args = command.ArgC() - 1;
List<CmdHook *>::iterator iter; // On a listen server, sometimes the server host's client index can be set
CmdHook *pHook; // as 0. So index 1 is passed to the command callback to correct this
// potential problem.
int realClient = (!engine->IsDedicatedServer() && client == 0)
? g_Players.ListenClient()
: client;
int dedicatedClient = engine->IsDedicatedServer() ? 0 : g_Players.ListenClient();
/* Execute server-only commands if viable */ for (CmdHookList::iterator iter = pInfo->hooks.begin(); iter != pInfo->hooks.end(); iter++)
if (client == 0 && pInfo->srvhooks.size())
{ {
cell_t tempres = result; CmdHook *hook = *iter;
for (iter=pInfo->srvhooks.begin();
iter!=pInfo->srvhooks.end();
iter++)
{
pHook = (*iter);
if (!pHook->pf->IsRunnable())
{
continue;
}
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 */ if (!hook->pf->IsRunnable())
if (result >= Pl_Stop) continue;
{
if (!pInfo->sourceMod)
{
RETURN_META(MRES_SUPERCEDE);
}
return;
}
}
/* Execute console commands */ if (hook->type == CmdHook::Server)
if (pInfo->conhooks.size())
{
cell_t tempres = result;
for (iter=pInfo->conhooks.begin();
iter!=pInfo->conhooks.end();
iter++)
{ {
pHook = (*iter); // Don't execute unless we're in the server console.
if (!pHook->pf->IsRunnable()) if (realClient != dedicatedClient)
{
continue; continue;
} } else {
if (client // Check admin rights if needed. realClient isn't needed since we
&& pHook->pAdmin // should bypass admin checks if client == 0 anyway.
&& !CheckAccess(client, cmd, pHook->pAdmin)) if (client && hook->admin && !CheckAccess(client, cmd, hook->admin))
{ {
if (result < Pl_Handled) if (result < Pl_Handled)
{
result = Pl_Handled; result = Pl_Handled;
}
continue; continue;
} }
/* On a listen server, sometimes the server host's client index can be set as 0. // Client hooks get a client argument.
* So index 1 is passed to the command callback to correct this potential problem. hook->pf->PushCell(realClient);
*/ }
if (!engine->IsDedicatedServer())
{
client = g_Players.ListenClient();
}
pHook->pf->PushCell(client); hook->pf->PushCell(args);
pHook->pf->PushCell(args);
if (pHook->pf->Execute(&tempres) == SP_ERROR_NONE) cell_t tempres = result;
{ if (hook->pf->Execute(&tempres) == SP_ERROR_NONE)
if (tempres > result) {
{ if (tempres > result)
result = tempres; result = tempres;
} if (result == Pl_Stop)
if (result == Pl_Stop) break;
{
break;
}
}
} }
} }
if (result >= Pl_Handled) if (result >= Pl_Handled)
{ {
if (!pInfo->sourceMod) if (!pInfo->sourceMod)
{
RETURN_META(MRES_SUPERCEDE); RETURN_META(MRES_SUPERCEDE);
}
return; return;
} }
} }
@ -575,19 +448,11 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags); ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo) if (!pInfo)
{
return false; return false;
}
CmdHook *pHook = new CmdHook(); CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description);
AdminCmdInfo *pAdmin = new AdminCmdInfo();
pHook->pf = pFunction; pHook->admin = new AdminCmdInfo();
if (description && description[0])
{
pHook->helptext.assign(description);
}
pHook->pAdmin = pAdmin;
int grpid; int grpid;
if (!m_CmdGrps.retrieve(group, &grpid)) if (!m_CmdGrps.retrieve(group, &grpid))
@ -596,46 +461,29 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction,
m_CmdGrps.insert(group, grpid); m_CmdGrps.insert(group, grpid);
} }
pAdmin->cmdGrpId = grpid; pHook->admin->cmdGrpId = grpid;
pAdmin->flags = adminflags; pHook->admin->flags = adminflags;
/* First get the command group override, if any */ /* First get the command group override, if any */
bool override = g_Admins.GetCommandOverride(group, bool override = g_Admins.GetCommandOverride(group,
Override_CommandGroup, Override_CommandGroup,
&(pAdmin->eflags)); &(pHook->admin->eflags));
/* Next get the command override, if any */ /* Next get the command override, if any */
if (g_Admins.GetCommandOverride(name, if (g_Admins.GetCommandOverride(name,
Override_Command, Override_Command,
&(pAdmin->eflags))) &(pHook->admin->eflags)))
{ {
override = true; override = true;
} }
/* Assign normal flags if there were no overrides */ /* Assign normal flags if there were no overrides */
if (!override) if (!override)
{ pHook->admin->eflags = pHook->admin->flags;
pAdmin->eflags = pAdmin->flags; pInfo->eflags = pHook->admin->eflags;
}
/* Finally, add the hook */
pInfo->conhooks.push_back(pHook);
pInfo->admin = *(pHook->pAdmin);
/* Now add to the plugin */
CmdList *pList;
IPlugin *pPlugin = scripts->FindPluginByContext(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);
pInfo->hooks.append(pHook);
RegisterInPlugin(pHook);
return true; return true;
} }
@ -648,63 +496,42 @@ bool ConCmdManager::AddServerCommand(IPluginFunction *pFunction,
ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags); ConCmdInfo *pInfo = AddOrFindCommand(name, description, flags);
if (!pInfo) if (!pInfo)
{
return false; return false;
}
CmdHook *pHook = new CmdHook(); CmdHook *pHook = new CmdHook(CmdHook::Server, pInfo, pFunction, description);
pHook->pf = pFunction;
if (description && description[0])
{
pHook->helptext.assign(description);
}
pInfo->srvhooks.push_back(pHook);
/* Add to the plugin */
CmdList *pList;
IPlugin *pPlugin = scripts->FindPluginByContext(pFunction->GetParentContext()->GetContext());
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new CmdList();
pPlugin->SetProperty("CommandList", pList);
}
PlCmdInfo info;
info.pInfo = pInfo;
info.type = Cmd_Server;
info.pHook = pHook;
AddToPlCmdList(pList, info);
pInfo->hooks.append(pHook);
RegisterInPlugin(pHook);
return true; return true;
} }
void AddToPlCmdList(CmdList *pList, const PlCmdInfo &info) void RegisterInPlugin(CmdHook *hook)
{ {
CmdList::iterator iter = pList->begin(); PluginHookList *pList;
bool inserted = false;
const char *orig = NULL;
orig = info.pInfo->pCmd->GetName(); IPlugin *pPlugin = scripts->FindPluginByContext(hook->pf->GetParentContext());
if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{
pList = new PluginHookList();
pPlugin->SetProperty("CommandList", pList);
}
const char *orig = hook->info->pCmd->GetName();
/* Insert this into the help list, SORTED alphabetically. */ /* Insert this into the help list, SORTED alphabetically. */
PluginHookList::iterator iter = pList->begin();
while (iter != pList->end()) while (iter != pList->end())
{ {
PlCmdInfo &obj = (*iter); const char *cmd = (*iter)->info->pCmd->GetName();
const char *cmd = obj.pInfo->pCmd->GetName();
if (strcmp(orig, cmd) < 0) if (strcmp(orig, cmd) < 0)
{ {
pList->insert(iter, info); pList->insertBefore(iter, hook);
inserted = true; return;
break;
} }
iter++; iter++;
} }
if (!inserted) pList->append(hook);
{
pList->push_back(info);
}
} }
void ConCmdManager::AddToCmdList(ConCmdInfo *info) void ConCmdManager::AddToCmdList(ConCmdInfo *info)
@ -739,29 +566,22 @@ void ConCmdManager::AddToCmdList(ConCmdInfo *info)
void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove) void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, FlagBits bits, bool remove)
{ {
ConCmdInfo *pInfo;
if (type == Override_Command) if (type == Override_Command)
{ {
ConCmdInfo *pInfo;
if (!m_Cmds.retrieve(cmd, &pInfo)) if (!m_Cmds.retrieve(cmd, &pInfo))
return; return;
List<CmdHook *>::iterator iter; for (CmdHookList::iterator iter = pInfo->hooks.begin(); iter != pInfo->hooks.end(); iter++)
CmdHook *pHook;
for (iter=pInfo->conhooks.begin(); iter!=pInfo->conhooks.end(); iter++)
{ {
pHook = (*iter); if (!iter->admin)
if (pHook->pAdmin) continue;
{
if (!remove) if (!remove)
{ iter->admin->eflags = bits;
pHook->pAdmin->eflags = bits; else
} else { iter->admin->eflags = iter->admin->flags;
pHook->pAdmin->eflags = pHook->pAdmin->flags; pInfo->eflags = iter->admin->eflags;
}
pInfo->admin = *(pHook->pAdmin);
}
} }
} }
else if (type == Override_CommandGroup) else if (type == Override_CommandGroup)
@ -772,25 +592,20 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag
/* This is bad :( loop through all commands */ /* This is bad :( loop through all commands */
List<ConCmdInfo *>::iterator iter; List<ConCmdInfo *>::iterator iter;
CmdHook *pHook;
for (iter=m_CmdList.begin(); iter!=m_CmdList.end(); iter++) for (iter=m_CmdList.begin(); iter!=m_CmdList.end(); iter++)
{ {
pInfo = (*iter); ConCmdInfo *pInfo = *iter;
for (List<CmdHook *>::iterator citer=pInfo->conhooks.begin(); for (CmdHookList::iterator citer = pInfo->hooks.begin(); citer != pInfo->hooks.end(); citer++)
citer!=pInfo->conhooks.end();
citer++)
{ {
pHook = (*citer); CmdHook *hook = (*citer);
if (pHook->pAdmin && pHook->pAdmin->cmdGrpId == grpid) if (!hook->admin || hook->admin->cmdGrpId != grpid)
{ continue;
if (remove)
{ if (remove)
pHook->pAdmin->eflags = bits; hook->admin->eflags = bits;
} else { else
pHook->pAdmin->eflags = pHook->pAdmin->flags; hook->admin->eflags = hook->admin->flags;
} pInfo->eflags = hook->admin->eflags;
pInfo->admin = *(pHook->pAdmin);
}
} }
} }
} }
@ -843,7 +658,7 @@ bool ConCmdManager::LookForSourceModCommand(const char *cmd)
if (!m_Cmds.retrieve(cmd, &pInfo)) if (!m_Cmds.retrieve(cmd, &pInfo))
return false; return false;
return pInfo->sourceMod && (pInfo->conhooks.size() > 0); return pInfo->sourceMod && !pInfo->hooks.empty();
} }
bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags) bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
@ -852,7 +667,7 @@ bool ConCmdManager::LookForCommandAdminFlags(const char *cmd, FlagBits *pFlags)
if (!m_Cmds.retrieve(cmd, &pInfo)) if (!m_Cmds.retrieve(cmd, &pInfo))
return false; return false;
*pFlags = pInfo->admin.eflags; *pFlags = pInfo->eflags;
return true; return true;
} }
@ -915,46 +730,36 @@ void ConCmdManager::OnRootConsoleCommand(const char *cmdname, const CCommand &co
const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo(); const sm_plugininfo_t *plinfo = pPlugin->GetPublicInfo();
const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename(); const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : pPlugin->GetFilename();
CmdList *pList; PluginHookList *pList;
if (!pPlugin->GetProperty("CommandList", (void **)&pList)) if (!pPlugin->GetProperty("CommandList", (void **)&pList))
{ {
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname); g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
return; return;
} }
if (!pList->size()) if (pList->empty())
{ {
g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname); g_RootMenu.ConsolePrint("[SM] No commands found for: %s", plname);
return; return;
} }
CmdList::iterator iter;
const char *type = NULL; const char *type = NULL;
const char *name; const char *name;
const char *help; const char *help;
g_RootMenu.ConsolePrint("[SM] Listing %d commands for: %s", pList->size(), plname); g_RootMenu.ConsolePrint("[SM] Listing commands for: %s", plname);
g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]"); g_RootMenu.ConsolePrint(" %-17.16s %-8.7s %s", "[Name]", "[Type]", "[Help]");
for (iter=pList->begin(); for (PluginHookList::iterator iter = pList->begin(); iter != pList->end(); iter++)
iter!=pList->end();
iter++)
{ {
PlCmdInfo &cmd = (*iter); CmdHook *hook = *iter;
if (cmd.type == Cmd_Server) if (hook->type == CmdHook::Server)
{
type = "server"; type = "server";
}
else if (cmd.type == Cmd_Admin)
{
type = (cmd.pInfo->admin.eflags == 0)?"console":"admin";
}
name = cmd.pInfo->pCmd->GetName();
if (cmd.pHook->helptext.size())
{
help = cmd.pHook->helptext.c_str();
}
else else
{ type = hook->info->eflags == 0 ? "console" : "admin";
help = cmd.pInfo->pCmd->GetHelpText();
} name = hook->info->pCmd->GetName();
if (hook->helptext.length())
help = hook->helptext.chars();
else
help = hook->info->pCmd->GetHelpText();
g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help); g_RootMenu.ConsolePrint(" %-17.16s %-12.11s %s", name, type, help);
} }

View File

@ -43,15 +43,11 @@
#include "concmd_cleaner.h" #include "concmd_cleaner.h"
#include <sm_stringhashmap.h> #include <sm_stringhashmap.h>
#include <am-utility.h> #include <am-utility.h>
#include <am-inlinelist.h>
#include <am-linkedlist.h>
using namespace SourceHook; using namespace SourceHook;
enum CmdType
{
Cmd_Server,
Cmd_Admin,
};
struct AdminCmdInfo struct AdminCmdInfo
{ {
AdminCmdInfo() AdminCmdInfo()
@ -65,30 +61,44 @@ struct AdminCmdInfo
FlagBits eflags; /* effective flags */ FlagBits eflags; /* effective flags */
}; };
struct CmdHook struct ConCmdInfo;
struct CmdHook : public ke::InlineListNode<CmdHook>
{ {
CmdHook() enum Type {
Server,
Client
};
CmdHook(Type type, ConCmdInfo *cmd, IPluginFunction *fun, const char *description)
: type(type),
info(cmd),
pf(fun),
helptext(description)
{ {
pf = NULL;
pAdmin = NULL;
} }
IPluginFunction *pf; /* function hook */
String helptext; /* help text */ Type type;
AdminCmdInfo *pAdmin; /* admin requirements, if any */ ConCmdInfo *info;
IPluginFunction *pf; /* function hook */
ke::AString helptext; /* help text */
ke::AutoPtr<AdminCmdInfo> admin; /* admin requirements, if any */
}; };
typedef ke::InlineList<CmdHook> CmdHookList;
struct ConCmdInfo struct ConCmdInfo
{ {
ConCmdInfo() ConCmdInfo()
{ {
sourceMod = false; sourceMod = false;
pCmd = NULL; pCmd = NULL;
eflags = 0;
} }
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 */
List<CmdHook *> srvhooks; /**< Hooks as a server command */ CmdHookList hooks; /**< Hook list */
List<CmdHook *> conhooks; /**< Hooks as a console command */ FlagBits eflags; /**< Effective admin flags */
AdminCmdInfo admin; /**< Admin info, if any */
}; };
typedef List<ConCmdInfo *> ConCmdList; typedef List<ConCmdInfo *> ConCmdList;
@ -139,8 +149,6 @@ private:
void SetCommandClient(int client); void SetCommandClient(int client);
void AddToCmdList(ConCmdInfo *info); void AddToCmdList(ConCmdInfo *info);
void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack); void RemoveConCmd(ConCmdInfo *info, const char *cmd, bool is_read_safe, bool untrack);
void RemoveConCmds(List<CmdHook *> &cmdlist);
void RemoveConCmds(List<CmdHook *> &cmdlist, IPluginContext *pContext);
bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin); bool CheckAccess(int client, const char *cmd, AdminCmdInfo *pAdmin);
// Case insensitive // Case insensitive

View File

@ -1278,7 +1278,7 @@ static cell_t ReadCommandIterator(IPluginContext *pContext, const cell_t *params
cell_t *addr; cell_t *addr;
pContext->LocalToPhysAddr(params[4], &addr); pContext->LocalToPhysAddr(params[4], &addr);
*addr = pInfo->admin.eflags; *addr = pInfo->eflags;
iter->iter++; iter->iter++;

View File

@ -140,6 +140,22 @@ class InlineList
return iterator(&head_); return iterator(&head_);
} }
iterator erase(iterator &at) {
iterator next = at;
next++;
remove(at.iter_);
// Iterator is no longer valid.
at.iter_ = NULL;
return next;
}
bool empty() const {
return head_.next_ == &head_;
}
void remove(Node *t) { void remove(Node *t) {
t->prev_->next_ = t->next_; t->prev_->next_ = t->next_;
t->next_->prev_ = t->prev_; t->next_->prev_ = t->prev_;