extensions/sdktools/vglobals.cpp
author Nicholas Hastings <skamonkey@gmail.com>
Sat Mar 16 14:11:56 2013 -0400 (2013-03-16)
changeset 3817 87d44c16b4d2
parent 3816 31650bb3c7e8
child 3823 a15fe74da328
permissions -rw-r--r--
Fixed some engine builds failing.
teame06@1245
     1
/**
teame06@1245
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
teame06@1245
     4
 * SourceMod SDKTools Extension
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
teame06@1245
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
teame06@1245
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
teame06@1245
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
teame06@1245
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
faluco@1247
    28
 *
faluco@1247
    29
 * Version: $Id$
faluco@1247
    30
 */
faluco@1247
    31
faluco@1247
    32
#include "extension.h"
skamonkey@3816
    33
#include "vhelpers.h"
faluco@1247
    34
faluco@1247
    35
void **g_pGameRules = NULL;
faluco@1247
    36
void *g_EntList = NULL;
skamonkey@3816
    37
CBaseHandle g_ResourceEntity;
faluco@1247
    38
pred@2746
    39
faluco@1247
    40
void InitializeValveGlobals()
faluco@1247
    41
{
pred@2746
    42
	g_EntList = gamehelpers->GetGlobalEntityList();
faluco@1247
    43
skamonkey@3221
    44
	/*
skamonkey@3221
    45
	 * g_pGameRules
skamonkey@3221
    46
	 *
skamonkey@3221
    47
	 * First try to lookup pointer directly for platforms with symbols.
skamonkey@3221
    48
	 * If symbols aren't present (Windows or stripped Linux/Mac), 
skamonkey@3221
    49
	 * attempt find via CreateGameRulesObject + offset
skamonkey@3221
    50
	 */
faluco@1718
    51
skamonkey@3221
    52
	char *addr;
skamonkey@3221
    53
	if (g_pGameConf->GetMemSig("g_pGameRules", (void **)&addr) && addr)
faluco@1718
    54
	{
skamonkey@3221
    55
		g_pGameRules = reinterpret_cast<void **>(addr);
faluco@1718
    56
	}
skamonkey@3221
    57
	else if (g_pGameConf->GetMemSig("CreateGameRulesObject", (void **)&addr) && addr)
faluco@1247
    58
	{
skamonkey@3221
    59
		int offset;
skamonkey@3221
    60
		if (!g_pGameConf->GetOffset("g_pGameRules", &offset) || !offset)
skamonkey@3221
    61
		{
skamonkey@3221
    62
			return;
skamonkey@3221
    63
		}
skamonkey@3221
    64
		g_pGameRules = *reinterpret_cast<void ***>(addr + offset);
faluco@1247
    65
	}
faluco@1247
    66
}
faluco@1769
    67
ds@2535
    68
size_t UTIL_StringToSignature(const char *str, char buffer[], size_t maxlength)
ds@1952
    69
{
ds@2535
    70
	size_t real_bytes = 0;
ds@2535
    71
	size_t length = strlen(str);
ds@1952
    72
ds@2535
    73
	for (size_t i=0; i<length; i++)
ds@2535
    74
	{
ds@2535
    75
		if (real_bytes >= maxlength)
ds@2535
    76
		{
ds@2535
    77
			break;
ds@2535
    78
		}
ds@2535
    79
		buffer[real_bytes++] = (unsigned char)str[i];
ds@2535
    80
		if (str[i] == '\\'
ds@2535
    81
			&& str[i+1] == 'x')
ds@2535
    82
		{
ds@2535
    83
			if (i + 3 >= length)
ds@2535
    84
			{
ds@2535
    85
				continue;
ds@2535
    86
			}
ds@2535
    87
			/* Get the hex part */
ds@2535
    88
			char s_byte[3];
ds@2535
    89
			int r_byte;
ds@2535
    90
			s_byte[0] = str[i+2];
ds@2535
    91
			s_byte[1] = str[i+3];
ds@2535
    92
			s_byte[2] = '\n';
ds@2535
    93
			/* Read it as an integer */
ds@2535
    94
			sscanf(s_byte, "%x", &r_byte);
ds@2535
    95
			/* Save the value */
ds@2535
    96
			buffer[real_bytes-1] = (unsigned char)r_byte;
ds@2535
    97
			/* Adjust index */
ds@2535
    98
			i += 3;
ds@2535
    99
		}
ds@2535
   100
	}
ds@2535
   101
ds@2535
   102
	return real_bytes;
ds@2535
   103
}
ds@2535
   104
