extensions/sdktools/vglobals.cpp
author Ruben Gonzalez <drifter01620@gmail.com>
Thu May 22 09:49:27 2014 -0400 (2014-05-22)
changeset 4378 568f4497ef4a
parent 4272 8b39aa02b05b
permissions -rw-r--r--
Update CS:GO team score gamedata.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod SDKTools Extension
     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 "extension.h"
    33 #include "vhelpers.h"
    34 
    35 void **g_pGameRules = NULL;
    36 void *g_EntList = NULL;
    37 CBaseHandle g_ResourceEntity;
    38 
    39 
    40 void InitializeValveGlobals()
    41 {
    42 	g_EntList = gamehelpers->GetGlobalEntityList();
    43 
    44 	/*
    45 	 * g_pGameRules
    46 	 *
    47 	 * First try to lookup pointer directly for platforms with symbols.
    48 	 * If symbols aren't present (Windows or stripped Linux/Mac), 
    49 	 * attempt find via CreateGameRulesObject + offset
    50 	 */
    51 
    52 	char *addr;
    53 	if (g_pGameConf->GetMemSig("g_pGameRules", (void **)&addr) && addr)
    54 	{
    55 		g_pGameRules = reinterpret_cast<void **>(addr);
    56 	}
    57 	else if (g_pGameConf->GetMemSig("CreateGameRulesObject", (void **)&addr) && addr)
    58 	{
    59 		int offset;
    60 		if (!g_pGameConf->GetOffset("g_pGameRules", &offset) || !offset)
    61 		{
    62 			return;
    63 		}
    64 		g_pGameRules = *reinterpret_cast<void ***>(addr + offset);
    65 	}
    66 }
    67 
    68 size_t UTIL_StringToSignature(const char *str, char buffer[], size_t maxlength)
    69 {
    70 	size_t real_bytes = 0;
    71 	size_t length = strlen(str);
    72 
    73 	for (size_t i=0; i<length; i++)
    74 	{
    75 		if (real_bytes >= maxlength)
    76 		{
    77 			break;
    78 		}
    79 		buffer[real_bytes++] = (unsigned char)str[i];
    80 		if (str[i] == '\\'
    81 			&& str[i+1] == 'x')
    82 		{
    83 			if (i + 3 >= length)
    84 			{
    85 				continue;
    86 			}
    87 			/* Get the hex part */
    88 			char s_byte[3];
    89 			int r_byte;
    90 			s_byte[0] = str[i+2];
    91 			s_byte[1] = str[i+3];
    92 			s_byte[2] = '\n';
    93 			/* Read it as an integer */
    94 			sscanf(s_byte, "%x", &r_byte);
    95 			/* Save the value */
    96 			buffer[real_bytes-1] = (unsigned char)r_byte;
    97 			/* Adjust index */
    98 			i += 3;
    99 		}
   100 	}
   101 
   102 	return real_bytes;
   103 }
   104 
   105 bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len)
   106 {
   107 	unsigned char *addr1 = (unsigned char *) addr;
   108 	unsigned char *addr2 = (unsigned char *) sig;
   109 
   110 	for (size_t i = 0; i < len; i++)
   111 	{
   112 		if (addr2[i] == '*')
   113 			continue;
   114 		if (addr1[i] != addr2[i])
   115 			return false;
   116 	}
   117 
   118 	return true;
   119 }
   120 
   121 #if defined PLATFORM_WINDOWS
   122 #define FAKECLIENT_KEY "CreateFakeClient_Windows"
   123 #elif defined PLATFORM_LINUX
   124 #define FAKECLIENT_KEY "CreateFakeClient_Linux"
   125 #elif defined PLATFORM_APPLE
   126 #define FAKECLIENT_KEY "CreateFakeClient_Mac"
   127 #else
   128 #error "Unsupported platform"
   129 #endif
   130 
   131 void GetIServer()
   132 {
   133 	void *addr;
   134 	const char *sigstr;
   135 	char sig[32];
   136 	size_t siglen;
   137 	int offset;
   138 	void *vfunc = NULL;
   139 
   140 	/* Use the symbol if it exists */
   141 	if (g_pGameConf->GetMemSig("sv", &addr) && addr)
   142 	{
   143 		iserver = reinterpret_cast<IServer *>(addr);
   144 		return;
   145 	}
   146 
   147 #if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
   148 	/* Get the CreateFakeClient function pointer */
   149 	if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient)))
   150 	{
   151 		return;
   152 	}
   153 #else
   154 	/* Get the interface manually */
   155 	SourceHook::MemFuncInfo info = {true, -1, 0, 0};
   156 	SourceHook::GetFuncInfo(&IVEngineServer::CreateFakeClient, info);
   157 
   158 	vfunc = enginePatch->GetOrigFunc(info.vtbloffs, info.vtblindex);
   159 	if (!vfunc)
   160 	{
   161 		void **vtable = *reinterpret_cast<void ***>(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs);
   162 		vfunc = vtable[info.vtblindex];
   163 	}
   164 #endif
   165 
   166 	/* Get signature string for IVEngineServer::CreateFakeClient() */
   167 	sigstr = g_pGameConf->GetKeyValue(FAKECLIENT_KEY);
   168 
   169 	if (!sigstr)
   170 	{
   171 		return;
   172 	}
   173 
   174 	/* Convert signature string to signature bytes */
   175 	siglen = UTIL_StringToSignature(sigstr, sig, sizeof(sig));
   176 
   177 	/* Check if we're on the expected function */
   178 	if (!UTIL_VerifySignature(vfunc, sig, siglen))
   179 	{
   180 		return;
   181 	}
   182 
   183 	/* Get the offset into CreateFakeClient */
   184 	if (!g_pGameConf->GetOffset("sv", &offset))
   185 	{
   186 		return;
   187 	}
   188 
   189 	/* Finally we have the interface we were looking for */
   190 	iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
   191 }
   192 
   193 void GetResourceEntity()
   194 {
   195 	g_ResourceEntity.Term();
   196 	
   197 #if SOURCE_ENGINE >= SE_ORANGEBOX
   198 	const char *classname = g_pGameConf->GetKeyValue("ResourceEntityClassname");
   199 	if (classname != NULL)
   200 	{
   201 		for (CBaseEntity *pEntity = (CBaseEntity *)servertools->FirstEntity(); pEntity; pEntity = (CBaseEntity *)servertools->NextEntity(pEntity))
   202 		{
   203 			if (!strcmp(gamehelpers->GetEntityClassname(pEntity), classname))
   204 			{
   205 				g_ResourceEntity = ((IHandleEntity *)pEntity)->GetRefEHandle();
   206 				break;
   207 			}
   208 		}
   209 	}
   210 	else
   211 #endif
   212 	{
   213 		int edictCount = gpGlobals->maxEntities;
   214 
   215 		for (int i=0; i<edictCount; i++)
   216 		{
   217 			edict_t *pEdict = PEntityOfEntIndex(i);
   218 			if (!pEdict || pEdict->IsFree())
   219 			{
   220 				continue;
   221 			}
   222 			if (!pEdict->GetNetworkable())
   223 			{
   224 				continue;
   225 			}
   226 
   227 			IHandleEntity *pHandleEnt = pEdict->GetNetworkable()->GetEntityHandle();
   228 			if (!pHandleEnt)
   229 			{
   230 				continue;
   231 			}
   232 
   233 			ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
   234 			if (FindNestedDataTable(pClass->m_pTable, "DT_PlayerResource"))
   235 			{
   236 				g_ResourceEntity = pHandleEnt->GetRefEHandle();
   237 				break;
   238 			}
   239 		}
   240 	}
   241 }
   242 
   243 const char *GetDTTypeName(int type)
   244 {
   245 	switch (type)
   246 	{
   247 	case DPT_Int:
   248 		{
   249 			return "integer";
   250 		}
   251 	case DPT_Float:
   252 		{
   253 			return "float";
   254 		}
   255 	case DPT_Vector:
   256 		{
   257 			return "vector";
   258 		}
   259 	case DPT_String:
   260 		{
   261 			return "string";
   262 		}
   263 	case DPT_Array:
   264 		{
   265 			return "array";
   266 		}
   267 	case DPT_DataTable:
   268 		{
   269 			return "datatable";
   270 		}
   271 #if SOURCE_ENGINE >= SE_ALIENSWARM
   272 	case DPT_Int64:
   273 		{
   274 			return "int64";
   275 		}
   276 #endif
   277 	default:
   278 		{
   279 			return NULL;
   280 		}
   281 	}
   282 
   283 	return NULL;
   284 }