extensions/sdktools/vhelpers.cpp
author Borja Ferrer <faluco@alliedmods.net>
Sun May 04 15:52:34 2008 +0000 (2008-05-04)
changeset 2038 a317edffcfa7
parent 2037 561de8cbcda5
child 2157 e3846fb56e8f
permissions -rw-r--r--
removed these functions in tf2 for now to avoid more crashes
ds@1952
     1
/**
ds@1952
     2
 * vim: set ts=4 :
ds@1952
     3
 * =============================================================================
ds@1952
     4
 * SourceMod SDKTools Extension
ds@1952
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1952
     6
 * =============================================================================
ds@1952
     7
 *
ds@1952
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1952
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1952
    10
 * Free Software Foundation.
ds@1952
    11
 * 
ds@1952
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1952
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1952
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1952
    15
 * details.
ds@1952
    16
 *
ds@1952
    17
 * You should have received a copy of the GNU General Public License along with
ds@1952
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
ds@1952
    19
 *
ds@1952
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1952
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1952
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1952
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1952
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1952
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1952
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1952
    27
 * or <http://www.sourcemod.net/license.php>.
ds@1952
    28
 *
ds@1952
    29
 * Version: $Id$
ds@1952
    30
 */
ds@1952
    31
ds@1952
    32
#include "extension.h"
ds@1952
    33
#include "util.h"
ds@1952
    34
#include "vhelpers.h"
ds@1952
    35
ds@1952
    36
CallHelper s_Teleport;
ds@1952
    37
CallHelper s_GetVelocity;
ds@1952
    38
CallHelper s_EyeAngles;
ds@1952
    39
ds@1952
    40
class CTraceFilterSimple : public CTraceFilterEntitiesOnly
ds@1952
    41
{
ds@1952
    42
public:
ds@1952
    43
	CTraceFilterSimple(const IHandleEntity *passentity): m_pPassEnt(passentity)
ds@1952
    44
	{
ds@1952
    45
	}
ds@1952
    46
	virtual bool ShouldHitEntity(IHandleEntity *pServerEntity, int contentsMask)
ds@1952
    47
	{
ds@1952
    48
		if (pServerEntity == m_pPassEnt)
ds@1952
    49
		{
ds@1952
    50
			return false;
ds@1952
    51
		}
ds@1952
    52
		return true;
ds@1952
    53
	}
ds@1952
    54
private:
ds@1952
    55
	const IHandleEntity *m_pPassEnt;
ds@1952
    56
};
ds@1952
    57
ds@1952
    58
bool SetupTeleport()
ds@1952
    59
{
ds@1952
    60
	if (s_Teleport.setup)
ds@1952
    61
	{
ds@1952
    62
		return s_Teleport.supported;
ds@1952
    63
	}
ds@1952
    64
ds@1952
    65
	/* Setup Teleport */
ds@1952
    66
	int offset;
ds@1952
    67
	if (g_pGameConf->GetOffset("Teleport", &offset))
ds@1952
    68
	{
ds@1952
    69
		PassInfo info[3];
ds@1952
    70
		info[0].flags = info[1].flags = info[2].flags = PASSFLAG_BYVAL;
ds@1952
    71
		info[0].size = info[1].size = info[2].size = sizeof(void *);
ds@1952
    72
		info[0].type = info[1].type = info[2].type = PassType_Basic;
ds@1952
    73
ds@1952
    74
		s_Teleport.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 3);
ds@1952
    75
ds@1952
    76
		if (s_Teleport.call != NULL)
ds@1952
    77
		{
ds@1952
    78
			s_Teleport.supported = true;
ds@1952
    79
		}
ds@1952
    80
	}
ds@1952
    81
ds@1952
    82
	s_Teleport.setup = true;
ds@1952
    83
ds@1952
    84
	return s_Teleport.supported;
ds@1952
    85
}
ds@1952
    86
ds@1952
    87
void Teleport(CBaseEntity *pEntity, Vector *origin, QAngle *ang, Vector *velocity)
ds@1952
    88
{
ds@1952
    89
	unsigned char params[sizeof(void *) * 4];
ds@1952
    90
	unsigned char *vptr = params;
ds@1952
    91
	*(CBaseEntity **)vptr = pEntity;
ds@1952
    92
	vptr += sizeof(CBaseEntity *);
ds@1952
    93
	*(Vector **)vptr = origin;
ds@1952
    94
	vptr += sizeof(Vector *);
ds@1952
    95
	*(QAngle **)vptr = ang;
ds@1952
    96
	vptr += sizeof(QAngle *);
ds@1952
    97
	*(Vector **)vptr = velocity;
ds@1952
    98
	
ds@1952
    99
	s_Teleport.call->Execute(params, NULL);
ds@1952
   100
}
ds@1952
   101
ds@1952
   102
bool IsTeleportSupported()
ds@1952
   103
{
ds@1952
   104
	return SetupTeleport();
ds@1952
   105
}
ds@1952
   106
ds@1952
   107
