extensions/sdktools/tempents.cpp
author David Anderson <dvander@alliedmods.net>
Sat Jul 07 20:45:48 2007 +0000 (2007-07-07)
changeset 1052 a2de25952811
parent 1039 71e55e3fd8f7
child 1059 255bb3a2f47b
permissions -rw-r--r--
added some quick commands to dump te info
faluco@1031
     1
/**
faluco@1031
     2
 * vim: set ts=4 :
faluco@1031
     3
 * ===============================================================
faluco@1031
     4
 * SourceMod SDK Tools Extension
faluco@1031
     5
 * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
faluco@1031
     6
 * ===============================================================
faluco@1031
     7
 *
faluco@1031
     8
 * This program is free software; you can redistribute it and/or
faluco@1031
     9
 * modify it under the terms of the GNU General Public License
faluco@1031
    10
 * as published by the Free Software Foundation; either version 2
faluco@1031
    11
 * of the License, or (at your option) any later version.
faluco@1031
    12
 * This program is distributed in the hope that it will be useful,
faluco@1031
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
faluco@1031
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
faluco@1031
    15
 * GNU General Public License for more details.
faluco@1031
    16
 * 
faluco@1031
    17
 * You should have received a copy of the GNU General Public License
faluco@1031
    18
 * along with this program; if not, write to the Free Software
faluco@1031
    19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
faluco@1031
    20
 *
faluco@1031
    21
 * Version: $Id$
faluco@1031
    22
 */
faluco@1031
    23
faluco@1031
    24
#include "tempents.h"
faluco@1031
    25
faluco@1031
    26
TempEntityManager g_TEManager;
faluco@1031
    27
ICallWrapper *g_GetServerClass = NULL;
faluco@1031
    28
dvander@1052
    29
CON_COMMAND(sm_print_telist, "Prints the temp entity list")
dvander@1052
    30
{
dvander@1052
    31
	if (!g_TEManager.IsAvailable())
dvander@1052
    32
	{
dvander@1052
    33
		META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
dvander@1052
    34
		META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
dvander@1052
    35
		return;
dvander@1052
    36
	}
dvander@1052
    37
	g_TEManager.DumpList();
dvander@1052
    38
}
dvander@1052
    39
dvander@1052
    40
CON_COMMAND(sm_dump_teprops, "Dumps tempentity props to a file")
dvander@1052
    41
{
dvander@1052
    42
	if (!g_TEManager.IsAvailable())
dvander@1052
    43
	{
dvander@1052
    44
		META_CONPRINT("The tempent portion of SDKTools failed to load.\n");
dvander@1052
    45
		META_CONPRINT("Check that you have the latest sdktools.games.txt file!\n");
dvander@1052
    46
		return;
dvander@1052
    47
	}
dvander@1052
    48
	int argc = engine->Cmd_Argc();
dvander@1052
    49
	if (argc < 2)
dvander@1052
    50
	{
dvander@1052
    51
		META_CONPRINT("Usage: sm_dump_teprops <file>\n");
dvander@1052
    52
		return;
dvander@1052
    53
	}
dvander@1052
    54
	const char *arg = engine->Cmd_Argv(1);
dvander@1052
    55
	FILE *fp = NULL;
dvander@1052
    56
	if (!arg || arg[0] == '\0' || ((fp = fopen(arg, "wt")) == NULL))
dvander@1052
    57
	{
dvander@1052
    58
		META_CONPRINTF("Could not open file \"%s\"\n", arg);
dvander@1052
    59
		return;
dvander@1052
    60
	}
dvander@1052
    61
	g_TEManager.DumpProps(fp);
dvander@1052
    62
	fclose(fp);
dvander@1052
    63
}
dvander@1052
    64
faluco@1031
    65
/*************************
faluco@1031
    66
*                        *
faluco@1031
    67
* Temp Entities Wrappers *
faluco@1031
    68
*                        *
faluco@1031
    69
**************************/
faluco@1031
    70
faluco@1031
    71
