extensions/sdktools/tempents.cpp
author Kyle Sanderson <kyle.leet@gmail.com>
Sat Mar 16 22:15:25 2013 -0400 (2013-03-16)
changeset 3819 d17aed3d46bf
parent 3221 ca0e525dcf86
child 4279 07c27b13d08b
permissions -rw-r--r--
Replace usages of deprecated Sourcehook Add/Remove macros (bug 5631, r=dvander).
faluco@1031
     1
/**
faluco@1031
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1233
     4
 * SourceMod SDKTools Extension
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
faluco@1031
     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.
dvander@1233
    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.
dvander@1233
    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/>.
dvander@1233
    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@1031
    28
 *
faluco@1031
    29
 * Version: $Id$
faluco@1031
    30
 */
faluco@1031
    31
faluco@1031
    32
#include "tempents.h"
faluco@1031
    33
faluco@1031
    34
TempEntityManager g_TEManager;
faluco@1031
    35
ICallWrapper *g_GetServerClass = NULL;
faluco@1031
    36
dvander@1052
    37
CON_COMMAND(sm_print_telist, "Prints the temp entity list")
dvander@1052
    38
{
dvander@1052
    39
	if (!g_TEManager.IsAvailable())
dvander@1052
    40
	{
dvander@1052
    41
		META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
dvander@1052
    42
		META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
dvander@1052
    43
		return;
dvander@1052
    44
	}
dvander@1052
    45
	g_TEManager.DumpList();
dvander@1052
    46
}
dvander@1052
    47
dvander@1052
    48
CON_COMMAND(sm_dump_teprops, "Dumps tempentity props to a file")
dvander@1052
    49
{
ds@2583
    50
#if SOURCE_ENGINE <= SE_DARKMESSIAH
faluco@1560
    51
	CCommand args;
faluco@1560
    52
#endif
dvander@1052
    53
	if (!g_TEManager.IsAvailable())
dvander@1052
    54
	{
dvander@1052
    55
		META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
dvander@1052
    56
		META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
dvander@1052
    57
		return;
dvander@1052
    58
	}
faluco@1560
    59
	int argc = args.ArgC();
dvander@1052
    60
	if (argc < 2)
dvander@1052
    61
	{
dvander@1052
    62
		META_CONPRINT("Usage: sm_dump_teprops <file>\n");
dvander@1052
    63
		return;
dvander@1052
    64
	}
dvander@1637
    65
faluco@1560
    66
	const char *arg = args.Arg(1);
dvander@1637
    67
dvander@1637
    68
	if (!arg || arg[0] == '\0')
dvander@1052
    69
	{
dvander@1637
    70
		META_CONPRINTF("Usage: sm_dump_teprops <file>\n");
dvander@1052
    71
		return;
dvander@1052
    72
	}
dvander@1637
    73
dvander@1637
    74
	char path[PLATFORM_MAX_PATH];
dvander@1637
    75
	g_pSM->BuildPath(Path_Game, path, sizeof(path), "%s", arg);
dvander@1637
    76
dvander@1637
    77
	FILE *fp = NULL;
dvander@1637
    78
	if ((fp = fopen(path, "wt")) == NULL)
dvander@1637
    79
	{
dvander@1637
    80
		META_CONPRINTF("Could not open file \"%s\"\n", path);
dvander@1637
    81
		return;
dvander@1637
    82
	}
dvander@1637
    83
dvander@1052
    84
	g_TEManager.DumpProps(fp);
dvander@1637
    85
dvander@1052
    86
	fclose(fp);
dvander@1052
    87
}
dvander@1052
    88
faluco@1031
    89
/*************************
faluco@1031
    90
*                        *
faluco@1031
    91
* Temp Entities Wrappers *
faluco@1031
    92
*                        *
faluco@1031
    93
**************************/
faluco@1031
    94
faluco@1031
    95
TempEntityInfo::TempEntityInfo(const char *name, void *me)
faluco@1031
    96
{
faluco@1031
    97
	m_Name.assign(name);
faluco@1031
    98
	m_Me = me;
faluco@1031
    99
	g_GetServerClass->Execute(&m_Me, &m_Sc);
faluco@1031
   100
}
faluco@1031
   101
