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 :
 | 
					 * vim: set ts=4 sw=4 tw=99 noet :
 | 
				
			||||||
 * =============================================================================
 | 
					 * =============================================================================
 | 
				
			||||||
 * SourceMod
 | 
					 * 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
 | 
					 * This program is free software; you can redistribute it and/or modify it under
 | 
				
			||||||
@ -46,6 +46,7 @@
 | 
				
			|||||||
#include "ConsoleDetours.h"
 | 
					#include "ConsoleDetours.h"
 | 
				
			||||||
#include "logic_bridge.h"
 | 
					#include "logic_bridge.h"
 | 
				
			||||||
#include <sourcemod_version.h>
 | 
					#include <sourcemod_version.h>
 | 
				
			||||||
 | 
					#include "smn_keyvalues.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PlayerManager g_Players;
 | 
					PlayerManager g_Players;
 | 
				
			||||||
bool g_OnMapStarted = false;
 | 
					bool g_OnMapStarted = false;
 | 
				
			||||||
@ -76,6 +77,9 @@ SH_DECL_HOOK1_void(IServerGameClients, ClientCommand, SH_NOATTRIB, 0, edict_t *)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
 | 
					SH_DECL_HOOK1_void(IServerGameClients, ClientSettingsChanged, SH_NOATTRIB, 0, edict_t *);
 | 
				
			||||||
#endif // SE_DOTA
 | 
					#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
 | 
					#if SOURCE_ENGINE == SE_DOTA
 | 
				
			||||||
SH_DECL_HOOK0_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0);
 | 
					SH_DECL_HOOK0_void(IServerGameDLL, ServerActivate, SH_NOATTRIB, 0);
 | 
				
			||||||
@ -136,6 +140,7 @@ PlayerManager::PlayerManager()
 | 
				
			|||||||
	m_SourceTVUserId = -1;
 | 
						m_SourceTVUserId = -1;
 | 
				
			||||||
	m_ReplayUserId = -1;
 | 
						m_ReplayUserId = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_bInCCKVHook = false;
 | 
				
			||||||
	m_bAuthstringValidation = true; // use steam auth by default
 | 
						m_bAuthstringValidation = true; // use steam auth by default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m_UserIdLookUp = new int[USHRT_MAX+1];
 | 
						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), false);
 | 
				
			||||||
	SH_ADD_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect_Post), true);
 | 
						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);
 | 
						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(IServerGameClients, ClientSettingsChanged, serverClients, SH_MEMBER(this, &PlayerManager::OnClientSettingsChanged), true);
 | 
				
			||||||
	SH_ADD_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true);
 | 
						SH_ADD_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true);
 | 
				
			||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
 | 
					#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 = forwardsys->CreateForward("OnClientDisconnect", ET_Ignore, 1, p2);
 | 
				
			||||||
	m_cldisconnect_post = forwardsys->CreateForward("OnClientDisconnect_Post", 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_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_clinfochanged = forwardsys->CreateForward("OnClientSettingsChanged", ET_Ignore, 1, p2);
 | 
				
			||||||
	m_clauth = forwardsys->CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
 | 
						m_clauth = forwardsys->CreateForward("OnClientAuthorized", ET_Ignore, 2, NULL, Param_Cell, Param_String);
 | 
				
			||||||
	m_onActivate = forwardsys->CreateForward("OnServerLoad", ET_Ignore, 0, NULL);
 | 
						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), false);
 | 
				
			||||||
	SH_REMOVE_HOOK(IServerGameClients, ClientDisconnect, serverClients, SH_MEMBER(this, &PlayerManager::OnClientDisconnect_Post), true);
 | 
						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);
 | 
						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(IServerGameClients, ClientSettingsChanged, serverClients, SH_MEMBER(this, &PlayerManager::OnClientSettingsChanged), true);
 | 
				
			||||||
	SH_REMOVE_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true);
 | 
						SH_REMOVE_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_MEMBER(this, &PlayerManager::OnServerActivate), true);
 | 
				
			||||||
#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
 | 
					#if SOURCE_ENGINE >= SE_LEFT4DEAD && SOURCE_ENGINE != SE_DOTA
 | 
				
			||||||