TempEntityInfo::TempEntityInfo(const char *name, void *me)
faluco@1031
    72
{
faluco@1031
    73
	m_Name.assign(name);
faluco@1031
    74
	m_Me = me;
faluco@1031
    75
	g_GetServerClass->Execute(&m_Me, &m_Sc);
faluco@1031
    76
}
faluco@1031
    77
faluco@1031
    78
const char *TempEntityInfo::GetName()
faluco@1031
    79
{
faluco@1031
    80
	return m_Name.c_str();
faluco@1031
    81
}
faluco@1031
    82
dvander@1052
    83
ServerClass *TempEntityInfo::GetServerClass()
dvander@1052
    84
{
dvander@1052
    85
	return m_Sc;
dvander@1052
    86
}
dvander@1052
    87
faluco@1031
    88
bool TempEntityInfo::IsValidProp(const char *name)
faluco@1031
    89
{
faluco@1031
    90
	return (g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name)) ? true : false;
faluco@1031
    91
}
faluco@1031
    92
faluco@1031
    93
int TempEntityInfo::_FindOffset(const char *name, int *size)
faluco@1031
    94
{
faluco@1031
    95
	int offset;
faluco@1031
    96
faluco@1031
    97
	SendProp *prop = g_pGameHelpers->FindInSendTable(m_Sc->GetName(), name);
faluco@1031
    98
	if (!prop)
faluco@1031
    99
	{
faluco@1031
   100
		return -1;
faluco@1031
   101
	}
faluco@1031
   102
faluco@1031
   103
	offset = prop->GetOffset();
faluco@1031
   104
	if (size)
faluco@1031
   105
	{
faluco@1032
   106
		*size = prop->m_nBits;
faluco@1031
   107
	}
faluco@1031
   108
faluco@1031
   109
	return offset;
faluco@1031
   110
}
faluco@1031
   111
faluco@1031
   112
bool TempEntityInfo::TE_SetEntData(const char *name, int value)
faluco@1031
   113
{
faluco@1031
   114
	/* Search for our offset */
faluco@1031
   115
	int size;
faluco@1031
   116
	int offset = _FindOffset(name, &size);
faluco@1031
   117
faluco@1031
   118
	if (offset < 0)
faluco@1031
   119
	{
faluco@1031
   120
		return false;
faluco@1031
   121
	}
faluco@1031
   122
faluco@1031
   123
	if (size <= 8)
faluco@1031
   124
	{
faluco@1031
   125
		*((uint8_t *)m_Me + offset) = value;
faluco@1031
   126
	} else if (size <= 16) {
faluco@1031
   127
		*(short *)((uint8_t *)m_Me + offset) = value;
faluco@1031
   128
	} else if (size <= 32){
faluco@1031
   129
		*(int *)((uint8_t *)m_Me + offset) = value;
faluco@1031
   130
	} else {
faluco@1031
   131
		return false;
faluco@1031
   132
	}
faluco@1031
   133
faluco@1031
   134
	return true;
faluco@1031
   135
}
faluco@1031
   136
faluco@1031
   137
bool TempEntityInfo::TE_SetEntDataFloat(const char *name, float value)
faluco@1031
   138
{
faluco@1031
   139
	/* Search for our offset */
faluco@1031
   140
	int offset = _FindOffset(name);
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
	*(float *)((uint8_t *)m_Me + offset) = value;
faluco@1031
   148
faluco@1031
   149
	return true;
faluco@1031
   150
}
faluco@1031
   151
faluco@1031
   152
bool TempEntityInfo::TE_SetEntDataVector(const char *name, float vector[3])
faluco@1031
   153
{
faluco@1031
   154
	/* Search for our offset */
faluco@1031
   155
	int offset = _FindOffset(name);
faluco@1031
   156
faluco@1031
   157
	if (offset < 0)
faluco@1031
   158
	{
faluco@1031
   159
		return false;
faluco@1031
   160
	}
faluco@1031
   161
faluco@1031
   162
	Vector *v = (Vector *)((uint8_t *)m_Me + offset);
faluco@1031
   163
	v->x = vector[0];
faluco@1031
   164
	v->y = vector[1];
faluco@1031
   165
	v->z = vector[2];
faluco@1031
   166
faluco@1031
   167
	return true;
faluco@1031
   168
}
faluco@1031
   169