ds@2535
   105
bool UTIL_VerifySignature(const void *addr, const char *sig, size_t len)
ds@2535
   106
{
ds@2535
   107
	unsigned char *addr1 = (unsigned char *) addr;
ds@2535
   108
	unsigned char *addr2 = (unsigned char *) sig;
ds@2535
   109
ds@2535
   110
	for (size_t i = 0; i < len; i++)
ds@1952
   111
	{
ds@1952
   112
		if (addr2[i] == '*')
ds@1952
   113
			continue;
ds@1952
   114
		if (addr1[i] != addr2[i])
ds@1952
   115
			return false;
ds@1952
   116
	}
ds@1952
   117
ds@1952
   118
	return true;
faluco@1773
   119
}
faluco@1773
   120
faluco@1769
   121
#if defined PLATFORM_WINDOWS
faluco@1769
   122
void GetIServer()
faluco@1769
   123
{
ds@2535
   124
	const char *sigstr;
ds@2535
   125
	char sig[32];
ds@2535
   126
	size_t siglen;
faluco@1769
   127
	int offset;
faluco@1769
   128
	void *vfunc = NULL;
faluco@1769
   129
ds@2858
   130
#if defined METAMOD_PLAPI_VERSION || PLAPI_VERSION >= 11
faluco@1769
   131
	/* Get the CreateFakeClient function pointer */
faluco@1769
   132
	if (!(vfunc=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient)))
faluco@1769
   133
	{
faluco@1769
   134
		return;
faluco@1769
   135
	}
faluco@1769
   136
#else
faluco@1769
   137
	/* Get the interface manually */
faluco@1769
   138
	SourceHook::MemFuncInfo info = {true, -1, 0, 0};
faluco@1769
   139
	SourceHook::GetFuncInfo(&IVEngineServer::CreateFakeClient, info);
faluco@1769
   140
faluco@1769
   141
	vfunc = enginePatch->GetOrigFunc(info.vtbloffs, info.vtblindex);
faluco@1769
   142
	if (!vfunc)
faluco@1769
   143
	{
faluco@1769
   144
		void **vtable = *reinterpret_cast<void ***>(enginePatch->GetThisPtr() + info.thisptroffs + info.vtbloffs);
faluco@1769
   145
		vfunc = vtable[info.vtblindex];
faluco@1769
   146
	}
ds@2535
   147
#endif
ds@2535
   148
ds@2535
   149
	/* Get signature string for IVEngineServer::CreateFakeClient() */
ds@2535
   150
	sigstr = g_pGameConf->GetKeyValue("CreateFakeClient_Windows");
ds@2535
   151
ds@2535
   152
	if (!sigstr)
faluco@1773
   153
	{
faluco@1773
   154
		return;
faluco@1773
   155
	}
faluco@1769
   156
ds@2535
   157
	/* Convert signature string to signature bytes */
ds@2535
   158
	siglen = UTIL_StringToSignature(sigstr, sig, sizeof(sig));
ds@2535
   159
ds@2535
   160
	/* Check if we're on the expected function */
ds@2535
   161
	if (!UTIL_VerifySignature(vfunc, sig, siglen))
ds@2535
   162
	{
ds@2535
   163
		return;
ds@2535
   164
	}
ds@2535
   165
ds@2535
   166
	/* Get the offset into CreateFakeClient */
ds@2535
   167
	if (!g_pGameConf->GetOffset("sv", &offset))
ds@2535
   168
	{
ds@2535
   169
		return;
ds@2535
   170
	}
ds@2535
   171
ds@2535
   172
	/* Finally we have the interface we were looking for */
faluco@1769
   173
	iserver = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(vfunc) + offset);
faluco@1769
   174
}
faluco@1769
   175
#elif defined PLATFORM_POSIX
faluco@1769
   176
void GetIServer()
faluco@1769
   177
{
faluco@1769
   178
	void *addr;
faluco@1769
   179
	if (!g_pGameConf->GetMemSig("sv", &addr) || !addr)
faluco@1769
   180
	{
faluco@1769
   181
		return;
faluco@1769
   182
	}
faluco@1769
   183
faluco@1773
   184
	iserver = reinterpret_cast<IServer *>(addr);
faluco@1769
   185
}
faluco@1769
   186
#endif
skamonkey@3333
   187
skamonkey@3816
   188