@ -233,6 +248,8 @@ void PlayerManager::OnSourceModShutdown()
 | 
				
			|||||||
	forwardsys->ReleaseForward(m_cldisconnect);
 | 
						forwardsys->ReleaseForward(m_cldisconnect);
 | 
				
			||||||
	forwardsys->ReleaseForward(m_cldisconnect_post);
 | 
						forwardsys->ReleaseForward(m_cldisconnect_post);
 | 
				
			||||||
	forwardsys->ReleaseForward(m_clcommand);
 | 
						forwardsys->ReleaseForward(m_clcommand);
 | 
				
			||||||
 | 
						forwardsys->ReleaseForward(m_clcommandkv);
 | 
				
			||||||
 | 
						forwardsys->ReleaseForward(m_clcommandkv_post);
 | 
				
			||||||
	forwardsys->ReleaseForward(m_clinfochanged);
 | 
						forwardsys->ReleaseForward(m_clinfochanged);
 | 
				
			||||||
	forwardsys->ReleaseForward(m_clauth);
 | 
						forwardsys->ReleaseForward(m_clauth);
 | 
				
			||||||
	forwardsys->ReleaseForward(m_onActivate);
 | 
						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
 | 
					#if SOURCE_ENGINE == SE_DOTA
 | 
				
			||||||
void PlayerManager::OnClientSettingsChanged(CEntityIndex index)
 | 
					void PlayerManager::OnClientSettingsChanged(CEntityIndex index)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
 * vim: set ts=4 :
 | 
					 * vim: set ts=4 :
 | 
				
			||||||
 * =============================================================================
 | 
					 * =============================================================================
 | 
				
			||||||
 * SourceMod
 | 
					 * 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
 | 
					 * 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);
 | 
						void OnClientDisconnect_Post(edict_t *pEntity);
 | 
				
			||||||
#if SOURCE_ENGINE >= SE_ORANGEBOX
 | 
					#if SOURCE_ENGINE >= SE_ORANGEBOX
 | 
				
			||||||
	void OnClientCommand(edict_t *pEntity, const CCommand &args);
 | 
						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
 | 
					#else
 | 
				
			||||||
	void OnClientCommand(edict_t *pEntity);
 | 
						void OnClientCommand(edict_t *pEntity);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -224,6 +228,10 @@ public:
 | 
				
			|||||||
	unsigned int GetReplyTo();
 | 
						unsigned int GetReplyTo();
 | 
				
			||||||
	unsigned int SetReplyTo(unsigned int reply);
 | 
						unsigned int SetReplyTo(unsigned int reply);
 | 
				
			||||||
	void MaxPlayersChanged(int newvalue = -1);
 | 
						void MaxPlayersChanged(int newvalue = -1);
 | 
				
			||||||
 | 
						inline bool InClientCommandKeyValuesHook()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return m_bInCCKVHook;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
#if SOURCE_ENGINE == SE_CSGO
 | 
					#if SOURCE_ENGINE == SE_CSGO
 | 
				
			||||||
	bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
 | 
						bool HandleConVarQuery(QueryCvarCookie_t cookie, edict_t *pPlayer, EQueryCvarValueStatus result, const char *cvarName, const char *cvarValue);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -242,6 +250,8 @@ private:
 | 
				
			|||||||
	IForward *m_cldisconnect_post;
 | 
						IForward *m_cldisconnect_post;
 | 
				
			||||||
	IForward *m_clputinserver;
 | 
						IForward *m_clputinserver;
 | 
				
			||||||
	IForward *m_clcommand;
 | 
						IForward *m_clcommand;
 | 
				
			||||||
 | 
						IForward *m_clcommandkv;
 | 
				
			||||||
 | 
						IForward *m_clcommandkv_post;
 | 
				
			||||||
	IForward *m_clinfochanged;
 | 
						IForward *m_clinfochanged;
 | 
				
			||||||
	IForward *m_clauth;
 | 
						IForward *m_clauth;
 | 
				
			||||||
	IForward *m_onActivate;
 | 
						IForward *m_onActivate;
 | 
				
			||||||
@ -262,6 +272,7 @@ private:
 | 
				
			|||||||
	bool m_bIsReplayActive;
 | 
						bool m_bIsReplayActive;
 | 
				
			||||||
	int m_SourceTVUserId;
 | 
						int m_SourceTVUserId;
 | 
				
			||||||
	int m_ReplayUserId;
 | 
						int m_ReplayUserId;
 | 
				
			||||||
 | 
						bool m_bInCCKVHook;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if SOURCE_ENGINE == SE_DOTA
 | 
					#if SOURCE_ENGINE == SE_DOTA
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,7 @@
 | 
				
			|||||||
