From 38bbb8580f06aa2aac5a8db11e4d76c257071f38 Mon Sep 17 00:00:00 2001 From: Kyle Sanderson Date: Sat, 1 Mar 2014 14:25:35 -0700 Subject: [PATCH] Move PlayerRunCmd to a global VTable Hook (bug 6051, r=psychonic). --- extensions/sdktools/hooks.cpp | 45 ++++----------- extensions/sdktools/hooks.h | 4 +- extensions/sdktools/voice.cpp | 2 - public/vtable_hook_helper.h | 104 ++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 36 deletions(-) create mode 100644 public/vtable_hook_helper.h diff --git a/extensions/sdktools/hooks.cpp b/extensions/sdktools/hooks.cpp index e4042bc4..2405716e 100644 --- a/extensions/sdktools/hooks.cpp +++ b/extensions/sdktools/hooks.cpp @@ -116,36 +116,18 @@ void CHookManager::OnClientPutInServer(int client) return; } - SH_ADD_MANUALHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false); -} - -void CHookManager::OnClientDisconnecting(int client) -{ - if (!PRCH_enabled) - return; - - if (!PRCH_used) - return; - - edict_t *pEdict = PEntityOfEntIndex(client); - if (!pEdict) + CVTableHook hook(pEntity); + for (size_t i = 0; i < m_runUserCmdHooks.length(); ++i) { - return; + if (hook == m_runUserCmdHooks[i]) + { + return; + } } - IServerUnknown *pUnknown = pEdict->GetUnknown(); - if (!pUnknown) - { - return; - } - - CBaseEntity *pEntity = pUnknown->GetBaseEntity(); - if (!pEntity) - { - return; - } - - SH_REMOVE_MANUALHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false); + int hookid = SH_ADD_MANUALVPHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false); + hook.SetHookID(hookid); + m_runUserCmdHooks.append(new CVTableHook(hook)); } void CHookManager::PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper) @@ -245,15 +227,12 @@ void CHookManager::OnPluginUnloaded(IPlugin *plugin) if (m_usercmdsFwd->GetFunctionCount()) return; - int MaxClients = playerhelpers->GetMaxClients(); - for (int i = 1; i <= MaxClients; i++) + for (size_t i = 0; i < m_runUserCmdHooks.length(); ++i) { - if (playerhelpers->GetGamePlayer(i)->IsInGame()) - { - OnClientDisconnecting(i); - } + delete m_runUserCmdHooks[i]; } + m_runUserCmdHooks.clear(); PRCH_used = false; } diff --git a/extensions/sdktools/hooks.h b/extensions/sdktools/hooks.h index 6452a4da..261e158d 100644 --- a/extensions/sdktools/hooks.h +++ b/extensions/sdktools/hooks.h @@ -35,6 +35,8 @@ class CUserCmd; #include "extension.h" +#include "amtl/am-vector.h" +#include "vtable_hook_helper.h" class CHookManager : IPluginsListener, IFeatureProvider { @@ -43,7 +45,6 @@ public: void Initialize(); void Shutdown(); void OnClientPutInServer(int client); - void OnClientDisconnecting(int client); void PlayerRunCmd(CUserCmd *ucmd, IMoveHelper *moveHelper); public: //IPluginsListener void OnPluginLoaded(IPlugin *plugin); @@ -53,6 +54,7 @@ public: //IFeatureProvider private: IForward *m_usercmdsFwd; + ke::Vector m_runUserCmdHooks; }; extern CHookManager g_Hooks; diff --git a/extensions/sdktools/voice.cpp b/extensions/sdktools/voice.cpp index 4ae2877e..95e8e2d9 100644 --- a/extensions/sdktools/voice.cpp +++ b/extensions/sdktools/voice.cpp @@ -173,8 +173,6 @@ bool SDKTools::OnSetClientListening(int iReceiver, int iSender, bool bListen) void SDKTools::OnClientDisconnecting(int client) { - g_Hooks.OnClientDisconnecting(client); - int max_clients = playerhelpers->GetMaxClients(); if (g_VoiceHookCount == 0) diff --git a/public/vtable_hook_helper.h b/public/vtable_hook_helper.h new file mode 100644 index 00000000..a1bf5940 --- /dev/null +++ b/public/vtable_hook_helper.h @@ -0,0 +1,104 @@ +/** + * vim: set ts=4 : + * ============================================================================= + * SourceMod + * Copyright (C) 2004-2008 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 . + * + * 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 . + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_VTABLE_HOOK_HELPER_H_ +#define _INCLUDE_VTABLE_HOOK_HELPER_H_ + +class CVTableHook +{ +public: + CVTableHook(void *takenclass) + { + this->vtableptr = *reinterpret_cast(takenclass); + this->hookid = 0; + } + + CVTableHook(void *vtable, int hook) + { + this->vtableptr = vtable; + this->hookid = hook; + } + + CVTableHook(CVTableHook &other) + { + this->vtableptr = other.vtableptr; + this->hookid = other.hookid; + + other.hookid = 0; + } + + CVTableHook(CVTableHook *other) + { + this->vtableptr = other->vtableptr; + this->hookid = other->hookid; + + other->hookid = 0; + } + + ~CVTableHook() + { + if (this->hookid) + { + SH_REMOVE_HOOK_ID(this->hookid); + this->hookid = 0; + } + } +public: + void *GetVTablePtr(void) + { + return this->vtableptr; + } + + void SetHookID(int hook) + { + this->hookid = hook; + } + + bool IsHooked(void) + { + return (this->hookid != 0); + } +public: + bool operator == (CVTableHook &other) + { + return (this->GetVTablePtr() == other.GetVTablePtr()); + } + + bool operator == (CVTableHook *other) + { + return (this->GetVTablePtr() == other->GetVTablePtr()); + } +private: + void *vtableptr; + int hookid; +}; + +#endif //_INCLUDE_VTABLE_HOOK_HELPER_H_