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