bool SetupGetVelocity()
ds@1952
   108
{
ds@1952
   109
	if (s_GetVelocity.setup)
ds@1952
   110
	{
ds@1952
   111
		return s_GetVelocity.supported;
ds@1952
   112
	}
ds@1952
   113
ds@1952
   114
	int offset;
ds@1952
   115
	if (g_pGameConf->GetOffset("GetVelocity", &offset))
ds@1952
   116
	{
ds@1952
   117
		PassInfo info[2];
ds@1952
   118
		info[0].flags = info[1].flags = PASSFLAG_BYVAL;
ds@1952
   119
		info[0].size = info[1].size = sizeof(void *);
ds@1952
   120
		info[0].type = info[1].type = PassType_Basic;
ds@1952
   121
ds@1952
   122
		s_GetVelocity.call = g_pBinTools->CreateVCall(offset, 0, 0, NULL, info, 2);
ds@1952
   123
ds@1952
   124
		if (s_GetVelocity.call != NULL)
ds@1952
   125
		{
ds@1952
   126
			s_GetVelocity.supported = true;
ds@1952
   127
		}
ds@1952
   128
	}
ds@1952
   129
ds@1952
   130
	s_GetVelocity.setup = true;
ds@1952
   131
ds@1952
   132
	return s_GetVelocity.supported;
ds@1952
   133
}
ds@1952
   134
ds@1952
   135
void GetVelocity(CBaseEntity *pEntity, Vector *velocity, AngularImpulse *angvelocity)
ds@1952
   136
{
ds@1952
   137
	unsigned char params[sizeof(void *) * 3];
ds@1952
   138
	unsigned char *vptr = params;
ds@1952
   139
	*(CBaseEntity **)vptr = pEntity;
ds@1952
   140
	vptr += sizeof(CBaseEntity *);
ds@1952
   141
	*(Vector **)vptr = velocity;
ds@1952
   142
	vptr += sizeof(Vector *);
ds@1952
   143
	*(AngularImpulse **)vptr = angvelocity;
ds@1952
   144
ds@1952
   145
	s_GetVelocity.call->Execute(params, NULL);
ds@1952
   146
}
ds@1952
   147
ds@1952
   148
bool IsGetVelocitySupported()
ds@1952
   149
{
ds@1952
   150
	return SetupGetVelocity();
ds@1952
   151
}
ds@1952
   152
ds@1952
   153
bool SetupGetEyeAngles()
ds@1952
   154
{
ds@1952
   155
	if (s_EyeAngles.setup)
ds@1952
   156
	{
ds@1952
   157
		return s_EyeAngles.supported;
ds@1952
   158
	}
ds@1952
   159
ds@1952
   160
	int offset;
ds@1952
   161
	if (g_pGameConf->GetOffset("EyeAngles", &offset))
ds@1952
   162
	{
ds@2037
   163
		PassInfo info[1];
ds@2037
   164
		info[0].flags = PASSFLAG_BYVAL;
ds@2037
   165
		info[0].size = sizeof(void *);
ds@2037
   166
		info[0].type = PassType_Basic;
ds@1952
   167
ds@2037
   168
		s_EyeAngles.call = g_pBinTools->CreateVCall(offset, 0, 0, info, NULL, 0);
ds@1952
   169
ds@1952
   170
		if (s_EyeAngles.call != NULL)
ds@1952
   171
		{
ds@1952
   172
			s_EyeAngles.supported = true;
ds@1952
   173
		}
ds@1952
   174
	}
ds@1952
   175
ds@1952
   176
	s_EyeAngles.setup = true;
ds@1952
   177
ds@1952
   178
	return s_EyeAngles.supported;
ds@1952
   179
}
ds@1952
   180
ds@1952
   181
bool GetEyeAngles(CBaseEntity *pEntity, QAngle *pAngles)
ds@1952
   182
{
ds@1952
   183
	if (!IsEyeAnglesSupported())
ds@1952
   184
	{
ds@1952
   185
		return false;
ds@1952
   186
	}
ds@1952
   187
ds@1952
   188
	QAngle *pRetAngle = NULL;
ds@1952
   189
	unsigned char params[sizeof(void *)];
ds@1952
   190
	unsigned char *vptr = params;
ds@1952
   191
ds@1952
   192
	*(CBaseEntity **)vptr = pEntity;
ds@1952
   193
ds@1952
   194
	s_EyeAngles.call->Execute(params, &pRetAngle);
ds@1952
   195
ds@1952
   196
	if (pRetAngle == NULL)
ds@1952
   197
	{
ds@1952
   198
		return false;
ds@1952
   199
	}
ds@1952
   200
ds@1952
   201
	*pAngles = *pRetAngle;
ds@1952
   202
ds@1952
   203
	return true;
ds@1952
   204
}
ds@1952
   205
ds@1952
   206
