From e00aa3cbd46a7f435579cc9ce9ff0eed22caa00d Mon Sep 17 00:00:00 2001 From: Scott Ehlert Date: Mon, 23 Jul 2007 18:19:02 +0000 Subject: [PATCH] Added OnUnlinkConCommandBase to IMetamodListener to notify when Metamod:Source is about remove a concommand or convar. --HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%40419 --- sourcemm/CPlugin.cpp | 4 ++-- sourcemm/CSmmAPI.cpp | 2 +- sourcemm/ISmmPlugin.h | 14 ++++++++++---- sourcemm/changelog.txt | 4 +++- sourcemm/concommands.cpp | 36 +++++++++++++++++++++++++++++++----- sourcemm/concommands.h | 2 +- 6 files changed, 48 insertions(+), 14 deletions(-) diff --git a/sourcemm/CPlugin.cpp b/sourcemm/CPlugin.cpp index 28e81f4..4f5d104 100644 --- a/sourcemm/CPlugin.cpp +++ b/sourcemm/CPlugin.cpp @@ -605,12 +605,12 @@ void CPluginManager::UnregAllConCmds(CPlugin *pl) SourceHook::List::iterator i; for (i=pl->m_Cvars.begin(); i!=pl->m_Cvars.end(); i++) - g_SMConVarAccessor.Unregister( (*i) ); + g_SMConVarAccessor.Unregister(pl->m_Id, (*i) ); pl->m_Cvars.clear(); for (i=pl->m_Cmds.begin(); i!=pl->m_Cmds.end(); i++) - g_SMConVarAccessor.Unregister( (*i) ); + g_SMConVarAccessor.Unregister(pl->m_Id, (*i) ); pl->m_Cmds.clear(); } diff --git a/sourcemm/CSmmAPI.cpp b/sourcemm/CSmmAPI.cpp index 94cd52a..a3847a9 100644 --- a/sourcemm/CSmmAPI.cpp +++ b/sourcemm/CSmmAPI.cpp @@ -118,7 +118,7 @@ void CSmmAPI::UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) g_PluginMngr.RemovePluginCvar(plugin, pCommand); } - g_SMConVarAccessor.Unregister(pCommand); + g_SMConVarAccessor.Unregister(g_PluginMngr.FindByAPI(plugin)->m_Id, pCommand); } void CSmmAPI::ConPrint(const char *fmt) diff --git a/sourcemm/ISmmPlugin.h b/sourcemm/ISmmPlugin.h index 867d757..b967d11 100644 --- a/sourcemm/ISmmPlugin.h +++ b/sourcemm/ISmmPlugin.h @@ -20,7 +20,7 @@ #include #include "ISmmAPI.h" -#define PLAPI_VERSION 11 +#define PLAPI_VERSION 12 #define PLAPI_NAME "ISmmPlugin" class ISmmAPI; @@ -313,9 +313,15 @@ public: * @param iface Interface pointer. If NULL, then the VSP listening construct * failed to initialize and is not available. */ - virtual void OnVSPListening(IServerPluginCallbacks *iface) - { - } + virtual void OnVSPListening(IServerPluginCallbacks *iface) { } + + /* @brief Called when Metamod:Source is about to remove a concommand or convar. + * This can also be called if ISmmAPI::UnregisterConCmdBase is used by a plugin. + * + * @param id Id of the plugin that created the concommand or convar. + * @param pCommand Pointer to concommand or convar that is being removed. + */ + virtual void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand) { } }; #define PL_EXPOSURE CreateInterface diff --git a/sourcemm/changelog.txt b/sourcemm/changelog.txt index a8da291..2374fee 100644 --- a/sourcemm/changelog.txt +++ b/sourcemm/changelog.txt @@ -8,7 +8,9 @@ instance pointer rather than a callclass pointer. - Added API for getting highest supported IServerPluginCallbacks interface version. - + - Added OnUnlinkConCommandBase to IMetamodListner to notify when Metamod:Source + is about to remove a concommand or convar. + 2007/06/26 1.4.2: - Fixed a bug where unloading all plugins could crash if one plugin had child plugins. diff --git a/sourcemm/concommands.cpp b/sourcemm/concommands.cpp index 5e0969e..fd62f58 100644 --- a/sourcemm/concommands.cpp +++ b/sourcemm/concommands.cpp @@ -57,18 +57,44 @@ void SMConVarAccessor::MarkCommandsAsGameDLL() } } -void SMConVarAccessor::Unregister(ConCommandBase *pCommand) +void SMConVarAccessor::Unregister(PluginId id, ConCommandBase *pCommand) { + /* Notify via IMetamodListener */ + PluginIter iter; + SourceMM::CPluginManager::CPlugin *pPlugin; + SourceHook::List::iterator event; + IMetamodListener *pML; + for (iter=g_PluginMngr._begin(); iter!=g_PluginMngr._end(); iter++) + { + pPlugin = (*iter); + if (pPlugin->m_Status < Pl_Paused) + { + continue; + } + /* Only valid for plugins >= 12 (v1:6, SourceMM 1.5) */ + if (pPlugin->m_API->GetApiVersion() < 12) + { + continue; + } + for (event=pPlugin->m_Events.begin(); + event!=pPlugin->m_Events.end(); + event++) + { + pML = (*event); + pML->OnUnlinkConCommandBase(id, pCommand); + } + } + ICvar *cv = g_Engine.icvar; ConCommandBase *ptr = cv->GetCommands(); if (ptr == pCommand) { - //first in list + /* First in list */ g_EternalCommand.BringToFront(); g_EternalCommand.SetNext(const_cast(pCommand->GetNext())); } else { - //find us and unregister us + /* Find us and unregister us */ ConCommandBase *pPrev = NULL; while (ptr) { @@ -91,10 +117,10 @@ void SMConVarAccessor::UnregisterGameDLLCommands() ConCommandBase *prev = NULL; while (iter) { - // watch out for the ETERNAL COMMAND! + /* Watch out for the ETERNAL COMMAND! */ if (iter != &g_EternalCommand && iter->IsBitSet(FCVAR_GAMEDLL)) { - // Remove it! + /* Remove it! */ if (iter == begin) { g_EternalCommand.BringToFront(); diff --git a/sourcemm/concommands.h b/sourcemm/concommands.h index 56ca953..0817afb 100644 --- a/sourcemm/concommands.h +++ b/sourcemm/concommands.h @@ -29,7 +29,7 @@ public: virtual bool RegisterConCommandBase(ConCommandBase *pCommand); bool Register(ConCommandBase *pCommand); void MarkCommandsAsGameDLL(); - void Unregister(ConCommandBase *pCommand); + void Unregister(PluginId id, ConCommandBase *pCommand); void UnregisterGameDLLCommands(); };