core/HalfLife2.cpp
author Scott Ehlert <ds@alliedmods.net>
Fri Jun 22 15:37:12 2007 +0000 (2007-06-22)
changeset 1001 8de56a71f200
parent 965 327edbb1357a
child 1132 e8d4e82e9541
permissions -rw-r--r--
Implemented amb423 - Added IsClientObserver() native
dvander@592
     1
/**
ds@653
     2
 * vim: set ts=4 :
dvander@592
     3
 * ===============================================================
dvander@592
     4
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
dvander@592
     5
 * ===============================================================
dvander@592
     6
 *
dvander@592
     7
 * This file is not open source and may not be copied without explicit
dvander@592
     8
 * written permission of AlliedModders LLC.  This file may not be redistributed 
dvander@592
     9
 * in whole or significant part.
dvander@592
    10
 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
dvander@592
    11
 *
dvander@592
    12
 * Version: $Id$
dvander@592
    13
 */
dvander@592
    14
dvander@592
    15
#include "HalfLife2.h"
ds@696
    16
#include "sourcemod.h"
dvander@592
    17
#include "sourcemm_api.h"
ds@873
    18
#include "UserMessages.h"
dvander@592
    19
dvander@592
    20
CHalfLife2 g_HL2;
dvander@685
    21
bool g_IsOriginalEngine = false;
dvander@592
    22
faluco@682
    23
namespace SourceHook
faluco@682
    24
{
faluco@682
    25
	template<>
faluco@682
    26
	int HashFunction<datamap_t *>(datamap_t * const &k)
faluco@682
    27
	{
faluco@682
    28
		return reinterpret_cast<int>(k);
faluco@682
    29
	}
faluco@682
    30
faluco@682
    31
	template<>
faluco@682
    32
	int Compare<datamap_t *>(datamap_t * const &k1, datamap_t * const &k2)
faluco@682
    33
	{
faluco@682
    34
		return (k1-k2);
faluco@682
    35
	}
faluco@682
    36
}
faluco@682
    37
dvander@592
    38
CHalfLife2::CHalfLife2()
dvander@592
    39
{
dvander@592
    40
	m_pClasses = sm_trie_create();
dvander@592
    41
}
dvander@592
    42
dvander@592
    43
CHalfLife2::~CHalfLife2()
dvander@592
    44
{
dvander@592
    45
	sm_trie_destroy(m_pClasses);
dvander@592
    46
dvander@592
    47
	List<DataTableInfo *>::iterator iter;
dvander@592
    48
	DataTableInfo *pInfo;
dvander@592
    49
	for (iter=m_Tables.begin(); iter!=m_Tables.end(); iter++)
dvander@592
    50
	{
dvander@592
    51
		pInfo = (*iter);
dvander@592
    52
		sm_trie_destroy(pInfo->lookup);
dvander@592
    53
		delete pInfo;
dvander@592
    54
	}
dvander@592
    55
dvander@592
    56
	m_Tables.clear();
faluco@682
    57
faluco@682
    58
	THash<datamap_t *, DataMapTrie>::iterator h_iter;
faluco@682
    59
	for (h_iter=m_Maps.begin(); h_iter!=m_Maps.end(); h_iter++)
faluco@682
    60
	{
faluco@682
    61
		if (h_iter->val.trie)
faluco@682
    62
		{
faluco@682
    63
			sm_trie_destroy(h_iter->val.trie);
faluco@682
    64
			h_iter->val.trie = NULL;
faluco@682
    65
		}
faluco@682
    66
	}
faluco@682
    67
faluco@682
    68
	m_Maps.clear();
dvander@592
    69
}
dvander@592
    70
dvander@677
    71
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
dvander@677
    72
dvander@592
    73