int GetClientAimTarget(edict_t *pEdict, bool only_players)
ds@1952
   207
{
ds@1952
   208
	CBaseEntity *pEntity = pEdict->GetUnknown() ? pEdict->GetUnknown()->GetBaseEntity() : NULL;
ds@1952
   209
ds@1952
   210
	if (pEntity == NULL)
ds@1952
   211
	{
ds@1952
   212
		return -1;
ds@1952
   213
	}
ds@1952
   214
ds@1952
   215
	Vector eye_position;
ds@1952
   216
	QAngle eye_angles;
ds@1952
   217
ds@1952
   218
	/* Get the private information we need */
ds@1952
   219
	serverClients->ClientEarPosition(pEdict, &eye_position);
ds@1952
   220
	if (!GetEyeAngles(pEntity, &eye_angles))
ds@1952
   221
	{
ds@1952
   222
		return -2;
ds@1952
   223
	}
ds@1952
   224
ds@1952
   225
	Vector aim_dir;
ds@1952
   226
	AngleVectors(eye_angles, &aim_dir);
ds@1952
   227
	VectorNormalize(aim_dir);
ds@1952
   228
ds@1952
   229
	Vector vec_end = eye_position + aim_dir * 8000;
ds@1952
   230
ds@1952
   231
	Ray_t ray;
ds@1952
   232
	ray.Init(eye_position, vec_end);
ds@1952
   233
ds@1952
   234
	trace_t tr;
ds@1952
   235
	CTraceFilterSimple simple(pEdict->GetIServerEntity());
ds@1952
   236
ds@1952
   237
	enginetrace->TraceRay(ray, MASK_SOLID|CONTENTS_DEBRIS|CONTENTS_HITBOX, &simple, &tr);
ds@1952
   238
ds@1952
   239
	if (tr.fraction == 1.0f || tr.m_pEnt == NULL)
ds@1952
   240
	{
ds@1952
   241
		return -1;
ds@1952
   242
	}
ds@1952
   243
ds@1952
   244
	edict_t *pTarget = gameents->BaseEntityToEdict(tr.m_pEnt);
ds@1952
   245
	if (pTarget == NULL)
ds@1952
   246
	{
ds@1952
   247
		return -1;
ds@1952
   248
	}
ds@1952
   249
ds@1952
   250
	int ent_index = engine->IndexOfEdict(pTarget);
ds@1952
   251
ds@1952
   252
	IGamePlayer *pTargetPlayer = playerhelpers->GetGamePlayer(ent_index);
ds@1952
   253
	if (pTargetPlayer != NULL && !pTargetPlayer->IsInGame())
ds@1952
   254
	{
ds@1952
   255
		return -1;
ds@1952
   256
	}
ds@1952
   257
	else if (only_players && pTargetPlayer == NULL)
ds@1952
   258
	{
ds@1952
   259
		return -1;
ds@1952
   260
	}
ds@1952
   261
ds@1952
   262
	return ent_index;
ds@1952
   263
}
ds@1952
   264
ds@1952
   265
bool IsEyeAnglesSupported()
ds@1952
   266
{
ds@1952
   267
	return SetupGetEyeAngles();
ds@1952
   268
}
ds@1952
   269
ds@1952
   270
bool GetPlayerInfo(int client, player_info_t *info)
ds@1952
   271
{
ds@1952
   272
#if defined ORANGEBOX_BUILD
ds@1952
   273
	return engine->GetPlayerInfo(client, info);
ds@1952
   274
#else
ds@1952
   275
	return (iserver) ? iserver->GetPlayerInfo(client-1, info) : false;
ds@1952
   276
#endif
ds@1952
   277
}
ds@1952
   278
ds@1952
   279
void ShutdownHelpers()
ds@1952
   280
{
ds@1952
   281
	s_Teleport.Shutdown();
ds@1952
   282
	s_GetVelocity.Shutdown();
ds@1952
   283
}
ds@1952
   284
ds@1952
   285
const char *GetDTTypeName(int type)
ds@1952
   286
{
ds@1952
   287
	switch (type)
ds@1952
   288
	{
ds@1952
   289
	case DPT_Int:
ds@1952
   290
		{
ds@1952
   291
			return "integer";
ds@1952
   292
		}
ds@1952
   293
	case DPT_Float:
ds@1952
   294
		{
ds@1952
   295
			return "float";
ds@1952
   296
		}
ds@1952
   297
	case DPT_Vector:
ds@1952
   298
		{
ds@1952
   299
			return "vector";
ds@1952
   300
		}
ds@1952
   301
	case DPT_String:
ds@1952
   302
		{
ds@1952
   303
			return "string";
ds@1952
   304
		}
ds@1952
   305
	case DPT_Array:
ds@1952
   306
		{
ds@1952
   307
			return "array";
ds@1952
   308
		}
ds@1952
   309
	case DPT_DataTable:
ds@1952
   310
		{
ds@1952
   311
			return "datatable";
ds@1952
   312
		}
ds@1952
   313
	default:
ds@1952
   314
		{
ds@1952
   315
			return NULL;
ds@1952
   316
		}
ds@1952
   317
	}
ds@1952
   318
ds@1952
   319
	return NULL;
ds@1952
   320
}
ds@1952
   321
ds@1952
   322
