1.1 --- a/core/ConVarManager.cpp Fri Jul 11 06:51:21 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,707 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
1.9 - * =============================================================================
1.10 - *
1.11 - * This program is free software; you can redistribute it and/or modify it under
1.12 - * the terms of the GNU General Public License, version 3.0, as published by the
1.13 - * Free Software Foundation.
1.14 - *
1.15 - * This program is distributed in the hope that it will be useful, but WITHOUT
1.16 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.18 - * details.
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License along with
1.21 - * this program. If not, see <http://www.gnu.org/licenses/>.
1.22 - *
1.23 - * As a special exception, AlliedModders LLC gives you permission to link the
1.24 - * code of this program (as well as its derivative works) to "Half-Life 2," the
1.25 - * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
1.26 - * by the Valve Corporation. You must obey the GNU General Public License in
1.27 - * all respects for all other code used. Additionally, AlliedModders LLC grants
1.28 - * this exception to all derivative works. AlliedModders LLC defines further
1.29 - * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
1.30 - * or <http://www.sourcemod.net/license.php>.
1.31 - *
1.32 - * Version: $Id$
1.33 - */
1.34 -
1.35 -#include "ConVarManager.h"
1.36 -#include "HalfLife2.h"
1.37 -#include "PluginSys.h"
1.38 -#include "ForwardSys.h"
1.39 -#include "HandleSys.h"
1.40 -#include "sm_srvcmds.h"
1.41 -#include "sm_stringutil.h"
1.42 -#include <sh_vector.h>
1.43 -#include <sm_trie_tpl.h>
1.44 -
1.45 -ConVarManager g_ConVarManager;
1.46 -
1.47 -#if !defined ORANGEBOX_BUILD
1.48 -#define CallGlobalChangeCallbacks CallGlobalChangeCallback
1.49 -#endif
1.50 -
1.51 -#if defined ORANGEBOX_BUILD
1.52 -SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
1.53 -#else
1.54 -SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
1.55 -#endif
1.56 -
1.57 -SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
1.58 -SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
1.59 -
1.60 -const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
1.61 -typedef List<const ConVar *> ConVarList;
1.62 -KTrie<ConVarInfo *> convar_cache;
1.63 -
1.64 -ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
1.65 -{
1.66 -}
1.67 -
1.68 -ConVarManager::~ConVarManager()
1.69 -{
1.70 -}
1.71 -
1.72 -void ConVarManager::OnSourceModStartup(bool late)
1.73 -{
1.74 - HandleAccess sec;
1.75 -
1.76 - /* Set up access rights for the 'ConVar' handle type */
1.77 - sec.access[HandleAccess_Read] = 0;
1.78 - sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
1.79 - sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
1.80 -
1.81 - /* Create the 'ConVar' handle type */
1.82 - m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
1.83 -}
1.84 -
1.85 -void ConVarManager::OnSourceModAllInitialized()
1.86 -{
1.87 - /**
1.88 - * Episode 2 has this function by default, but the older versions do not.
1.89 - */
1.90 -#if !defined ORANGEBOX_BUILD
1.91 - if (g_SMAPI->GetGameDLLVersion() >= 6)
1.92 - {
1.93 - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.94 - m_bIsDLLQueryHooked = true;
1.95 - }
1.96 -#endif
1.97 -
1.98 - SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
1.99 -
1.100 - /* Add the 'convars' option to the 'sm' console command */
1.101 - g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
1.102 -}
1.103 -
1.104 -void ConVarManager::OnSourceModShutdown()
1.105 -{
1.106 - List<ConVarInfo *>::iterator iter = m_ConVars.begin();
1.107 - HandleSecurity sec(NULL, g_pCoreIdent);
1.108 -
1.109 - /* Iterate list of ConVarInfo structures, remove every one of them */
1.110 - while (iter != m_ConVars.end())
1.111 - {
1.112 - ConVarInfo *pInfo = (*iter);
1.113 -
1.114 - iter = m_ConVars.erase(iter);
1.115 -
1.116 - g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.117 - if (pInfo->pChangeForward != NULL)
1.118 - {
1.119 - g_Forwards.ReleaseForward(pInfo->pChangeForward);
1.120 - }
1.121 - if (pInfo->sourceMod)
1.122 - {
1.123 - /* If we created it, we won't be tracking it, therefore it is
1.124 - * safe to remove everything in one go.
1.125 - */
1.126 - META_UNREGCVAR(pInfo->pVar);
1.127 - delete [] pInfo->pVar->GetName();
1.128 - delete [] pInfo->pVar->GetHelpText();
1.129 - delete [] pInfo->pVar->GetDefault();
1.130 - delete pInfo->pVar;
1.131 - }
1.132 - else
1.133 - {
1.134 - /* If we didn't create it, we might be tracking it. Also,
1.135 - * it could be unreadable.
1.136 - */
1.137 - UntrackConCommandBase(pInfo->pVar, this);
1.138 - }
1.139 -
1.140 - /* It's not safe to read the name here, so we simply delete the
1.141 - * the info struct and clear the lookup cache at the end.
1.142 - */
1.143 - delete pInfo;
1.144 - }
1.145 - convar_cache.clear();
1.146 -
1.147 - /* Unhook things */
1.148 - if (m_bIsDLLQueryHooked)
1.149 - {
1.150 - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.151 - m_bIsDLLQueryHooked = false;
1.152 - }
1.153 - else if (m_bIsVSPQueryHooked)
1.154 - {
1.155 - SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.156 - m_bIsVSPQueryHooked = false;
1.157 - }
1.158 -
1.159 - SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
1.160 -
1.161 - /* Remove the 'convars' option from the 'sm' console command */
1.162 - g_RootMenu.RemoveRootConsoleCommand("cvars", this);
1.163 -
1.164 - /* Remove the 'ConVar' handle type */
1.165 - g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
1.166 -}
1.167 -
1.168 -/**
1.169 - * Orange Box will never use this.
1.170 - */
1.171 -void ConVarManager::OnSourceModVSPReceived()
1.172 -{
1.173 - /**
1.174 - * Don't bother if the DLL is already hooked.
1.175 - */
1.176 - if (m_bIsDLLQueryHooked)
1.177 - {
1.178 - return;
1.179 - }
1.180 -
1.181 - /* For later MM:S versions, use the updated API, since it's cleaner. */
1.182 -#if defined METAMOD_PLAPI_VERSION
1.183 - int engine = g_SMAPI->GetSourceEngineBuild();
1.184 - if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
1.185 - {
1.186 - return;
1.187 - }
1.188 -#else
1.189 - if (g_HL2.IsOriginalEngine() || vsp_version < 2)
1.190 - {
1.191 - return;
1.192 - }
1.193 -#endif
1.194 -
1.195 - SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.196 - m_bIsVSPQueryHooked = true;
1.197 -}
1.198 -
1.199 -bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
1.200 -{
1.201 - ConVarInfo **pLookup = convar_cache.retrieve(name);
1.202 - if (pLookup != NULL)
1.203 - {
1.204 - *pVar = *pLookup;
1.205 - return true;
1.206 - }
1.207 - else
1.208 - {
1.209 - return false;
1.210 - }
1.211 -}
1.212 -
1.213 -void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
1.214 -{
1.215 - /* Only check convars that have not been created by SourceMod's core */
1.216 - ConVarInfo *pInfo;
1.217 - if (!convar_cache_lookup(name, &pInfo))
1.218 - {
1.219 - return;
1.220 - }
1.221 -
1.222 - HandleSecurity sec(NULL, g_pCoreIdent);
1.223 -
1.224 - /* Remove it from our cache */
1.225 - m_ConVars.remove(pInfo);
1.226 - convar_cache.remove(name);
1.227 -
1.228 - /* Now make sure no plugins are referring to this pointer */
1.229 - IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
1.230 - while (pl_iter->MorePlugins())
1.231 - {
1.232 - IPlugin *pl = pl_iter->GetPlugin();
1.233 -
1.234 - ConVarList *pConVarList;
1.235 - if (pl->GetProperty("ConVarList", (void **)&pConVarList, true)
1.236 - && pConVarList != NULL)
1.237 - {
1.238 - pConVarList->remove(pInfo->pVar);
1.239 - }
1.240 -
1.241 - pl_iter->NextPlugin();
1.242 - }
1.243 -
1.244 - /* Free resources */
1.245 - g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.246 - delete pInfo;
1.247 -}
1.248 -
1.249 -void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
1.250 -{
1.251 - ConVarList *pConVarList;
1.252 -
1.253 - /* If plugin has a convar list, free its memory */
1.254 - if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
1.255 - {
1.256 - delete pConVarList;
1.257 - }
1.258 -}
1.259 -
1.260 -void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
1.261 -{
1.262 -}
1.263 -
1.264 -bool ConVarManager::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
1.265 -{
1.266 - *pSize = sizeof(ConVar) + sizeof(ConVarInfo);
1.267 - return true;
1.268 -}
1.269 -
1.270 -void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
1.271 -{
1.272 - int argcount = command.ArgC();
1.273 - if (argcount >= 3)
1.274 - {
1.275 - /* Get plugin index that was passed */
1.276 - const char *arg = command.Arg(2);
1.277 -
1.278 - /* Get plugin object */
1.279 - CPlugin *plugin = g_PluginSys.FindPluginByConsoleArg(arg);
1.280 -
1.281 - if (!plugin)
1.282 - {
1.283 - g_RootMenu.ConsolePrint("[SM] Plugin \"%s\" was not found.", arg);
1.284 - return;
1.285 - }
1.286 -
1.287 - /* Get plugin name */
1.288 - const sm_plugininfo_t *plinfo = plugin->GetPublicInfo();
1.289 - const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename();
1.290 -
1.291 - ConVarList *pConVarList;
1.292 - ConVarList::iterator iter;
1.293 -
1.294 - /* If no convar list... */
1.295 - if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
1.296 - {
1.297 - g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname);
1.298 - return;
1.299 - }
1.300 -
1.301 - g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
1.302 - g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
1.303 -
1.304 - /* Iterate convar list and display each one */
1.305 - for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
1.306 - {
1.307 - const ConVar *pConVar = (*iter);
1.308 - g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
1.309 - }
1.310 -
1.311 - return;
1.312 - }
1.313 -
1.314 - /* Display usage of subcommand */
1.315 - g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>");
1.316 -}
1.317 -
1.318 -Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name, const char *defaultVal, const char *description, int flags, bool hasMin, float min, bool hasMax, float max)
1.319 -{
1.320 - ConVar *pConVar = NULL;
1.321 - ConVarInfo *pInfo = NULL;
1.322 - Handle_t hndl = 0;
1.323 -
1.324 - /* Find out if the convar exists already */
1.325 - pConVar = icvar->FindVar(name);
1.326 -
1.327 - /* If the convar already exists... */
1.328 - if (pConVar)
1.329 - {
1.330 - /* Add convar to plugin's list */
1.331 - AddConVarToPluginList(pContext, pConVar);
1.332 -
1.333 - /* First find out if we already have a handle to it */
1.334 - if (convar_cache_lookup(name, &pInfo))
1.335 - {
1.336 - return pInfo->handle;
1.337 - }
1.338 - else
1.339 - {
1.340 - /* Create and initialize ConVarInfo structure */
1.341 - pInfo = new ConVarInfo();
1.342 - pInfo->sourceMod = false;
1.343 - pInfo->pChangeForward = NULL;
1.344 - pInfo->pVar = pConVar;
1.345 -
1.346 - /* If we don't, then create a new handle from the convar */
1.347 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.348 - if (hndl == BAD_HANDLE)
1.349 - {
1.350 - delete pInfo;
1.351 - return BAD_HANDLE;
1.352 - }
1.353 -
1.354 - pInfo->handle = hndl;
1.355 -
1.356 - /* Insert struct into caches */
1.357 - m_ConVars.push_back(pInfo);
1.358 - convar_cache.insert(name, pInfo);
1.359 - TrackConCommandBase(pConVar, this);
1.360 -
1.361 - return hndl;
1.362 - }
1.363 - }
1.364 -
1.365 - /* To prevent creating a convar that has the same name as a console command... ugh */
1.366 - ConCommandBase *pBase = icvar->GetCommands();
1.367 -
1.368 - while (pBase)
1.369 - {
1.370 - if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
1.371 - {
1.372 - return BAD_HANDLE;
1.373 - }
1.374 -
1.375 - pBase = const_cast<ConCommandBase *>(pBase->GetNext());
1.376 - }
1.377 -
1.378 - /* Create and initialize ConVarInfo structure */
1.379 - pInfo = new ConVarInfo();
1.380 - pInfo->handle = hndl;
1.381 - pInfo->sourceMod = true;
1.382 - pInfo->pChangeForward = NULL;
1.383 -
1.384 - /* Create a handle from the new convar */
1.385 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.386 - if (hndl == BAD_HANDLE)
1.387 - {
1.388 - delete pInfo;
1.389 - return BAD_HANDLE;
1.390 - }
1.391 -
1.392 - pInfo->handle = hndl;
1.393 -
1.394 - /* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */
1.395 - pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max);
1.396 - pInfo->pVar = pConVar;
1.397 -
1.398 - /* Add convar to plugin's list */
1.399 - AddConVarToPluginList(pContext, pConVar);
1.400 -
1.401 - /* Insert struct into caches */
1.402 - m_ConVars.push_back(pInfo);
1.403 - convar_cache.insert(name, pInfo);
1.404 -
1.405 - return hndl;
1.406 -}
1.407 -
1.408 -Handle_t ConVarManager::FindConVar(const char *name)
1.409 -{
1.410 - ConVar *pConVar = NULL;
1.411 - ConVarInfo *pInfo;
1.412 - Handle_t hndl;
1.413 -
1.414 - /* Search for convar */
1.415 - pConVar = icvar->FindVar(name);
1.416 -
1.417 - /* If it doesn't exist, then return an invalid handle */
1.418 - if (!pConVar)
1.419 - {
1.420 - return BAD_HANDLE;
1.421 - }
1.422 -
1.423 - /* At this point, the convar exists. So, find out if we already have a handle */
1.424 - if (convar_cache_lookup(name, &pInfo))
1.425 - {
1.426 - return pInfo->handle;
1.427 - }
1.428 -
1.429 - /* Create and initialize ConVarInfo structure */
1.430 - pInfo = new ConVarInfo();
1.431 - pInfo->sourceMod = false;
1.432 - pInfo->pChangeForward = NULL;
1.433 - pInfo->pVar = pConVar;
1.434 -
1.435 - /* If we don't have a handle, then create a new one */
1.436 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.437 - if (hndl == BAD_HANDLE)
1.438 - {
1.439 - delete pInfo;
1.440 - return BAD_HANDLE;
1.441 - }
1.442 -
1.443 - pInfo->handle = hndl;
1.444 -
1.445 - /* Insert struct into our caches */
1.446 - m_ConVars.push_back(pInfo);
1.447 - convar_cache.insert(name, pInfo);
1.448 - TrackConCommandBase(pConVar, this);
1.449 -
1.450 - return hndl;
1.451 -}
1.452 -
1.453 -void ConVarManager::AddConVarChangeListener(const char *name, IConVarChangeListener *pListener)
1.454 -{
1.455 - ConVarInfo *pInfo;
1.456 -
1.457 - if (FindConVar(name) == BAD_HANDLE)
1.458 - {
1.459 - return;
1.460 - }
1.461 -
1.462 - /* Find the convar in the lookup trie */
1.463 - if (convar_cache_lookup(name, &pInfo))
1.464 - {
1.465 - pInfo->changeListeners.push_back(pListener);
1.466 - }
1.467 -}
1.468 -
1.469 -void ConVarManager::RemoveConVarChangeListener(const char *name, IConVarChangeListener *pListener)
1.470 -{
1.471 - ConVarInfo *pInfo;
1.472 -
1.473 - /* Find the convar in the lookup trie */
1.474 - if (convar_cache_lookup(name, &pInfo))
1.475 - {
1.476 - pInfo->changeListeners.remove(pListener);
1.477 - }
1.478 -}
1.479 -
1.480 -void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
1.481 -{
1.482 - ConVarInfo *pInfo;
1.483 - IChangeableForward *pForward;
1.484 -
1.485 - /* Find the convar in the lookup trie */
1.486 - if (convar_cache_lookup(pConVar->GetName(), &pInfo))
1.487 - {
1.488 - /* Get the forward */
1.489 - pForward = pInfo->pChangeForward;
1.490 -
1.491 - /* If forward does not exist, create it */
1.492 - if (!pForward)
1.493 - {
1.494 - pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
1.495 - pInfo->pChangeForward = pForward;
1.496 - }
1.497 -
1.498 - /* Add function to forward's list */
1.499 - pForward->AddFunction(pFunction);
1.500 - }
1.501 -}
1.502 -
1.503 -void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
1.504 -{
1.505 - ConVarInfo *pInfo;
1.506 - IChangeableForward *pForward;
1.507 - IPluginContext *pContext = pFunction->GetParentContext();
1.508 -
1.509 - /* Find the convar in the lookup trie */
1.510 - if (convar_cache_lookup(pConVar->GetName(), &pInfo))
1.511 - {
1.512 - /* Get the forward */
1.513 - pForward = pInfo->pChangeForward;
1.514 -
1.515 - /* If the forward doesn't exist, we can't unhook anything */
1.516 - if (!pForward)
1.517 - {
1.518 - pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName());
1.519 - return;
1.520 - }
1.521 -
1.522 - /* Remove the function from the forward's list */
1.523 - if (!pForward->RemoveFunction(pFunction))
1.524 - {
1.525 - pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName());
1.526 - return;
1.527 - }
1.528 -
1.529 - /* If the forward now has 0 functions in it... */
1.530 - if (pForward->GetFunctionCount() == 0)
1.531 - {
1.532 - /* Free this forward */
1.533 - g_Forwards.ReleaseForward(pForward);
1.534 - pInfo->pChangeForward = NULL;
1.535 - }
1.536 - }
1.537 -}
1.538 -
1.539 -QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
1.540 -{
1.541 - QueryCvarCookie_t cookie;
1.542 -
1.543 - /* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
1.544 - if (m_bIsDLLQueryHooked)
1.545 - {
1.546 - cookie = engine->StartQueryCvarValue(pPlayer, name);
1.547 - }
1.548 - else if (m_bIsVSPQueryHooked)
1.549 - {
1.550 - cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
1.551 - }
1.552 - else
1.553 - {
1.554 - return InvalidQueryCvarCookie;
1.555 - }
1.556 -
1.557 - ConVarQuery query = {cookie, pCallback, hndl};
1.558 - m_ConVarQueries.push_back(query);
1.559 -
1.560 - return cookie;
1.561 -}
1.562 -
1.563 -void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar)
1.564 -{
1.565 - ConVarList *pConVarList;
1.566 - ConVarList::iterator iter;
1.567 - bool inserted = false;
1.568 - const char *orig = pConVar->GetName();
1.569 -
1.570 - IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.571 -
1.572 - /* Check plugin for an existing convar list */
1.573 - if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
1.574 - {
1.575 - pConVarList = new ConVarList();
1.576 - plugin->SetProperty("ConVarList", pConVarList);
1.577 - }
1.578 - else if (pConVarList->find(pConVar) != pConVarList->end())
1.579 - {
1.580 - /* If convar is already in list, then don't add it */
1.581 - return;
1.582 - }
1.583 -
1.584 - /* Insert convar into list which is sorted alphabetically */
1.585 - for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
1.586 - {
1.587 - if (strcmp(orig, (*iter)->GetName()) < 0)
1.588 - {
1.589 - pConVarList->insert(iter, pConVar);
1.590 - inserted = true;
1.591 - break;
1.592 - }
1.593 - }
1.594 -
1.595 - if (!inserted)
1.596 - {
1.597 - pConVarList->push_back(pConVar);
1.598 - }
1.599 -}
1.600 -
1.601 -#if defined ORANGEBOX_BUILD
1.602 -void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
1.603 -#else
1.604 -void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
1.605 -#endif
1.606 -{
1.607 - /* If the values are the same, exit early in order to not trigger callbacks */
1.608 - if (strcmp(pConVar->GetString(), oldValue) == 0)
1.609 - {
1.610 - return;
1.611 - }
1.612 -
1.613 - ConVarInfo *pInfo;
1.614 -
1.615 - /* Find the convar in the lookup trie */
1.616 - if (!convar_cache_lookup(pConVar->GetName(), &pInfo))
1.617 - {
1.618 - return;
1.619 - }
1.620 -
1.621 - IChangeableForward *pForward = pInfo->pChangeForward;
1.622 -
1.623 - if (pInfo->changeListeners.size() != 0)
1.624 - {
1.625 - for (List<IConVarChangeListener *>::iterator i = pInfo->changeListeners.begin();
1.626 - i != pInfo->changeListeners.end();
1.627 - i++)
1.628 - {
1.629 -#if defined ORANGEBOX_BUILD
1.630 - (*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
1.631 -#else
1.632 - (*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
1.633 -#endif
1.634 - }
1.635 - }
1.636 -
1.637 - if (pForward != NULL)
1.638 - {
1.639 - /* Now call forwards in plugins that have hooked this */
1.640 - pForward->PushCell(pInfo->handle);
1.641 - pForward->PushString(oldValue);
1.642 - pForward->PushString(pConVar->GetString());
1.643 - pForward->Execute(NULL);
1.644 - }
1.645 -}
1.646 -
1.647 -bool ConVarManager::IsQueryingSupported()
1.648 -{
1.649 - return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
1.650 -}
1.651 -
1.652 -void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
1.653 -{
1.654 - IPluginFunction *pCallback = NULL;
1.655 - cell_t value = 0;
1.656 - List<ConVarQuery>::iterator iter;
1.657 -
1.658 - for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++)
1.659 - {
1.660 - ConVarQuery &query = (*iter);
1.661 - if (query.cookie == cookie)
1.662 - {
1.663 - pCallback = query.pCallback;
1.664 - value = query.value;
1.665 - break;
1.666 - }
1.667 - }
1.668 -
1.669 - if (pCallback)
1.670 - {
1.671 - cell_t ret;
1.672 -
1.673 - pCallback->PushCell(cookie);
1.674 - pCallback->PushCell(engine->IndexOfEdict(pPlayer));
1.675 - pCallback->PushCell(result);
1.676 - pCallback->PushString(cvarName);
1.677 -
1.678 - if (result == eQueryCvarValueStatus_ValueIntact)
1.679 - {
1.680 - pCallback->PushString(cvarValue);
1.681 - }
1.682 - else
1.683 - {
1.684 - pCallback->PushString("\0");
1.685 - }
1.686 -
1.687 - pCallback->PushCell(value);
1.688 - pCallback->Execute(&ret);
1.689 -
1.690 - m_ConVarQueries.erase(iter);
1.691 - }
1.692 -}
1.693 -
1.694 -HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
1.695 -{
1.696 - ConVarInfo *pInfo;
1.697 - HandleError error;
1.698 -
1.699 - if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
1.700 - {
1.701 - return error;
1.702 - }
1.703 -
1.704 - if (pVar)
1.705 - {
1.706 - *pVar = pInfo->pVar;
1.707 - }
1.708 -
1.709 - return error;
1.710 -}