Add support for listening to, blocking, changing, and faking ClientCommandKeyValues.
This commit is contained in:
+88
-1
@@ -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,76 @@ 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;
|
||||
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_DOTA
|
||||
void PlayerManager::OnClientSettingsChanged(CEntityIndex index)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user