core/HalfLife2.cpp
author Scott Ehlert <ds@alliedmods.net>
Fri Jun 01 06:33:54 2007 +0000 (2007-06-01)
changeset 873 a2136b3be10d
parent 729 110c14c99545
child 965 327edbb1357a
permissions -rw-r--r--
- Added natives: PrintToChat() and PrintCenterText()
- Bit of reorganization with moving some natives from sourcemod.inc to halflife.inc
     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 }
    89 
    90 IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
    91 {
    92 	return engine->GetChangeAccessor( (const edict_t *)this );
    93 }
    94 
    95 SendProp *UTIL_FindInSendTable(SendTable *pTable, const char *name)
    96 {
    97 	const char *pname;
    98 	int props = pTable->GetNumProps();
    99 	SendProp *prop;
   100 
   101 	for (int i=0; i<props; i++)
   102 	{
   103 		prop = pTable->GetProp(i);
   104 		pname = prop->GetName();
   105 		if (pname && strcmp(name, pname) == 0)
   106 		{
   107 			return prop;
   108 		}
   109 		if (prop->GetDataTable())
   110 		{
   111 			if ((prop=UTIL_FindInSendTable(prop->GetDataTable(), name)) != NULL)
   112 			{
   113 				return prop;
   114 			}
   115 		}
   116 	}
   117 
   118 	return NULL;
   119 }
   120 
   121 typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
   122 {
   123 	while (pMap)
   124 	{
   125 		for (int i=0; i<pMap->dataNumFields; i++)
   126 		{
   127 			if (pMap->dataDesc[i].fieldName == NULL)
   128 			{
   129 				continue;
   130 			}
   131 			if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
   132 			{
   133 				return &(pMap->dataDesc[i]);
   134 			}
   135 			if (pMap->dataDesc[i].td)
   136 			{
   137 				typedescription_t *_td;
   138 				if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
   139 				{
   140 					return _td;
   141 				}
   142 			}
   143 		}
   144 		pMap = pMap->baseMap;
   145 	}
   146 
   147 	return NULL; 
   148 }
   149 
   150 ServerClass *CHalfLife2::FindServerClass(const char *classname)
   151 {
   152 	DataTableInfo *pInfo = _FindServerClass(classname);
   153 	if (!pInfo)
   154 	{
   155 		return NULL;
   156 	}
   157 
   158 	return pInfo->sc;
   159 }
   160 
   161 DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
   162 {
   163 	DataTableInfo *pInfo = NULL;
   164 
   165 	if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
   166 	{
   167 		ServerClass *sc = gamedll->GetAllServerClasses();
   168 		while (sc)
   169 		{
   170 			if (strcmp(classname, sc->GetName()) == 0)
   171 			{
   172 				pInfo = new DataTableInfo;
   173 				pInfo->lookup = sm_trie_create();
   174 				pInfo->sc = sc;
   175 				sm_trie_insert(m_pClasses, classname, pInfo);
   176 				m_Tables.push_back(pInfo);
   177 				break;
   178 			}
   179 			sc = sc->m_pNext;
   180 		}
   181 		if (!pInfo)
   182 		{
   183 			return NULL;
   184 		}
   185 	}
   186 
   187 	return pInfo;
   188 }
   189 
   190 SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
   191 {
   192 	DataTableInfo *pInfo = _FindServerClass(classname);
   193 
   194 	if (!pInfo)
   195 	{
   196 		return NULL;
   197 	}
   198 
   199 	SendProp *pProp = NULL;
   200 	if (!sm_trie_retrieve(pInfo->lookup, offset, (void **)&pProp))
   201 	{
   202 		if ((pProp = UTIL_FindInSendTable(pInfo->sc->m_pTable, offset)) != NULL)
   203 		{
   204 			sm_trie_insert(pInfo->lookup, offset, pProp);
   205 		}
   206 	}
   207 
   208 	return pProp;
   209 }
   210 
   211 typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
   212 {
   213 	typedescription_t *td = NULL;
   214 	DataMapTrie &val = m_Maps[pMap];
   215 
   216 	if (!val.trie)
   217 	{
   218 		val.trie = sm_trie_create();
   219 	}
   220 	if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
   221 	{
   222 		if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
   223 		{
   224 			sm_trie_insert(val.trie, offset, td);
   225 		}
   226 	}
   227 
   228 	return td;
   229 }
   230 
   231 void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
   232 {
   233 	if (!g_IsOriginalEngine)
   234 	{
   235 		if (offset)
   236 		{
   237 			pEdict->StateChanged(offset);
   238 		} else {
   239 			pEdict->StateChanged();
   240 		}
   241 	} else {
   242 		pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
   243 	}
   244 }
   245 
   246 void CHalfLife2::TextMsg(int client, int dest, const char *msg)
   247 {
   248 	bf_write *pBitBuf = NULL;
   249 	cell_t players[] = {client};
   250 
   251 	pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE);
   252 	pBitBuf->WriteByte(dest);
   253 	pBitBuf->WriteString(msg);
   254 	g_UserMsgs.EndMessage();
   255 }