core/HalfLife2.cpp
author David Anderson <dvander@alliedmods.net>
Tue May 22 20:50:48 2007 +0000 (2007-05-22)
changeset 833 732bedfcbe3e
parent 729 110c14c99545
child 873 a2136b3be10d
permissions -rw-r--r--
added ReplaceString and ReplaceStringEx (phew!)
     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 
    19 CHalfLife2 g_HL2;
    20 bool g_IsOriginalEngine = false;
    21 
    22 namespace SourceHook
    23 {
    24 	template<>
    25 	int HashFunction<datamap_t *>(datamap_t * const &k)
    26 	{
    27 		return reinterpret_cast<int>(k);
    28 	}
    29 
    30 	template<>
    31 	int Compare<datamap_t *>(datamap_t * const &k1, datamap_t * const &k2)
    32 	{
    33 		return (k1-k2);
    34 	}
    35 }
    36 
    37 CHalfLife2::CHalfLife2()
    38 {
    39 	m_pClasses = sm_trie_create();
    40 }
    41 
    42 CHalfLife2::~CHalfLife2()
    43 {
    44 	sm_trie_destroy(m_pClasses);
    45 
    46 	List<DataTableInfo *>::iterator iter;
    47 	DataTableInfo *pInfo;
    48 	for (iter=m_Tables.begin(); iter!=m_Tables.end(); iter++)
    49 	{
    50 		pInfo = (*iter);
    51 		sm_trie_destroy(pInfo->lookup);
    52 		delete pInfo;
    53 	}
    54 
    55 	m_Tables.clear();
    56 
    57 	THash<datamap_t *, DataMapTrie>::iterator h_iter;
    58 	for (h_iter=m_Maps.begin(); h_iter!=m_Maps.end(); h_iter++)
    59 	{
    60 		if (h_iter->val.trie)
    61 		{
    62 			sm_trie_destroy(h_iter->val.trie);
    63 			h_iter->val.trie = NULL;
    64 		}
    65 	}
    66 
    67 	m_Maps.clear();
    68 }
    69 
    70 CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
    71 
    72 void CHalfLife2::OnSourceModStartup(bool late)
    73 {
    74 	/* The Ship currently is the only known game to use an older version of the engine */
    75 	if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
    76 	{
    77 		/* :TODO: Better engine versioning - perhaps something added to SourceMM? */
    78 		g_IsOriginalEngine = true;
    79 	} else if (!g_pSharedChangeInfo) {
    80 		g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
    81 	}
    82 }
    83 
    84 IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
    85 {
    86 	return engine->GetChangeAccessor( (const edict_t *)this );
    87 }
    88 
    89 SendProp *UTIL_FindInSendTable(SendTable *pTable, const char *name)
    90 {
    91 	const char *pname;
    92 	int props = pTable->GetNumProps();
    93 	SendProp *prop;
    94 
    95 	for (int i=0; i<props; i++)
    96 	{
    97 		prop = pTable->GetProp(i);
    98 		pname = prop->GetName();
    99 		if (pname && strcmp(name, pname) == 0)
   100 		{
   101 			return prop;
   102 		}
   103 		if (prop->GetDataTable())
   104 		{
   105 			if ((prop=UTIL_FindInSendTable(prop->GetDataTable(), name)) != NULL)
   106 			{
   107 				return prop;
   108 			}
   109 		}
   110 	}
   111 
   112 	return NULL;
   113 }
   114 
   115 typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
   116 {
   117 	while (pMap)
   118 	{
   119 		for (int i=0; i<pMap->dataNumFields; i++)
   120 		{
   121 			if (pMap->dataDesc[i].fieldName == NULL)
   122 			{
   123 				continue;
   124 			}
   125 			if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
   126 			{
   127 				return &(pMap->dataDesc[i]);
   128 			}
   129 			if (pMap->dataDesc[i].td)
   130 			{
   131 				typedescription_t *_td;
   132 				if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
   133 				{
   134 					return _td;
   135 				}
   136 			}
   137 		}
   138 		pMap = pMap->baseMap;
   139 	}
   140 
   141 	return NULL; 
   142 }
   143 
   144 ServerClass *CHalfLife2::FindServerClass(const char *classname)
   145 {
   146 	DataTableInfo *pInfo = _FindServerClass(classname);
   147 	if (!pInfo)
   148 	{
   149 		return NULL;
   150 	}
   151 
   152 	return pInfo->sc;
   153 }
   154 
   155 DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
   156 {
   157 	DataTableInfo *pInfo = NULL;
   158 
   159 	if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
   160 	{
   161 		ServerClass *sc = gamedll->GetAllServerClasses();
   162 		while (sc)
   163 		{
   164 			if (strcmp(classname, sc->GetName()) == 0)
   165 			{
   166 				pInfo = new DataTableInfo;
   167 				pInfo->lookup = sm_trie_create();
   168 				pInfo->sc = sc;
   169 				sm_trie_insert(m_pClasses, classname, pInfo);
   170 				m_Tables.push_back(pInfo);
   171 				break;
   172 			}
   173 			sc = sc->m_pNext;
   174 		}
   175 		if (!pInfo)
   176 		{
   177 			return NULL;
   178 		}
   179 	}
   180 
   181 	return pInfo;
   182 }
   183 
   184 SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
   185 {
   186 	DataTableInfo *pInfo = _FindServerClass(classname);
   187 
   188 	if (!pInfo)
   189 	{
   190 		return NULL;
   191 	}
   192 
   193 	SendProp *pProp = NULL;
   194 	if (!sm_trie_retrieve(pInfo->lookup, offset, (void **)&pProp))
   195 	{
   196 		if ((pProp = UTIL_FindInSendTable(pInfo->sc->m_pTable, offset)) != NULL)
   197 		{
   198 			sm_trie_insert(pInfo->lookup, offset, pProp);
   199 		}
   200 	}
   201 
   202 	return pProp;
   203 }
   204 
   205 typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
   206 {
   207 	typedescription_t *td = NULL;
   208 	DataMapTrie &val = m_Maps[pMap];
   209 
   210 	if (!val.trie)
   211 	{
   212 		val.trie = sm_trie_create();
   213 	}
   214 	if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
   215 	{
   216 		if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
   217 		{
   218 			sm_trie_insert(val.trie, offset, td);
   219 		}
   220 	}
   221 
   222 	return td;
   223 }
   224 
   225 void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
   226 {
   227 	if (!g_IsOriginalEngine)
   228 	{
   229 		if (offset)
   230 		{
   231 			pEdict->StateChanged(offset);
   232 		} else {
   233 			pEdict->StateChanged();
   234 		}
   235 	} else {
   236 		pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
   237 	}
   238 }