/** * vim: set ts=4 : * =============================================================== * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. * =============================================================== * * This file is not open source and may not be copied without explicit * written permission of AlliedModders LLC. This file may not be redistributed * in whole or significant part. * For information, see LICENSE.txt or http://www.sourcemod.net/license.php * * Version: $Id$ */ #include "HalfLife2.h" #include "sourcemod.h" #include "sourcemm_api.h" CHalfLife2 g_HL2; bool g_IsOriginalEngine = false; namespace SourceHook { template<> int HashFunction(datamap_t * const &k) { return reinterpret_cast(k); } template<> int Compare(datamap_t * const &k1, datamap_t * const &k2) { return (k1-k2); } } CHalfLife2::CHalfLife2() { m_pClasses = sm_trie_create(); } CHalfLife2::~CHalfLife2() { sm_trie_destroy(m_pClasses); List::iterator iter; DataTableInfo *pInfo; for (iter=m_Tables.begin(); iter!=m_Tables.end(); iter++) { pInfo = (*iter); sm_trie_destroy(pInfo->lookup); delete pInfo; } m_Tables.clear(); THash::iterator h_iter; for (h_iter=m_Maps.begin(); h_iter!=m_Maps.end(); h_iter++) { if (h_iter->val.trie) { sm_trie_destroy(h_iter->val.trie); h_iter->val.trie = NULL; } } m_Maps.clear(); } CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL; void CHalfLife2::OnSourceModStartup(bool late) { /* The Ship currently is the only known game to use an older version of the engine */ if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0) { /* :TODO: Better engine versioning - perhaps something added to SourceMM? */ g_IsOriginalEngine = true; } else if (!g_pSharedChangeInfo) { g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo(); } } IChangeInfoAccessor *CBaseEdict::GetChangeAccessor() { return engine->GetChangeAccessor( (const edict_t *)this ); } SendProp *UTIL_FindInSendTable(SendTable *pTable, const char *name) { const char *pname; int props = pTable->GetNumProps(); SendProp *prop; for (int i=0; iGetProp(i); pname = prop->GetName(); if (pname && strcmp(name, pname) == 0) { return prop; } if (prop->GetDataTable()) { if ((prop=UTIL_FindInSendTable(prop->GetDataTable(), name)) != NULL) { return prop; } } } return NULL; } typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name) { while (pMap) { for (int i=0; idataNumFields; i++) { if (pMap->dataDesc[i].fieldName == NULL) { continue; } if (strcmp(name, pMap->dataDesc[i].fieldName) == 0) { return &(pMap->dataDesc[i]); } if (pMap->dataDesc[i].td) { typedescription_t *_td; if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL) { return _td; } } } pMap = pMap->baseMap; } return NULL; } ServerClass *CHalfLife2::FindServerClass(const char *classname) { DataTableInfo *pInfo = _FindServerClass(classname); if (!pInfo) { return NULL; } return pInfo->sc; } DataTableInfo *CHalfLife2::_FindServerClass(const char *classname) { DataTableInfo *pInfo = NULL; if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo)) { ServerClass *sc = gamedll->GetAllServerClasses(); while (sc) { if (strcmp(classname, sc->GetName()) == 0) { pInfo = new DataTableInfo; pInfo->lookup = sm_trie_create(); pInfo->sc = sc; sm_trie_insert(m_pClasses, classname, pInfo); m_Tables.push_back(pInfo); break; } sc = sc->m_pNext; } if (!pInfo) { return NULL; } } return pInfo; } SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset) { DataTableInfo *pInfo = _FindServerClass(classname); if (!pInfo) { return NULL; } SendProp *pProp = NULL; if (!sm_trie_retrieve(pInfo->lookup, offset, (void **)&pProp)) { if ((pProp = UTIL_FindInSendTable(pInfo->sc->m_pTable, offset)) != NULL) { sm_trie_insert(pInfo->lookup, offset, pProp); } } return pProp; } typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset) { typedescription_t *td = NULL; DataMapTrie &val = m_Maps[pMap]; if (!val.trie) { val.trie = sm_trie_create(); } if (!sm_trie_retrieve(val.trie, offset, (void **)&td)) { if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL) { sm_trie_insert(val.trie, offset, td); } } return td; } void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset) { if (!g_IsOriginalEngine) { if (offset) { pEdict->StateChanged(offset); } else { pEdict->StateChanged(); } } else { pEdict->m_fStateFlags |= FL_EDICT_CHANGED; } }