Merge pull request #360 from alliedmodders/cckv
Add support for listening to, blocking, changing, and faking ClientCommandKeyValues.
This commit is contained in:
		
						commit
						d30cab04c3
					
				@ -2,7 +2,7 @@
 | 
			
		||||
 * vim: set ts=4 sw=4 tw=99 noet :
 | 
			
		||||
 * =============================================================================
 | 
			
		||||
 * SourceMod
 | 
			
		||||
 * Copyright (C) 2004-2009 AlliedModders LLC.  All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2015 AlliedModders LLC.  All rights reserved.
 | 
			
		||||
 * =============================================================================
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
			
		||||
@ -46,6 +46,7 @@
 | 
			
		||||
#include "ConsoleDetours.h"
 | 
			
		||||
#include "logic_bridge.h"
 | 
			
		||||
#include <sourcemod_version.h>
 | 
			
		||||
#include "smn_keyvalues.h"
 | 
			
		||||
 | 
			
		||||
PlayerManager g_Players;
 | 
			
		||||
bool g_OnMapStarted = false;
 | 
			
		||||
@ -76,6 +77,9 @@ SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *)
 | 
			
		||||
#endif
 | 
			
		||||
SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
 | 
			
		||||
#endif // SE_DOTA
 | 
			
		||||
#if SOURCE_ENGINE >= SE_EYE && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
SH_DECL_HOOK2_void(IServerGameClients, ClientCommandKeyValues, SH_NOATTRIB, 0, edict_t *, KeyValues *);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if SOURCE_ENGINE == SE_DOTA
 | 
			
		||||
SH_DECL_HOOK0_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0);
 | 
			
		||||
@ -136,6 +140,7 @@ PlayerManager::PlayerManager()
 | 
			
		||||
	m_SourceTVUserId = -1;
 | 
			
		||||
	m_ReplayUserId = -1;
 | 
			
		||||
 | 
			
		||||
	m_bInCCKVHook = false;
 | 
			
		||||
	m_bAuthstringValidation = true; // use steam auth by default
 | 
			
		||||
 | 
			
		||||
	m_UserIdLookUp = new int[USHRT_MAX+1];
 | 
			
		||||
@ -171,6 +176,10 @@ void PlayerManager::OnSourceModAllInitialized()
 | 
			
		||||
	SH_ADD_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect), false);
 | 
			
		||||
	SH_ADD_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect_Post), true);
 | 
			
		||||
	SH_ADD_HOOK(IServerGameClients, ClientCommand, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommand), false);
 | 
			
		||||
#if SOURCE_ENGINE >= SE_EYE && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
	SH_ADD_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues), false);
 | 
			
		||||
	SH_ADD_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues_Post), true);
 | 
			
		||||
#endif
 | 
			
		||||
	SH_ADD_HOOK(IServerGameClients, ClientSettingsChanged, serverClients, SH_MEMBER(this, &PlayerManager::OnClientSettingsChanged), true);
 | 
			
		||||
	SH_ADD_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true);
 | 
			
		||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
@ -190,6 +199,8 @@ void PlayerManager::OnSourceModAllInitialized()
 | 
			
		||||
	m_cldisconnect = forwardsys->CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
 | 
			
		||||
	m_cldisconnect_post = forwardsys->CreateForward("OnClientDisconnect_Post", ET_Ignore, 1, p2);
 | 
			
		||||
	m_clcommand = forwardsys->CreateForward("OnClientCommand", ET_Hook, 2, NULL, Param_Cell, Param_Cell);
 | 
			
		||||
	m_clcommandkv = forwardsys->CreateForward("OnClientCommandKeyValues", ET_Hook, 2, NULL, Param_Cell, Param_Cell);
 | 
			
		||||
	m_clcommandkv_post = forwardsys->CreateForward("OnClientCommandKeyValues_Post", ET_Ignore, 2, NULL, Param_Cell, Param_Cell);
 | 
			
		||||
	m_clinfochanged = forwardsys->CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2);
 | 
			
		||||
	m_clauth = forwardsys->CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
 | 
			
		||||
	m_onActivate = forwardsys->CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
 | 
			
		||||
@ -218,6 +229,10 @@ void PlayerManager::OnSourceModShutdown()
 | 
			
		||||
	SH_REMOVE_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect), false);
 | 
			
		||||
	SH_REMOVE_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect_Post), true);
 | 
			
		||||
	SH_REMOVE_HOOK(IServerGameClients, ClientCommand, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommand), false);
 | 
			
		||||
