core/HalfLife2.cpp
author Matt Woodrow <pred@alliedmods.net>
Sun Feb 22 14:38:05 2009 +1300 (2009-02-22)
changeset 2596 4fb11ed1e6bc
parent 2583 d3b2571c378b
child 2628 541e48653064
permissions -rw-r--r--
Added edict_t and CBaseHandle conversion functions to IGameHelpers (bug 2616, r=dvander)
dvander@592
     1
/**
ds@653
     2
 * vim: set ts=4 :
ds@1330
     3
 * =============================================================================
dvander@1231
     4
 * SourceMod
ds@1947
     5
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
ds@1330
     6
 * =============================================================================
dvander@592
     7
 *
ds@1330
     8
 * This program is free software; you can redistribute it and/or modify it under
ds@1330
     9
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330
    10
 * Free Software Foundation.
dvander@1231
    11
 * 
ds@1330
    12
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330
    13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330
    14
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1330
    15
 * details.
dvander@1231
    16
 *
ds@1330
    17
 * You should have received a copy of the GNU General Public License along with
ds@1330
    18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
ds@1330
    20
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330
    21
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330
    22
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330
    23
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1330
    24
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1330
    25
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1330
    26
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330
    27
 * or <http://www.sourcemod.net/license.php>.
dvander@592
    28
 *
dvander@592
    29
 * Version: $Id$
dvander@592
    30
 */
dvander@592
    31
dvander@592
    32
#include "HalfLife2.h"
ds@696
    33
#include "sourcemod.h"
dvander@592
    34
#include "sourcemm_api.h"
ds@873
    35
#include "UserMessages.h"
dvander@1338
    36
#include "PlayerManager.h"
dvander@1547
    37
#include "sm_stringutil.h"
dvander@1690
    38
#include "GameConfigs.h"
dvander@1547
    39
#include <compat_wrappers.h>
dvander@592
    40
dvander@592
    41
CHalfLife2 g_HL2;
dvander@1423
    42
ConVar *sv_lan = NULL;
dvander@592
    43
faluco@682
    44
namespace SourceHook
faluco@682
    45
{
faluco@682
    46
	template<>
faluco@682
    47
	int HashFunction<datamap_t *>(datamap_t * const &k)
faluco@682
    48
	{
faluco@682
    49
		return reinterpret_cast<int>(k);
faluco@682
    50
	}
faluco@682
    51
faluco@682
    52
	template<>
faluco@682
    53
	int Compare<datamap_t *>(datamap_t * const &k1, datamap_t * const &k2)
faluco@682
    54
	{
faluco@682
    55
		return (k1-k2);
faluco@682
    56
	}
faluco@682
    57
}
faluco@682
    58
dvander@592
    59
CHalfLife2::CHalfLife2()
dvander@592
    60
{
dvander@592
    61
	m_pClasses = sm_trie_create();
dvander@592
    62
}
dvander@592
    63
dvander@592
    64
CHalfLife2::~CHalfLife2()
dvander@592
    65
{
dvander@592
    66
	sm_trie_destroy(m_pClasses);
dvander@592
    67
dvander@592
    68
	List<DataTableInfo *>::iterator iter;
dvander@592
    69
	DataTableInfo *pInfo;
dvander@592
    70
	for (iter=m_Tables.begin(); iter!=m_Tables.end(); iter++)
dvander@592
    71
	{
dvander@592
    72
		pInfo = (*iter);
dvander@592
    73
		delete pInfo;
dvander@592
    74
	}
dvander@592
    75
dvander@592
    76
	m_Tables.clear();
faluco@682
    77
faluco@682
    78
	THash<datamap_t *, DataMapTrie>::iterator h_iter;
faluco@682
    79
	for (h_iter=m_Maps.begin(); h_iter!=m_Maps.end(); h_iter++)
faluco@682
    80
	{
faluco@682
    81
		if (h_iter->val.trie)
faluco@682
    82
		{
faluco@682
    83
			sm_trie_destroy(h_iter->val.trie);
faluco@682
    84
			h_iter->val.trie = NULL;
faluco@682
    85
		}
faluco@682
    86
	}
faluco@682
    87
faluco@682
    88
	m_Maps.clear();
dvander@592
    89
}
dvander@592
    90