void UTIL_DrawSendTable_XML(FILE *fp, SendTable *pTable, int space_count)
ds@1952
   323
{
ds@1952
   324
	char spaces[255];
ds@1952
   325
ds@1952
   326
	for (int i = 0; i < space_count; i++)
ds@1952
   327
	{
ds@1952
   328
		spaces[i] = ' ';
ds@1952
   329
	}
ds@1952
   330
	spaces[space_count] = '\0';
ds@1952
   331
ds@1952
   332
	const char *type_name;
ds@1952
   333
	SendTable *pOtherTable;
ds@1952
   334
	SendProp *pProp;
ds@1952
   335
ds@1952
   336
	fprintf(fp, " %s<sendtable name=\"%s\">\n", spaces, pTable->GetName());
ds@1952
   337
	for (int i = 0; i < pTable->GetNumProps(); i++)
ds@1952
   338
	{
ds@1952
   339
		pProp = pTable->GetProp(i);
ds@1952
   340
ds@1952
   341
		fprintf(fp, "  %s<property name=\"%s\">\n", spaces, pProp->GetName());
ds@1952
   342
ds@1952
   343
		if ((type_name = GetDTTypeName(pProp->GetType())) != NULL)
ds@1952
   344
		{
ds@1952
   345
			fprintf(fp, "   %s<type>%s</type>\n", spaces, type_name);
ds@1952
   346
		}
ds@1952
   347
		else
ds@1952
   348
		{
ds@1952
   349
			fprintf(fp, "   %s<type>%d</type>\n", spaces, pProp->GetType());
ds@1952
   350
		}
ds@1952
   351
ds@1952
   352
		fprintf(fp, "   %s<offset>%d</offset>\n", spaces, pProp->GetOffset());
ds@1952
   353
		fprintf(fp, "   %s<bits>%d</bits>\n", spaces, pProp->m_nBits);
ds@1952
   354
ds@1952
   355
		if ((pOtherTable = pTable->GetProp(i)->GetDataTable()) != NULL)
ds@1952
   356
		{
ds@1952
   357
			UTIL_DrawSendTable_XML(fp, pOtherTable, space_count + 3);
ds@1952
   358
		}
ds@1952
   359
ds@1952
   360
		fprintf(fp, "  %s</property>\n", spaces);
ds@1952
   361
	}
ds@1952
   362
	fprintf(fp, " %s</sendtable>\n", spaces);
ds@1952
   363
}
ds@1952
   364
ds@1952
   365
void UTIL_DrawServerClass_XML(FILE *fp, ServerClass *sc)
ds@1952
   366
{
ds@1952
   367
	fprintf(fp, "<serverclass name=\"%s\">\n", sc->GetName());
ds@1952
   368
	UTIL_DrawSendTable_XML(fp, sc->m_pTable, 0);
ds@1952
   369
	fprintf(fp, "</serverclass>\n");
ds@1952
   370
}
ds@1952
   371
ds@1952
   372
void UTIL_DrawSendTable(FILE *fp, SendTable *pTable, int level)
ds@1952
   373
{
ds@1952
   374
	char spaces[255];
ds@1952
   375
	for (int i=0; i<level; i++)
ds@1952
   376
		spaces[i] = ' ';
ds@1952
   377
	spaces[level] = '\0';
ds@1952
   378
ds@1952
   379
	const char *name, *type;
ds@1952
   380
	SendProp *pProp;
ds@1952
   381
ds@1952
   382
	fprintf(fp, "%sSub-Class Table (%d Deep): %s\n", spaces, level, pTable->GetName());
ds@1952
   383
ds@1952
   384
	for (int i=0; i<pTable->GetNumProps(); i++)
ds@1952
   385
	{
ds@1952
   386
		pProp = pTable->GetProp(i);
ds@1952
   387
		name = pProp->GetName();
ds@1952
   388
		if (pProp->GetDataTable())
ds@1952
   389
		{
ds@1952
   390
			UTIL_DrawSendTable(fp, pProp->GetDataTable(), level + 1);
ds@1952
   391
		}
ds@1952
   392
		else
ds@1952
   393
		{
ds@1952
   394
			type = GetDTTypeName(pProp->GetType());
ds@1952
   395
ds@1952
   396
			if (type != NULL)
ds@1952
   397
			{
ds@1952
   398
				fprintf(fp,
ds@1952
   399
					"%s-Member: %s (offset %d) (type %s) (bits %d)\n", 
ds@1952
   400
					spaces, 
ds@1952
   401
					pProp->GetName(),
ds@1952
   402
					pProp->GetOffset(),
ds@1952
   403
					type,
ds@1952
   404
					pProp->m_nBits);
ds@1952
   405
			}
ds@1952
   406
			else
ds@1952
   407
			{
ds@1952
   408
				fprintf(fp,
ds@1952
   409
					"%s-Member: %s (offset %d) (type %d) (bits %d)\n", 
ds@1952
   410
					spaces, 
ds@1952
   411
					pProp->GetName(),
ds@1952
   412
					pProp->GetOffset(),
ds@1952
   413
					pProp->GetType(),
ds@1952
   414
					pProp->m_nBits);
ds@1952
   415
			}
ds@1952
   416
		}
ds@1952
   417
	}
ds@1952
   418
}
ds@1952
   419
ds@1952
   420
