1.1 --- a/core/ConVarManager.cpp Fri Mar 28 06:21:34 2008 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,823 +0,0 @@
1.4 -/**
1.5 - * vim: set ts=4 :
1.6 - * =============================================================================
1.7 - * SourceMod
1.8 - * Copyright (C) 2004-2007 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 -SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
1.48 -SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
1.49 -
1.50 -const ParamType CONVARCHANGE_PARAMS[] = {Param_Cell, Param_String, Param_String};
1.51 -typedef List<const ConVar *> ConVarList;
1.52 -KTrie<ConVarInfo *> convar_cache;
1.53 -
1.54 -ConVarManager::ConVarManager() : m_ConVarType(0), m_bIsDLLQueryHooked(false), m_bIsVSPQueryHooked(false)
1.55 -{
1.56 -}
1.57 -
1.58 -ConVarManager::~ConVarManager()
1.59 -{
1.60 -}
1.61 -
1.62 -void ConVarManager::OnSourceModAllInitialized()
1.63 -{
1.64 - /**
1.65 - * Episode 2 has this function by default, but the older versions do not.
1.66 - */
1.67 -#if !defined ORANGEBOX_BUILD
1.68 - if (g_SMAPI->GetGameDLLVersion() >= 6)
1.69 -#endif
1.70 - {
1.71 - SH_ADD_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.72 - m_bIsDLLQueryHooked = true;
1.73 - }
1.74 -
1.75 - HandleAccess sec;
1.76 -
1.77 - /* Set up access rights for the 'ConVar' handle type */
1.78 - sec.access[HandleAccess_Read] = 0;
1.79 - sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
1.80 - sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
1.81 -
1.82 - /* Create the 'ConVar' handle type */
1.83 - m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
1.84 -
1.85 - /* Add the 'convars' option to the 'sm' console command */
1.86 - g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
1.87 -}
1.88 -
1.89 -void ConVarManager::OnSourceModShutdown()
1.90 -{
1.91 - List<ConVarInfo *>::iterator iter = m_ConVars.begin();
1.92 - HandleSecurity sec(NULL, g_pCoreIdent);
1.93 -
1.94 - /* Iterate list of ConVarInfo structures, remove every one of them */
1.95 - while (iter != m_ConVars.end())
1.96 - {
1.97 - ConVarInfo *pInfo = (*iter);
1.98 -
1.99 - iter = m_ConVars.erase(iter);
1.100 -
1.101 - g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.102 - if (pInfo->pChangeForward != NULL)
1.103 - {
1.104 - g_Forwards.ReleaseForward(pInfo->pChangeForward);
1.105 - }
1.106 - if (pInfo->sourceMod)
1.107 - {
1.108 - /* If we created it, we won't be tracking it, therefore it is
1.109 - * safe to remove everything in one go.
1.110 - */
1.111 - META_UNREGCVAR(pInfo->pVar);
1.112 - delete [] pInfo->pVar->GetName();
1.113 - delete [] pInfo->pVar->GetHelpText();
1.114 - delete [] pInfo->pVar->GetDefault();
1.115 - delete pInfo->pVar;
1.116 - }
1.117 - else
1.118 - {
1.119 - /* If we didn't create it, we might be tracking it. Also,
1.120 - * it could be unreadable.
1.121 - */
1.122 - UntrackConCommandBase(pInfo->pVar, this);
1.123 - }
1.124 -
1.125 - /* It's not safe to read the name here, so we simply delete the
1.126 - * the info struct and clear the lookup cache at the end.
1.127 - */
1.128 - delete pInfo;
1.129 - }
1.130 - convar_cache.clear();
1.131 -
1.132 - /* Unhook things */
1.133 - if (m_bIsDLLQueryHooked)
1.134 - {
1.135 - SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, OnQueryCvarValueFinished, gamedll, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.136 - m_bIsDLLQueryHooked = false;
1.137 - }
1.138 - else if (m_bIsVSPQueryHooked)
1.139 - {
1.140 - SH_REMOVE_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.141 - m_bIsVSPQueryHooked = false;
1.142 - }
1.143 -
1.144 - /* Remove the 'convars' option from the 'sm' console command */
1.145 - g_RootMenu.RemoveRootConsoleCommand("cvars", this);
1.146 -
1.147 - /* Remove the 'ConVar' handle type */
1.148 - g_HandleSys.RemoveType(m_ConVarType, g_pCoreIdent);
1.149 -}
1.150 -
1.151 -/**
1.152 - * Orange Box will never use this.
1.153 - */
1.154 -void ConVarManager::OnSourceModVSPReceived()
1.155 -{
1.156 - /**
1.157 - * Don't bother if the DLL is already hooked.
1.158 - */
1.159 - if (m_bIsDLLQueryHooked)
1.160 - {
1.161 - return;
1.162 - }
1.163 -
1.164 - /* For later MM:S versions, use the updated API, since it's cleaner. */
1.165 -#if defined METAMOD_PLAPI_VERSION
1.166 - int engine = g_SMAPI->GetSourceEngineBuild();
1.167 - if (engine == SOURCE_ENGINE_ORIGINAL || vsp_version < 2)
1.168 - {
1.169 - return;
1.170 - }
1.171 -#else
1.172 - if (g_HL2.IsOriginalEngine() || vsp_version < 2)
1.173 - {
1.174 - return;
1.175 - }
1.176 -#endif
1.177 -
1.178 - SH_ADD_HOOK_MEMFUNC(IServerPluginCallbacks, OnQueryCvarValueFinished, vsp_interface, this, &ConVarManager::OnQueryCvarValueFinished, false);
1.179 - m_bIsVSPQueryHooked = true;
1.180 -}
1.181 -
1.182 -bool convar_cache_lookup(const char *name, ConVarInfo **pVar)
1.183 -{
1.184 - ConVarInfo **pLookup = convar_cache.retrieve(name);
1.185 - if (pLookup != NULL)
1.186 - {
1.187 - *pVar = *pLookup;
1.188 - return true;
1.189 - }
1.190 - else
1.191 - {
1.192 - return false;
1.193 - }
1.194 -}
1.195 -
1.196 -void ConVarManager::OnUnlinkConCommandBase(ConCommandBase *pBase, const char *name, bool is_read_safe)
1.197 -{
1.198 - /* Only check convars that have not been created by SourceMod's core */
1.199 - ConVarInfo *pInfo;
1.200 - if (!convar_cache_lookup(name, &pInfo))
1.201 - {
1.202 - return;
1.203 - }
1.204 -
1.205 - HandleSecurity sec(NULL, g_pCoreIdent);
1.206 -
1.207 - /* Remove it from our cache */
1.208 - m_ConVars.remove(pInfo);
1.209 - convar_cache.remove(name);
1.210 -
1.211 - /* Now make sure no plugins are referring to this pointer */
1.212 - IPluginIterator *pl_iter = g_PluginSys.GetPluginIterator();
1.213 - while (pl_iter->MorePlugins())
1.214 - {
1.215 - IPlugin *pl = pl_iter->GetPlugin();
1.216 -
1.217 - ConVarList *pConVarList;
1.218 - if (pl->GetProperty("ConVarList", (void **)&pConVarList, true)
1.219 - && pConVarList != NULL)
1.220 - {
1.221 - pConVarList->remove(pInfo->pVar);
1.222 - }
1.223 -
1.224 - pl_iter->NextPlugin();
1.225 - }
1.226 -
1.227 - /* Free resources */
1.228 - g_HandleSys.FreeHandle(pInfo->handle, &sec);
1.229 - delete pInfo;
1.230 -}
1.231 -
1.232 -void ConVarManager::OnPluginUnloaded(IPlugin *plugin)
1.233 -{
1.234 - ConVarList *pConVarList;
1.235 -
1.236 - /* If plugin has a convar list, free its memory */
1.237 - if (plugin->GetProperty("ConVarList", (void **)&pConVarList, true))
1.238 - {
1.239 - delete pConVarList;
1.240 - }
1.241 -}
1.242 -
1.243 -void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
1.244 -{
1.245 -}
1.246 -
1.247 -void ConVarManager::OnRootConsoleCommand(const char *cmdname, const CCommand &command)
1.248 -{
1.249 - int argcount = command.ArgC();
1.250 - if (argcount >= 3)
1.251 - {
1.252 - /* Get plugin index that was passed */
1.253 - int id = atoi(command.Arg(2));
1.254 -
1.255 - /* Get plugin object */
1.256 - CPlugin *plugin = g_PluginSys.GetPluginByOrder(id);
1.257 -
1.258 - if (!plugin)
1.259 - {
1.260 - g_RootMenu.ConsolePrint("[SM] Plugin index %d not found.", id);
1.261 - return;
1.262 - }
1.263 -
1.264 - /* Get plugin name */
1.265 - const sm_plugininfo_t *plinfo = plugin->GetPublicInfo();
1.266 - const char *plname = IS_STR_FILLED(plinfo->name) ? plinfo->name : plugin->GetFilename();
1.267 -
1.268 - ConVarList *pConVarList;
1.269 - ConVarList::iterator iter;
1.270 -
1.271 - /* If no convar list... */
1.272 - if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
1.273 - {
1.274 - g_RootMenu.ConsolePrint("[SM] No convars found for: %s", plname);
1.275 - return;
1.276 - }
1.277 -
1.278 - g_RootMenu.ConsolePrint("[SM] Listing %d convars for: %s", pConVarList->size(), plname);
1.279 - g_RootMenu.ConsolePrint(" %-32.31s %s", "[Name]", "[Value]");
1.280 -
1.281 - /* Iterate convar list and display each one */
1.282 - for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
1.283 - {
1.284 - const ConVar *pConVar = (*iter);
1.285 - g_RootMenu.ConsolePrint(" %-32.31s %s", pConVar->GetName(), pConVar->GetString());
1.286 - }
1.287 -
1.288 - return;
1.289 - }
1.290 -
1.291 - /* Display usage of subcommand */
1.292 - g_RootMenu.ConsolePrint("[SM] Usage: sm convars <plugin #>");
1.293 -}
1.294 -
1.295 -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.296 -{
1.297 - ConVar *pConVar = NULL;
1.298 - ConVarInfo *pInfo = NULL;
1.299 - Handle_t hndl = 0;
1.300 -
1.301 - /* Find out if the convar exists already */
1.302 - pConVar = icvar->FindVar(name);
1.303 -
1.304 - /* If the convar already exists... */
1.305 - if (pConVar)
1.306 - {
1.307 - /* Add convar to plugin's list */
1.308 - AddConVarToPluginList(pContext, pConVar);
1.309 -
1.310 - /* First find out if we already have a handle to it */
1.311 - if (convar_cache_lookup(name, &pInfo))
1.312 - {
1.313 - return pInfo->handle;
1.314 - }
1.315 - else
1.316 - {
1.317 - /* Create and initialize ConVarInfo structure */
1.318 - pInfo = new ConVarInfo();
1.319 - pInfo->sourceMod = false;
1.320 - pInfo->pChangeForward = NULL;
1.321 - pInfo->origCallback = pConVar->GetCallback();
1.322 - pInfo->pVar = pConVar;
1.323 -
1.324 - /* If we don't, then create a new handle from the convar */
1.325 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.326 - if (hndl == BAD_HANDLE)
1.327 - {
1.328 - delete pInfo;
1.329 - return BAD_HANDLE;
1.330 - }
1.331 -
1.332 - pInfo->handle = hndl;
1.333 -
1.334 - /* Insert struct into caches */
1.335 - m_ConVars.push_back(pInfo);
1.336 - convar_cache.insert(name, pInfo);
1.337 - TrackConCommandBase(pConVar, this);
1.338 -
1.339 - return hndl;
1.340 - }
1.341 - }
1.342 -
1.343 - /* To prevent creating a convar that has the same name as a console command... ugh */
1.344 - ConCommandBase *pBase = icvar->GetCommands();
1.345 -
1.346 - while (pBase)
1.347 - {
1.348 - if (pBase->IsCommand() && strcmp(pBase->GetName(), name) == 0)
1.349 - {
1.350 - return BAD_HANDLE;
1.351 - }
1.352 -
1.353 - pBase = const_cast<ConCommandBase *>(pBase->GetNext());
1.354 - }
1.355 -
1.356 - /* Create and initialize ConVarInfo structure */
1.357 - pInfo = new ConVarInfo();
1.358 - pInfo->handle = hndl;
1.359 - pInfo->sourceMod = true;
1.360 - pInfo->pChangeForward = NULL;
1.361 - pInfo->origCallback = NULL;
1.362 -
1.363 - /* Create a handle from the new convar */
1.364 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.365 - if (hndl == BAD_HANDLE)
1.366 - {
1.367 - delete pInfo;
1.368 - return BAD_HANDLE;
1.369 - }
1.370 -
1.371 - pInfo->handle = hndl;
1.372 -
1.373 - /* Since an existing convar (or concmd with the same name) was not found , now we can finally create it */
1.374 - pConVar = new ConVar(sm_strdup(name), sm_strdup(defaultVal), flags, sm_strdup(description), hasMin, min, hasMax, max);
1.375 - pInfo->pVar = pConVar;
1.376 -
1.377 - /* Add convar to plugin's list */
1.378 - AddConVarToPluginList(pContext, pConVar);
1.379 -
1.380 - /* Insert struct into caches */
1.381 - m_ConVars.push_back(pInfo);
1.382 - convar_cache.insert(name, pInfo);
1.383 -
1.384 - return hndl;
1.385 -}
1.386 -
1.387 -Handle_t ConVarManager::FindConVar(const char *name)
1.388 -{
1.389 - ConVar *pConVar = NULL;
1.390 - ConVarInfo *pInfo;
1.391 - Handle_t hndl;
1.392 -
1.393 - /* Search for convar */
1.394 - pConVar = icvar->FindVar(name);
1.395 -
1.396 - /* If it doesn't exist, then return an invalid handle */
1.397 - if (!pConVar)
1.398 - {
1.399 - return BAD_HANDLE;
1.400 - }
1.401 -
1.402 - /* At this point, the convar exists. So, find out if we already have a handle */
1.403 - if (convar_cache_lookup(name, &pInfo))
1.404 - {
1.405 - return pInfo->handle;
1.406 - }
1.407 -
1.408 - /* Create and initialize ConVarInfo structure */
1.409 - pInfo = new ConVarInfo();
1.410 - pInfo->sourceMod = false;
1.411 - pInfo->pChangeForward = NULL;
1.412 - pInfo->origCallback = pConVar->GetCallback();
1.413 - pInfo->pVar = pConVar;
1.414 -
1.415 - /* If we don't have a handle, then create a new one */
1.416 - hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
1.417 - if (hndl == BAD_HANDLE)
1.418 - {
1.419 - delete pInfo;
1.420 - return BAD_HANDLE;
1.421 - }
1.422 -
1.423 - pInfo->handle = hndl;
1.424 -
1.425 - /* Insert struct into our caches */
1.426 - m_ConVars.push_back(pInfo);
1.427 - convar_cache.insert(name, pInfo);
1.428 - TrackConCommandBase(pConVar, this);
1.429 -
1.430 - return hndl;
1.431 -}
1.432 -
1.433 -void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
1.434 -{
1.435 - ConVarInfo *pInfo;
1.436 - IChangeableForward *pForward;
1.437 -
1.438 - /* Find the convar in the lookup trie */
1.439 - if (convar_cache_lookup(pConVar->GetName(), &pInfo))
1.440 - {
1.441 - /* Get the forward */
1.442 - pForward = pInfo->pChangeForward;
1.443 -
1.444 - /* If forward does not exist, create it */
1.445 - if (!pForward)
1.446 - {
1.447 - pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
1.448 - pInfo->pChangeForward = pForward;
1.449 -
1.450 - /* Install our own callback */
1.451 - pConVar->InstallChangeCallback(OnConVarChanged);
1.452 - }
1.453 -
1.454 - /* Add function to forward's list */
1.455 - pForward->AddFunction(pFunction);
1.456 - }
1.457 -}
1.458 -
1.459 -void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
1.460 -{
1.461 - ConVarInfo *pInfo;
1.462 - IChangeableForward *pForward;
1.463 - IPluginContext *pContext = pFunction->GetParentContext();
1.464 -
1.465 - /* Find the convar in the lookup trie */
1.466 - if (convar_cache_lookup(pConVar->GetName(), &pInfo))
1.467 - {
1.468 - /* Get the forward */
1.469 - pForward = pInfo->pChangeForward;
1.470 -
1.471 - /* If the forward doesn't exist, we can't unhook anything */
1.472 - if (!pForward)
1.473 - {
1.474 - pContext->ThrowNativeError("Convar \"%s\" has no active hook", pConVar->GetName());
1.475 - return;
1.476 - }
1.477 -
1.478 - /* Remove the function from the forward's list */
1.479 - if (!pForward->RemoveFunction(pFunction))
1.480 - {
1.481 - pContext->ThrowNativeError("Invalid hook callback specified for convar \"%s\"", pConVar->GetName());
1.482 - return;
1.483 - }
1.484 -
1.485 - /* If the forward now has 0 functions in it... */
1.486 - if (pForward->GetFunctionCount() == 0)
1.487 - {
1.488 - /* Free this forward */
1.489 - g_Forwards.ReleaseForward(pForward);
1.490 - pInfo->pChangeForward = NULL;
1.491 -
1.492 - /* Put back the original convar callback */
1.493 - pConVar->InstallChangeCallback(pInfo->origCallback);
1.494 - }
1.495 - }
1.496 -}
1.497 -
1.498 -QueryCvarCookie_t ConVarManager::QueryClientConVar(edict_t *pPlayer, const char *name, IPluginFunction *pCallback, Handle_t hndl)
1.499 -{
1.500 - QueryCvarCookie_t cookie;
1.501 -
1.502 - /* Call StartQueryCvarValue() in either the IVEngineServer or IServerPluginHelpers depending on situation */
1.503 - if (m_bIsDLLQueryHooked)
1.504 - {
1.505 - cookie = engine->StartQueryCvarValue(pPlayer, name);
1.506 - }
1.507 - else if (m_bIsVSPQueryHooked)
1.508 - {
1.509 - cookie = serverpluginhelpers->StartQueryCvarValue(pPlayer, name);
1.510 - }
1.511 - else
1.512 - {
1.513 - return InvalidQueryCvarCookie;
1.514 - }
1.515 -
1.516 - ConVarQuery query = {cookie, pCallback, hndl};
1.517 - m_ConVarQueries.push_back(query);
1.518 -
1.519 - return cookie;
1.520 -}
1.521 -
1.522 -void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar)
1.523 -{
1.524 - ConVarList *pConVarList;
1.525 - ConVarList::iterator iter;
1.526 - bool inserted = false;
1.527 - const char *orig = pConVar->GetName();
1.528 -
1.529 - IPlugin *plugin = g_PluginSys.FindPluginByContext(pContext->GetContext());
1.530 -
1.531 - /* Check plugin for an existing convar list */
1.532 - if (!plugin->GetProperty("ConVarList", (void **)&pConVarList))
1.533 - {
1.534 - pConVarList = new ConVarList();
1.535 - plugin->SetProperty("ConVarList", pConVarList);
1.536 - }
1.537 - else if (pConVarList->find(pConVar) != pConVarList->end())
1.538 - {
1.539 - /* If convar is already in list, then don't add it */
1.540 - return;
1.541 - }
1.542 -
1.543 - /* Insert convar into list which is sorted alphabetically */
1.544 - for (iter = pConVarList->begin(); iter != pConVarList->end(); iter++)
1.545 - {
1.546 - if (strcmp(orig, (*iter)->GetName()) < 0)
1.547 - {
1.548 - pConVarList->insert(iter, pConVar);
1.549 - inserted = true;
1.550 - break;
1.551 - }
1.552 - }
1.553 -
1.554 - if (!inserted)
1.555 - {
1.556 - pConVarList->push_back(pConVar);
1.557 - }
1.558 -}
1.559 -
1.560 -#if defined ORANGEBOX_BUILD
1.561 -void ConVarManager::OnConVarChanged(IConVar *pIConVar, const char *oldValue, float flOldValue)
1.562 -#else
1.563 -void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
1.564 -#endif
1.565 -{
1.566 - /* If the values are the same, exit early in order to not trigger callbacks */
1.567 -#if defined ORANGEBOX_BUILD
1.568 - ConVar *pConVar = (ConVar *)pIConVar;
1.569 -#endif
1.570 - if (strcmp(pConVar->GetString(), oldValue) == 0)
1.571 - {
1.572 - return;
1.573 - }
1.574 -
1.575 - ConVarInfo *pInfo;
1.576 -
1.577 - /* Find the convar in the lookup trie */
1.578 - if (!convar_cache_lookup(pConVar->GetName(), &pInfo))
1.579 - {
1.580 - return;
1.581 - }
1.582 -
1.583 - FnChangeCallback_t origCallback = pInfo->origCallback;
1.584 - IChangeableForward *pForward = pInfo->pChangeForward;
1.585 -
1.586 - /* If there was a change callback installed previously, call it */
1.587 - if (origCallback)
1.588 - {
1.589 -#if defined ORANGEBOX_BUILD
1.590 - origCallback(pConVar, oldValue, flOldValue);
1.591 -#else
1.592 - origCallback(pConVar, oldValue);
1.593 -#endif
1.594 - }
1.595 -
1.596 - /* Now call forwards in plugins that have hooked this */
1.597 - pForward->PushCell(pInfo->handle);
1.598 - pForward->PushString(oldValue);
1.599 - pForward->PushString(reinterpret_cast<ConVar *>(pConVar)->GetString());
1.600 - pForward->Execute(NULL);
1.601 -}
1.602 -
1.603 -bool ConVarManager::IsQueryingSupported()
1.604 -{
1.605 - return (m_bIsDLLQueryHooked || m_bIsVSPQueryHooked);
1.606 -}
1.607 -
1.608 -void ConVarManager::OnQueryCvarValueFinished(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue)
1.609 -{
1.610 - IPluginFunction *pCallback = NULL;
1.611 - cell_t value = 0;
1.612 - List<ConVarQuery>::iterator iter;
1.613 -
1.614 - for (iter = m_ConVarQueries.begin(); iter != m_ConVarQueries.end(); iter++)
1.615 - {
1.616 - ConVarQuery &query = (*iter);
1.617 - if (query.cookie == cookie)
1.618 - {
1.619 - pCallback = query.pCallback;
1.620 - value = query.value;
1.621 - break;
1.622 - }
1.623 - }
1.624 -
1.625 - if (pCallback)
1.626 - {
1.627 - cell_t ret;
1.628 -
1.629 - pCallback->PushCell(cookie);
1.630 - pCallback->PushCell(engine->IndexOfEdict(pPlayer));
1.631 - pCallback->PushCell(result);
1.632 - pCallback->PushString(cvarName);
1.633 -
1.634 - if (result == eQueryCvarValueStatus_ValueIntact)
1.635 - {
1.636 - pCallback->PushString(cvarValue);
1.637 - }
1.638 - else
1.639 - {
1.640 - pCallback->PushString("\0");
1.641 - }
1.642 -
1.643 - pCallback->PushCell(value);
1.644 - pCallback->Execute(&ret);
1.645 -
1.646 - m_ConVarQueries.erase(iter);
1.647 - }
1.648 -}
1.649 -
1.650 -HandleError ConVarManager::ReadConVarHandle(Handle_t hndl, ConVar **pVar)
1.651 -{
1.652 - ConVarInfo *pInfo;
1.653 - HandleError error;
1.654 -
1.655 - if ((error = g_HandleSys.ReadHandle(hndl, m_ConVarType, NULL, (void **)&pInfo)) != HandleError_None)
1.656 - {
1.657 - return error;
1.658 - }
1.659 -
1.660 - if (pVar)
1.661 - {
1.662 - *pVar = pInfo->pVar;
1.663 - }
1.664 -
1.665 - return error;
1.666 -}
1.667 -
1.668 -static int s_YamagramState = 0;
1.669 -
1.670 -void _YamagramPrinterTwoPointOhOh(int yamagram)
1.671 -{
1.672 - switch (yamagram)
1.673 - {
1.674 - case 0:
1.675 - g_RootMenu.ConsolePrint("Answer the following questions correctly and Gaben may not eat you after all.");
1.676 - g_RootMenu.ConsolePrint("You will be given one hint in the form of my patented yamagrams.");
1.677 - g_RootMenu.ConsolePrint("Type sm_nana to see the last question.");
1.678 - g_RootMenu.ConsolePrint("Type sm_nana <answer> to attempt an answer of the question.");
1.679 - g_RootMenu.ConsolePrint("-------------------------------");
1.680 - _YamagramPrinterTwoPointOhOh(1);
1.681 - return;
1.682 - case 1:
1.683 - g_RootMenu.ConsolePrint("Question Ichi (1)");
1.684 - g_RootMenu.ConsolePrint("One can turn into a cow by doing what action?");
1.685 - g_RootMenu.ConsolePrint("Hint: AGE SANS GRIT");
1.686 - break;
1.687 - case 2:
1.688 - g_RootMenu.ConsolePrint("Question Ni (2)");
1.689 - g_RootMenu.ConsolePrint("What kind of hat should you wear when using the Internet?");
1.690 - g_RootMenu.ConsolePrint("Hint: BRR MOOSE");
1.691 - break;
1.692 - case 3:
1.693 - g_RootMenu.ConsolePrint("Question San (3)");
1.694 - g_RootMenu.ConsolePrint("Who is the lead developer of SourceMod?");
1.695 - g_RootMenu.ConsolePrint("Hint: VEAL BANDANA DID RIP SOON");
1.696 - break;
1.697 - case 4:
1.698 - g_RootMenu.ConsolePrint("Question Yon (4)");
1.699 - g_RootMenu.ConsolePrint("A terrible translation of 'SVN Revision' to Japanese romaji might be ...");
1.700 - g_RootMenu.ConsolePrint("Hint: I TAKE IN AN AIR OK");
1.701 - break;
1.702 - case 5:
1.703 - g_RootMenu.ConsolePrint("Question Go (5)");
1.704 - g_RootMenu.ConsolePrint("What is a fundamental concept in the game of Go?");
1.705 - g_RootMenu.ConsolePrint("Hint: AD LADEN THIEF");
1.706 - break;
1.707 - case 6:
1.708 - g_RootMenu.ConsolePrint("Question Roku (6)");
1.709 - g_RootMenu.ConsolePrint("Why am I asking all these strange questions?");
1.710 - g_RootMenu.ConsolePrint("Hint: CHUBBY TITAN EATS EWE WAGE DATA");
1.711 - break;
1.712 - case 7:
1.713 - g_RootMenu.ConsolePrint("Question Nana (7)");
1.714 - g_RootMenu.ConsolePrint("What is my name?");
1.715 - g_RootMenu.ConsolePrint("Hint: AD MODE LAG US");
1.716 - break;
1.717 - default:
1.718 - break;
1.719 - }
1.720 -
1.721 - s_YamagramState = yamagram;
1.722 -}
1.723 -
1.724 -#if defined ORANGEBOX_BUILD
1.725 -void _IntExt_CallYamagrams(const CCommand &cmd)
1.726 -{
1.727 -#else
1.728 -void _IntExt_CallYamagrams()
1.729 -{
1.730 - CCommand cmd;
1.731 -#endif
1.732 - bool correct = false;
1.733 - const char *arg = cmd.ArgS();
1.734 -
1.735 - if (!arg || arg[0] == '\0')
1.736 - {
1.737 - _YamagramPrinterTwoPointOhOh(s_YamagramState);
1.738 - return;
1.739 - }
1.740 -
1.741 - switch (s_YamagramState)
1.742 - {
1.743 - case 1:
1.744 - correct = !strcasecmp(arg, "eating grass");
1.745 - break;
1.746 - case 2:
1.747 - correct = !strcasecmp(arg, "sombrero");
1.748 - break;
1.749 - case 3:
1.750 - correct = !strcasecmp(arg, "david bailopan anderson");
1.751 - break;
1.752 - case 4:
1.753 - correct = !strcasecmp(arg, "kaitei no kairan");
1.754 - break;
1.755 - case 5:
1.756 - correct = !strcasecmp(arg, "life and death");
1.757 - break;
1.758 - case 6:
1.759 - correct = !strcasecmp(arg, "because gabe wanted it that way");
1.760 - if (correct)
1.761 - {
1.762 - g_RootMenu.ConsolePrint("Congratulations, you have answered 6 of my questions.");
1.763 - g_RootMenu.ConsolePrint("However, I have one final question for you. It wouldn't be nana without it.");
1.764 - g_RootMenu.ConsolePrint("-------------------------------");
1.765 - _YamagramPrinterTwoPointOhOh(7);
1.766 - return;
1.767 - }
1.768 - break;
1.769 - case 7:
1.770 - correct = !strcasecmp(arg, "damaged soul");
1.771 - if (correct)
1.772 - {
1.773 - g_RootMenu.ConsolePrint("You don't know how lucky you are to still be alive!");
1.774 - g_RootMenu.ConsolePrint("Congratulations. You have answered all 7 questions correctly.");
1.775 - g_RootMenu.ConsolePrint("The SourceMod Dev Team will be at your door with anti-Gaben grenades");
1.776 - g_RootMenu.ConsolePrint("within seconds. You will also be provided with a rocket launcher,");
1.777 - g_RootMenu.ConsolePrint("just in case Alfred decides to strike you with a blitzkrieg in retaliation.");
1.778 -
1.779 - s_YamagramState = 0;
1.780 - return;
1.781 - }
1.782 - break;
1.783 - default:
1.784 - break;
1.785 - }
1.786 -
1.787 - if (s_YamagramState > 0)
1.788 - {
1.789 - if (correct)
1.790 - {
1.791 - g_RootMenu.ConsolePrint("Correct! You are one step closer to avoiding the deadly jaws of Gaben.");
1.792 - g_RootMenu.ConsolePrint("-------------------------------");
1.793 - s_YamagramState++;
1.794 - } else {
1.795 - g_RootMenu.ConsolePrint("Wrong! You better be more careful. Gaben may be at your door at any minute.");
1.796 - return;
1.797 - }
1.798 - }
1.799 -
1.800 - _YamagramPrinterTwoPointOhOh(s_YamagramState);
1.801 -}
1.802 -
1.803 -void _IntExt_EnableYamagrams()
1.804 -{
1.805 - static ConCommand *pCmd = NULL;
1.806 - if (!pCmd)
1.807 - {
1.808 - pCmd = new ConCommand("sm_nana", _IntExt_CallYamagrams, "Try these yamagrams!", FCVAR_GAMEDLL);
1.809 - g_RootMenu.ConsolePrint("[SM] Warning: Gaben has been alerted of your actions. You may be eaten.");
1.810 - } else {
1.811 - g_RootMenu.ConsolePrint("[SM] Gaben has already been alerted of your actions...");
1.812 - }
1.813 -}
1.814 -
1.815 -#if defined ORANGEBOX_BUILD
1.816 -void _IntExt_OnHostnameChanged(IConVar *pConVar, const char *oldValue, float flOldValue)
1.817 -#else
1.818 -void _IntExt_OnHostnameChanged(ConVar *pConVar, char const *oldValue)
1.819 -#endif
1.820 -{
1.821 - if (strcmp(oldValue, "Good morning, DS-san.") == 0
1.822 - && strcmp(reinterpret_cast<ConVar *>(pConVar)->GetString(), "Good night, talking desk lamp.") == 0)
1.823 - {
1.824 - _IntExt_EnableYamagrams();
1.825 - }
1.826 -}