faluco@1031
   102
const char *TempEntityInfo::GetName()
faluco@1031
   103
{
faluco@1031
   104
	return m_Name.c_str();
faluco@1031
   105
}
faluco@1031
   106
dvander@1052
   107
ServerClass *TempEntityInfo::GetServerClass()
dvander@1052
   108
{
dvander@1052
   109
	return m_Sc;
dvander@1052
   110
}
dvander@1052
   111
faluco@1031
   112
bool TempEntityInfo::IsValidProp(const char *name)
faluco@1031
   113
{
faluco@1031
   114
	return (g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name)) ? true : false;
faluco@1031
   115
}
faluco@1031
   116
faluco@1031
   117
int TempEntityInfo::_FindOffset(const char *name, int *size)
faluco@1031
   118
{
faluco@1031
   119
	int offset;
faluco@1031
   120
faluco@1031
   121
	SendProp *prop = g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name);
faluco@1031
   122
	if (!prop)
faluco@1031
   123
	{
faluco@1031
   124
		return -1;
faluco@1031
   125
	}
faluco@1031
   126
faluco@1031
   127
	offset = prop->GetOffset();
faluco@1031
   128
	if (size)
faluco@1031
   129
	{
faluco@1032
   130
		*size = prop->m_nBits;
faluco@1031
   131
	}
faluco@1031
   132
faluco@1031
   133
	return offset;
faluco@1031
   134
}
faluco@1031
   135
faluco@1031
   136
bool TempEntityInfo::TE_SetEntData(const char *name, int value)
faluco@1031
   137
{
faluco@1031
   138
	/* Search for our offset */
faluco@1031
   139
	int size;
faluco@1031
   140
	int offset = _FindOffset(name, &size);
faluco@1031
   141
faluco@1031
   142
	if (offset < 0)
faluco@1031
   143
	{
faluco@1031
   144
		return false;
faluco@1031
   145
	}
faluco@1031
   146
faluco@1031
   147
	if (size <= 8)
faluco@1031
   148
	{
faluco@1031
   149
		*((uint8_t *)m_Me + offset) = value;
faluco@1031
   150
	} else if (size <= 16) {
faluco@1031
   151
		*(short *)((uint8_t *)m_Me + offset) = value;
faluco@1075
   152
	} else if (size <= 32) {
faluco@1031
   153
		*(int *)((uint8_t *)m_Me + offset) = value;
faluco@1031
   154
	} else {
faluco@1031
   155
		return false;
faluco@1031
   156
	}
faluco@1031
   157
faluco@1031
   158
	return true;
faluco@1031
   159
}
faluco@1031
   160
faluco@1255
   161
bool TempEntityInfo::TE_GetEntData(const char *name, int *value)
faluco@1255
   162
{
faluco@1255
   163
	/* Search for our offset */
faluco@1255
   164
	int size;
faluco@1255
   165
	int offset = _FindOffset(name, &size);
faluco@1255
   166
faluco@1255
   167
	if (offset < 0)
faluco@1255
   168
	{
faluco@1255
   169
		return false;
faluco@1255
   170
	}
faluco@1255
   171
faluco@1255
   172
	if (size <= 8)
faluco@1255
   173
	{
faluco@1255
   174
		*value = *((uint8_t *)m_Me + offset);
faluco@1255
   175
	} else if (size <= 16) {
faluco@1255
   176
		*value = *(short *)((uint8_t *)m_Me + offset);
faluco@1255
   177
	} else if (size <= 32) {
faluco@1255
   178
		*value = *(int *)((uint8_t *)m_Me + offset);
faluco@1255
   179
	} else {
faluco@1255
   180
		return false;
faluco@1255
   181
	}
faluco@1255
   182
faluco@1255
   183
	return true;
faluco@1255
   184
}
faluco@1255
   185
faluco@1031
   186