void GetResourceEntity()
skamonkey@3816
   189
{
skamonkey@3816
   190
	g_ResourceEntity.Term();
skamonkey@3816
   191
	
skamonkey@3817
   192
#if SOURCE_ENGINE >= SE_ORANGEBOX
skamonkey@3816
   193
	const char *classname = g_pGameConf->GetKeyValue("ResourceEntityClassname");
skamonkey@3816
   194
	if (classname != NULL)
skamonkey@3816
   195
	{
skamonkey@3817
   196
		for (CBaseEntity *pEntity = (CBaseEntity *)servertools->FirstEntity(); pEntity; pEntity = (CBaseEntity *)servertools->NextEntity(pEntity))
skamonkey@3816
   197
		{
skamonkey@3817
   198
			if (!strcmp(gamehelpers->GetEntityClassname(pEntity), classname))
skamonkey@3816
   199
			{
skamonkey@3816
   200
				g_ResourceEntity = ((IHandleEntity *)pEntity)->GetRefEHandle();
skamonkey@3816
   201
				break;
skamonkey@3816
   202
			}
skamonkey@3816
   203
		}
skamonkey@3816
   204
	}
skamonkey@3816
   205
	else
skamonkey@3817
   206
#endif
skamonkey@3816
   207
	{
skamonkey@3816
   208
		int edictCount = gpGlobals->maxEntities;
skamonkey@3816
   209
skamonkey@3816
   210
		for (int i=0; i<edictCount; i++)
skamonkey@3816
   211
		{
skamonkey@3816
   212
			edict_t *pEdict = PEntityOfEntIndex(i);
skamonkey@3816
   213
			if (!pEdict || pEdict->IsFree())
skamonkey@3816
   214
			{
skamonkey@3816
   215
				continue;
skamonkey@3816
   216
			}
skamonkey@3816
   217
			if (!pEdict->GetNetworkable())
skamonkey@3816
   218
			{
skamonkey@3816
   219
				continue;
skamonkey@3816
   220
			}
skamonkey@3816
   221
skamonkey@3816
   222
			IHandleEntity *pHandleEnt = pEdict->GetNetworkable()->GetEntityHandle();
skamonkey@3816
   223
			if (!pHandleEnt)
skamonkey@3816
   224
			{
skamonkey@3816
   225
				continue;
skamonkey@3816
   226
			}
skamonkey@3816
   227
skamonkey@3816
   228
			ServerClass *pClass = pEdict->GetNetworkable()->GetServerClass();
skamonkey@3816
   229
			if (FindNestedDataTable(pClass->m_pTable, "DT_PlayerResource"))
skamonkey@3816
   230
			{
skamonkey@3816
   231
				g_ResourceEntity = pHandleEnt->GetRefEHandle();
skamonkey@3816
   232
				break;
skamonkey@3816
   233
			}
skamonkey@3816
   234
		}
skamonkey@3816
   235
	}
skamonkey@3816
   236
}
skamonkey@3816
   237
skamonkey@3333
   238
const char *GetDTTypeName(int type)
skamonkey@3333
   239
{
skamonkey@3333
   240
	switch (type)
skamonkey@3333
   241
	{
skamonkey@3333
   242
	case DPT_Int:
skamonkey@3333
   243
		{
skamonkey@3333
   244
			return "integer";
skamonkey@3333
   245
		}
skamonkey@3333
   246
	case DPT_Float:
skamonkey@3333
   247
		{
skamonkey@3333
   248
			return "float";
skamonkey@3333
   249
		}
skamonkey@3333
   250
	case DPT_Vector:
skamonkey@3333
   251
		{
skamonkey@3333
   252
			return "vector";
skamonkey@3333
   253
		}
skamonkey@3333
   254
	case DPT_String:
skamonkey@3333
   255
		{
skamonkey@3333
   256
			return "string";
skamonkey@3333
   257
		}
skamonkey@3333
   258
	case DPT_Array:
skamonkey@3333
   259
		{
skamonkey@3333
   260
			return "array";
skamonkey@3333
   261
		}
skamonkey@3333
   262
	case DPT_DataTable:
skamonkey@3333
   263
		{
skamonkey@3333
   264
			return "datatable";
skamonkey@3333
   265
		}
skamonkey@3333
   266
	default:
skamonkey@3333
   267
		{
skamonkey@3333
   268
			return NULL;
skamonkey@3333
   269
		}
skamonkey@3333
   270
	}
skamonkey@3333
   271
skamonkey@3333
   272
	return NULL;
skamonkey@3333
   273
}