faluco@1039
   170
bool TempEntityInfo::TE_SetEntDataFloatArray(const char *name, cell_t *array, int size)
faluco@1039
   171
{
faluco@1039
   172
	/* Search for our offset */
faluco@1039
   173
	int offset = _FindOffset(name);
faluco@1039
   174
faluco@1039
   175
	if (offset < 0)
faluco@1039
   176
	{
faluco@1039
   177
		return false;
faluco@1039
   178
	}
faluco@1039
   179
faluco@1039
   180
	float *base = (float *)((uint8_t *)m_Me + offset);
faluco@1039
   181
	for (int i=0; i<size; i++)
faluco@1039
   182
	{
faluco@1039
   183
		base[i] = sp_ctof(array[i]);
faluco@1039
   184
	}
faluco@1039
   185
faluco@1039
   186
	return true;
faluco@1039
   187
}
faluco@1039
   188
faluco@1031
   189
void TempEntityInfo::Send(IRecipientFilter &filter, float delay)
faluco@1031
   190
{
faluco@1039
   191
	engine->PlaybackTempEntity(filter, delay, m_Me, m_Sc->m_pTable, m_Sc->m_ClassID);
faluco@1031
   192
}
faluco@1031
   193
faluco@1031
   194
/**********************
faluco@1031
   195
*                     *
faluco@1031
   196
* Temp Entity Manager *
faluco@1031
   197
*                     *
faluco@1031
   198
***********************/
faluco@1031
   199
faluco@1031
   200
void TempEntityManager::Initialize()
faluco@1031
   201
{
faluco@1031
   202
	void *addr;
faluco@1031
   203
	int offset;
faluco@1031
   204
	m_Loaded = false;
faluco@1031
   205
faluco@1031
   206
	/* Read our sigs and offsets from the config file */
faluco@1031
   207
	if (!g_pGameConf->GetMemSig("CBaseTempEntity", &addr) || !addr)
faluco@1031
   208
	{
faluco@1031
   209
		return;
faluco@1031
   210
	}
faluco@1031
   211
	if (!g_pGameConf->GetOffset("s_pTempEntities", &offset) || !offset)
faluco@1031
   212
	{
faluco@1031
   213
		return;
faluco@1031
   214
	}
faluco@1031
   215
	if (!g_pGameConf->GetOffset("GetTEName", &m_NameOffs) || !m_NameOffs)
faluco@1031
   216
	{
faluco@1031
   217
		return;
faluco@1031
   218
	}
faluco@1031
   219
	if (!g_pGameConf->GetOffset("GetTENext", &m_NextOffs) || !m_NextOffs)
faluco@1031
   220
	{
faluco@1031
   221
		return;
faluco@1031
   222
	}
faluco@1031
   223
	if (!g_pGameConf->GetOffset("TE_GetServerClass", &m_GetClassNameOffs) || !m_GetClassNameOffs)
faluco@1031
   224
	{
faluco@1031
   225
		return;
faluco@1031
   226
	}
faluco@1031
   227
faluco@1031
   228
	/* Store the head of the TE linked list */
faluco@1031
   229
	m_ListHead = **(void ***)((unsigned char *)addr + offset);
faluco@1031
   230
faluco@1031
   231
	/* Create our trie */
faluco@1031
   232
	m_TempEntInfo = adtfactory->CreateBasicTrie();
faluco@1031
   233
faluco@1031
   234
	/* Create the GetServerClass call */
faluco@1031
   235
	PassInfo retinfo;
faluco@1031
   236
	retinfo.flags = PASSFLAG_BYVAL;
faluco@1031
   237
	retinfo.type = PassType_Basic;
faluco@1031
   238
	retinfo.size = sizeof(ServerClass *);
faluco@1031
   239
	g_GetServerClass = g_pBinTools->CreateVCall(m_GetClassNameOffs, 0, 0, &retinfo, NULL, 0);
faluco@1031
   240
faluco@1031
   241
	/* We're done */
faluco@1031
   242
	m_Loaded = true;
faluco@1031
   243
}
faluco@1031
   244
faluco@1031
   245
