diff --git a/core/ConVarManager.cpp b/core/ConVarManager.cpp index 6b171cff..1041a832 100644 --- a/core/ConVarManager.cpp +++ b/core/ConVarManager.cpp @@ -31,6 +31,10 @@ typedef List ConVarList; ConVarManager::ConVarManager() : m_ConVarType(0), m_VSPIface(NULL), m_CanQueryConVars(false) { +#if PLAPI_VERSION < 12 + m_IgnoreHandle = false; +#endif + /* Create a convar lookup trie */ m_ConVarCache = sm_trie_create(); } @@ -127,6 +131,52 @@ void ConVarManager::OnSourceModVSPReceived(IServerPluginCallbacks *iface) } } +#if PLAPI_VERSION >= 12 +void ConVarManager::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand) +{ + /* Only check convars that have not been created by SourceMod's core */ + if (id != g_PLID && !pCommand->IsCommand()) + { + ConVarInfo *pInfo; + HandleSecurity sec(NULL, g_pCoreIdent); + bool handleExists = sm_trie_retrieve(m_ConVarCache, pCommand->GetName(), reinterpret_cast(&pInfo)); + + if (handleExists) + { + g_HandleSys.FreeHandle(pInfo->handle, &sec); + } + } +} + +#else + +/* I truly detest this code */ +void ConVarManager::OnMetamodPluginUnloaded(PluginId id) +{ + ConVarInfo *pInfo; + const char *cvarName; + HandleSecurity sec(NULL, g_pCoreIdent); + + List::iterator i; + for (i = m_ConVars.begin(); i != m_ConVars.end(); i++) + { + pInfo = (*i); + cvarName = pInfo->name; + + if (!icvar->FindVar(cvarName)) + { + m_IgnoreHandle = true; + g_HandleSys.FreeHandle(pInfo->handle, &sec); + + sm_trie_delete(m_ConVarCache, cvarName); + m_ConVars.erase(i); + + delete [] cvarName; + } + } +} +#endif + void ConVarManager::OnPluginUnloaded(IPlugin *plugin) { ConVarList *pConVarList; @@ -140,6 +190,15 @@ void ConVarManager::OnPluginUnloaded(IPlugin *plugin) void ConVarManager::OnHandleDestroy(HandleType_t type, void *object) { +#if PLAPI_VERSION < 12 + /* Lovely workaround for our workaround! */ + if (m_IgnoreHandle) + { + m_IgnoreHandle = false; + return; + } +#endif + ConVarInfo *info; ConVar *pConVar = static_cast(object); @@ -235,6 +294,9 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, pInfo->sourceMod = false; pInfo->pChangeForward = NULL; pInfo->origCallback = pConVar->GetCallback(); + #if PLAPI_VERSION < 12 + pInfo->name = sm_strdup(pConVar->GetName()); + #endif /* Insert struct into caches */ m_ConVars.push_back(pInfo); @@ -310,6 +372,9 @@ Handle_t ConVarManager::FindConVar(const char *name) pInfo->sourceMod = false; pInfo->pChangeForward = NULL; pInfo->origCallback = pConVar->GetCallback(); +#if PLAPI_VERSION < 12 + pInfo->name = sm_strdup(pConVar->GetName()); +#endif /* Insert struct into our caches */ m_ConVars.push_back(pInfo); diff --git a/core/ConVarManager.h b/core/ConVarManager.h index 191ceb48..f033d8d5 100644 --- a/core/ConVarManager.h +++ b/core/ConVarManager.h @@ -35,6 +35,9 @@ struct ConVarInfo bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */ IChangeableForward *pChangeForward; /**< Forward associated with convar */ FnChangeCallback origCallback; /**< The original callback function */ +#if PLAPI_VERSION < 12 + const char *name; /**< Name of convar */ +#endif }; /** @@ -109,6 +112,18 @@ public: */ QueryCvarCookie_t QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl); + +#if PLAPI_VERSION >= 12 + /** + * Called when Metamod:Source is about to remove convar + */ + void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand); +#else + /** + * Called when Metamod:Source has unloaded a plugin + */ + void OnMetamodPluginUnloaded(PluginId id); +#endif private: /** * Adds a convar to a plugin's list. @@ -132,6 +147,9 @@ private: Trie *m_ConVarCache; IServerPluginCallbacks *m_VSPIface; bool m_CanQueryConVars; +#if PLAPI_VERSION < 12 + bool m_IgnoreHandle; +#endif }; extern ConVarManager g_ConVarManager; diff --git a/core/sourcemm_api.cpp b/core/sourcemm_api.cpp index e1ded5e3..97912282 100644 --- a/core/sourcemm_api.cpp +++ b/core/sourcemm_api.cpp @@ -17,6 +17,7 @@ #include "sm_version.h" #include "sourcemod.h" #include "Logger.h" +#include "ConVarManager.h" SourceMod_Core g_SourceMod_Core; IVEngineServer *engine = NULL; @@ -148,3 +149,15 @@ void SourceMod_Core::OnVSPListening(IServerPluginCallbacks *iface) pBase = pBase->m_pGlobalClassNext; } } + +#if PLAPI_VERSION >= 12 +void SourceMod_Core::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand) +{ + g_ConVarManager.OnUnlinkConCommandBase(id, pCommand); +} +#else +void SourceMod_Core::OnPluginUnload(PluginId id) +{ + g_ConVarManager.OnMetamodPluginUnloaded(id); +} +#endif diff --git a/core/sourcemm_api.h b/core/sourcemm_api.h index 2428ff62..80a35bfb 100644 --- a/core/sourcemm_api.h +++ b/core/sourcemm_api.h @@ -49,6 +49,11 @@ public: const char *GetLogTag(); public: void OnVSPListening(IServerPluginCallbacks *iface); +#if PLAPI_VERSION >= 12 + void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand); +#else + void OnPluginUnload(PluginId id); +#endif }; extern SourceMod_Core g_SourceMod_Core;