bool TempEntityInfo::TE_SetEntDataFloat(const char *name, float value)
faluco@1031
   187
{
faluco@1031
   188
	/* Search for our offset */
faluco@1031
   189
	int offset = _FindOffset(name);
faluco@1031
   190
faluco@1031
   191
	if (offset < 0)
faluco@1031
   192
	{
faluco@1031
   193
		return false;
faluco@1031
   194
	}
faluco@1031
   195
faluco@1031
   196
	*(float *)((uint8_t *)m_Me + offset) = value;
faluco@1031
   197
faluco@1031
   198
	return true;
faluco@1031
   199
}
faluco@1031
   200
faluco@1255
   201
bool TempEntityInfo::TE_GetEntDataFloat(const char *name, float *value)
faluco@1255
   202
{
faluco@1255
   203
	/* Search for our offset */
faluco@1255
   204
	int offset = _FindOffset(name);
faluco@1255
   205
faluco@1255
   206
	if (offset < 0)
faluco@1255
   207
	{
faluco@1255
   208
		return false;
faluco@1255
   209
	}
faluco@1255
   210
faluco@1255
   211
	*value = *(float *)((uint8_t *)m_Me + offset);
faluco@1255
   212
faluco@1255
   213
	return true;
faluco@1255
   214
}
faluco@1255
   215
faluco@1031
   216
bool TempEntityInfo::TE_SetEntDataVector(const char *name, float vector[3])
faluco@1031
   217
{
faluco@1031
   218
	/* Search for our offset */
faluco@1031
   219
	int offset = _FindOffset(name);
faluco@1031
   220
faluco@1031
   221
	if (offset < 0)
faluco@1031
   222
	{
faluco@1031
   223
		return false;
faluco@1031
   224
	}
faluco@1031
   225
faluco@1031
   226
	Vector *v = (Vector *)((uint8_t *)m_Me + offset);
faluco@1031
   227
	v->x = vector[0];
faluco@1031
   228
	v->y = vector[1];
faluco@1031
   229
	v->z = vector[2];
faluco@1031
   230
faluco@1031
   231
	return true;
faluco@1031
   232
}
faluco@1031
   233
faluco@1255
   234
bool TempEntityInfo::TE_GetEntDataVector(const char *name, float vector[3])
faluco@1255
   235
{
faluco@1255
   236
	/* Search for our offset */
faluco@1255
   237
	int offset = _FindOffset(name);
faluco@1255
   238
faluco@1255
   239
	if (offset < 0)
faluco@1255
   240
	{
faluco@1255
   241
		return false;
faluco@1255
   242
	}
faluco@1255
   243
faluco@1255
   244
	Vector *v = (Vector *)((uint8_t *)m_Me + offset);
faluco@1255
   245
	vector[0] = v->x;
faluco@1255
   246
	vector[1] = v->y;
faluco@1255
   247
	vector[2] = v->z;
faluco@1255
   248
faluco@1255
   249
	return true;
faluco@1255
   250
}
faluco@1255
   251
faluco@1039
   252
bool TempEntityInfo::TE_SetEntDataFloatArray(const char *name, cell_t *array, int size)
faluco@1039
   253
{
faluco@1039
   254
	/* Search for our offset */
faluco@1039
   255
	int offset = _FindOffset(name);
faluco@1039
   256
faluco@1039
   257
	if (offset < 0)
faluco@1039
   258
	{
faluco@1039
   259
		return false;
faluco@1039
   260
	}
faluco@1039
   261
faluco@1039
   262
	float *base = (float *)((uint8_t *)m_Me + offset);
faluco@1039
   263
	for (int i=0; i<size; i++)
faluco@1039
   264
	{
faluco@1039
   265
		base[i] = sp_ctof(array[i]);
faluco@1039
   266
	}
faluco@1039
   267
faluco@1039
   268
	return true;
faluco@1039
   269
}
faluco@1039
   270
faluco@1031
   271
void TempEntityInfo::Send(IRecipientFilter &filter, float delay)
faluco@1031
   272
{
faluco@1039
   273
	engine->PlaybackTempEntity(filter, delay, m_Me, m_Sc->m_pTable, m_Sc->m_ClassID);
faluco@1031
   274
}
faluco@1031
   275