bool TempEntityManager::IsAvailable()
faluco@1031
   246
{
faluco@1031
   247
	return m_Loaded;
faluco@1031
   248
}
faluco@1031
   249
faluco@1031
   250
void TempEntityManager::Shutdown()
faluco@1031
   251
{
faluco@1031
   252
	if (!IsAvailable())
faluco@1031
   253
	{
faluco@1031
   254
		return;
faluco@1031
   255
	}
faluco@1031
   256
faluco@1031
   257
	List<TempEntityInfo *>::iterator iter;
faluco@1031
   258
	for (iter=m_TEList.begin(); iter!=m_TEList.end(); iter++)
faluco@1031
   259
	{
faluco@1031
   260
		delete (*iter);
faluco@1031
   261
	}
faluco@1031
   262
	m_TEList.clear();
faluco@1031
   263
faluco@1031
   264
	m_TempEntInfo->Destroy();
faluco@1031
   265
	g_GetServerClass->Destroy();
faluco@1031
   266
	g_GetServerClass = NULL;
faluco@1031
   267
	m_ListHead = NULL;
faluco@1031
   268
	m_NextOffs = m_NameOffs = m_GetClassNameOffs = 0;
faluco@1031
   269
	m_Loaded = false;
faluco@1031
   270
}
faluco@1031
   271
faluco@1031
   272
TempEntityInfo *TempEntityManager::GetTempEntityInfo(const char *name)
faluco@1031
   273
{
faluco@1031
   274
	/* If the system is unloaded skip the search */
faluco@1031
   275
	if (!IsAvailable())
faluco@1031
   276
	{
faluco@1031
   277
		return NULL;
faluco@1031
   278
	}
faluco@1031
   279
faluco@1031
   280
	TempEntityInfo *te = NULL;
faluco@1031
   281
faluco@1031
   282
	/* Start searching for the TE inside the engine */
faluco@1031
   283
	if (!m_TempEntInfo->Retrieve(name, reinterpret_cast<void **>(&te)))
faluco@1031
   284
	{
faluco@1031
   285
		void *iter = m_ListHead;
faluco@1031
   286
		while (iter)
faluco@1031
   287
		{
faluco@1031
   288
			const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
faluco@1031
   289
			if (!realname)
faluco@1031
   290
			{
faluco@1031
   291
				continue;
faluco@1031
   292
			}
faluco@1031
   293
			if (strcmp(name, realname) == 0)
faluco@1031
   294
			{
faluco@1031
   295
				te = new TempEntityInfo(name, iter);
faluco@1031
   296
				m_TempEntInfo->Insert(name, (void *)te);
faluco@1031
   297
				m_TEList.push_back(te);
faluco@1031
   298
				return te;
faluco@1031
   299
			}
faluco@1031
   300
			iter = *(void **)((unsigned char *)iter + m_NextOffs);
faluco@1031
   301
		}
faluco@1031
   302
		return NULL;
faluco@1031
   303
	}
faluco@1031
   304
faluco@1031
   305
	return te;
faluco@1031
   306
}
dvander@1052
   307
dvander@1052
   308
void TempEntityManager::DumpList()
dvander@1052
   309
{
dvander@1052
   310
	unsigned int index = 0;
dvander@1052
   311
	META_CONPRINT("Listing temp entities:\n");
dvander@1052
   312
	void *iter = m_ListHead;
dvander@1052
   313
	while (iter)
dvander@1052
   314
	{
dvander@1052
   315
		const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
dvander@1052
   316
		if (!realname)
dvander@1052
   317
		{
dvander@1052
   318
			break;
dvander@1052
   319
		}
dvander@1052
   320
		TempEntityInfo *info = GetTempEntityInfo(realname);
dvander@1052
   321
		if (!info)
dvander@1052
   322
		{
dvander@1052
   323
			continue;
dvander@1052
   324
		}
dvander@1052
   325
		ServerClass *sc = info->GetServerClass();
dvander@1052
   326
		META_CONPRINTF("[%02d] %s (%s)\n", index++, realname, sc->GetName());
dvander@1052
   327
		iter = *(void **)((unsigned char *)iter + m_NextOffs);
dvander@1052
   328
	}
dvander@1052
   329
	META_CONPRINTF("%d tempent%s found.\n", index, (index == 1) ? " was" : "s were");
dvander@1052
   330
}
dvander@1052
   331
