core/concmd_cleaner.cpp
author Scott Ehlert <ds@alliedmods.net>
Sun Mar 30 07:00:22 2008 +0000 (2008-03-30)
changeset 1952 b7aa2b626807
child 2289 44045ead61cd
permissions -rw-r--r--
Spring Cleaning, Part Ichi (1)
Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile
     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 
    39 #if defined ORANGEBOX_BUILD
    40 SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
    41 #endif
    42 
    43 using namespace SourceHook;
    44 
    45 struct ConCommandInfo
    46 {
    47 	ConCommandBase *pBase;
    48 	IConCommandTracker *cls;
    49 	char name[64];
    50 };
    51 
    52 List<ConCommandInfo *> tracked_bases;
    53 
    54 ConCommandBase *FindConCommandBase(const char *name);
    55 
    56 class ConCommandCleaner : public SMGlobalClass
    57 {
    58 public:
    59 #if defined ORANGEBOX_BUILD
    60 	void OnSourceModAllInitialized()
    61 	{
    62 		SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
    63 	}
    64 
    65 	void OnSourceModShutdown()
    66 	{
    67 		SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
    68 	}
    69 #endif
    70 
    71 	void UnlinkConCommandBase(ConCommandBase *pBase)
    72 	{
    73 		ConCommandInfo *pInfo;
    74 		List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
    75 
    76 		if (pBase)
    77 		{
    78 			while (iter != tracked_bases.end())
    79 			{
    80 				if ((*iter)->pBase == pBase)
    81 				{
    82 					pInfo = (*iter);
    83 					iter = tracked_bases.erase(iter);
    84 					pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
    85 					delete pInfo;
    86 				}
    87 				else
    88 				{
    89 					iter++;
    90 				}
    91 			}
    92 		}
    93 		else
    94 		{
    95 			while (iter != tracked_bases.end())
    96 			{
    97 				/* This is just god-awful! */
    98 				if (FindConCommandBase((*iter)->name) != (*iter)->pBase)
    99 				{
   100 					pInfo = (*iter);
   101 					iter = tracked_bases.erase(iter);
   102 					pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false);
   103 					delete pInfo;
   104 				}
   105 				else
   106 				{
   107 					iter++;
   108 				}
   109 			}
   110 		}
   111 	}
   112 
   113 	void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
   114 	{
   115 		ConCommandInfo *info = new ConCommandInfo;
   116 
   117 		info->pBase = pBase;
   118 		info->cls = cls;
   119 		strncopy(info->name, pBase->GetName(), sizeof(info->name));
   120 
   121 		tracked_bases.push_back(info);
   122 	}
   123 
   124 	void RemoveTarget(ConCommandBase *pBase, IConCommandTracker *cls)
   125 	{
   126 		List<ConCommandInfo *>::iterator iter;
   127 		ConCommandInfo *pInfo;
   128 
   129 		iter = tracked_bases.begin();
   130 		while (iter != tracked_bases.end())
   131 		{
   132 			pInfo = (*iter);
   133 			if (pInfo->pBase == pBase && pInfo->cls == cls)
   134 			{
   135 				delete pInfo;
   136 				iter = tracked_bases.erase(iter);
   137 			}
   138 			else
   139 			{
   140 				iter++;
   141 			}
   142 		}
   143 	}
   144 } s_ConCmdTracker;
   145 
   146 ConCommandBase *FindConCommandBase(const char *name)
   147 {
   148 	const ConCommandBase *pBase = icvar->GetCommands();
   149 
   150 	while (pBase != NULL)
   151 	{
   152 		if (strcmp(pBase->GetName(), name) == 0)
   153 		{
   154 			return const_cast<ConCommandBase *>(pBase);
   155 		}
   156 		pBase = pBase->GetNext();
   157 	}
   158 
   159 	return NULL;
   160 }
   161 
   162 void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
   163 {
   164 	s_ConCmdTracker.AddTarget(pBase, me);
   165 }
   166 
   167 void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
   168 {
   169 	s_ConCmdTracker.RemoveTarget(pBase, me);
   170 }
   171 
   172 void Global_OnUnlinkConCommandBase(ConCommandBase *pBase)
   173 {
   174 	s_ConCmdTracker.UnlinkConCommandBase(pBase);
   175 }