faluco@1031
   276
/**********************
faluco@1031
   277
*                     *
faluco@1031
   278
* Temp Entity Manager *
faluco@1031
   279
*                     *
faluco@1031
   280
***********************/
faluco@1031
   281
faluco@1031
   282
void TempEntityManager::Initialize()
faluco@1031
   283
{
faluco@1031
   284
	void *addr;
faluco@1031
   285
	int offset;
faluco@1031
   286
	m_Loaded = false;
faluco@1031
   287
skamonkey@3221
   288
	/*
skamonkey@3221
   289
	 * First try to lookup s_pTempEntities directly for platforms with symbols.
skamonkey@3221
   290
	 * If symbols aren't present (Windows or stripped Linux/Mac), 
skamonkey@3221
   291
	 * attempt find via CBaseTempEntity ctor + offset
skamonkey@3221
   292
	 */
skamonkey@3221
   293
faluco@1031
   294
	/* Read our sigs and offsets from the config file */
skamonkey@3221
   295
	if (g_pGameConf->GetMemSig("s_pTempEntities", &addr) && addr)
faluco@1031
   296
	{
skamonkey@3221
   297
		
skamonkey@3221
   298
		/* Store the head of the TE linked list */
skamonkey@3221
   299
		m_ListHead = *(void **)addr;
faluco@1031
   300
	}
skamonkey@3221
   301
	else if (g_pGameConf->GetMemSig("CBaseTempEntity", &addr) && addr)
skamonkey@3221
   302
	{
skamonkey@3221
   303
		if (!g_pGameConf->GetOffset("s_pTempEntities", &offset))
skamonkey@3221
   304
		{
skamonkey@3221
   305
			return;
skamonkey@3221
   306
		}
skamonkey@3221
   307
		/* Store the head of the TE linked list */
skamonkey@3221
   308
		m_ListHead = **(void ***)((unsigned char *)addr + offset);
skamonkey@3221
   309
	}
skamonkey@3221
   310
	else
faluco@1031
   311
	{
faluco@1031
   312
		return;
faluco@1031
   313
	}
skamonkey@3221
   314
dvander@1059
   315
	if (!g_pGameConf->GetOffset("GetTEName", &m_NameOffs))
faluco@1031
   316
	{
faluco@1031
   317
		return;
faluco@1031
   318
	}
dvander@1059
   319
	if (!g_pGameConf->GetOffset("GetTENext", &m_NextOffs))
faluco@1031
   320
	{
faluco@1031
   321
		return;
faluco@1031
   322
	}
dvander@1059
   323
	if (!g_pGameConf->GetOffset("TE_GetServerClass", &m_GetClassNameOffs))
faluco@1031
   324
	{
faluco@1031
   325
		return;
faluco@1031
   326
	}
faluco@1031
   327
faluco@1031
   328
	/* Create our trie */
faluco@1031
   329
	m_TempEntInfo = adtfactory->CreateBasicTrie();
faluco@1031
   330
faluco@1031
   331
	/* Create the GetServerClass call */
faluco@1031
   332
	PassInfo retinfo;
faluco@1031
   333
	retinfo.flags = PASSFLAG_BYVAL;
faluco@1031
   334
	retinfo.type = PassType_Basic;
faluco@1031
   335
	retinfo.size = sizeof(ServerClass *);
faluco@1031
   336
	g_GetServerClass = g_pBinTools->CreateVCall(m_GetClassNameOffs, 0, 0, &retinfo, NULL, 0);
faluco@1031
   337
faluco@1031
   338
	/* We're done */
faluco@1031
   339
	m_Loaded = true;
faluco@1031
   340
}
faluco@1031
   341
faluco@1031
   342
bool TempEntityManager::IsAvailable()
faluco@1031
   343
{
faluco@1031
   344
	return m_Loaded;
faluco@1031
   345
}
faluco@1031
   346
faluco@1031
   347