CON_COMMAND(sm_dump_netprops_xml, "Dumps the networkable property table as an XML file")
ds@1952
   421
{
ds@1952
   422
#if !defined ORANGEBOX_BUILD
ds@1952
   423
	CCommand args;
ds@1952
   424
#endif
ds@1952
   425
ds@1952
   426
	if (args.ArgC() < 2)
ds@1952
   427
	{
ds@1952
   428
		META_CONPRINT("Usage: sm_dump_netprops_xml <file>\n");
ds@1952
   429
		return;
ds@1952
   430
	}
ds@1952
   431
ds@1952
   432
	const char *file = args.Arg(1);
ds@1952
   433
	if (!file || file[0] == '\0')
ds@1952
   434
	{
ds@1952
   435
		META_CONPRINT("Usage: sm_dump_netprops_xml <file>\n");
ds@1952
   436
		return;
ds@1952
   437
	}
ds@1952
   438
ds@1952
   439
	char path[PLATFORM_MAX_PATH];
ds@1952
   440
	g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
ds@1952
   441
ds@1952
   442
	FILE *fp = NULL;
ds@1952
   443
	if ((fp = fopen(path, "wt")) == NULL)
ds@1952
   444
	{
ds@1952
   445
		META_CONPRINTF("Could not open file \"%s\"\n", path);
ds@1952
   446
		return;
ds@1952
   447
	}
ds@1952
   448
ds@1952
   449
	fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
ds@1952
   450
	fprintf(fp, "<!-- Dump of all network properties for \"%s\" follows -->\n\n", g_pSM->GetGameFolderName());
ds@1952
   451
ds@1952
   452
	ServerClass *pBase = gamedll->GetAllServerClasses();
ds@1952
   453
	while (pBase != NULL)
ds@1952
   454
	{
ds@1952
   455
		UTIL_DrawServerClass_XML(fp, pBase);
ds@1952
   456
		pBase = pBase->m_pNext;
ds@1952
   457
	}
ds@1952
   458
ds@1952
   459
	fclose(fp);
ds@1952
   460
}
ds@1952
   461
ds@1952
   462
CON_COMMAND(sm_dump_netprops, "Dumps the networkable property table as a text file")
ds@1952
   463
{
ds@1952
   464
#if !defined ORANGEBOX_BUILD
ds@1952
   465
	CCommand args;
ds@1952
   466
#endif
ds@1952
   467
ds@1952
   468
	if (args.ArgC() < 2)
ds@1952
   469
	{
ds@1952
   470
		META_CONPRINT("Usage: sm_dump_netprops <file>\n");
ds@1952
   471
		return;
ds@1952
   472
	}
ds@1952
   473
ds@1952
   474
	const char *file = args.Arg(1);
ds@1952
   475
	if (!file || file[0] == '\0')
ds@1952
   476
	{
ds@1952
   477
		META_CONPRINT("Usage: sm_dump_netprops <file>\n");
ds@1952
   478
		return;
ds@1952
   479
	}
ds@1952
   480
ds@1952
   481
	char path[PLATFORM_MAX_PATH];
ds@1952
   482
	g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
ds@1952
   483
ds@1952
   484
	FILE *fp = NULL;
ds@1952
   485
	if ((fp = fopen(path, "wt")) == NULL)
ds@1952
   486
	{
ds@1952
   487
		META_CONPRINTF("Could not open file \"%s\"\n", path);
ds@1952
   488
		return;
ds@1952
   489
	}
ds@1952
   490
ds@1952
   491
	fprintf(fp, "// Dump of all network properties for \"%s\" follows\n//\n\n", g_pSM->GetGameFolderName());
ds@1952
   492
ds@1952
   493
	ServerClass *pBase = gamedll->GetAllServerClasses();
ds@1952
   494
	while (pBase != NULL)
ds@1952
   495
	{
ds@1952
   496
		fprintf(fp, "%s:\n", pBase->GetName());
ds@1952
   497
		UTIL_DrawSendTable(fp, pBase->m_pTable, 1);
ds@1952
   498
		pBase = pBase->m_pNext;
ds@1952
   499
	}
ds@1952
   500
ds@1952
   501
	fclose(fp);
ds@1952
   502
}
ds@1952
   503
ds@1952
   504
#if defined SUBPLATFORM_SECURECRT
ds@1952
   505
void _ignore_invalid_parameter(
ds@1952
   506
						const wchar_t * expression,
ds@1952
   507
						const wchar_t * function, 
ds@1952
   508
						const wchar_t * file, 
ds@1952
   509
						unsigned int line,
ds@1952
   510
						uintptr_t pReserved
ds@1952
   511
						)
ds@1952
   512
{
ds@1952
   513
	/* Wow we don't care, thanks Microsoft. */
ds@1952
   514
}
ds@1952
   515
#endif
ds@1952
   516
ds@1952
   517
