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