core/HalfLife2.cpp
author Scott Ehlert <ds@alliedmods.net>
Sat Apr 21 17:03:28 2007 +0000 (2007-04-21)
changeset 702 ff520b71249c
parent 696 d5cc8d0fa899
child 709 2e7e13504a64
permissions -rw-r--r--
Wow, how did I forget this - exported IMemoryUtils interface
     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.GetModFolderName(), "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 (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
   122 			{
   123 				return &(pMap->dataDesc[i]);
   124 			}
   125 			if (pMap->dataDesc[i].td)
   126 			{
   127 				typedescription_t *_td;
   128 				if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
   129 				{
   130 					return _td;
   131 				}
   132 			}
   133 		}
   134 		pMap = pMap->baseMap;
   135 	}
   136 
   137 	return NULL; 
   138 }
   139 
   140 ServerClass *CHalfLife2::FindServerClass(const char *classname)
   141 {
   142 	DataTableInfo *pInfo = _FindServerClass(classname);
   143 	if (!pInfo)
   144 	{
   145 		return NULL;
   146 	}
   147 
   148 	return pInfo->sc;
   149 }
   150 
   151 DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
   152 {
   153 	DataTableInfo *pInfo = NULL;
   154 
   155 	if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
   156 	{
   157 		ServerClass *sc = gamedll->GetAllServerClasses();
   158 		while (sc)
   159 		{
   160 			if (strcmp(classname, sc->GetName()) == 0)
   161 			{
   162 				pInfo = new DataTableInfo;
   163 				pInfo->lookup = sm_trie_create();
   164 				pInfo->sc = sc;
   165 				sm_trie_insert(m_pClasses, classname, pInfo);
   166 				m_Tables.push_back(pInfo);
   167 				break;
   168 			}
   169 			sc = sc->m_pNext;
   170 		}
   171 		if (!pInfo)
   172 		{
   173 			return NULL;
   174 		}
   175 	}
   176 
   177 	return pInfo;
   178 }
   179 
   180 SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
   181 {
   182 	DataTableInfo *pInfo = _FindServerClass(classname);
   183 
   184 	if (!pInfo)
   185 	{
   186 		return NULL;
   187 	}
   188 
   189 	SendProp *pProp = NULL;
   190 	if (!sm_trie_retrieve(pInfo->lookup, offset, (void **)&pProp))
   191 	{
   192 		if ((pProp = UTIL_FindInSendTable(pInfo->sc->m_pTable, offset)) != NULL)
   193 		{
   194 			sm_trie_insert(pInfo->lookup, offset, pProp);
   195 		}
   196 	}
   197 
   198 	return pProp;
   199 }
   200 
   201 typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
   202 {
   203 	typedescription_t *td = NULL;
   204 	DataMapTrie &val = m_Maps[pMap];
   205 
   206 	if (!val.trie)
   207 	{
   208 		val.trie = sm_trie_create();
   209 	}
   210 	if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
   211 	{
   212 		if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
   213 		{
   214 			sm_trie_insert(val.trie, offset, td);
   215 		}
   216 	}
   217 
   218 	return td;
   219 }
   220 
   221 void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
   222 {
   223 	if (!g_IsOriginalEngine)
   224 	{
   225 		if (offset)
   226 		{
   227 			pEdict->StateChanged(offset);
   228 		} else {
   229 			pEdict->StateChanged();
   230 		}
   231 	} else {
   232 		pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
   233 	}
   234 }