CON_COMMAND(sm_dump_classes, "Dumps the class list as a text file")
ds@1952
   518
{
ds@1952
   519
#if !defined ORANGEBOX_BUILD
ds@1952
   520
	CCommand args;
ds@1952
   521
#endif
ds@1952
   522
ds@1952
   523
	if (args.ArgC() < 2)
ds@1952
   524
	{
ds@1952
   525
		META_CONPRINT("Usage: sm_dump_classes <file>\n");
ds@1952
   526
		return;
ds@1952
   527
	}
ds@1952
   528
ds@1952
   529
	const char *file = args.Arg(1);
ds@1952
   530
	if (!file || file[0] == '\0')
ds@1952
   531
	{
ds@1952
   532
		META_CONPRINT("Usage: sm_dump_classes <file>\n");
ds@1952
   533
		return;
ds@1952
   534
	}
ds@1952
   535
ds@1952
   536
	ICallWrapper *pWrapper = NULL;
ds@1952
   537
ds@1952
   538
	if (!pWrapper)
ds@1952
   539
	{
ds@1952
   540
		PassInfo retData;
ds@1952
   541
		retData.flags = PASSFLAG_BYVAL;
ds@1952
   542
		retData.size = sizeof(void *);
ds@1952
   543
		retData.type = PassType_Basic;
ds@1952
   544
ds@1952
   545
		void *addr;
ds@1952
   546
		if (!g_pGameConf->GetMemSig("EntityFactory", &addr) || addr == NULL)
ds@1952
   547
		{
ds@1952
   548
			META_CONPRINT("Failed to locate function\n");
ds@1952
   549
			return;
ds@1952
   550
		}
ds@1952
   551
ds@1952
   552
		pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retData, NULL, 0);
ds@1952
   553
	}
ds@1952
   554
ds@1952
   555
ds@1952
   556
	void *returnData = NULL;
ds@1952
   557
ds@1952
   558
	pWrapper->Execute(NULL, &returnData);
ds@1952
   559
ds@1952
   560
	pWrapper->Destroy();
ds@1952
   561
ds@1952
   562
	if (returnData == NULL)
ds@1952
   563
	{
ds@1952
   564
		return;
ds@1952
   565
	}
ds@1952
   566
ds@1952
   567
	CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )returnData;
ds@1952
   568
ds@1952
   569
	if ( !dict )
ds@1952
   570
	{
ds@1952
   571
		return;
ds@1952
   572
	}
ds@1952
   573
ds@1952
   574
	char path[PLATFORM_MAX_PATH];
ds@1952
   575
	g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
ds@1952
   576
ds@1952
   577
	FILE *fp = NULL;
ds@1952
   578
	if ((fp = fopen(path, "wt")) == NULL)
ds@1952
   579
	{
ds@1952
   580
		META_CONPRINTF("Could not open file \"%s\"\n", path);
ds@1952
   581
		return;
ds@1952
   582
	}
ds@1952
   583
ds@1952
   584
	char buffer[80];
ds@1952
   585
	buffer[0] = 0;
ds@1952
   586
ds@1952
   587
#if defined SUBPLATFORM_SECURECRT
ds@1952
   588
	_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
ds@1952
   589
#endif
ds@1952
   590
ds@1952
   591
	time_t t = g_pSM->GetAdjustedTime();
ds@1952
   592
	size_t written = strftime(buffer, sizeof(buffer), "%d/%m/%Y", localtime(&t));
ds@1952
   593
ds@1952
   594
#if defined SUBPLATFORM_SECURECRT
ds@1952
   595
	_set_invalid_parameter_handler(handler);
ds@1952
   596
#endif
ds@1952
   597
ds@1952
   598
	fprintf(fp, "// Dump of all classes for \"%s\" as at %s\n//\n\n", g_pSM->GetGameFolderName(), buffer);
ds@1952
   599
ds@1952
   600
	for ( int i = dict->m_Factories.First(); i != dict->m_Factories.InvalidIndex(); i = dict->m_Factories.Next( i ) )
ds@1952
   601
	{
ds@1952
   602
		IServerNetworkable *entity = dict->Create(dict->m_Factories.GetElementName(i));
ds@1952
   603
		ServerClass *sclass = entity->GetServerClass();
ds@1952
   604
		fprintf(fp,"%s - %s\n",sclass->GetName(), dict->m_Factories.GetElementName(i));
ds@1952
   605
ds@1952
   606
		typedescription_t *datamap = gamehelpers->FindInDataMap(gamehelpers->GetDataMap(entity->GetBaseEntity()), "m_iEFlags");
ds@1952
   607
		
ds@1952
   608
		int *eflags = (int *)((char *)entity->GetBaseEntity() + datamap->fieldOffset[TD_OFFSET_NORMAL]);
ds@1952
   609
		*eflags |= (1<<0); // EFL_KILLME
ds@1952
   610
	}
ds@1952
   611
ds@1952
   612
	fclose(fp);
ds@1952
   613
ds@1952
   614
}
ds@1952
   615
pred@1954
   616
