1.1 --- a/core/ConVarManager.cpp Mon Oct 15 22:15:22 2007 +0000
1.2 +++ b/core/ConVarManager.cpp Tue Oct 16 01:17:08 2007 +0000
1.3 @@ -37,6 +37,7 @@
1.4 #include "sm_srvcmds.h"
1.5 #include "sm_stringutil.h"
1.6 #include <sh_vector.h>
1.7 +#include <sm_trie_tpl.h>
1.8
1.9 ConVarManager g_ConVarManager;
1.10
1.11 @@ -45,31 +46,14 @@
1.12
1.13 const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
1.14 typedef List<const ConVar *> ConVarList;
1.15 +KTrie<ConVarInfo *> convar_cache;
1.16
1.17 ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
1.18 {
1.19 -#if PLAPI_VERSION < 12
1.20 - m_IgnoreHandle = false;
1.21 -#endif
1.22 -
1.23 - /* Create a convar lookup trie */
1.24 - m_ConVarCache = sm_trie_create();
1.25 }
1.26
1.27 ConVarManager::~ConVarManager()
1.28 {
1.29 - List<ConVarInfo *>::iterator iter;
1.30 -
1.31 - /* Destroy our convar lookup trie */
1.32 - sm_trie_destroy(m_ConVarCache);
1.33 -
1.34 - /* Destroy all the ConVarInfo structures */
1.35 - for (iter = m_ConVars.begin(); iter != m_ConVars.end(); iter++)
1.36 - {
1.37 - delete (*iter);
1.38 - }
1.39 -
1.40 - m_ConVars.clear();
1.41 }
1.42
1.43 void ConVarManager::OnSourceModAllInitialized()
1.44 @@ -101,6 +85,48 @@
1.45
1.46 void ConVarManager::OnSourceModShutdown()
1.47 {
1.48 + List<ConVarInfo *>::iterator iter = m_ConVars.begin();
1.49 + HandleSecurity sec(NULL, g_pCoreIdent);
1.50 +
1.51 + /* Iterate list of ConVarInfo structures, remove every one of them */
1.52 + while (iter != m_ConVars.end())
1.53 + {
1.54 + ConVarInfo *pInfo = (*iter);
1.55 +
1.56 + iter = m_ConVars.erase(iter);
1.57 +
1.58 + g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.59 + if (pInfo->pChangeForward != NULL)
1.60 + {
1.61 + g_Forwards.ReleaseForward(pInfo->pChangeForward);
1.62 + }
1.63 + if (pInfo->sourceMod)
1.64 + {
1.65 + /* If we created it, we won't be tracking it, therefore it is
1.66 + * safe to remove everything in one go.
1.67 + */
1.68 + META_UNREGCVAR(pInfo->pVar);
1.69 + delete [] pInfo->pVar->GetName();
1.70 + delete [] pInfo->pVar->GetHelpText();
1.71 + delete [] pInfo->pVar->GetDefault();
1.72 + delete pInfo->pVar;
1.73 + }
1.74 + else
1.75 + {
1.76 + /* If we didn't create it, we might be tracking it. Also,
1.77 + * it could be unreadable.
1.78 + */
1.79 + UntrackConCommandBase(pInfo->pVar, this);
1.80 + }
1.81 +
1.82 + /* It's not safe to read the name here, so we simply delete the
1.83 + * the info struct and clear the lookup cache at the end.
1.84 + */
1.85 + delete pInfo;
1.86 + }
1.87 + convar_cache.clear();
1.88 +
1.89 + /* Unhook things */
1.90 if (m_bIsDLLQueryHooked)
1.91 {
1.92 SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.93 @@ -112,21 +138,6 @@
1.94 m_bIsVSPQueryHooked = false;
1.95 }
1.96
1.97 - IChangeableForward *fwd;
1.98 - List<ConVarInfo *>::iterator i;
1.99 -
1.100 - /* Iterate list of ConVarInfo structures */
1.101 - for (i = m_ConVars.begin(); i != m_ConVars.end(); i++)
1.102 - {
1.103 - fwd = (*i)->pChangeForward;
1.104 -
1.105 - /* Free any convar-change forwards that still exist */
1.106 - if (fwd)
1.107 - {
1.108 - g_Forwards.ReleaseForward(fwd);
1.109 - }
1.110 - }
1.111 -
1.112 /* Remove the 'convars' option from the 'sm' console command */
1.113 g_RootMenu.RemoveRootConsoleCommand("cvars", this);
1.114
1.115 @@ -165,54 +176,55 @@
1.116 m_bIsVSPQueryHooked = true;
1.117 }
1.118
1.119 -#if PLAPI_VERSION >= 12
1.120 -void ConVarManager::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand)
1.121 +bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
1.122 {
1.123 - /* Only check convars that have not been created by SourceMod's core */
1.124 - if (id != g_PLID && !pCommand->IsCommand())
1.125 + ConVarInfo **pLookup = convar_cache.retrieve(name);
1.126 + if (pLookup != NULL)
1.127 {
1.128 - ConVarInfo *pInfo;
1.129 - const char *cvarName = pCommand->GetName();
1.130 - HandleSecurity sec(NULL, g_pCoreIdent);
1.131 - bool handleExists = sm_trie_retrieve(m_ConVarCache, cvarName, reinterpret_cast<void **>(&pInfo));
1.132 -
1.133 - if (handleExists)
1.134 - {
1.135 - g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.136 - sm_trie_delete(m_ConVarCache, cvarName);
1.137 - m_ConVars.remove(pInfo);
1.138 - }
1.139 + *pVar = *pLookup;
1.140 + return true;
1.141 + }
1.142 + else
1.143 + {
1.144 + return false;
1.145 }
1.146 }
1.147
1.148 -#else
1.149 +void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
1.150 +{
1.151 + /* Only check convars that have not been created by SourceMod's core */
1.152 + ConVarInfo *pInfo;
1.153 + if (!convar_cache_lookup(name, &pInfo))
1.154 + {
1.155 + return;
1.156 + }
1.157
1.158 -/* I truly detest this code */
1.159 -void ConVarManager::OnMetamodPluginUnloaded(PluginId id)
1.160 -{
1.161 - ConVarInfo *pInfo;
1.162 - const char *cvarName;
1.163 HandleSecurity sec(NULL, g_pCoreIdent);
1.164
1.165 - List<ConVarInfo *>::iterator i;
1.166 - for (i = m_ConVars.begin(); i != m_ConVars.end(); i++)
1.167 + /* Remove it from our cache */
1.168 + m_ConVars.remove(pInfo);
1.169 + convar_cache.remove(name);
1.170 +
1.171 + /* Now make sure no plugins are referring to this pointer */
1.172 + IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
1.173 + while (pl_iter->MorePlugins())
1.174 {
1.175 - pInfo = (*i);
1.176 - cvarName = pInfo->name;
1.177 + IPlugin *pl = pl_iter->GetPlugin();
1.178
1.179 - if (cvarName && !icvar->FindVar(cvarName))
1.180 + ConVarList *pConVarList;
1.181 + if (pl->GetProperty("ConVarList", (void **)&pConVarList, true)
1.182 + && pConVarList != NULL)
1.183 {
1.184 - m_IgnoreHandle = true;
1.185 - g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.186 -
1.187 - sm_trie_delete(m_ConVarCache, cvarName);
1.188 - m_ConVars.erase(i);
1.189 + pConVarList->remove(pInfo->pVar);
1.190 + }
1.191
1.192 - delete [] cvarName;
1.193 - }
1.194 + pl_iter->NextPlugin();
1.195 }
1.196 +
1.197 + /* Free resources */
1.198 + g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.199 + delete pInfo;
1.200 }
1.201 -#endif
1.202
1.203 void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
1.204 {
1.205 @@ -227,33 +239,6 @@
1.206
1.207 void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
1.208 {
1.209 -#if PLAPI_VERSION < 12
1.210 - /* Lovely workaround for our workaround! */
1.211 - if (m_IgnoreHandle)
1.212 - {
1.213 - m_IgnoreHandle = false;
1.214 - return;
1.215 - }
1.216 -#endif
1.217 -
1.218 - ConVarInfo *info;
1.219 - ConVar *pConVar = static_cast<ConVar *>(object);
1.220 -
1.221 - /* Find convar in lookup trie */
1.222 - sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), reinterpret_cast<void **>(&info));
1.223 -
1.224 - /* If convar was created by SourceMod plugin... */
1.225 - if (info->sourceMod)
1.226 - {
1.227 - /* Then unlink it from SourceMM */
1.228 - g_SMAPI->UnregisterConCommandBase(g_PLAPI, pConVar);
1.229 -
1.230 - /* Delete string allocations */
1.231 - delete [] pConVar->GetName();
1.232 - delete [] pConVar->GetDefault();
1.233 - delete [] pConVar->GetHelpText();
1.234 - delete pConVar;
1.235 - }
1.236 }
1.237
1.238 void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
1.239 @@ -320,28 +305,33 @@
1.240 AddConVarToPluginList(pContext, pConVar);
1.241
1.242 /* First find out if we already have a handle to it */
1.243 - if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
1.244 + if (convar_cache_lookup(name, &pInfo))
1.245 {
1.246 return pInfo->handle;
1.247 }
1.248 else
1.249 {
1.250 - /* If we don't, then create a new handle from the convar */
1.251 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
1.252 -
1.253 /* Create and initialize ConVarInfo structure */
1.254 pInfo = new ConVarInfo();
1.255 - pInfo->handle = hndl;
1.256 pInfo->sourceMod = false;
1.257 pInfo->pChangeForward = NULL;
1.258 pInfo->origCallback = pConVar->GetCallback();
1.259 - #if PLAPI_VERSION < 12
1.260 - pInfo->name = sm_strdup(pConVar->GetName());
1.261 - #endif
1.262 + pInfo->pVar = pConVar;
1.263 +
1.264 + /* If we don't, then create a new handle from the convar */
1.265 + hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.266 + if (hndl == BAD_HANDLE)
1.267 + {
1.268 + delete pInfo;
1.269 + return BAD_HANDLE;
1.270 + }
1.271 +
1.272 + pInfo->handle = hndl;
1.273
1.274 /* Insert struct into caches */
1.275 m_ConVars.push_back(pInfo);
1.276 - sm_trie_insert(m_ConVarCache, name, pInfo);
1.277 + convar_cache.insert(name, pInfo);
1.278 + TrackConCommandBase(pConVar, this);
1.279
1.280 return hndl;
1.281 }
1.282 @@ -360,28 +350,33 @@
1.283 pBase = const_cast<ConCommandBase *>(pBase->GetNext());
1.284 }
1.285
1.286 - /* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */
1.287 - pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max);
1.288 -
1.289 - /* Add convar to plugin's list */
1.290 - AddConVarToPluginList(pContext, pConVar);
1.291 -
1.292 - /* Create a handle from the new convar */
1.293 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
1.294 -
1.295 /* Create and initialize ConVarInfo structure */
1.296 pInfo = new ConVarInfo();
1.297 pInfo->handle = hndl;
1.298 pInfo->sourceMod = true;
1.299 pInfo->pChangeForward = NULL;
1.300 pInfo->origCallback = NULL;
1.301 -#if PLAPI_VERSION < 12
1.302 - pInfo->name = NULL;
1.303 -#endif
1.304 +
1.305 + /* Create a handle from the new convar */
1.306 + hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.307 + if (hndl == BAD_HANDLE)
1.308 + {
1.309 + delete pInfo;
1.310 + return BAD_HANDLE;
1.311 + }
1.312 +
1.313 + pInfo->handle = hndl;
1.314 +
1.315 + /* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */
1.316 + pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max);
1.317 + pInfo->pVar = pConVar;
1.318 +
1.319 + /* Add convar to plugin's list */
1.320 + AddConVarToPluginList(pContext, pConVar);
1.321
1.322 /* Insert struct into caches */
1.323 m_ConVars.push_back(pInfo);
1.324 - sm_trie_insert(m_ConVarCache, name, pInfo);
1.325 + convar_cache.insert(name, pInfo);
1.326
1.327 return hndl;
1.328 }
1.329 @@ -402,27 +397,32 @@
1.330 }
1.331
1.332 /* At this point, the convar exists. So, find out if we already have a handle */
1.333 - if (sm_trie_retrieve(m_ConVarCache, name, (void **)&pInfo))
1.334 + if (convar_cache_lookup(name, &pInfo))
1.335 {
1.336 return pInfo->handle;
1.337 }
1.338
1.339 - /* If we don't have a handle, then create a new one */
1.340 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pConVar, NULL, g_pCoreIdent, NULL);
1.341 -
1.342 /* Create and initialize ConVarInfo structure */
1.343 pInfo = new ConVarInfo();
1.344 - pInfo->handle = hndl;
1.345 pInfo->sourceMod = false;
1.346 pInfo->pChangeForward = NULL;
1.347 pInfo->origCallback = pConVar->GetCallback();
1.348 -#if PLAPI_VERSION < 12
1.349 - pInfo->name = sm_strdup(pConVar->GetName());
1.350 -#endif
1.351 + pInfo->pVar = pConVar;
1.352 +
1.353 + /* If we don't have a handle, then create a new one */
1.354 + hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.355 + if (hndl == BAD_HANDLE)
1.356 + {
1.357 + delete pInfo;
1.358 + return BAD_HANDLE;
1.359 + }
1.360 +
1.361 + pInfo->handle = hndl;
1.362
1.363 /* Insert struct into our caches */
1.364 m_ConVars.push_back(pInfo);
1.365 - sm_trie_insert(m_ConVarCache, name, pInfo);
1.366 + convar_cache.insert(name, pInfo);
1.367 + TrackConCommandBase(pConVar, this);
1.368
1.369 return hndl;
1.370 }
1.371 @@ -433,7 +433,7 @@
1.372 IChangeableForward *pForward;
1.373
1.374 /* Find the convar in the lookup trie */
1.375 - if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo))
1.376 + if (convar_cache_lookup(pConVar->GetName(), &pInfo))
1.377 {
1.378 /* Get the forward */
1.379 pForward = pInfo->pChangeForward;
1.380 @@ -460,7 +460,7 @@
1.381 IPluginContext *pContext = pFunction->GetParentContext();
1.382
1.383 /* Find the convar in the lookup trie */
1.384 - if (sm_trie_retrieve(m_ConVarCache, pConVar->GetName(), (void **)&pInfo))
1.385 + if (convar_cache_lookup(pConVar->GetName(), &pInfo))
1.386 {
1.387 /* Get the forward */
1.388 pForward = pInfo->pChangeForward;
1.389 @@ -569,11 +569,13 @@
1.390 return;
1.391 }
1.392
1.393 - Trie *pCache = g_ConVarManager.GetConVarCache();
1.394 ConVarInfo *pInfo;
1.395
1.396 /* Find the convar in the lookup trie */
1.397 - sm_trie_retrieve(pCache, pConVar->GetName(), (void **)&pInfo);
1.398 + if (!convar_cache_lookup(pConVar->GetName(), &pInfo))
1.399 + {
1.400 + return;
1.401 + }
1.402
1.403 FnChangeCallback_t origCallback = pInfo->origCallback;
1.404 IChangeableForward *pForward = pInfo->pChangeForward;
1.405 @@ -642,6 +644,23 @@
1.406 }
1.407 }
1.408
1.409 +HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
1.410 +{
1.411 + ConVarInfo *pInfo;
1.412 + HandleError error;
1.413 +
1.414 + if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
1.415 + {
1.416 + return error;
1.417 + }
1.418 +
1.419 + if (pVar)
1.420 + {
1.421 + *pVar = pInfo->pVar;
1.422 + }
1.423 +
1.424 + return error;
1.425 +}
1.426
1.427 static int s_YamagramState = 0;
1.428
2.1 --- a/core/ConVarManager.h Mon Oct 15 22:15:22 2007 +0000
2.2 +++ b/core/ConVarManager.h Tue Oct 16 01:17:08 2007 +0000
2.3 @@ -34,13 +34,13 @@
2.4
2.5 #include "sm_globals.h"
2.6 #include "sourcemm_api.h"
2.7 -#include "sm_trie.h"
2.8 #include <sh_list.h>
2.9 #include <IPluginSys.h>
2.10 #include <IForwardSys.h>
2.11 #include <IHandleSys.h>
2.12 #include <IRootConsoleMenu.h>
2.13 #include <compat_wrappers.h>
2.14 +#include "concmd_cleaner.h"
2.15
2.16 using namespace SourceHook;
2.17
2.18 @@ -49,13 +49,11 @@
2.19 */
2.20 struct ConVarInfo
2.21 {
2.22 - Handle_t handle; /**< Handle to convar */
2.23 + Handle_t handle; /**< Handle to self */
2.24 bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */
2.25 IChangeableForward *pChangeForward; /**< Forward associated with convar */
2.26 FnChangeCallback_t origCallback; /**< The original callback function */
2.27 -#if PLAPI_VERSION < 12
2.28 - const char *name; /**< Name of convar */
2.29 -#endif
2.30 + ConVar *pVar; /**< The actual convar */
2.31 };
2.32
2.33 /**
2.34 @@ -72,7 +70,8 @@
2.35 public SMGlobalClass,
2.36 public IHandleTypeDispatch,
2.37 public IPluginsListener,
2.38 - public IRootConsoleCommand
2.39 + public IRootConsoleCommand,
2.40 + public IConCommandTracker
2.41 {
2.42 public:
2.43 ConVarManager();
2.44 @@ -87,22 +86,8 @@
2.45 void OnPluginUnloaded(IPlugin *plugin);
2.46 public: //IRootConsoleCommand
2.47 void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
2.48 -public:
2.49 - /**
2.50 - * Get the 'ConVar' handle type ID.
2.51 - */
2.52 - inline HandleType_t GetHandleType()
2.53 - {
2.54 - return m_ConVarType;
2.55 - }
2.56 -
2.57 - /**
2.58 - * Get the convar lookup trie.
2.59 - */
2.60 - inline Trie *GetConVarCache()
2.61 - {
2.62 - return m_ConVarCache;
2.63 - }
2.64 +public: //IConCommandTracker
2.65 + void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe);
2.66 public:
2.67 /**
2.68 * Create a convar and return a handle to it.
2.69 @@ -133,17 +118,8 @@
2.70
2.71 bool IsQueryingSupported();
2.72
2.73 -#if PLAPI_VERSION >= 12
2.74 - /**
2.75 - * Called when Metamod:Source is about to remove convar
2.76 - */
2.77 - void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand);
2.78 -#else
2.79 - /**
2.80 - * Called when Metamod:Source has unloaded a plugin
2.81 - */
2.82 - void OnMetamodPluginUnloaded(PluginId id);
2.83 -#endif
2.84 + HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar);
2.85 +
2.86 private:
2.87 /**
2.88 * Adds a convar to a plugin's list.
2.89 @@ -168,12 +144,8 @@
2.90 HandleType_t m_ConVarType;
2.91 List<ConVarInfo *> m_ConVars;
2.92 List<ConVarQuery> m_ConVarQueries;
2.93 - Trie *m_ConVarCache;
2.94 bool m_bIsDLLQueryHooked;
2.95 bool m_bIsVSPQueryHooked;
2.96 -#if PLAPI_VERSION < 12
2.97 - bool m_IgnoreHandle;
2.98 -#endif
2.99 };
2.100
2.101 extern ConVarManager g_ConVarManager;
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/core/concmd_cleaner.cpp Tue Oct 16 01:17:08 2007 +0000
3.3 @@ -0,0 +1,175 @@
3.4 +/**
3.5 + * vim: set ts=4 :
3.6 + * =============================================================================
3.7 + * SourceMod
3.8 + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
3.9 + * =============================================================================
3.10 + *
3.11 + * This program is free software; you can redistribute it and/or modify it under
3.12 + * the terms of the GNU General Public License, version 3.0, as published by the
3.13 + * Free Software Foundation.
3.14 + *
3.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
3.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3.18 + * details.
3.19 + *
3.20 + * You should have received a copy of the GNU General Public License along with
3.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
3.22 + *
3.23 + * As a special exception, AlliedModders LLC gives you permission to link the
3.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
3.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
3.26 + * by the Valve Corporation. You must obey the GNU General Public License in
3.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
3.28 + * this exception to all derivative works. AlliedModders LLC defines further
3.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
3.30 + * or <http://www.sourcemod.net/license.php>.
3.31 + *
3.32 + * Version: $Id$
3.33 + */
3.34 +
3.35 +#include "sm_globals.h"
3.36 +#include <sh_list.h>
3.37 +#include <convar.h>
3.38 +#include "concmd_cleaner.h"
3.39 +#include "sm_stringutil.h"
3.40 +#include "sourcemm_api.h"
3.41 +
3.42 +#if defined ORANGEBOX_BUILD
3.43 +SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
3.44 +#endif
3.45 +
3.46 +using namespace SourceHook;
3.47 +
3.48 +struct ConCommandInfo
3.49 +{
3.50 + ConCommandBase *pBase;
3.51 + IConCommandTracker *cls;
3.52 + char name[64];
3.53 +};
3.54 +
3.55 +List<ConCommandInfo *> tracked_bases;
3.56 +
3.57 +ConCommandBase *FindConCommandBase(const char *name);
3.58 +
3.59 +class ConCommandCleaner : public SMGlobalClass
3.60 +{
3.61 +public:
3.62 +#if defined ORANGEBOX_BUILD
3.63 + void OnSourceModAllInitialized()
3.64 + {
3.65 + SH_ADD_HOOK(ICvar, UnregisterConCommand, SH_NOATTRIB, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
3.66 + }
3.67 +
3.68 + void OnSourceModShutdown()
3.69 + {
3.70 + SH_REMOVE_HOOK(ICvar, UnregisterConCommand, SH_NOATTRIB, SH_MEMBER(this, &ConCommandCleaner::UnlinkConCommandBase), false);
3.71 + }
3.72 +#endif
3.73 +
3.74 + void UnlinkConCommandBase(ConCommandBase *pBase)
3.75 + {
3.76 + ConCommandInfo *pInfo;
3.77 + List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
3.78 +
3.79 + if (pBase)
3.80 + {
3.81 + while (iter != tracked_bases.end())
3.82 + {
3.83 + if ((*iter)->pBase == pBase)
3.84 + {
3.85 + pInfo = (*iter);
3.86 + iter = tracked_bases.erase(iter);
3.87 + pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
3.88 + delete pInfo;
3.89 + }
3.90 + else
3.91 + {
3.92 + iter++;
3.93 + }
3.94 + }
3.95 + }
3.96 + else
3.97 + {
3.98 + while (iter != tracked_bases.end())
3.99 + {
3.100 + /* This is just god-awful! */
3.101 + if (FindConCommandBase((*iter)->name) != (*iter)->pBase)
3.102 + {
3.103 + pInfo = (*iter);
3.104 + iter = tracked_bases.erase(iter);
3.105 + pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
3.106 + delete pInfo;
3.107 + }
3.108 + else
3.109 + {
3.110 + iter++;
3.111 + }
3.112 + }
3.113 + }
3.114 + }
3.115 +
3.116 + void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
3.117 + {
3.118 + ConCommandInfo *info = new ConCommandInfo;
3.119 +
3.120 + info->pBase = pBase;
3.121 + info->cls = cls;
3.122 + strncopy(info->name, pBase->GetName(), sizeof(info->name));
3.123 +
3.124 + tracked_bases.push_back(info);
3.125 + }
3.126 +
3.127 + void RemoveTarget(ConCommandBase *pBase, IConCommandTracker *cls)
3.128 + {
3.129 + List<ConCommandInfo *>::iterator iter;
3.130 + ConCommandInfo *pInfo;
3.131 +
3.132 + iter = tracked_bases.begin();
3.133 + while (iter != tracked_bases.end())
3.134 + {
3.135 + pInfo = (*iter);
3.136 + if (pInfo->pBase == pBase && pInfo->cls == cls)
3.137 + {
3.138 + delete pInfo;
3.139 + iter = tracked_bases.erase(iter);
3.140 + }
3.141 + else
3.142 + {
3.143 + iter++;
3.144 + }
3.145 + }
3.146 + }
3.147 +} s_ConCmdTracker;
3.148 +
3.149 +ConCommandBase *FindConCommandBase(const char *name)
3.150 +{
3.151 + const ConCommandBase *pBase = icvar->GetCommands();
3.152 +
3.153 + while (pBase != NULL)
3.154 + {
3.155 + if (strcmp(pBase->GetName(), name) == 0)
3.156 + {
3.157 + return const_cast<ConCommandBase *>(pBase);
3.158 + }
3.159 + pBase = pBase->GetNext();
3.160 + }
3.161 +
3.162 + return NULL;
3.163 +}
3.164 +
3.165 +void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
3.166 +{
3.167 + s_ConCmdTracker.AddTarget(pBase, me);
3.168 +}
3.169 +
3.170 +void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
3.171 +{
3.172 + s_ConCmdTracker.RemoveTarget(pBase, me);
3.173 +}
3.174 +
3.175 +void Global_OnUnlinkConCommandBase(ConCommandBase *pBase)
3.176 +{
3.177 + s_ConCmdTracker.UnlinkConCommandBase(pBase);
3.178 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/core/concmd_cleaner.h Tue Oct 16 01:17:08 2007 +0000
4.3 @@ -0,0 +1,41 @@
4.4 +/**
4.5 + * vim: set ts=4 :
4.6 + * =============================================================================
4.7 + * SourceMod
4.8 + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
4.9 + * =============================================================================
4.10 + *
4.11 + * This program is free software; you can redistribute it and/or modify it under
4.12 + * the terms of the GNU General Public License, version 3.0, as published by the
4.13 + * Free Software Foundation.
4.14 + *
4.15 + * This program is distributed in the hope that it will be useful, but WITHOUT
4.16 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
4.18 + * details.
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License along with
4.21 + * this program. If not, see <http://www.gnu.org/licenses/>.
4.22 + *
4.23 + * As a special exception, AlliedModders LLC gives you permission to link the
4.24 + * code of this program (as well as its derivative works) to "Half-Life 2," the
4.25 + * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
4.26 + * by the Valve Corporation. You must obey the GNU General Public License in
4.27 + * all respects for all other code used. Additionally, AlliedModders LLC grants
4.28 + * this exception to all derivative works. AlliedModders LLC defines further
4.29 + * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
4.30 + * or <http://www.sourcemod.net/license.php>.
4.31 + *
4.32 + * Version: $Id$
4.33 + */
4.34 +
4.35 +class IConCommandTracker
4.36 +{
4.37 +public:
4.38 + virtual void OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe) = 0;
4.39 +};
4.40 +
4.41 +void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
4.42 +void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me);
4.43 +void Global_OnUnlinkConCommandBase(ConCommandBase *pBase);
4.44 +
5.1 --- a/core/msvc8/sourcemod_mm.vcproj Mon Oct 15 22:15:22 2007 +0000
5.2 +++ b/core/msvc8/sourcemod_mm.vcproj Tue Oct 16 01:17:08 2007 +0000
5.3 @@ -610,6 +610,10 @@
5.4 >
5.5 </File>
5.6 <File
5.7 + RelativePath="..\concmd_cleaner.cpp"
5.8 + >
5.9 + </File>
5.10 + <File
5.11 RelativePath="..\ConCmdManager.cpp"
5.12 >
5.13 </File>
5.14 @@ -804,6 +808,10 @@
5.15 >
5.16 </File>
5.17 <File
5.18 + RelativePath="..\concmd_cleaner.h"
5.19 + >
5.20 + </File>
5.21 + <File
5.22 RelativePath="..\ConCmdManager.h"
5.23 >
5.24 </File>
6.1 --- a/core/smn_console.cpp Mon Oct 15 22:15:22 2007 +0000
6.2 +++ b/core/smn_console.cpp Tue Oct 16 01:17:08 2007 +0000
6.3 @@ -110,7 +110,9 @@
6.4 if (IsFlagSet(pConVar, FCVAR_PROTECTED))
6.5 {
6.6 pEvent->SetString("cvarvalue", "***PROTECTED***");
6.7 - } else {
6.8 + }
6.9 + else
6.10 + {
6.11 pEvent->SetString("cvarvalue", pConVar->GetString());
6.12 }
6.13
6.14 @@ -141,7 +143,7 @@
6.15
6.16 if (hndl == BAD_HANDLE)
6.17 {
6.18 - return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same name already exists.", name);
6.19 + return pContext->ThrowNativeError("Convar \"%s\" was not created. A console command with the same might already exist.", name);
6.20 }
6.21
6.22 return hndl;
6.23 @@ -162,7 +164,7 @@
6.24 HandleError err;
6.25 ConVar *pConVar;
6.26
6.27 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.28 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.29 != HandleError_None)
6.30 {
6.31 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.32 @@ -186,7 +188,7 @@
6.33 HandleError err;
6.34 ConVar *pConVar;
6.35
6.36 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.37 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.38 != HandleError_None)
6.39 {
6.40 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.41 @@ -210,7 +212,7 @@
6.42 HandleError err;
6.43 ConVar *pConVar;
6.44
6.45 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.46 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.47 != HandleError_None)
6.48 {
6.49 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.50 @@ -225,7 +227,7 @@
6.51 HandleError err;
6.52 ConVar *pConVar;
6.53
6.54 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.55 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.56 != HandleError_None)
6.57 {
6.58 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.59 @@ -241,7 +243,7 @@
6.60 HandleError err;
6.61 ConVar *pConVar;
6.62
6.63 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.64 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.65 != HandleError_None)
6.66 {
6.67 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.68 @@ -270,7 +272,7 @@
6.69 HandleError err;
6.70 ConVar *pConVar;
6.71
6.72 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.73 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.74 != HandleError_None)
6.75 {
6.76 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.77 @@ -287,7 +289,7 @@
6.78 HandleError err;
6.79 ConVar *pConVar;
6.80
6.81 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.82 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.83 != HandleError_None)
6.84 {
6.85 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.86 @@ -317,7 +319,7 @@
6.87 HandleError err;
6.88 ConVar *pConVar;
6.89
6.90 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.91 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.92 != HandleError_None)
6.93 {
6.94 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.95 @@ -334,7 +336,7 @@
6.96 HandleError err;
6.97 ConVar *pConVar;
6.98
6.99 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.100 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.101 != HandleError_None)
6.102 {
6.103 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.104 @@ -366,7 +368,7 @@
6.105 HandleError err;
6.106 ConVar *pConVar;
6.107
6.108 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.109 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.110 != HandleError_None)
6.111 {
6.112 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.113 @@ -395,7 +397,7 @@
6.114 HandleError err;
6.115 ConVar *pConVar;
6.116
6.117 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.118 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.119 != HandleError_None)
6.120 {
6.121 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.122 @@ -410,7 +412,7 @@
6.123 HandleError err;
6.124 ConVar *pConVar;
6.125
6.126 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.127 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.128 != HandleError_None)
6.129 {
6.130 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.131 @@ -427,7 +429,7 @@
6.132 HandleError err;
6.133 ConVar *pConVar;
6.134
6.135 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.136 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.137 != HandleError_None)
6.138 {
6.139 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.140 @@ -461,7 +463,7 @@
6.141 HandleError err;
6.142 ConVar *pConVar;
6.143
6.144 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.145 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.146 != HandleError_None)
6.147 {
6.148 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
6.149 @@ -488,7 +490,7 @@
6.150 HandleError err;
6.151 ConVar *pConVar;
6.152
6.153 - if ((err=g_HandleSys.ReadHandle(hndl, g_ConVarManager.GetHandleType(), NULL, (void **)&pConVar))
6.154 + if ((err=g_ConVarManager.ReadConVarHandle(hndl, &pConVar))
6.155 != HandleError_None)
6.156 {
6.157 return pContext->ThrowNativeError("Invalid convar handle %x (error %d)", hndl, err);
7.1 --- a/core/sourcemm_api.cpp Mon Oct 15 22:15:22 2007 +0000
7.2 +++ b/core/sourcemm_api.cpp Tue Oct 16 01:17:08 2007 +0000
7.3 @@ -33,7 +33,7 @@
7.4 #include "sourcemm_api.h"
7.5 #include "sm_version.h"
7.6 #include "Logger.h"
7.7 -#include "ConVarManager.h"
7.8 +#include "concmd_cleaner.h"
7.9
7.10 SourceMod_Core g_SourceMod_Core;
7.11 IVEngineServer *engine = NULL;
7.12 @@ -203,14 +203,18 @@
7.13 }
7.14 }
7.15
7.16 -#if PLAPI_VERSION >= 12
7.17 +#if defined METAMOD_PLAPI_VERSION
7.18 +
7.19 void SourceMod_Core::OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand)
7.20 {
7.21 - g_ConVarManager.OnUnlinkConCommandBase(id, pCommand);
7.22 + Global_OnUnlinkConCommandBase(pCommand);
7.23 }
7.24 +
7.25 #else
7.26 +
7.27 void SourceMod_Core::OnPluginUnload(PluginId id)
7.28 {
7.29 - g_ConVarManager.OnMetamodPluginUnloaded(id);
7.30 + Global_OnUnlinkConCommandBase(NULL);
7.31 }
7.32 +
7.33 #endif
8.1 --- a/core/sourcemm_api.h Mon Oct 15 22:15:22 2007 +0000
8.2 +++ b/core/sourcemm_api.h Tue Oct 16 01:17:08 2007 +0000
8.3 @@ -74,7 +74,7 @@
8.4 const char *GetLogTag();
8.5 public:
8.6 void OnVSPListening(IServerPluginCallbacks *iface);
8.7 -#if PLAPI_VERSION >= 12
8.8 +#if defined METAMOD_PLAPI_VERSION
8.9 void OnUnlinkConCommandBase(PluginId id, ConCommandBase *pCommand);
8.10 #else
8.11 void OnPluginUnload(PluginId id);