extensions/sdktools/teamnatives.cpp
author David Anderson <dvander@alliedmods.net>
Sun Nov 11 06:50:50 2007 +0000 (2007-11-11)
changeset 1673 a3674bdc4672
parent 1613 9ed3c8cf2af1
child 1947 e73a1e51833b
permissions -rw-r--r--
fixed bug amb1132 - team finding code crashed ins from null deref
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SDKTools Extension
     5  * Copyright (C) 2004-2007 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 "extension.h"
    33 #include <sh_vector.h>
    34 
    35 struct TeamInfo
    36 {
    37 	const char *ClassName;
    38 	CBaseEntity *pEnt;
    39 };
    40 
    41 SourceHook::CVector<TeamInfo> g_Teams;
    42 
    43 bool FindTeamEntities(SendTable *pTable, const char *name)
    44 {
    45 	int props = pTable->GetNumProps();
    46 	SendProp *prop;
    47 
    48 	for (int i=0; i<props; i++)
    49 	{
    50 		prop = pTable->GetProp(i);
    51 		if (prop->GetDataTable())
    52 		{
    53 			if (strcmp(prop->GetDataTable()->GetName(), name) == 0)
    54 			{
    55 				return true;
    56 			}
    57 			if (FindTeamEntities(prop->GetDataTable(), name))
    58 			{
    59 				return true;
    60 			}
    61 		}
    62 	}
    63 
    64 	return false;
    65 }
    66 
    67 void SDKTools::OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
    68 {
    69 	g_Teams.clear();
    70 	g_Teams.resize(1);
    71 
    72 	for (int i=0; i<edictCount; i++)
    73 	{
    74 		edict_t *pEdict = engine->PEntityOfEntIndex(i);
    75 		if (!pEdict || pEdict->IsFree())
    76 		{
    77 			continue;
    78 		}
    79 		if (!pEdict->GetNetworkable())
    80 		{
    81 			continue;
    82 		}
    83 
    84 		ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
    85 		if (FindTeamEntities(pClass->m_pTable, "DT_Team"))
    86 		{
    87 			SendProp *pTeamNumProp = g_pGameHelpers->FindInSendTable(pClass->GetName(), "m_iTeamNum");
    88 
    89 			if (pTeamNumProp != NULL)
    90 			{
    91 				int offset = pTeamNumProp->GetOffset();
    92 				CBaseEntity *pEnt = pEdict->GetUnknown()->GetBaseEntity();
    93 				int TeamIndex = *(int *)((unsigned char *)pEnt + offset);
    94 
    95 				if (TeamIndex >= (int)g_Teams.size())
    96 				{
    97 					g_Teams.resize(TeamIndex+1);
    98 				}
    99 				g_Teams[TeamIndex].ClassName = pClass->GetName();
   100 				g_Teams[TeamIndex].pEnt = pEnt;
   101 			}
   102 		}
   103 	}
   104 }
   105 
   106 static cell_t GetTeamCount(IPluginContext *pContext, const cell_t *params)
   107 {
   108 	return g_Teams.size();
   109 }
   110 
   111 static cell_t GetTeamName(IPluginContext *pContext, const cell_t *params)
   112 {
   113 	int teamindex = params[1];
   114 	if (teamindex > (int)g_Teams.size())
   115 	{
   116 		pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   117 	}
   118 
   119 	static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_szTeamname")->GetOffset();
   120 	char *name = (char *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
   121 
   122 	pContext->StringToLocalUTF8(params[2], params[3], name, NULL);
   123 
   124 	return 1;
   125 }
   126 
   127 static cell_t GetTeamScore(IPluginContext *pContext, const cell_t *params)
   128 {
   129 	int teamindex = params[1];
   130 	if (teamindex > (int)g_Teams.size())
   131 	{
   132 		pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   133 	}
   134 
   135 	static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
   136 
   137 	return *(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset);
   138 }
   139 
   140 static cell_t SetTeamScore(IPluginContext *pContext, const cell_t *params)
   141 {
   142 	int teamindex = params[1];
   143 	if (teamindex > (int)g_Teams.size())
   144 	{
   145 		pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   146 	}
   147 
   148 	static int offset = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "m_iScore")->GetOffset();
   149 	*(int *)((unsigned char *)g_Teams[teamindex].pEnt + offset) = params[2];
   150 
   151 	return 1;
   152 }
   153 
   154 static cell_t GetTeamClientCount(IPluginContext *pContext, const cell_t *params)
   155 {
   156 	int teamindex = params[1];
   157 	if (teamindex > (int)g_Teams.size())
   158 	{
   159 		pContext->ThrowNativeError("Team index %d is invalid", teamindex);
   160 	}
   161 
   162 	SendProp *pProp = g_pGameHelpers->FindInSendTable(g_Teams[teamindex].ClassName, "\"player_array\"");
   163 	ArrayLengthSendProxyFn fn = pProp->GetArrayLengthProxy();
   164 
   165 	return fn(g_Teams[teamindex].pEnt, 0);
   166 }
   167 
   168 sp_nativeinfo_t g_TeamNatives[] = 
   169 {
   170 	{"GetTeamCount",			GetTeamCount},
   171 	{"GetTeamName",				GetTeamName},
   172 	{"GetTeamScore",			GetTeamScore},
   173 	{"SetTeamScore",			SetTeamScore},
   174 	{"GetTeamClientCount",		GetTeamClientCount},
   175 	{NULL,						NULL}
   176 };