dvander@1052
   332
const char *SendPropTypeToString(SendPropType type)
dvander@1052
   333
{
dvander@1052
   334
	if (type == DPT_Int)
dvander@1052
   335
	{
dvander@1052
   336
		return "int";
dvander@1052
   337
	} else if (type == DPT_Float) {
dvander@1052
   338
		return "float";
dvander@1052
   339
	} else if (type == DPT_Vector) {
dvander@1052
   340
		return "vector";
dvander@1052
   341
	} else if (type == DPT_String) {
dvander@1052
   342
		return "string";
dvander@1052
   343
	} else if (type == DPT_Array) {
dvander@1052
   344
		return "array";
dvander@1052
   345
	} else if (type == DPT_DataTable) {
dvander@1052
   346
		return "datatable";
dvander@1052
   347
	} else {
dvander@1052
   348
		return "unknown";
dvander@1052
   349
	}
dvander@1052
   350
}
dvander@1052
   351
dvander@1052
   352
void _DumpProps(FILE *fp, SendTable *pTable)
dvander@1052
   353
{
dvander@1052
   354
	SendTable *pOther;
dvander@1052
   355
	for (int i=0; i<pTable->GetNumProps(); i++)
dvander@1052
   356
	{
dvander@1052
   357
		SendProp *prop = pTable->GetProp(i);
dvander@1052
   358
		if ((pOther = prop->GetDataTable()) != NULL)
dvander@1052
   359
		{
dvander@1052
   360
			_DumpProps(fp, pOther);
dvander@1052
   361
		} else {
dvander@1052
   362
			fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", 
dvander@1052
   363
				prop->GetName() ? prop->GetName() : "unknown",
dvander@1052
   364
				SendPropTypeToString(prop->GetType()));
dvander@1052
   365
		}
dvander@1052
   366
	}
dvander@1052
   367
}
dvander@1052
   368
dvander@1052
   369
void TempEntityManager::DumpProps(FILE *fp)
dvander@1052
   370
{
dvander@1052
   371
	unsigned int index = 0;
dvander@1052
   372
	void *iter = m_ListHead;
dvander@1052
   373
	fprintf(fp, "\"TempEnts\"\n{\n");
dvander@1052
   374
	while (iter)
dvander@1052
   375
	{
dvander@1052
   376
		const char *realname = *(const char **)((unsigned char *)iter + m_NameOffs);
dvander@1052
   377
		if (!realname)
dvander@1052
   378
		{
dvander@1052
   379
			break;
dvander@1052
   380
		}
dvander@1052
   381
		TempEntityInfo *info = GetTempEntityInfo(realname);
dvander@1052
   382
		if (!info)
dvander@1052
   383
		{
dvander@1052
   384
			continue;
dvander@1052
   385
		}
dvander@1052
   386
		ServerClass *sc = info->GetServerClass();
dvander@1052
   387
		fprintf(fp, "\t\"%s\"\n", sc->GetName());
dvander@1052
   388
		fprintf(fp, "\t{\n");
dvander@1052
   389
		fprintf(fp, "\t\t\"name\"\t\t\"%s\"\n", realname);
dvander@1052
   390
		fprintf(fp, "\t\t\"index\"\t\t\"%d\"\n", index++);
dvander@1052
   391
		fprintf(fp, "\t\t\"SendTable\"\n\t\t{\n");
dvander@1052
   392
		_DumpProps(fp, sc->m_pTable);
dvander@1052
   393
		fprintf(fp, "\t\t}\n\t}\n");
dvander@1052
   394
		iter = *(void **)((unsigned char *)iter + m_NextOffs);
dvander@1052
   395
	}
dvander@1052
   396
	fprintf(fp, "}\n");
dvander@1052
   397
	META_CONPRINTF("%d tempent%s written to file.\n", index, (index == 1) ? " was" : "s were");
dvander@1052
   398
}