#if SOURCE_ENGINE >= SE_EYE && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
	SH_REMOVE_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues), false);
 | 
			
		||||
	SH_REMOVE_HOOK(IServerGameClients, ClientCommandKeyValues, serverClients, SH_MEMBER(this, &PlayerManager::OnClientCommandKeyValues_Post), true);
 | 
			
		||||
#endif
 | 
			
		||||
	SH_REMOVE_HOOK(IServerGameClients, ClientSettingsChanged, serverClients, SH_MEMBER(this, &PlayerManager::OnClientSettingsChanged), true);
 | 
			
		||||
	SH_REMOVE_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true);
 | 
			
		||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
@ -233,6 +248,8 @@ void PlayerManager::OnSourceModShutdown()
 | 
			
		||||
	forwardsys->ReleaseForward(m_cldisconnect);
 | 
			
		||||
	forwardsys->ReleaseForward(m_cldisconnect_post);
 | 
			
		||||
	forwardsys->ReleaseForward(m_clcommand);
 | 
			
		||||
	forwardsys->ReleaseForward(m_clcommandkv);
 | 
			
		||||
	forwardsys->ReleaseForward(m_clcommandkv_post);
 | 
			
		||||
	forwardsys->ReleaseForward(m_clinfochanged);
 | 
			
		||||
	forwardsys->ReleaseForward(m_clauth);
 | 
			
		||||
	forwardsys->ReleaseForward(m_onActivate);
 | 
			
		||||
@ -1219,6 +1236,86 @@ void PlayerManager::OnClientCommand(edict_t *pEntity)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if SOURCE_ENGINE >= SE_EYE && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
static bool s_LastCCKVAllowed = true;
 | 
			
		||||
 | 
			
		||||