ds@2583
    91
#if SOURCE_ENGINE != SE_DARKMESSIAH
dvander@677
    92
CSharedEdictChangeInfo *g_pSharedChangeInfo = NULL;
ds@2583
    93
#endif
ds@2583
    94
dvander@1581
    95
bool is_original_engine = false;
dvander@677
    96
dvander@592
    97
void CHalfLife2::OnSourceModStartup(bool late)
dvander@592
    98
{
ds@2583
    99
#if SOURCE_ENGINE != SE_DARKMESSIAH
ds@2583
   100
ds@696
   101
	/* The Ship currently is the only known game to use an older version of the engine */
dvander@1581
   102
#if defined METAMOD_PLAPI_VERSION
dvander@1581
   103
	if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
dvander@1581
   104
#else
ds@729
   105
	if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
dvander@1581
   106
#endif
dvander@677
   107
	{
dvander@1581
   108
		is_original_engine = true;
dvander@1581
   109
	}
dvander@1581
   110
	else if (g_pSharedChangeInfo == NULL)
dvander@1581
   111
	{
dvander@677
   112
		g_pSharedChangeInfo = engine->GetSharedEdictChangeInfo();
dvander@677
   113
	}
ds@2583
   114
#endif
dvander@592
   115
}
dvander@592
   116
ds@873
   117
void CHalfLife2::OnSourceModAllInitialized()
ds@873
   118
{
ds@873
   119
	m_MsgTextMsg = g_UserMsgs.GetMessageIndex("TextMsg");
faluco@1218
   120
	m_HinTextMsg = g_UserMsgs.GetMessageIndex("HintText");
ds@2583
   121
	m_SayTextMsg = g_UserMsgs.GetMessageIndex("SayText");
faluco@1218
   122
	m_VGUIMenu = g_UserMsgs.GetMessageIndex("VGUIMenu");
dvander@965
   123
	g_ShareSys.AddInterface(NULL, this);
ds@873
   124
}
ds@873
   125
dvander@1581
   126
#if !defined METAMOD_PLAPI_VERSION
dvander@1581
   127
bool CHalfLife2::IsOriginalEngine()
dvander@1581
   128
{
dvander@1581
   129
	return is_original_engine;
dvander@1581
   130
}
dvander@1581
   131
#endif
dvander@1581
   132
ds@2583
   133
#if SOURCE_ENGINE != SE_DARKMESSIAH
dvander@678
   134
IChangeInfoAccessor *CBaseEdict::GetChangeAccessor()
dvander@678
   135
{
dvander@678
   136
	return engine->GetChangeAccessor( (const edict_t *)this );
dvander@678
   137
}
ds@2583
   138
#endif
dvander@678
   139
dvander@1847
   140
bool UTIL_FindInSendTable(SendTable *pTable, 
dvander@1847
   141
						  const char *name,
dvander@1847
   142
						  sm_sendprop_info_t *info,
dvander@1847
   143
						  unsigned int offset)