char *UTIL_FlagsToString(int flags)
pred@1954
   617
{
pred@1954
   618
	static char str[1024];
pred@1954
   619
	str[0] = 0;
ds@1952
   620
pred@1954
   621
	if (flags & FTYPEDESC_GLOBAL)
pred@1954
   622
	{
pred@1954
   623
		strcat(str,	"Global|");
pred@1954
   624
	}
pred@1954
   625
	if (flags & FTYPEDESC_SAVE)
pred@1954
   626
	{
pred@1954
   627
		strcat(str,	"Save|");
pred@1954
   628
	}
pred@1954
   629
	if (flags & FTYPEDESC_KEY)
pred@1954
   630
	{
pred@1954
   631
		strcat(str,	"Key|");
pred@1954
   632
	}
pred@1954
   633
	if (flags & FTYPEDESC_INPUT)
pred@1954
   634
	{
pred@1954
   635
		strcat(str,	"Input|");
pred@1954
   636
	}
pred@1954
   637
	if (flags & FTYPEDESC_OUTPUT)
pred@1954
   638
	{
pred@1954
   639
		strcat(str,	"Output|");
pred@1954
   640
	}
pred@1954
   641
	if (flags & FTYPEDESC_FUNCTIONTABLE)
pred@1954
   642
	{
pred@1954
   643
		strcat(str,	"FunctionTable|");
pred@1954
   644
	}
pred@1954
   645
	if (flags & FTYPEDESC_PTR)
pred@1954
   646
	{
pred@1954
   647
		strcat(str,	"Ptr|");
pred@1954
   648
	}
pred@1954
   649
	if (flags & FTYPEDESC_OVERRIDE)
pred@1954
   650
	{
pred@1954
   651
		strcat(str,	"Override|");
pred@1954
   652
	}
pred@1954
   653
pred@1954
   654
	int len = strlen(str) - 1;
pred@1954
   655
	if (len > 0)
pred@1954
   656
	{
pred@1954
   657
		str[len] = 0; // Strip the final '|'
pred@1954
   658
	}
pred@1954
   659
pred@1954
   660
	return str;
pred@1954
   661
}
pred@1954
   662
pred@1954
   663
void UTIL_DrawDataTable(FILE *fp, datamap_t *pMap, int level)
pred@1954
   664
{
pred@1954
   665
	char spaces[255];
pred@1954
   666
pred@1954
   667
	for (int i=0; i<level; i++)
pred@1954
   668
	{
pred@1954
   669
		spaces[i] = ' ';
pred@1954
   670
	}
pred@1954
   671
pred@1954
   672
	spaces[level] = '\0';
pred@1954
   673
pred@1954
   674
	const char *externalname;
pred@1954
   675
	char *flags;
pred@1954
   676
pred@1954
   677
	while (pMap)
pred@1954
   678
	{
pred@1954
   679
		for (int i=0; i<pMap->dataNumFields; i++)
pred@1954
   680
		{
pred@1954
   681
			if (pMap->dataDesc[i].fieldName == NULL)
pred@1954
   682
			{
pred@1954
   683
				continue;
pred@1954
   684
			}
pred@1954
   685
pred@1954
   686
			if (pMap->dataDesc[i].td)
pred@1954
   687
			{
pred@1954
   688
				fprintf(fp, " %sSub-Class Table (%d Deep): %s - %s\n", spaces, level+1, pMap->dataDesc[i].fieldName, pMap->dataDesc[i].td->dataClassName);
pred@1954
   689
				UTIL_DrawDataTable(fp, pMap->dataDesc[i].td, level+1);
pred@1954
   690
			}
pred@1954
   691
			else
pred@1954
   692
			{
pred@1954
   693
				externalname  = pMap->dataDesc[i].externalName;
pred@1954
   694
				flags = UTIL_FlagsToString(pMap->dataDesc[i].flags);
pred@1954
   695
pred@1954
   696
				if (externalname == NULL)
pred@1954
   697
				{
pred@1954
   698
					fprintf(fp,"%s- %s (%s)(%i Bytes)\n", spaces, pMap->dataDesc[i].fieldName, flags, pMap->dataDesc[i].fieldSizeInBytes);
pred@1954
   699
				}
pred@1954
   700
				else
pred@1954
   701
				{
pred@1954
   702
					fprintf(fp,"%s- %s (%s)(%i Bytes) - %s\n", spaces, pMap->dataDesc[i].fieldName, flags, pMap->dataDesc[i].fieldSizeInBytes, externalname);
pred@1954
   703
				}
pred@1954
   704
			}
pred@1954
   705
		}
pred@1954
   706
		pMap = pMap->baseMap;
pred@1954
   707
	}
pred@1954
   708
}
pred@1954
   709
pred@1954
   710
