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