core/concmd_cleaner.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 16 16:06:18 2008 -0800 (2008-11-16)
changeset 2411 8dfaa3d730b5
parent 2289 44045ead61cd
child 2400 76b7b4575e21
permissions -rw-r--r--
Removed pointless "systems" folder from core.
     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 }