core/concmd_cleaner.cpp
author David Anderson <dvander@alliedmods.net>
Mon Sep 07 21:29:18 2009 -0700 (2009-09-07)
changeset 2798 6dd90eaa0593
parent 2400 76b7b4575e21
child 2806 686c283b08fc
permissions -rw-r--r--
Fixed invalid array access in PluginSys (bug 3933, r=pred).
dvander@1582
     1
/**
dvander@1582
     2
 * vim: set ts=4 :
dvander@1582
     3
 * =============================================================================
dvander@1582
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 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"
ds@2400
    38
#include "compat_wrappers.h"
dvander@1582
    39
ds@2400
    40
#if SOURCE_ENGINE >= SE_ORANGEBOX
dvander@1582
    41
SH_DECL_HOOK1_void(ICvar, UnregisterConCommand, SH_NOATTRIB, 0, ConCommandBase *);
dvander@1582
    42
#endif
dvander@1582
    43
dvander@1582
    44
using namespace SourceHook;
dvander@1582
    45
dvander@1582
    46
struct ConCommandInfo
dvander@1582
    47
{
dvander@1582
    48
	ConCommandBase *pBase;
dvander@1582
    49
	IConCommandTracker *cls;
dvander@1582
    50
	char name[64];
dvander@1582
    51
};
dvander@1582
    52
dvander@1582
    53
List<ConCommandInfo *> tracked_bases;
dvander@1582
    54
dvander@1582
    55
ConCommandBase *FindConCommandBase(const char *name);
dvander@1582
    56
dvander@1582
    57
class ConCommandCleaner : public SMGlobalClass
dvander@1582
    58
{
dvander@1582
    59
public:
ds@2400
    60
#if SOURCE_ENGINE >= SE_ORANGEBOX
dvander@1582
    61
	void OnSourceModAllInitialized()
dvander@1582
    62
	{
dvander@1585
    63
		SH_ADD_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
dvander@1582
    64
	}
dvander@1582
    65
dvander@1582
    66
	void OnSourceModShutdown()
dvander@1582
    67
	{
dvander@1585
    68
		SH_REMOVE_HOOK_MEMFUNC(ICvar, UnregisterConCommand, icvar, this, &ConCommandCleaner::UnlinkConCommandBase, false);
dvander@1582
    69
	}
dvander@1582
    70
#endif
dvander@1582
    71
dvander@1582
    72
	void UnlinkConCommandBase(ConCommandBase *pBase)
dvander@1582
    73
	{
dvander@1582
    74
		ConCommandInfo *pInfo;
dvander@1582
    75
		List<ConCommandInfo *>::iterator iter = tracked_bases.begin();
dvander@1582
    76
dvander@1582
    77
		if (pBase)
dvander@1582
    78
		{
dvander@1582
    79
			while (iter != tracked_bases.end())
dvander@1582
    80
			{
dvander@1582
    81
				if ((*iter)->pBase == pBase)
dvander@1582
    82
				{
dvander@1582
    83
					pInfo = (*iter);
dvander@1582
    84
					iter = tracked_bases.erase(iter);
dvander@1582
    85
					pInfo->cls->OnUnlinkConCommandBase(pBase, pBase->GetName(), true);
dvander@1582
    86
					delete pInfo;
dvander@1582
    87
				}
dvander@1582
    88
				else
dvander@1582
    89
				{
dvander@1582
    90
					iter++;
dvander@1582
    91
				}
dvander@1582
    92
			}
dvander@1582
    93
		}
dvander@1582
    94
		else
dvander@1582
    95
		{
dvander@1582
    96
			while (iter != tracked_bases.end())
dvander@1582
    97
			{
dvander@1582
    98
				/* This is just god-awful! */
ds@2400
    99
				if (FindCommandBase((*iter)->name) != (*iter)->pBase)
dvander@1582
   100
				{
dvander@1582
   101
					pInfo = (*iter);
dvander@1582
   102
					iter = tracked_bases.erase(iter);
dvander@1584
   103
					pInfo->cls->OnUnlinkConCommandBase(pBase, pInfo->name, false);
dvander@1582
   104
					delete pInfo;
dvander@1582
   105
				}
dvander@1582
   106
				else
dvander@1582
   107
				{
dvander@1582
   108
					iter++;
dvander@1582
   109
				}
dvander@1582
   110
			}
dvander@1582
   111
		}
dvander@1582
   112
	}
dvander@1582
   113
dvander@1582
   114
	void AddTarget(ConCommandBase *pBase, IConCommandTracker *cls)
dvander@1582
   115
	{
dvander@1582
   116
		ConCommandInfo *info = new ConCommandInfo;
dvander@1582
   117
dvander@1582
   118
		info->pBase = pBase;
dvander@1582
   119
		info->cls = cls;
dvander@1582
   120
		strncopy(info->name, pBase->GetName(), sizeof(info->name));
dvander@1582
   121
dvander@1582
   122
		tracked_bases.push_back(info);
dvander@1582
   123
	}
dvander@1582
   124
dvander@1582
   125
	void RemoveTarget(ConCommandBase *pBase, IConCommandTracker *cls)
dvander@1582
   126
	{
dvander@1582
   127
		List<ConCommandInfo *>::iterator iter;
dvander@1582
   128
		ConCommandInfo *pInfo;
dvander@1582
   129
dvander@1582
   130
		iter = tracked_bases.begin();
dvander@1582
   131
		while (iter != tracked_bases.end())
dvander@1582
   132
		{
dvander@1582
   133
			pInfo = (*iter);
dvander@1582
   134
			if (pInfo->pBase == pBase && pInfo->cls == cls)
dvander@1582
   135
			{
dvander@1582
   136
				delete pInfo;
dvander@1582
   137
				iter = tracked_bases.erase(iter);
dvander@1582
   138
			}
dvander@1582
   139
			else
dvander@1582
   140
			{
dvander@1582
   141
				iter++;
dvander@1582
   142
			}
dvander@1582
   143
		}
dvander@1582
   144
	}
dvander@1582
   145
} s_ConCmdTracker;
dvander@1582
   146
dvander@1582
   147
void TrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
dvander@1582
   148
{
dvander@1582
   149
	s_ConCmdTracker.AddTarget(pBase, me);
dvander@1582
   150
}
dvander@1582
   151
dvander@1582
   152
void UntrackConCommandBase(ConCommandBase *pBase, IConCommandTracker *me)
dvander@1582
   153
{
dvander@1582
   154
	s_ConCmdTracker.RemoveTarget(pBase, me);
dvander@1582
   155
}
dvander@1582
   156
dvander@1582
   157
void Global_OnUnlinkConCommandBase(ConCommandBase *pBase)
dvander@1582
   158
{
dvander@1582
   159
	s_ConCmdTracker.UnlinkConCommandBase(pBase);
dvander@1582
   160
}