dvander@592
   144
{
dvander@592
   145
	const char *pname;
dvander@592
   146
	int props = pTable->GetNumProps();
dvander@592
   147
	SendProp *prop;
dvander@592
   148
dvander@592
   149
	for (int i=0; i<props; i++)
dvander@592
   150
	{
dvander@592
   151
		prop = pTable->GetProp(i);
dvander@592
   152
		pname = prop->GetName();
dvander@592
   153
		if (pname && strcmp(name, pname) == 0)
dvander@592
   154
		{
dvander@1847
   155
			info->prop = prop;
dvander@1847
   156
			info->actual_offset = offset + info->prop->GetOffset();
dvander@1847
   157
			return true;
dvander@592
   158
		}
dvander@592
   159
		if (prop->GetDataTable())
dvander@592
   160
		{
dvander@1847
   161
			if (UTIL_FindInSendTable(prop->GetDataTable(), 
dvander@1847
   162
				name,
dvander@1847
   163
				info,
dvander@1847
   164
				offset + prop->GetOffset())
dvander@1847
   165
				)
dvander@592
   166
			{
dvander@1847
   167
				return true;
dvander@592
   168
			}
dvander@592
   169
		}
dvander@592
   170
	}
dvander@592
   171
dvander@1848
   172
	return false;
dvander@592
   173
}
dvander@592
   174
faluco@682
   175
typedescription_t *UTIL_FindInDataMap(datamap_t *pMap, const char *name)
faluco@682
   176
{
faluco@682
   177
	while (pMap)
faluco@682
   178
	{
faluco@682
   179
		for (int i=0; i<pMap->dataNumFields; i++)
faluco@682
   180
		{
dvander@709
   181
			if (pMap->dataDesc[i].fieldName == NULL)
dvander@709
   182
			{
dvander@709
   183
				continue;
dvander@709
   184
			}
faluco@682
   185
			if (strcmp(name, pMap->dataDesc[i].fieldName) == 0)
faluco@682
   186
			{
faluco@682
   187
				return &(pMap->dataDesc[i]);
faluco@682
   188
			}
faluco@682
   189
			if (pMap->dataDesc[i].td)
faluco@682
   190
			{
faluco@682
   191
				typedescription_t *_td;
faluco@682
   192
				if ((_td=UTIL_FindInDataMap(pMap->dataDesc[i].td, name)) != NULL)
faluco@682
   193
				{
faluco@682
   194
					return _td;
faluco@682
   195
				}
faluco@682
   196
			}
faluco@682
   197
		}
faluco@682
   198
		pMap = pMap->baseMap;
faluco@682
   199
	}
faluco@682
   200
faluco@682
   201
	return NULL; 
faluco@682
   202
}
faluco@682
   203
dvander@592
   204
ServerClass *CHalfLife2::FindServerClass(const char *classname)
dvander@592
   205
{
dvander@592
   206
	DataTableInfo *pInfo = _FindServerClass(classname);
dvander@1847
   207
dvander@592
   208
	if (!pInfo)
dvander@592
   209
	{
dvander@592
   210
		return NULL;
dvander@592
   211
	}
dvander@592
   212
dvander@592
   213
	return pInfo->sc;
dvander@592
   214
}
dvander@592
   215
dvander@592
   216
DataTableInfo *CHalfLife2::_FindServerClass(const char *classname)
dvander@592
   217
{
dvander@592
   218
	DataTableInfo *pInfo = NULL;
dvander@592
   219
dvander@592
   220
	if (!sm_trie_retrieve(m_pClasses, classname, (void **)&pInfo))
dvander@592
   221
	{
dvander@592
   222
		ServerClass *sc = gamedll->GetAllServerClasses();
dvander@592
   223
		while (sc)
dvander@592
   224
		{
dvander@592
   225
			if (strcmp(classname, sc->GetName()) == 0)
dvander@592
   226
			{
dvander@592
   227
				pInfo = new DataTableInfo;
dvander@592
   228
				pInfo->sc = sc;
dvander@592
   229
				sm_trie_insert(m_pClasses, classname, pInfo);
faluco@682
   230
				m_Tables.push_back(pInfo);
dvander@592
   231
				break;
dvander@592
   232
			}
dvander@592
   233
			sc = sc->m_pNext;
dvander@592
   234
		}
dvander@592
   235
		if (!pInfo)
dvander@592
   236
		{
dvander@592
   237
			return NULL;
dvander@592
   238
		}
dvander@592
   239
	}
dvander@592
   240
dvander@592
   241
	return pInfo;
dvander@592
   242
}
dvander@592
   243