void TempEntityManager::Shutdown()
faluco@1031
   348
{
faluco@1031
   349
	if (!IsAvailable())
faluco@1031
   350
	{
faluco@1031
   351
		return;
faluco@1031
   352
	}
faluco@1031
   353
faluco@1560
   354
	SourceHook::List<TempEntityInfo *>::iterator iter;
faluco@1031
   355
	for (iter=m_TEList.begin(); iter!=m_TEList.end(); iter++)
faluco@1031
   356
	{
faluco@1031
   357
		delete (*iter);
faluco@1031
   358
	}
faluco@1031
   359
	m_TEList.clear();
faluco@1031
   360
faluco@1031
   361
	m_TempEntInfo->Destroy();
faluco@1031
   362
	g_GetServerClass->Destroy();
faluco@1031
   363
	g_GetServerClass = NULL;
faluco@1031
   364
	m_ListHead = NULL;
faluco@1031
   365
	m_NextOffs = m_NameOffs = m_GetClassNameOffs = 0;
faluco@1031
   366
	m_Loaded = false;
faluco@1031
   367
}
faluco@1031
   368
faluco@1031
   369
TempEntityInfo *TempEntityManager::GetTempEntityInfo(const char *name)
faluco@1031
   370
{
faluco@1031
   371
	/* If the system is unloaded skip the search */
faluco@1031
   372
	if (!IsAvailable())
faluco@1031
   373
	{
faluco@1031
   374
		return NULL;
faluco@1031
   375
	}
faluco@1031
   376
faluco@1031
   377
	TempEntityInfo *te = NULL;
faluco@1031
   378
faluco@1031
   379
	/* Start searching for the TE inside the engine */
faluco@1031
   380
	if (!m_TempEntInfo->Retrieve(name, reinterpret_cast<void **>(&te)))
faluco@1031
   381
	{
faluco@1031
   382
		void *iter = m_ListHead;
faluco@1031
   383
		while (iter)
faluco@1031
   384
		{
faluco@1031
   385
			const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
faluco@1031
   386
			if (!realname)
faluco@1031
   387
			{
faluco@1031
   388
				continue;
faluco@1031
   389
			}
faluco@1031
   390
			if (strcmp(name, realname) == 0)
faluco@1031
   391
			{
faluco@1031
   392
				te = new TempEntityInfo(name, iter);
faluco@1031
   393
				m_TempEntInfo->Insert(name, (void *)te);
faluco@1031
   394
				m_TEList.push_back(te);
faluco@1031
   395
				return te;
faluco@1031
   396
			}
faluco@1031
   397
			iter = *(void **)((unsigned char *)iter + m_NextOffs);
faluco@1031
   398
		}
faluco@1031
   399
		return NULL;
faluco@1031
   400
	}
faluco@1031
   401
faluco@1031
   402
	return te;
faluco@1031
   403
}
dvander@1052
   404
faluco@1255
   405
const char *TempEntityManager::GetNameFromThisPtr(void *me)
faluco@1255
   406
{
faluco@1255
   407
	return *(const char **)((unsigned char *)me + m_NameOffs);
faluco@1255
   408
}
faluco@1255
   409
dvander@1052
   410
void TempEntityManager::DumpList()
dvander@1052
   411
{
dvander@1052
   412
	unsigned int index = 0;
dvander@1052
   413
	META_CONPRINT("Listing temp entities:\n");
dvander@1052
   414
	void *iter = m_ListHead;
dvander@1052
   415
	while (iter)
dvander@1052
   416
	{
dvander@1052
   417
		const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
dvander@1052
   418
		if (!realname)
dvander@1052
   419
		{
dvander@1052
   420
			break;
dvander@1052
   421
		}
dvander@1052
   422
		TempEntityInfo *info = GetTempEntityInfo(realname);
dvander@1052
   423
		if (!info)
dvander@1052
   424
		{
dvander@1052
   425
			continue;
dvander@1052
   426
		}
dvander@1052
   427
		ServerClass *sc = info->GetServerClass();
dvander@1052
   428
		META_CONPRINTF("[%02d] %s (%s)\n", index++, realname, sc->GetName());
dvander@1052
   429
		iter = *(void **)((unsigned char *)iter + m_NextOffs);
dvander@1052
   430
	}
dvander@1052
   431
	META_CONPRINTF("%d tempent%s found.\n", index, (index == 1) ? " was" : "s were");
dvander@1052
   432
}
dvander@1052
   433
