extensions/sdktools/vglobals.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Wed Aug 14 14:20:57 2013 -0400 (2013-08-14)
changeset 4008 490b01aa0683
parent 3823 a15fe74da328
child 4272 8b39aa02b05b
permissions -rw-r--r--
Updated some CS:GO 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 void GetIServer()
   123 {
   124 	const char *sigstr;
   125 	char sig[32];
   126 	size_t siglen;
   127 	int offset;
   128 	void *vfunc = NULL;
   129 
   130 #if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
   131 	/* Get the CreateFakeClient function pointer */
   132 	if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient)))
   133 	{
   134 		return;
   135 	}
   136 #else
   137 	/* Get the interface manually */
   138 	SourceHook::MemFuncInfo info = {true, -1, 0, 0};
   139 	SourceHook::GetFuncInfo(&IVEngineServer::CreateFakeClient, info);
   140 
   141 	vfunc = enginePatch->GetOrigFunc(info.vtbloffs, info.vtblindex);
   142 	if (!vfunc)
   143 	{
   144 		void **vtable = *reinterpret_cast<void ***>(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs);
   145 		vfunc = vtable[info.vtblindex];
   146 	}
   147 #endif
   148 
   149 	/* Get signature string for IVEngineServer::CreateFakeClient() */
   150 	sigstr = g_pGameConf->GetKeyValue("CreateFakeClient_Windows");
   151 
   152 	if (!sigstr)
   153 	{
   154 		return;
   155 	}
   156 
   157 	/* Convert signature string to signature bytes */
   158 	siglen = UTIL_StringToSignature(sigstr, sig, sizeof(sig));
   159 
   160 	/* Check if we're on the expected function */
   161 	if (!UTIL_VerifySignature(vfunc, sig, siglen))
   162 	{
   163 		return;
   164 	}
   165 
   166 	/* Get the offset into CreateFakeClient */
   167 	if (!g_pGameConf->GetOffset("sv", &offset))
   168 	{
   169 		return;
   170 	}
   171 
   172 	/* Finally we have the interface we were looking for */
   173 	iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
   174 }
   175 #elif defined PLATFORM_POSIX
   176 void GetIServer()
   177 {
   178 	void *addr;
   179 	if (!g_pGameConf->GetMemSig("sv", &addr) || !addr)
   180 	{
   181 		return;
   182 	}
   183 
   184 	iserver = reinterpret_cast<IServer *>(addr);
   185 }
   186 #endif
   187 
   188 void GetResourceEntity()
   189 {
   190 	g_ResourceEntity.Term();
   191 	
   192 #if SOURCE_ENGINE >= SE_ORANGEBOX
   193 	const char *classname = g_pGameConf->GetKeyValue("ResourceEntityClassname");
   194 	if (classname != NULL)
   195 	{
   196 		for (CBaseEntity *pEntity = (CBaseEntity *)servertools->FirstEntity(); pEntity; pEntity = (CBaseEntity *)servertools->NextEntity(pEntity))
   197 		{
   198 			if (!strcmp(gamehelpers->GetEntityClassname(pEntity), classname))
   199 			{
   200 				g_ResourceEntity = ((IHandleEntity *)pEntity)->GetRefEHandle();
   201 				break;
   202 			}
   203 		}
   204 	}
   205 	else
   206 #endif
   207 	{
   208 		int edictCount = gpGlobals->maxEntities;
   209 
   210 		for (int i=0; i<edictCount; i++)
   211 		{
   212 			edict_t *pEdict = PEntityOfEntIndex(i);
   213 			if (!pEdict || pEdict->IsFree())
   214 			{
   215 				continue;
   216 			}
   217 			if (!pEdict->GetNetworkable())
   218 			{
   219 				continue;
   220 			}
   221 
   222 			IHandleEntity *pHandleEnt = pEdict->GetNetworkable()->GetEntityHandle();
   223 			if (!pHandleEnt)
   224 			{
   225 				continue;
   226 			}
   227 
   228 			ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
   229 			if (FindNestedDataTable(pClass->m_pTable, "DT_PlayerResource"))
   230 			{
   231 				g_ResourceEntity = pHandleEnt->GetRefEHandle();
   232 				break;
   233 			}
   234 		}
   235 	}
   236 }
   237 
   238 const char *GetDTTypeName(int type)
   239 {
   240 	switch (type)
   241 	{
   242 	case DPT_Int:
   243 		{
   244 			return "integer";
   245 		}
   246 	case DPT_Float:
   247 		{
   248 			return "float";
   249 		}
   250 	case DPT_Vector:
   251 		{
   252 			return "vector";
   253 		}
   254 	case DPT_String:
   255 		{
   256 			return "string";
   257 		}
   258 	case DPT_Array:
   259 		{
   260 			return "array";
   261 		}
   262 	case DPT_DataTable:
   263 		{
   264 			return "datatable";
   265 		}
   266 #if SOURCE_ENGINE >= SE_ALIENSWARM
   267 	case DPT_Int64:
   268 		{
   269 			return "int64";
   270 		}
   271 #endif
   272 	default:
   273 		{
   274 			return NULL;
   275 		}
   276 	}
   277 
   278 	return NULL;
   279 }