void PlayerManager::OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pCommand)
 | 
			
		||||
{
 | 
			
		||||
	int client = IndexOfEdict(pEntity);
 | 
			
		||||
 | 
			
		||||
	cell_t res = Pl_Continue;
 | 
			
		||||
	CPlayer *pPlayer = &m_Players[client];
 | 
			
		||||
 | 
			
		||||
	if (!pPlayer->IsInGame())
 | 
			
		||||
	{
 | 
			
		||||
		RETURN_META(MRES_IGNORED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	KeyValueStack *pStk = new KeyValueStack;
 | 
			
		||||
	pStk->pBase = pCommand;
 | 
			
		||||
	pStk->pCurRoot.push(pStk->pBase);
 | 
			
		||||
	pStk->m_bDeleteOnDestroy = false;
 | 
			
		||||
 | 
			
		||||
	Handle_t hndl = handlesys->CreateHandle(g_KeyValueType, pStk, g_pCoreIdent, g_pCoreIdent, NULL);
 | 
			
		||||
 | 
			
		||||
	m_bInCCKVHook = true;
 | 
			
		||||
	m_clcommandkv->PushCell(client);
 | 
			
		||||
	m_clcommandkv->PushCell(hndl);
 | 
			
		||||
	m_clcommandkv->Execute(&res);
 | 
			
		||||
	m_bInCCKVHook = false;
 | 
			
		||||
 | 
			
		||||
	HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
 | 
			
		||||
 | 
			
		||||
	// Deletes pStk
 | 
			
		||||
	handlesys->FreeHandle(hndl, &sec);
 | 
			
		||||
 | 
			
		||||
	if (res >= Pl_Handled)
 | 
			
		||||
	{
 | 
			
		||||
		s_LastCCKVAllowed = false;
 | 
			
		||||
		RETURN_META(MRES_SUPERCEDE);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s_LastCCKVAllowed = true;
 | 
			
		||||
 | 
			
		||||
	RETURN_META(MRES_IGNORED);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PlayerManager::OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *pCommand)
 | 
			
		||||
{
 | 
			
		||||
	if (!s_LastCCKVAllowed)
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int client = IndexOfEdict(pEntity);
 | 
			
		||||
 | 
			
		||||
	CPlayer *pPlayer = &m_Players[client];
 | 
			
		||||
 | 
			
		||||
	if (!pPlayer->IsInGame())
 | 
			
		||||
	{
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	KeyValueStack *pStk = new KeyValueStack;
 | 
			
		||||
	pStk->pBase = pCommand;
 | 
			
		||||
	pStk->pCurRoot.push(pStk->pBase);
 | 
			
		||||
	pStk->m_bDeleteOnDestroy = false;
 | 
			
		||||
 | 
			
		||||
	Handle_t hndl = handlesys->CreateHandle(g_KeyValueType, pStk, g_pCoreIdent, g_pCoreIdent, NULL);
 | 
			
		||||
 | 
			
		||||
	m_bInCCKVHook = true;
 | 
			
		||||
	m_clcommandkv_post->PushCell(client);
 | 
			
		||||
	m_clcommandkv_post->PushCell(hndl);
 | 
			
		||||
	m_clcommandkv_post->Execute();
 | 
			
		||||
	m_bInCCKVHook = false;
 | 
			
		||||
 | 
			
		||||
	HandleSecurity sec(g_pCoreIdent, g_pCoreIdent);
 | 
			
		||||
 | 
			
		||||
	// Deletes pStk
 | 
			
		||||
	handlesys->FreeHandle(hndl, &sec);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if SOURCE_ENGINE == SE_DOTA
 | 
			
		||||
void PlayerManager::OnClientSettingsChanged(CEntityIndex index)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
 * vim: set ts=4 :
 | 
			
		||||
 * =============================================================================
 | 
			
		||||
 * SourceMod
 | 
			
		||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2015 AlliedModders LLC.  All rights reserved.
 | 
			
		||||
 * =============================================================================
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
			
		||||
@ -181,6 +181,10 @@ public:
 | 
			
		||||
	void OnClientDisconnect_Post(edict_t *pEntity);
 | 
			
		||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
 | 
			
		||||
	void OnClientCommand(edict_t *pEntity, const CCommand &args);
 | 
			
		||||
#if SOURCE_ENGINE >= SE_EYE && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
	void OnClientCommandKeyValues(edict_t *pEntity, KeyValues *pCommand);
 | 
			
		||||
	void OnClientCommandKeyValues_Post(edict_t *pEntity, KeyValues *pCommand);
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
	void OnClientCommand(edict_t *pEntity);
 | 
			
		||||
#endif
 | 
			
		||||
@ -224,6 +228,10 @@ public:
 | 
			
		||||
	unsigned int GetReplyTo();
 | 
			
		||||
	unsigned int SetReplyTo(unsigned int reply);
 | 
			
		||||
	void MaxPlayersChanged(int newvalue = -1);
 | 
			
		||||
	inline bool InClientCommandKeyValuesHook()
 | 
			
		||||
	{
 | 
			
		||||
		return m_bInCCKVHook;
 | 
			
		||||
	}
 | 
			
		||||
#if SOURCE_ENGINE == SE_CSGO
 | 
			
		||||
	bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
 | 
			
		||||
#endif
 | 
			
		||||
@ -242,6 +250,8 @@ private:
 | 
			
		||||
	IForward *m_cldisconnect_post;
 | 
			
		||||
	IForward *m_clputinserver;
 | 
			
		||||
	IForward *m_clcommand;
 | 
			
		||||
	IForward *m_clcommandkv;
 | 
			
		||||
	IForward *m_clcommandkv_post;
 | 
			
		||||
	IForward *m_clinfochanged;
 | 
			
		||||
	IForward *m_clauth;
 | 
			
		||||
	IForward *m_onActivate;
 | 
			
		||||
@ -262,6 +272,7 @@ private:
 | 
			
		||||
	bool m_bIsReplayActive;
 | 
			
		||||
	int m_SourceTVUserId;
 | 
			
		||||
	int m_ReplayUserId;
 | 
			
		||||
	bool m_bInCCKVHook;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if SOURCE_ENGINE == SE_DOTA
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,7 @@
 | 
			
		||||
#include "ConCommandBaseIterator.h"
 | 
			
		||||
#include "logic_bridge.h"
 | 
			
		||||
#include <sm_namehashset.h>
 | 
			
		||||
#include "smn_keyvalues.h"
 | 
			
		||||
 | 
			
		||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
 | 
			
		||||
#include <netmessages.pb.h>
 | 
			
		||||
@ -1292,6 +1293,50 @@ static cell_t ConVar_ReplicateToClient(IPluginContext *pContext, const cell_t *p
 | 
			
		||||
	return SendConVarValue(pContext, new_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static cell_t FakeClientCommandKeyValues(IPluginContext *pContext, const cell_t *params)
 | 
			
		||||
{
 | 
			
		||||
#if SOURCE_ENGINE >= SE_EYE && SOURCE_ENGINE != SE_DOTA
 | 
			
		||||
	int client = params[1];
 | 
			
		||||
 | 
			
		||||
	CPlayer *pPlayer = g_Players.GetPlayerByIndex(client);
 | 
			
		||||
	if (!pPlayer)
 | 
			
		||||
	{
 | 
			
		||||
		return pContext->ThrowNativeError("Client index %d is invalid", client);
 | 
			
		||||
	}
 | 
			
		||||
	else if (!pPlayer->IsConnected())
 | 
			
		||||
	{
 | 
			
		||||
		return pContext->ThrowNativeError("Client %d is not connected", client);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Handle_t hndl = static_cast<Handle_t>(params[2]);
 | 
			
		||||
	HandleError herr;
 | 
			
		||||
	HandleSecurity sec;
 | 
			
		||||
	KeyValueStack *pStk;
 | 
			
		||||
 | 
			
		||||
	sec.pOwner = NULL;
 | 
			
		||||
	sec.pIdentity = g_pCoreIdent;
 | 
			
		||||
 | 
			
		||||
	if ((herr = handlesys->ReadHandle(hndl, g_KeyValueType, &sec, (void **) &pStk))
 | 
			
		||||
		!= HandleError_None)
 | 
			
		||||
	{
 | 
			
		||||
		return pContext->ThrowNativeError("Invalid key value handle %x (error %d)", hndl, herr);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_Players.InClientCommandKeyValuesHook())
 | 
			
		||||
	{
 | 
			
		||||
		SH_CALL(serverClients, &IServerGameClients::ClientCommandKeyValues)(pPlayer->GetEdict(), pStk->pBase);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		serverClients->ClientCommandKeyValues(pPlayer->GetEdict(), pStk->pBase);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
#else
 | 
			
		||||
	return pContext->ThrowNativeError("FakeClientCommandKeyValues is not supported on this game.");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
REGISTER_NATIVES(consoleNatives)
 | 
			
		||||
{
 | 
			
		||||
	{"CreateConVar",		sm_CreateConVar},
 | 
			
		||||
@ -1332,6 +1377,7 @@ REGISTER_NATIVES(consoleNatives)
 | 
			
		||||
	{"SendConVarValue",		SendConVarValue},
 | 
			
		||||
	{"AddCommandListener",	AddCommandListener},
 | 
			
		||||
	{"RemoveCommandListener", RemoveCommandListener},
 | 
			
		||||
	{"FakeClientCommandKeyValues", FakeClientCommandKeyValues},
 | 
			
		||||
 | 
			
		||||
	// Transitional syntax support.
 | 
			
		||||
	{"ConVar.BoolValue.get",	sm_GetConVarBool},
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
 * vim: set ts=4 :
 | 
			
		||||
 * =============================================================================
 | 
			
		||||
 * SourceMod
 | 
			
		||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
			
		||||
 * Copyright (C) 2004-2015 AlliedModders LLC.  All rights reserved.
 | 
			
		||||
 * =============================================================================
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
			
		||||
@ -29,6 +29,8 @@
 | 
			
		||||
 * Version: $Id$
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "smn_keyvalues.h"
 | 
			
		||||
 | 
			
		||||
#include "sourcemod.h"
 | 
			
		||||
#include "sourcemm_api.h"
 | 
			
		||||
#include "sm_stringutil.h"
 | 
			
		||||
@ -39,12 +41,6 @@
 | 
			
		||||
 | 
			
		||||
HandleType_t g_KeyValueType;
 | 
			
		||||
 | 
			
		||||
struct KeyValueStack 
 | 
			
		||||
{
 | 
			
		||||
	KeyValues *pBase;
 | 
			
		||||
	CStack<KeyValues *> pCurRoot;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class KeyValueNatives : 
 | 
			
		||||
	public SMGlobalClass,
 | 
			
		||||
	public IHandleTypeDispatch
 | 
			
		||||
@ -62,7 +58,11 @@ public:
 | 
			
		||||
	void OnHandleDestroy(HandleType_t type, void *object)
 | 
			
		||||
	{
 | 
			
		||||
		KeyValueStack *pStk = reinterpret_cast<KeyValueStack *>(object);
 | 
			
		||||
		if (pStk->m_bDeleteOnDestroy)
 | 
			
		||||
		{
 | 
			
		||||
			pStk->pBase->deleteThis();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		delete pStk;
 | 
			
		||||
	}
 | 
			
		||||
	int CalcKVSizeR(KeyValues *pv)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										51
									
								
								core/smn_keyvalues.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								core/smn_keyvalues.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
			
		||||
/**
 | 
			
		||||
* vim: set ts=4 :
 | 
			
		||||
* =============================================================================
 | 
			
		||||
* SourceMod
 | 
			
		||||
* Copyright (C) 2004-2015 AlliedModders LLC.  All rights reserved.
 | 
			
		||||
* =============================================================================
 | 
			
		||||
*
 | 
			
		||||
* This program is free software; you can redistribute it and/or modify it under
 | 
			
		||||
* the terms of the GNU General Public License, version 3.0, as published by the
 | 
			
		||||
* Free Software Foundation.
 | 
			
		||||
*
 | 
			
		||||
* This program is distributed in the hope that it will be useful, but WITHOUT
 | 
			
		||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
* FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
			
		||||
* details.
 | 
			
		||||
*
 | 
			
		||||
* You should have received a copy of the GNU General Public License along with
 | 
			
		||||
* this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
*
 | 
			
		||||
* As a special exception, AlliedModders LLC gives you permission to link the
 | 
			
		||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
			
		||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
			
		||||
* by the Valve Corporation.  You must obey the GNU General Public License in
 | 
			
		||||
* all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
			
		||||
* this exception to all derivative works.  AlliedModders LLC defines further
 | 
			
		||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
			
		||||
* or <http://www.sourcemod.net/license.php>.
 | 
			
		||||
*
 | 
			
		||||
* Version: $Id$
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef _INCLUDE_SOURCEMOD_KVWRAPPER_H_
 | 
			
		||||
#define _INCLUDE_SOURCEMOD_KVWRAPPER_H_
 | 
			
		||||
 | 
			
		||||
#include <IHandleSys.h>
 | 
			
		||||
#include <sh_stack.h>
 | 
			
		||||
 | 
			
		||||
using namespace SourceMod;
 | 
			
		||||
 | 
			
		||||
class KeyValues;
 | 
			
		||||
 | 
			
		||||
struct KeyValueStack
 | 
			
		||||
{
 | 
			
		||||
	KeyValues *pBase;
 | 
			
		||||
	SourceHook::CStack<KeyValues *> pCurRoot;
 | 
			
		||||
	bool m_bDeleteOnDestroy = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern HandleType_t g_KeyValueType;;
 | 
			
		||||
 | 
			
		||||
#endif // _INCLUDE_SOURCEMOD_KVWRAPPER_H_
 | 
			
		||||
@ -138,10 +138,34 @@ forward void OnClientDisconnect_Post(client);
 | 
			
		||||
 *
 | 
			
		||||
 * @param client		Client index.
 | 
			
		||||
 * @param args			Number of arguments.
 | 
			
		||||
 * @noreturn
 | 
			
		||||
 * @return				Plugin_Handled blocks the command from being sent,
 | 
			
		||||
 *						and Plugin_Continue resumes normal functionality.
 | 
			
		||||
 */
 | 
			
		||||
forward Action:OnClientCommand(client, args);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called when a client is sending a KeyValues command.
 | 
			
		||||
 *
 | 
			
		||||
 * @param client		Client index.
 | 
			
		||||
 * @param kv			Editable KeyValues data to be sent as the command.
 | 
			
		||||
 *						(This handle should not be stored and will be closed
 | 
			
		||||
 *						after this forward completes.)
 | 
			
		||||
 * @return				Plugin_Handled blocks the command from being sent,
 | 
			
		||||
 *						and Plugin_Continue resumes normal functionality.
 | 
			
		||||
 */
 | 
			
		||||
forward Action OnClientCommandKeyValues(int client, KeyValues kv);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called after a client has sent a KeyValues command.
 | 
			
		||||
 *
 | 
			
		||||
 * @param client		Client index.
 | 
			
		||||
 * @param kv			KeyValues data sent as the command.
 | 
			
		||||
 *						(This handle should not be stored and will be closed
 | 
			
		||||
 *						after this forward completes.)
 | 
			
		||||
 * @noreturn
 | 
			
		||||
 */
 | 
			
		||||
forward void OnClientCommandKeyValues_Post(int client, KeyValues kv);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Called whenever the client's settings are changed.
 | 
			
		||||
 *
 | 
			
		||||
 | 
			
		||||
@ -190,6 +190,17 @@ native FakeClientCommand(client, const String:fmt[], any:...);
 | 
			
		||||
 */
 | 
			
		||||
native FakeClientCommandEx(client, const String:fmt[], any:...);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Executes a KeyValues client command on the server without being networked.
 | 
			
		||||
 *
 | 
			
		||||
 * @param client		Index of the client.
 | 
			
		||||
 * @param kv			KeyValues data to be sent.
 | 
			
		||||
 * @noreturn
 | 
			
		||||
 * @error				Invalid client index, client not connected,
 | 
			
		||||
 *						or unsupported on current game.
 | 
			
		||||
 */
 | 
			
		||||
native void FakeClientCommandKeyValues(int client, KeyValues kv);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Sends a message to the server console.
 | 
			
		||||
 *
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user