void CHalfLife2::OnSourceModStartup(bool late)
dvander@592
    74
{
ds@696
    75
	/* The Ship currently is the only known game to use an older version of the engine */
ds@729
    76
	if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
dvander@677
    77
	{
ds@696
    78
		/* :TODO: Better engine versioning - perhaps something added to SourceMM? */
ds@696
    79
		g_IsOriginalEngine = true;
ds@696
    80
	} else if (!g_pSharedChangeInfo) {
dvander@677
    81
		g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
dvander@677
    82
	}
dvander@592
    83
}
dvander@592
    84
ds@873
    85
void CHalfLife2::OnSourceModAllInitialized()
ds@873
    86
{
ds@873
    87
	m_MsgTextMsg = g_UserMsgs.GetMessageIndex("TextMsg");
dvander@965
    88
	g_ShareSys.AddInterface(NULL, this);
ds@873
    89
}
ds@873
    90
dvander@678
    91
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
dvander@678
    92
{
dvander@678
    93
	return engine->GetChangeAccessor( (const edict_t *)this );
dvander@678
    94
}
dvander@678
    95
dvander@592
    96
SendProp *UTIL_FindInSendTable(SendTable *pTable, const char *name)
dvander@592
    97
{
dvander@592
    98
	const char *pname;
dvander@592
    99
	int props = pTable->GetNumProps();
dvander@592
   100
	SendProp *prop;
dvander@592
   101
dvander@592
   102
	for (int i=0; i<props; i++)
dvander@592
   103
	{
dvander@592
   104
		prop = pTable->GetProp(i);
dvander@592
   105
		pname = prop->GetName();
dvander@592
   106
		if (pname && strcmp(name, pname) == 0)
dvander@592
   107
		{
dvander@592
   108
			return prop;
dvander@592
   109
		}
dvander@592
   110
		if (prop->GetDataTable())
dvander@592
   111
		{
dvander@592
   112
			if ((prop=UTIL_FindInSendTable(prop->GetDataTable(), name)) != NULL)
dvander@592
   113
			{
dvander@592
   114
				return prop;
dvander@592
   115
			}
dvander@592
   116
		}
dvander@592
   117
	}
dvander@592
   118
dvander@592
   119
	return NULL;
dvander@592
   120
}
dvander@592
   121
faluco@682
   122
typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
faluco@682
   123
{
faluco@682
   124
	while (pMap)
faluco@682
   125
	{
faluco@682
   126
		for (int i=0; i<pMap->dataNumFields; i++)
faluco@682
   127
		{
dvander@709
   128
			if (pMap->dataDesc[i].fieldName == NULL)
dvander@709
   129
			{
dvander@709
   130
				continue;
dvander@709
   131
			}
faluco@682
   132
			if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
faluco@682
   133
			{
faluco@682
   134
				return &(pMap->dataDesc[i]);
faluco@682
   135
			}
faluco@682
   136
			if (pMap->dataDesc[i].td)
faluco@682
   137
			{
faluco@682
   138
				typedescription_t *_td;
faluco@682
   139
				if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
faluco@682
   140
				{
faluco@682
   141
					return _td;
faluco@682
   142
				}
faluco@682
   143
			}
faluco@682
   144
		}
faluco@682
   145
		pMap = pMap->baseMap;
faluco@682
   146
	}
faluco@682
   147
faluco@682
   148
	return NULL; 
faluco@682
   149
}
faluco@682
   150
dvander@592
   151
ServerClass *CHalfLife2::FindServerClass(const char *classname)
dvander@592
   152
{
dvander@592
   153
	DataTableInfo *pInfo = _FindServerClass(classname);
dvander@592
   154
	if (!pInfo)
dvander@592
   155
	{
dvander@592
   156
		return NULL;
dvander@592
   157
	}
dvander@592
   158
dvander@592
   159
	return pInfo->sc;
dvander@592
   160
}
dvander@592
   161
dvander@592
   162
DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
dvander@592
   163
{
dvander@592
   164
	DataTableInfo *pInfo = NULL;
dvander@592
   165
dvander@592
   166
	if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
dvander@592
   167
	{
dvander@592
   168
		ServerClass *sc = gamedll->GetAllServerClasses();
dvander@592
   169
		while (sc)
dvander@592
   170
		{
dvander@592
   171
			if (strcmp(classname, sc->GetName()) == 0)
dvander@592
   172
			{
dvander@592
   173
				pInfo = new DataTableInfo;
dvander@592
   174
				pInfo->lookup = sm_trie_create();
dvander@592
   175
				pInfo->sc = sc;
dvander@592
   176
				sm_trie_insert(m_pClasses, classname, pInfo);
faluco@682
   177
				m_Tables.push_back(pInfo);
dvander@592
   178
				break;
dvander@592
   179
			}
dvander@592
   180
			sc = sc->m_pNext;
dvander@592
   181
		}
dvander@592
   182
		if (!pInfo)
dvander@592
   183
		{
dvander@592
   184
			return NULL;
dvander@592
   185
		}
dvander@592
   186
	}
dvander@592
   187
dvander@592
   188
	return pInfo;
dvander@592
   189
}
dvander@592
   190
dvander@592
   191
SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
dvander@592
   192
{
dvander@592
   193
	DataTableInfo *pInfo = _FindServerClass(classname);
dvander@592
   194
dvander@592
   195
	if (!pInfo)
dvander@592
   196
	{
dvander@592
   197
		return NULL;
dvander@592
   198
	}
dvander@592
   199
faluco@682
   200
	SendProp *pProp = NULL;
dvander@592
   201
	if (!sm_trie_retrieve(pInfo->lookup, offset, (void **)&pProp))
dvander@592
   202
	{
dvander@592
   203
		if ((pProp = UTIL_FindInSendTable(pInfo->sc->m_pTable, offset)) != NULL)
dvander@592
   204
		{
dvander@592
   205
			sm_trie_insert(pInfo->lookup, offset, pProp);
dvander@592
   206
		}
dvander@592
   207
	}
dvander@592
   208
dvander@592
   209
	return pProp;
dvander@592
   210
}
faluco@682
   211
faluco@682
   212
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
faluco@682
   213
{
faluco@682
   214
	typedescription_t *td = NULL;
faluco@682
   215
	DataMapTrie &val = m_Maps[pMap];
faluco@682
   216
faluco@682
   217
	if (!val.trie)
faluco@682
   218
	{
faluco@682
   219
		val.trie = sm_trie_create();
faluco@682
   220
	}
faluco@682
   221
	if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
faluco@682
   222
	{
faluco@682
   223
		if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
faluco@682
   224
		{
faluco@682
   225
			sm_trie_insert(val.trie, offset, td);
faluco@682
   226
		}
faluco@682
   227
	}
faluco@682
   228
faluco@682
   229
	return td;
faluco@682
   230
}
dvander@685
   231
dvander@685
   232
void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
dvander@685
   233
{
dvander@685
   234
	if (!g_IsOriginalEngine)
dvander@685
   235
	{
dvander@685
   236
		if (offset)
dvander@685
   237
		{
dvander@685
   238
			pEdict->StateChanged(offset);
dvander@685
   239
		} else {
dvander@685
   240
			pEdict->StateChanged();
dvander@685
   241
		}
dvander@685
   242
	} else {
dvander@685
   243
		pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
dvander@685
   244
	}
dvander@685
   245
}
ds@873
   246
ds@873
   247
void CHalfLife2::TextMsg(int client, int dest, const char *msg)
ds@873
   248
{
ds@873
   249
	bf_write *pBitBuf = NULL;
ds@873
   250
	cell_t players[] = {client};
ds@873
   251
ds@873
   252
	pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE);
ds@873
   253
	pBitBuf->WriteByte(dest);
ds@873
   254
	pBitBuf->WriteString(msg);
ds@873
   255
	g_UserMsgs.EndMessage();
ds@873
   256
}