#include "ConCommandBaseIterator.h"
 | 
					#include "ConCommandBaseIterator.h"
 | 
				
			||||||
#include "logic_bridge.h"
 | 
					#include "logic_bridge.h"
 | 
				
			||||||
#include <sm_namehashset.h>
 | 
					#include <sm_namehashset.h>
 | 
				
			||||||
 | 
					#include "smn_keyvalues.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
 | 
					#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_DOTA
 | 
				
			||||||
#include <netmessages.pb.h>
 | 
					#include <netmessages.pb.h>
 | 
				
			||||||
@ -1292,6 +1293,50 @@ static cell_t ConVar_ReplicateToClient(IPluginContext *pContext, const cell_t *p
 | 
				
			|||||||
	return SendConVarValue(pContext, new_params);
 | 
						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)
 | 
					REGISTER_NATIVES(consoleNatives)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	{"CreateConVar",		sm_CreateConVar},
 | 
						{"CreateConVar",		sm_CreateConVar},
 | 
				
			||||||
@ -1332,6 +1377,7 @@ REGISTER_NATIVES(consoleNatives)
 | 
				
			|||||||
	{"SendConVarValue",		SendConVarValue},
 | 
						{"SendConVarValue",		SendConVarValue},
 | 
				
			||||||
	{"AddCommandListener",	AddCommandListener},
 | 
						{"AddCommandListener",	AddCommandListener},
 | 
				
			||||||
	{"RemoveCommandListener", RemoveCommandListener},
 | 
						{"RemoveCommandListener", RemoveCommandListener},
 | 
				
			||||||
 | 
						{"FakeClientCommandKeyValues", FakeClientCommandKeyValues},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Transitional syntax support.
 | 
						// Transitional syntax support.
 | 
				
			||||||
	{"ConVar.BoolValue.get",	sm_GetConVarBool},
 | 
						{"ConVar.BoolValue.get",	sm_GetConVarBool},
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
 * vim: set ts=4 :
 | 
					 * vim: set ts=4 :
 | 
				
			||||||
 * =============================================================================
 | 
					 * =============================================================================
 | 
				
			||||||
 * SourceMod
 | 
					 * 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
 | 
					 * This program is free software; you can redistribute it and/or modify it under
 | 
				
			||||||
@ -29,6 +29,8 @@
 | 
				
			|||||||
 * Version: $Id$
 | 
					 * Version: $Id$
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "smn_keyvalues.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "sourcemod.h"
 | 
					#include "sourcemod.h"
 | 
				
			||||||
#include "sourcemm_api.h"
 | 
					#include "sourcemm_api.h"
 | 
				
			||||||
#include "sm_stringutil.h"
 | 
					#include "sm_stringutil.h"
 | 
				
			||||||
@ -39,12 +41,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
HandleType_t g_KeyValueType;
 | 
					HandleType_t g_KeyValueType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct KeyValueStack 
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	KeyValues *pBase;
 | 
					 | 
				
			||||||
	CStack<KeyValues *> pCurRoot;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class KeyValueNatives : 
 | 
					class KeyValueNatives : 
 | 
				
			||||||
	public SMGlobalClass,
 | 
						public SMGlobalClass,
 | 
				
			||||||
	public IHandleTypeDispatch
 | 
						public IHandleTypeDispatch
 | 
				
			||||||
@ -62,7 +58,11 @@ public:
 | 
				
			|||||||
	void OnHandleDestroy(HandleType_t type, void *object)
 | 
						void OnHandleDestroy(HandleType_t type, void *object)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		KeyValueStack *pStk = reinterpret_cast<KeyValueStack *>(object);
 | 
							KeyValueStack *pStk = reinterpret_cast<KeyValueStack *>(object);
 | 
				
			||||||
 | 
							if (pStk->m_bDeleteOnDestroy)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
			pStk->pBase->deleteThis();
 | 
								pStk->pBase->deleteThis();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		delete pStk;
 | 
							delete pStk;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	int CalcKVSizeR(KeyValues *pv)
 | 
						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 client		Client index.
 | 
				
			||||||
 * @param args			Number of arguments.
 | 
					 * @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);
 | 
					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.
 | 
					 * 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:...);
 | 
					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.
 | 
					 * Sends a message to the server console.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user