dvander@1847
   244
bool CHalfLife2::FindSendPropInfo(const char *classname, const char *offset, sm_sendprop_info_t *info)
dvander@1847
   245
{
dvander@1847
   246
	DataTableInfo *pInfo;
dvander@1847
   247
	sm_sendprop_info_t *prop;
dvander@1847
   248
dvander@1847
   249
	if ((pInfo = _FindServerClass(classname)) == NULL)
dvander@1847
   250
	{
dvander@1847
   251
		return false;
dvander@1847
   252
	}
dvander@1847
   253
dvander@1847
   254
	if ((prop = pInfo->lookup.retrieve(offset)) == NULL)
dvander@1847
   255
	{
dvander@1847
   256
		sm_sendprop_info_t temp_info;
dvander@1847
   257
dvander@1847
   258
		if (!UTIL_FindInSendTable(pInfo->sc->m_pTable, offset, &temp_info, 0))
dvander@1847
   259
		{
dvander@1847
   260
			return false;
dvander@1847
   261
		}
dvander@1847
   262
dvander@1847
   263
		pInfo->lookup.insert(offset, temp_info);
dvander@1847
   264
		*info = temp_info;
dvander@1847
   265
	}
dvander@1847
   266
	else
dvander@1847
   267
	{
dvander@1847
   268
		*info = *prop;
dvander@1847
   269
	}
dvander@1847
   270
	
dvander@1847
   271
	return true;
dvander@1847
   272
}
dvander@1847
   273
dvander@592
   274
SendProp *CHalfLife2::FindInSendTable(const char *classname, const char *offset)
dvander@592
   275
{
dvander@1847
   276
	sm_sendprop_info_t info;
dvander@592
   277
dvander@1847
   278
	if (!FindSendPropInfo(classname, offset, &info))
dvander@592
   279
	{
dvander@592
   280
		return NULL;
dvander@592
   281
	}
dvander@592
   282
dvander@1847
   283
	return info.prop;
dvander@592
   284
}
faluco@682
   285
faluco@682
   286
typedescription_t *CHalfLife2::FindInDataMap(datamap_t *pMap, const char *offset)
faluco@682
   287
{
faluco@682
   288
	typedescription_t *td = NULL;
faluco@682
   289
	DataMapTrie &val = m_Maps[pMap];
faluco@682
   290
faluco@682
   291
	if (!val.trie)
faluco@682
   292
	{
faluco@682
   293
		val.trie = sm_trie_create();
faluco@682
   294
	}
faluco@682
   295
	if (!sm_trie_retrieve(val.trie, offset, (void **)&td))
faluco@682
   296
	{
faluco@682
   297
		if ((td = UTIL_FindInDataMap(pMap, offset)) != NULL)
faluco@682
   298
		{
faluco@682
   299
			sm_trie_insert(val.trie, offset, td);
faluco@682
   300
		}
faluco@682
   301
	}
faluco@682
   302
faluco@682
   303
	return td;
faluco@682
   304
}
dvander@685
   305
dvander@685
   306
void CHalfLife2::SetEdictStateChanged(edict_t *pEdict, unsigned short offset)
dvander@685
   307
{
ds@2583
   308
#if SOURCE_ENGINE != SE_DARKMESSIAH
dvander@1581
   309
	if (g_pSharedChangeInfo != NULL)
dvander@685
   310
	{
dvander@685
   311
		if (offset)
dvander@685
   312
		{
dvander@685
   313
			pEdict->StateChanged(offset);
dvander@1847
   314
		}
dvander@1847
   315
		else
dvander@1847
   316
		{
dvander@685
   317
			pEdict->StateChanged();
dvander@685
   318
		}
dvander@1581
   319
	}
dvander@1581
   320
	else
ds@2583
   321
#endif
dvander@1581
   322
	{
dvander@685
   323
		pEdict->m_fStateFlags |= FL_EDICT_CHANGED;
dvander@685
   324
	}
dvander@685
   325
}
ds@873
   326
