core/concmd_cleaner.cpp
author David Anderson <dvander@alliedmods.net>
Sun Feb 08 15:40:48 2009 -0500 (2009-02-08)
changeset 2571 5c995a647735
parent 2400 76b7b4575e21
child 2806 686c283b08fc
permissions -rw-r--r--
Fixed documentation typos in dbi.inc (bug 3587).
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sm_globals.h"
    33 #include <sh_list.h>
    34 #include <convar.h>
    35 #include "concmd_cleaner.h"
    36 #include "sm_stringutil.h"
    37 #include "sourcemm_api.h"
    38 #include "compat_wrappers.h"
    39 
    40 #if SOURCE_ENGINE >= SE_ORANGEBOX
    41 SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
    42 #endif
    43 
    44 using namespace SourceHook;
    45 
    46 struct ConCommandInfo
    47 {
    48 	ConCommandBase *pBase;
    49 	IConCommandTracker *cls;
    50 	char name[64];
    51 };
    52 
    53 List<ConCommandInfo *> tracked_bases;
    54 
    55 ConCommandBase *FindConCommandBase(const char *name);
    56 
    57 class ConCommandCleaner : public SMGlobalClass
    58 {
    59 public:
    60 #if SOURCE_ENGINE >= SE_ORANGEBOX
    61 	void OnSourceModAllInitialized()
    62 	{
    63 		SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
    64 	}
    65 
    66 	void OnSourceModShutdown()
    67 	{
    68 		SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
    69 	}
    70 #endif
    71 
    72 	void UnlinkConCommandBase(ConCommandBase *pBase)
    73 	{
    74 		ConCommandInfo *pInfo;
    75 		List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
    76 
    77 		if (pBase)
    78 		{
    79 			while (iter != tracked_bases.end())
    80 			{
    81 				if ((*iter)->pBase == pBase)
    82 				{
    83 					pInfo = (*iter);
    84 					iter = tracked_bases.erase(iter);
    85 					pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
    86 					delete pInfo;
    87 				}
    88 				else
    89 				{
    90 					iter++;
    91 				}
    92 			}
    93 		}
    94 		else
    95 		{
    96 			while (iter != tracked_bases.end())
    97 			{
    98 				/* This is just god-awful! */
    99 				if (FindCommandBase((*iter)->name) != (*iter)->pBase)
   100 				{
   101 					pInfo = (*iter);
   102 					iter = tracked_bases.erase(iter);
   103 					pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false);
   104 					delete pInfo;
   105 				}
   106 				else
   107 				{
   108 					iter++;
   109 				}
   110 			}
   111 		}
   112 	}
   113 
   114 	void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
   115 	{
   116 		ConCommandInfo *info = new ConCommandInfo;
   117 
   118 		info->pBase = pBase;
   119 		info->cls = cls;
   120 		strncopy(info->name, pBase->GetName(), sizeof(info->name));
   121 
   122 		tracked_bases.push_back(info);
   123 	}
   124 
   125 	void RemoveTarget(ConCommandBase *pBase, IConCommandTracker *cls)
   126 	{
   127 		List<ConCommandInfo *>::iterator iter;
   128 		ConCommandInfo *pInfo;
   129 
   130 		iter = tracked_bases.begin();
   131 		while (iter != tracked_bases.end())
   132 		{
   133 			pInfo = (*iter);
   134 			if (pInfo->pBase == pBase && pInfo->cls == cls)
   135 			{
   136 				delete pInfo;
   137 				iter = tracked_bases.erase(iter);
   138 			}
   139 			else
   140 			{
   141 				iter++;
   142 			}
   143 		}
   144 	}
   145 } s_ConCmdTracker;
   146 
   147 void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
   148 {
   149 	s_ConCmdTracker.AddTarget(pBase, me);
   150 }
   151 
   152 void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
   153 {
   154 	s_ConCmdTracker.RemoveTarget(pBase, me);
   155 }
   156 
   157 void Global_OnUnlinkConCommandBase(ConCommandBase *pBase)
   158 {
   159 	s_ConCmdTracker.UnlinkConCommandBase(pBase);
   160 }