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