dvander@1132
   327
bool CHalfLife2::TextMsg(int client, int dest, const char *msg)
ds@873
   328
{
ds@873
   329
	bf_write *pBitBuf = NULL;
ds@873
   330
	cell_t players[] = {client};
ds@873
   331
ds@2583
   332
	if (dest == HUD_PRINTTALK)
ds@2583
   333
	{
ds@2583
   334
		const char *chat_saytext = g_pGameConf->GetKeyValue("ChatSayText");
ds@2583
   335
ds@2583
   336
		/* Use SayText user message instead */
ds@2583
   337
		if (chat_saytext != NULL && strcmp(chat_saytext, "yes") == 0)
ds@2583
   338
		{
ds@2583
   339
			char buffer[192];
ds@2583
   340
			UTIL_Format(buffer, sizeof(buffer), "%s\1\n", msg);
ds@2583
   341
ds@2583
   342
			if ((pBitBuf = g_UserMsgs.StartMessage(m_SayTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
ds@2583
   343
			{
ds@2583
   344
				return false;
ds@2583
   345
			}
ds@2583
   346
ds@2583
   347
			pBitBuf->WriteByte(0);
ds@2583
   348
			pBitBuf->WriteString(buffer);
ds@2583
   349
			pBitBuf->WriteByte(1);
ds@2583
   350
ds@2583
   351
			g_UserMsgs.EndMessage();
ds@2583
   352
ds@2583
   353
			return true;
ds@2583
   354
		}
ds@2583
   355
	}
ds@2583
   356
dvander@1132
   357
	if ((pBitBuf = g_UserMsgs.StartMessage(m_MsgTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
dvander@1132
   358
	{
dvander@1132
   359
		return false;
dvander@1132
   360
	}
dvander@1132
   361
ds@873
   362
	pBitBuf->WriteByte(dest);
ds@873
   363
	pBitBuf->WriteString(msg);
ds@2583
   364
ds@873
   365
	g_UserMsgs.EndMessage();
dvander@1132
   366
dvander@1132
   367
	return true;
ds@873
   368
}
faluco@1218
   369
teame06@1264
   370
bool CHalfLife2::HintTextMsg(int client, const char *msg)
faluco@1218
   371
{
faluco@1218
   372
	bf_write *pBitBuf = NULL;
faluco@1218
   373
	cell_t players[] = {client};
faluco@1218
   374
faluco@1218
   375
	if ((pBitBuf = g_UserMsgs.StartMessage(m_HinTextMsg, players, 1, USERMSG_RELIABLE)) == NULL)
faluco@1218
   376
	{
faluco@1218
   377
		return false;
faluco@1218
   378
	}
faluco@1218
   379
dvander@1690
   380
	const char *pre_byte = g_pGameConf->GetKeyValue("HintTextPreByte");
dvander@1690
   381
	if (pre_byte != NULL && strcmp(pre_byte, "yes") == 0)
dvander@1690
   382
	{
dvander@1690
   383
		pBitBuf->WriteByte(1);
dvander@1690
   384
	}
faluco@1218
   385
	pBitBuf->WriteString(msg);
faluco@1218
   386
	g_UserMsgs.EndMessage();
faluco@1218
   387
faluco@1218
   388
	return true;
faluco@1218
   389
}
faluco@1218
   390
faluco@1218
   391
bool CHalfLife2::ShowVGUIMenu(int client, const char *name, KeyValues *data, bool show)
faluco@1218
   392
{
faluco@1218
   393
	bf_write *pBitBuf = NULL;
faluco@1218
   394
	KeyValues *SubKey = NULL;
faluco@1218
   395
	int count = 0;
faluco@1218
   396
	cell_t players[] = {client};
faluco@1218
   397
faluco@1218
   398
	if ((pBitBuf = g_UserMsgs.StartMessage(m_VGUIMenu, players, 1, USERMSG_RELIABLE)) == NULL)
faluco@1218
   399
	{
faluco@1218
   400
		return false;
faluco@1218
   401
	}
faluco@1218
   402
faluco@1218
   403
	if (data)
faluco@1218
   404
	{
faluco@1218
   405
		SubKey = data->GetFirstSubKey();
faluco@1218
   406
		while (SubKey)
faluco@1218
   407
		{
faluco@1218
   408
			count++;
faluco@1218
   409
			SubKey = SubKey->GetNextKey();
faluco@1218
   410
		}
faluco@1218
   411
		SubKey = data->GetFirstSubKey();
faluco@1218
   412
	}
faluco@1218
   413
faluco@1218
   414
	pBitBuf->WriteString(name);
faluco@1218
   415
	pBitBuf->WriteByte((show) ? 1 : 0);
faluco@1218
   416
	pBitBuf->WriteByte(count);
faluco@1218
   417
	while (SubKey)
faluco@1218
   418
	{
faluco@1218
   419
		pBitBuf->WriteString(SubKey->GetName());
faluco@1218
   420
		pBitBuf->WriteString(SubKey->GetString());
faluco@1218
   421
		SubKey = SubKey->GetNextKey();
faluco@1218
   422
	}
faluco@1218
   423
	g_UserMsgs.EndMessage();
faluco@1218
   424
faluco@1218
   425
	return true;
faluco@1218
   426
}
dvander@1338
   427
dvander@1338
   428
void CHalfLife2::AddToFakeCliCmdQueue(int client, int userid, const char *cmd)
dvander@1338
   429
{
dvander@1338
   430
	DelayedFakeCliCmd *pFake;
dvander@1338
   431
dvander@1338
   432
	if (m_FreeCmds.empty())
dvander@1338
   433
	{
dvander@1338
   434
		pFake = new DelayedFakeCliCmd;
dvander@1338
   435
	} else {
dvander@1338
   436
		pFake = m_FreeCmds.front();
dvander@1338
   437
		m_FreeCmds.pop();
dvander@1338
   438
	}
dvander@1338
   439
dvander@1338
   440
	pFake->client = client;
dvander@1338
   441
	pFake->userid = userid;
dvander@1338
   442
	pFake->cmd.assign(cmd);
dvander@1338
   443
dvander@1338
   444
	m_CmdQueue.push(pFake);
dvander@1338
   445
}
dvander@1338
   446
dvander@1338
   447
void CHalfLife2::ProcessFakeCliCmdQueue()
dvander@1338
   448
{
dvander@1338
   449
	while (!m_CmdQueue.empty())
dvander@1338
   450
	{
dvander@1338
   451
		DelayedFakeCliCmd *pFake = m_CmdQueue.first();
dvander@1338
   452
dvander@1338
   453
		if (g_Players.GetClientOfUserId(pFake->userid) == pFake->client)
dvander@1338
   454
		{
dvander@1338
   455
			CPlayer *pPlayer = g_Players.GetPlayerByIndex(pFake->client);
dvander@1338
   456
			serverpluginhelpers->ClientCommand(pPlayer->GetEdict(), pFake->cmd.c_str());
dvander@1338
   457
		}
dvander@1338
   458
dvander@1338
   459
		m_CmdQueue.pop();
dvander@1338
   460
	}
dvander@1338
   461
}
dvander@1423
   462
dvander@1423
   463
bool CHalfLife2::IsLANServer()
dvander@1423
   464
{
dvander@1423
   465
	sv_lan = icvar->FindVar("sv_lan");
dvander@1423
   466
dvander@1423
   467
	if (!sv_lan)
dvander@1423
   468
	{
dvander@1423
   469
		return false;
dvander@1423
   470
	}
dvander@1423
   471
dvander@1423
   472
	return (sv_lan->GetInt() != 0);
dvander@1423
   473
}
dvander@1544
   474
ds@1944
   475
bool CHalfLife2::KVLoadFromFile(KeyValues *kv, IBaseFileSystem *filesystem, const char *resourceName, const char *pathID)
ds@1944
   476
{
ds@1944
   477
#if defined METAMOD_PLAPI_VERSION
ds@1944
   478
	if (g_SMAPI->GetSourceEngineBuild() == SOURCE_ENGINE_ORIGINAL)
ds@1944
   479
#else
ds@1944
   480
	if (strcasecmp(g_SourceMod.GetGameFolderName(), "ship") == 0)
ds@1944
   481
#endif
ds@1944
   482
	{
ds@1944
   483
		Assert(filesystem);
ds@1944
   484
#ifdef _MSC_VER
ds@1944
   485
		Assert(_heapchk() == _HEAPOK);
ds@1944
   486
#endif
ds@1944
   487
ds@1944
   488
		FileHandle_t f = filesystem->Open(resourceName, "rb", pathID);
ds@1944
   489
		if (!f)
ds@1944
   490
			return false;
ds@1944
   491
ds@1944
   492
		// load file into a null-terminated buffer
ds@1944
   493
		int fileSize = filesystem->Size(f);
ds@1944
   494
		char *buffer = (char *)MemAllocScratch(fileSize + 1);
ds@1944
   495
ds@1944
   496
		Assert(buffer);
ds@1944
   497
ds@1944
   498
		filesystem->Read(buffer, fileSize, f); // read into local buffer
ds@1944
   499
ds@1944
   500
		buffer[fileSize] = 0; // null terminate file as EOF
ds@1944
   501
ds@1944
   502
		filesystem->Close( f );	// close file after reading
ds@1944
   503
ds@1944
   504
		bool retOK = kv->LoadFromBuffer( resourceName, buffer, filesystem );
ds@1944
   505
ds@1944
   506
		MemFreeScratch();
ds@1944
   507
ds@1944
   508
		return retOK;
ds@1944
   509
	}
ds@1944
   510
	else
ds@1944
   511
	{
ds@1944
   512
		return kv->LoadFromFile(filesystem, resourceName, pathID);
ds@1944
   513
	}
ds@1944
   514
}
ds@1944
   515
dvander@1544
   516
void CHalfLife2::PushCommandStack(const CCommand *cmd)
dvander@1544
   517
{
dvander@1544
   518
	CachedCommandInfo info;
dvander@1544
   519
dvander@1544
   520
	info.args = cmd;
ds@2583
   521
#if SOURCE_ENGINE <= SE_DARKMESSIAH
dvander@1544
   522
	strncopy(info.cmd, cmd->Arg(0), sizeof(info.cmd));
dvander@1544
   523
#endif
dvander@1544
   524
dvander@1544
   525
	m_CommandStack.push(info);
dvander@1544
   526
}
dvander@1544
   527
dvander@1544
   528
const CCommand *CHalfLife2::PeekCommandStack()
dvander@1544
   529
{
dvander@1544
   530
	if (m_CommandStack.empty())
dvander@1544
   531
	{
dvander@1544
   532
		return NULL;
dvander@1544
   533
	}
dvander@1544
   534
dvander@1544
   535
	return m_CommandStack.front().args;
dvander@1544
   536
}
dvander@1544
   537
dvander@1544
   538
void CHalfLife2::PopCommandStack()
dvander@1544
   539
{
dvander@1544
   540
	m_CommandStack.pop();
dvander@1544
   541
}
dvander@1544
   542
dvander@1544
   543
const char *CHalfLife2::CurrentCommandName()
dvander@1544
   544
{
ds@2400
   545
#if SOURCE_ENGINE >= SE_ORANGEBOX
dvander@1544
   546
	return m_CommandStack.front().args->Arg(0);
dvander@1544
   547
#else
dvander@1544
   548
	return m_CommandStack.front().cmd;
dvander@1544
   549
#endif
dvander@1544
   550
}
dvander@2162
   551
dvander@2162
   552
void CHalfLife2::AddDelayedKick(int client, int userid, const char *msg)
dvander@2162
   553
{
dvander@2162
   554
	DelayedKickInfo kick;
dvander@2162
   555
dvander@2162
   556
	kick.client = client;
dvander@2162
   557
	kick.userid = userid;
dvander@2162
   558
	UTIL_Format(kick.buffer, sizeof(kick.buffer), "%s", msg);
dvander@2162
   559
dvander@2162
   560
	m_DelayedKicks.push(kick);
dvander@2162
   561
}
dvander@2162
   562
dvander@2162
   563
void CHalfLife2::ProcessDelayedKicks()
dvander@2162
   564
{
dvander@2162
   565
	while (!m_DelayedKicks.empty())
dvander@2162
   566
	{
dvander@2162
   567
		DelayedKickInfo info = m_DelayedKicks.first();
dvander@2162
   568
		m_DelayedKicks.pop();
dvander@2162
   569
dvander@2162
   570
		CPlayer *player = g_Players.GetPlayerByIndex(info.client);
dvander@2162
   571
		if (player == NULL || player->GetUserId() != info.userid)
dvander@2162
   572
		{
dvander@2162
   573
			continue;
dvander@2162
   574
		}
dvander@2162
   575
dvander@2162
   576
		player->Kick(info.buffer);
dvander@2162
   577
	}
dvander@2162
   578
}
pred@2596
   579
pred@2596
   580
edict_t *CHalfLife2::EdictOfIndex(int index)
pred@2596
   581
{
pred@2596
   582
	return ::PEntityOfEntIndex(index);
pred@2596
   583
}
pred@2596
   584
pred@2596
   585
int CHalfLife2::IndexOfEdict(edict_t *pEnt)
pred@2596
   586
{
pred@2596
   587
	return ::IndexOfEdict(pEnt);
pred@2596
   588
}
pred@2596
   589
pred@2596
   590
edict_t *CHalfLife2::GetHandleEntity(CBaseHandle &hndl)
pred@2596
   591
{
pred@2596
   592
	if (!hndl.IsValid())
pred@2596
   593
	{
pred@2596
   594
		return NULL;
pred@2596
   595
	}
pred@2596
   596
pred@2596
   597
	int index = hndl.GetEntryIndex();
pred@2596
   598
pred@2596
   599
	edict_t *pStoredEdict;
pred@2596
   600
	CBaseEntity *pStoredEntity;
pred@2596
   601
pred@2596
   602
	pStoredEdict = GetEntity(index, &pStoredEntity);
pred@2596
   603
pred@2596
   604
	if (pStoredEdict == NULL || pStoredEntity == NULL)
pred@2596
   605
	{
pred@2596
   606
		return NULL;
pred@2596
   607
	}
pred@2596
   608
pred@2596
   609
	IServerEntity *pSE = pStoredEdict->GetIServerEntity();
pred@2596
   610
pred@2596
   611
	if (pSE == NULL)
pred@2596
   612
	{
pred@2596
   613
		return NULL;
pred@2596
   614
	}
pred@2596
   615
pred@2596
   616
	if (pSE->GetRefEHandle() != hndl)
pred@2596
   617
	{
pred@2596
   618
		return NULL;
pred@2596
   619
	}
pred@2596
   620
pred@2596
   621
	return pStoredEdict;
pred@2596
   622
}
pred@2596
   623
pred@2596
   624
void CHalfLife2::SetHandleEntity(CBaseHandle &hndl, edict_t *pEnt)
pred@2596
   625
{
pred@2596
   626
	IServerEntity *pEntOther = pEnt->GetIServerEntity();
pred@2596
   627
pred@2596
   628
	if (pEntOther == NULL)
pred@2596
   629
	{
pred@2596
   630
		return;
pred@2596
   631
	}
pred@2596
   632
pred@2596
   633
	hndl.Set(pEntOther);
pred@2596
   634
}