dvander@1052
   434
const char *SendPropTypeToString(SendPropType type)
dvander@1052
   435
{
dvander@1052
   436
	if (type == DPT_Int)
dvander@1052
   437
	{
dvander@1052
   438
		return "int";
dvander@1052
   439
	} else if (type == DPT_Float) {
dvander@1052
   440
		return "float";
dvander@1052
   441
	} else if (type == DPT_Vector) {
dvander@1052
   442
		return "vector";
dvander@1052
   443
	} else if (type == DPT_String) {
dvander@1052
   444
		return "string";
dvander@1052
   445
	} else if (type == DPT_Array) {
dvander@1052
   446
		return "array";
dvander@1052
   447
	} else if (type == DPT_DataTable) {
dvander@1052
   448
		return "datatable";
dvander@1052
   449
	} else {
dvander@1052
   450
		return "unknown";
dvander@1052
   451
	}
dvander@1052
   452
}
dvander@1052
   453
dvander@1052
   454
void _DumpProps(FILE *fp, SendTable *pTable)
dvander@1052
   455
{
dvander@1052
   456
	SendTable *pOther;
dvander@1052
   457
	for (int i=0; i<pTable->GetNumProps(); i++)
dvander@1052
   458
	{
dvander@1052
   459
		SendProp *prop = pTable->GetProp(i);
dvander@1052
   460
		if ((pOther = prop->GetDataTable()) != NULL)
dvander@1052
   461
		{
dvander@1052
   462
			_DumpProps(fp, pOther);
dvander@1052
   463
		} else {
dvander@1052
   464
			fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", 
dvander@1052
   465
				prop->GetName() ? prop->GetName() : "unknown",
dvander@1052
   466
				SendPropTypeToString(prop->GetType()));
dvander@1052
   467
		}
dvander@1052
   468
	}
dvander@1052
   469
}
dvander@1052
   470
dvander@1052
   471
void TempEntityManager::DumpProps(FILE *fp)
dvander@1052
   472
{
dvander@1052
   473
	unsigned int index = 0;
dvander@1052
   474
	void *iter = m_ListHead;
dvander@1052
   475
	fprintf(fp, "\"TempEnts\"\n{\n");
dvander@1052
   476
	while (iter)
dvander@1052
   477
	{
dvander@1052
   478
		const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
dvander@1052
   479
		if (!realname)
dvander@1052
   480
		{
dvander@1052
   481
			break;
dvander@1052
   482
		}
dvander@1052
   483
		TempEntityInfo *info = GetTempEntityInfo(realname);
dvander@1052
   484
		if (!info)
dvander@1052
   485
		{
dvander@1052
   486
			continue;
dvander@1052
   487
		}
dvander@1052
   488
		ServerClass *sc = info->GetServerClass();
dvander@1052
   489
		fprintf(fp, "\t\"%s\"\n", sc->GetName());
dvander@1052
   490
		fprintf(fp, "\t{\n");
dvander@1052
   491
		fprintf(fp, "\t\t\"name\"\t\t\"%s\"\n", realname);
dvander@1052
   492
		fprintf(fp, "\t\t\"index\"\t\t\"%d\"\n", index++);
dvander@1052
   493
		fprintf(fp, "\t\t\"SendTable\"\n\t\t{\n");
dvander@1052
   494
		_DumpProps(fp, sc->m_pTable);
dvander@1052
   495
		fprintf(fp, "\t\t}\n\t}\n");
dvander@1052
   496
		iter = *(void **)((unsigned char *)iter + m_NextOffs);
dvander@1052
   497
	}
dvander@1052
   498
	fprintf(fp, "}\n");
dvander@1052
   499
	META_CONPRINTF("%d tempent%s written to file.\n", index, (index == 1) ? " was" : "s were");
dvander@1052
   500
}