CON_COMMAND(sm_dump_datamaps, "Dumps the data map list as a text file")
pred@1954
   711
{
pred@1954
   712
#if !defined ORANGEBOX_BUILD
pred@1954
   713
	CCommand args;
pred@1954
   714
#endif
pred@1954
   715
pred@1954
   716
	if (args.ArgC() < 2)
pred@1954
   717
	{
pred@1954
   718
		META_CONPRINT("Usage: sm_dump_datamaps <file>\n");
pred@1954
   719
		return;
pred@1954
   720
	}
pred@1954
   721
pred@1954
   722
	const char *file = args.Arg(1);
pred@1954
   723
	if (!file || file[0] == '\0')
pred@1954
   724
	{
pred@1954
   725
		META_CONPRINT("Usage: sm_dump_datamaps <file>\n");
pred@1954
   726
		return;
pred@1954
   727
	}
pred@1954
   728
pred@1954
   729
	ICallWrapper *pWrapper = NULL;
pred@1954
   730
pred@1954
   731
	if (!pWrapper)
pred@1954
   732
	{
pred@1954
   733
		PassInfo retData;
pred@1954
   734
		retData.flags = PASSFLAG_BYVAL;
pred@1954
   735
		retData.size = sizeof(void *);
pred@1954
   736
		retData.type = PassType_Basic;
pred@1954
   737
pred@1954
   738
		void *addr;
pred@1954
   739
		if (!g_pGameConf->GetMemSig("EntityFactory", &addr) || addr == NULL)
pred@1954
   740
		{
pred@1954
   741
			META_CONPRINT("Failed to locate function\n");
pred@1954
   742
			return;
pred@1954
   743
		}
pred@1954
   744
pred@1954
   745
		pWrapper = g_pBinTools->CreateCall(addr, CallConv_Cdecl, &retData, NULL, 0);
pred@1954
   746
	}
pred@1954
   747
pred@1954
   748
pred@1954
   749
	void *returnData = NULL;
pred@1954
   750
pred@1954
   751
	pWrapper->Execute(NULL, &returnData);
pred@1954
   752
pred@1954
   753
	pWrapper->Destroy();
pred@1954
   754
pred@1954
   755
	if (returnData == NULL)
pred@1954
   756
	{
pred@1954
   757
		return;
pred@1954
   758
	}
pred@1954
   759
pred@1954
   760
	CEntityFactoryDictionary *dict = ( CEntityFactoryDictionary * )returnData;
pred@1954
   761
pred@1954
   762
	if ( !dict )
pred@1954
   763
	{
pred@1954
   764
		return;
pred@1954
   765
	}
pred@1954
   766
pred@1954
   767
	char path[PLATFORM_MAX_PATH];
pred@1954
   768
	g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", file);
pred@1954
   769
pred@1954
   770
	FILE *fp = NULL;
pred@1954
   771
	if ((fp = fopen(path, "wt")) == NULL)
pred@1954
   772
	{
pred@1954
   773
		META_CONPRINTF("Could not open file \"%s\"\n", path);
pred@1954
   774
		return;
pred@1954
   775
	}
pred@1954
   776
pred@1954
   777
	char buffer[80];
pred@1954
   778
	buffer[0] = 0;
pred@1954
   779
pred@1954
   780
#if defined SUBPLATFORM_SECURECRT
pred@1954
   781
	_invalid_parameter_handler handler = _set_invalid_parameter_handler(_ignore_invalid_parameter);
pred@1954
   782
#endif
pred@1954
   783
pred@1954
   784
	time_t t = g_pSM->GetAdjustedTime();
pred@1954
   785
	size_t written = strftime(buffer, sizeof(buffer), "%d/%m/%Y", localtime(&t));
pred@1954
   786
pred@1954
   787
#if defined SUBPLATFORM_SECURECRT
pred@1954
   788
	_set_invalid_parameter_handler(handler);
pred@1954
   789
#endif
pred@1954
   790
pred@1954
   791
	fprintf(fp, "// Dump of all datamaps for \"%s\" as at %s\n//\n//\n", g_pSM->GetGameFolderName(), buffer);
pred@1954
   792
pred@1954
   793
pred@1954
   794
	fprintf(fp, "// Flag Details:\n//\n");
pred@1954
   795
pred@1954
   796
	fprintf(fp, "// Global: This field is masked for global entity save/restore\n");
pred@1954
   797
	fprintf(fp, "// Save: This field is saved to disk\n");
pred@1954
   798
	fprintf(fp, "// Key: This field can be requested and written to by string name at load time\n");
pred@1954
   799
	fprintf(fp, "// Input: This field can be written to by string name at run time, and a function called\n");
pred@1954
   800
	fprintf(fp, "// Output: This field propogates it's value to all targets whenever it changes\n");
pred@1954
   801
	fprintf(fp, "// FunctionTable: This is a table entry for a member function pointer\n");
pred@1954
   802
	fprintf(fp, "// Ptr: This field is a pointer, not an embedded object\n");
pred@1954
   803
	fprintf(fp, "// Override: The field is an override for one in a base class (only used by prediction system for now)\n");
pred@1954
   804
pred@1954
   805
	fprintf(fp, "//\n\n");
pred@1954
   806
pred@1954
   807
	for ( int i = dict->m_Factories.First(); i != dict->m_Factories.InvalidIndex(); i = dict->m_Factories.Next( i ) )
pred@1954
   808
	{
pred@1954
   809
		IServerNetworkable *entity = dict->Create(dict->m_Factories.GetElementName(i));
pred@1954
   810
		ServerClass *sclass = entity->GetServerClass();
pred@1954
   811
		datamap_t *pMap = gamehelpers->GetDataMap(entity->GetBaseEntity());
pred@1954
   812
pred@1954
   813
		fprintf(fp,"%s - %s\n", sclass->GetName(), dict->m_Factories.GetElementName(i));
pred@1954
   814
pred@1954
   815
		UTIL_DrawDataTable(fp, pMap, 0);
pred@1954
   816
pred@1955
   817
		typedescription_t *datamap = gamehelpers->FindInDataMap(pMap, "m_iEFlags");
pred@1954
   818
		
pred@1954
   819
		int *eflags = (int *)((char *)entity->GetBaseEntity() + datamap->fieldOffset[TD_OFFSET_NORMAL]);
pred@1954
   820
		*eflags |= (1<<0); // EFL_KILLME
pred@1954
   821
	}
pred@1954
   822
pred@1954
   823
	fclose(fp);
pred@1954
   824
pred@1954
   825
}