diff --git a/core/ConCmdManager.cpp b/core/ConCmdManager.cpp index 200390a7..3e6144a0 100644 --- a/core/ConCmdManager.cpp +++ b/core/ConCmdManager.cpp @@ -38,6 +38,8 @@ #include "ChatTriggers.h" #include "logic_bridge.h" +using namespace ke; + ConCmdManager g_ConCmds; #if SOURCE_ENGINE == SE_DOTA @@ -53,7 +55,7 @@ SH_DECL_HOOK1_void(IServerGameClients, SetCommandClient, SH_NOATTRIB, false, int typedef ke::LinkedList PluginHookList; void RegisterInPlugin(CmdHook *hook); -ConCmdManager::ConCmdManager() : m_Strings(1024) +ConCmdManager::ConCmdManager() { m_CmdClient = 0; } @@ -105,6 +107,9 @@ void ConCmdManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *na } } + if (hook->admin) + hook->admin->group->hooks.remove(hook); + iter = pInfo->hooks.erase(iter); delete hook; } @@ -124,6 +129,8 @@ void ConCmdManager::OnPluginDestroyed(IPlugin *plugin) CmdHook *hook = *iter; hook->info->hooks.remove(hook); + if (hook->admin) + hook->admin->group->hooks.remove(hook); if (hook->info->hooks.empty()) RemoveConCmd(hook->info, hook->info->pCmd->GetName(), true, true); @@ -450,19 +457,17 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction, if (!pInfo) return false; - CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description); - - pHook->admin = new AdminCmdInfo(); - - int grpid; - if (!m_CmdGrps.retrieve(group, &grpid)) + GroupMap::Insert i = m_CmdGrps.findForAdd(group); + if (!i.found()) { - grpid = m_Strings.AddString(group); - m_CmdGrps.insert(group, grpid); + if (!m_CmdGrps.add(i, group)) + return false; + i->value = NoAddRef(new CommandGroup()); } + Ref cmdgroup = i->value; - pHook->admin->cmdGrpId = grpid; - pHook->admin->flags = adminflags; + CmdHook *pHook = new CmdHook(CmdHook::Client, pInfo, pFunction, description); + pHook->admin = new AdminCmdInfo(cmdgroup, adminflags); /* First get the command group override, if any */ bool override = g_Admins.GetCommandOverride(group, @@ -482,6 +487,7 @@ bool ConCmdManager::AddAdminCommand(IPluginFunction *pFunction, pHook->admin->eflags = pHook->admin->flags; pInfo->eflags = pHook->admin->eflags; + cmdgroup->hooks.append(pHook); pInfo->hooks.append(pHook); RegisterInPlugin(pHook); return true; @@ -586,27 +592,20 @@ void ConCmdManager::UpdateAdminCmdFlags(const char *cmd, OverrideType type, Flag } else if (type == Override_CommandGroup) { - int grpid; - if (!m_CmdGrps.retrieve(cmd, &grpid)) + GroupMap::Result r = m_CmdGrps.find(cmd); + if (!r.found()) return; - /* This is bad :( loop through all commands */ - List::iterator iter; - for (iter=m_CmdList.begin(); iter!=m_CmdList.end(); iter++) - { - ConCmdInfo *pInfo = *iter; - for (CmdHookList::iterator citer = pInfo->hooks.begin(); citer != pInfo->hooks.end(); citer++) - { - CmdHook *hook = (*citer); - if (!hook->admin || hook->admin->cmdGrpId != grpid) - continue; + Ref group(r->value); - if (remove) - hook->admin->eflags = bits; - else - hook->admin->eflags = hook->admin->flags; - pInfo->eflags = hook->admin->eflags; - } + for (PluginHookList::iterator iter = group->hooks.begin(); iter != group->hooks.end(); iter++) + { + CmdHook *hook = *iter; + if (remove) + hook->admin->eflags = bits; + else + hook->admin->eflags = hook->admin->flags; + hook->info->eflags = hook->admin->eflags; } } } diff --git a/core/ConCmdManager.h b/core/ConCmdManager.h index 96ac1e52..2dac0234 100644 --- a/core/ConCmdManager.h +++ b/core/ConCmdManager.h @@ -35,7 +35,6 @@ #include "sm_globals.h" #include "sourcemm_api.h" #include "ForwardSys.h" -#include "sm_memtable.h" #include #include #include @@ -45,24 +44,31 @@ #include #include #include +#include using namespace SourceHook; +struct CmdHook; +struct ConCmdInfo; + +struct CommandGroup : public ke::Refcounted +{ + ke::LinkedList hooks; +}; + struct AdminCmdInfo { - AdminCmdInfo() + AdminCmdInfo(const ke::Ref &group, FlagBits flags) + : group(group), + flags(flags), + eflags(0) { - cmdGrpId = -1; - flags = 0; - eflags = 0; } - int cmdGrpId; /* index into cmdgroup string table */ + ke::Ref group; FlagBits flags; /* default flags */ FlagBits eflags; /* effective flags */ }; -struct ConCmdInfo; - struct CmdHook : public ke::InlineListNode { enum Type { @@ -166,11 +172,12 @@ public: return m_CmdList; } private: + typedef StringHashMap > GroupMap; + StringHashMap m_Cmds; /* command lookup */ - StringHashMap m_CmdGrps; /* command group lookup */ + GroupMap m_CmdGrps; /* command group map */ ConCmdList m_CmdList; /* command list */ int m_CmdClient; /* current client */ - BaseStringTable m_Strings; /* string table */ }; extern ConCmdManager g_ConCmds; diff --git a/public/amtl/am-refcounting.h b/public/amtl/am-refcounting.h index 6323dcf8..71a6f554 100644 --- a/public/amtl/am-refcounting.h +++ b/public/amtl/am-refcounting.h @@ -58,6 +58,13 @@ class Newborn mutable T *thing_; }; +template +static inline Newborn +NoAddRef(T *t) +{ + return Newborn(t); +} + // When returning a value, we'd rather not be needlessly changing the refcount, // so we have a special type to use for returns. template