Switch TF2 extension to hook CTFGameRules::IsHolidayActive for holiday forward (bug 6137).

This commit is contained in:
Nicholas Hastings 2014-06-19 23:22:47 -04:00
parent 210759907d
commit 151c6d246e
5 changed files with 203 additions and 59 deletions

View File

@ -42,6 +42,7 @@
#include "teleporter.h"
#include "CDetour/detours.h"
#include "ISDKHooks.h"
#include "ISDKTools.h"
/**
* @file extension.cpp
@ -54,6 +55,7 @@ IGameConfig *g_pGameConf = NULL;
IBinTools *g_pBinTools = NULL;
ISDKHooks *g_pSDKHooks = NULL;
ISDKTools *g_pSDKTools = NULL;
SMEXT_LINK(&g_TF2Tools);
@ -94,6 +96,7 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late)
sharesys->AddDependency(myself, "bintools.ext", true, true);
sharesys->AddDependency(myself, "sdkhooks.ext", true, true);
sharesys->AddDependency(myself, "sdktools.ext", false, true);
char conf_error[255] = "";
if (!gameconfs->LoadGameConfigFile("sm-tf2.games", &g_pGameConf, conf_error, sizeof(conf_error)))
@ -116,7 +119,6 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late)
playerhelpers->AddClientListener(this);
g_critForward = forwards->CreateForward("TF2_CalcIsAttackCritical", ET_Hook, 4, NULL, Param_Cell, Param_Cell, Param_String, Param_CellByRef);
g_isHolidayForward = forwards->CreateForward("TF2_OnIsHolidayActive", ET_Event, 2, NULL, Param_Cell, Param_CellByRef);
g_addCondForward = forwards->CreateForward("TF2_OnConditionAdded", ET_Ignore, 2, NULL, Param_Cell, Param_Cell);
g_removeCondForward = forwards->CreateForward("TF2_OnConditionRemoved", ET_Ignore, 2, NULL, Param_Cell, Param_Cell);
g_waitingPlayersStartForward = forwards->CreateForward("TF2_OnWaitingForPlayersStart", ET_Ignore, 0, NULL);
@ -126,11 +128,13 @@ bool TF2Tools::SDK_OnLoad(char *error, size_t maxlength, bool late)
g_pCVar = icvar;
m_CritDetoursEnabled = false;
m_IsHolidayDetourEnabled = false;
m_IsHolidayHookEnabled = false;
m_CondChecksEnabled = false;
m_RulesDetoursEnabled = false;
m_TeleportDetourEnabled = false;
g_HolidayManager.OnSDKLoad(late);
return true;
}
@ -164,6 +168,8 @@ void TF2Tools::SDK_OnUnload()
{
SH_REMOVE_HOOK(IServerGameDLL, ServerActivate, gamedll, SH_STATIC(OnServerActivate), true);
g_HolidayManager.OnSDKUnload();
g_RegNatives.UnregisterAll();
gameconfs->CloseGameConfigFile(g_pGameConf);
playerhelpers->UnregisterCommandTargetProcessor(this);
@ -172,7 +178,6 @@ void TF2Tools::SDK_OnUnload()
plsys->RemovePluginsListener(this);
forwards->ReleaseForward(g_critForward);
forwards->ReleaseForward(g_isHolidayForward);
forwards->ReleaseForward(g_addCondForward);
forwards->ReleaseForward(g_removeCondForward);
forwards->ReleaseForward(g_waitingPlayersStartForward);
@ -189,6 +194,7 @@ void TF2Tools::SDK_OnAllLoaded()
{
SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
SM_GET_LATE_IFACE(SDKHOOKS, g_pSDKHooks);
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
if (g_pSDKHooks != NULL)
{
@ -227,6 +233,11 @@ bool TF2Tools::QueryInterfaceDrop(SMInterface *pInterface)
return false;
}
if (pInterface == g_pSDKTools)
{
g_pSDKTools = NULL;
}
return IExtensionInterface::QueryInterfaceDrop(pInterface);
}
@ -238,6 +249,7 @@ void TF2Tools::NotifyInterfaceDrop(SMInterface *pInterface)
void OnServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
{
g_resourceEntity = FindResourceEntity();
g_HolidayManager.OnServerActivated();
}
bool TF2Tools::ProcessCommandTarget(cmd_target_info_t *info)
@ -342,11 +354,6 @@ void TF2Tools::OnPluginLoaded(IPlugin *plugin)
m_CritDetoursEnabled = g_CritManager.TryEnable();
}
if (!m_IsHolidayDetourEnabled && g_isHolidayForward->GetFunctionCount())
{
m_IsHolidayDetourEnabled = InitialiseIsHolidayDetour();
}
if (!m_CondChecksEnabled
&& ( g_addCondForward->GetFunctionCount() || g_removeCondForward->GetFunctionCount() )
)
@ -374,11 +381,6 @@ void TF2Tools::OnPluginUnloaded(IPlugin *plugin)
g_CritManager.Disable();
m_CritDetoursEnabled = false;
}
if (m_IsHolidayDetourEnabled && !g_isHolidayForward->GetFunctionCount())
{
RemoveIsHolidayDetour();
m_IsHolidayDetourEnabled = false;
}
if (m_CondChecksEnabled)
{
if (!g_addCondForward->GetFunctionCount() && !g_removeCondForward->GetFunctionCount())

View File

@ -42,6 +42,10 @@
#include <server_class.h>
#include <igameevents.h>
namespace SourceMod {
class ISDKTools;
}
/**
* @brief Sample implementation of the SDK Extension.
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
@ -116,7 +120,7 @@ public:
#endif
private:
bool m_CritDetoursEnabled;
bool m_IsHolidayDetourEnabled;
bool m_IsHolidayHookEnabled;
bool m_CondChecksEnabled;
bool m_RulesDetoursEnabled;
bool m_TeleportDetourEnabled;
@ -139,6 +143,7 @@ enum TFClassType
TFClassType ClassnameToType(const char *classname);
extern IBinTools *g_pBinTools;
extern ISDKTools *g_pSDKTools;
extern IGameConfig *g_pGameConf;
extern sm_sendprop_info_t *playerSharedOffset;

View File

@ -31,49 +31,143 @@
#include "holiday.h"
CDetour *isHolidayDetour = NULL;
SH_DECL_MANUALHOOK1(IsHolidayActive, 0, 0, 0, bool, int);
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0);
IForward *g_isHolidayForward = NULL;
HolidayManager g_HolidayManager;
DETOUR_DECL_STATIC1(IsHolidayActive, bool, int, holiday)
HolidayManager::HolidayManager() :
m_iHookID(0),
m_isHolidayForward(NULL),
m_bInMap(false)
{
bool actualres = DETOUR_STATIC_CALL(IsHolidayActive)(holiday);
if (!g_isHolidayForward)
}
void HolidayManager::OnSDKLoad(bool bLate)
{
m_bInMap = bLate;
plsys->AddPluginsListener(this);
m_isHolidayForward = forwards->CreateForward("TF2_OnIsHolidayActive", ET_Event, 2, NULL, Param_Cell, Param_CellByRef);
SH_ADD_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &HolidayManager::Hook_LevelShutdown), false);
}
void HolidayManager::OnSDKUnload()
{
UnhookIfNecessary();
SH_REMOVE_HOOK(IServerGameDLL, LevelShutdown, gamedll, SH_MEMBER(this, &HolidayManager::Hook_LevelShutdown), false);
plsys->RemovePluginsListener(this);
forwards->ReleaseForward(m_isHolidayForward);
}
void HolidayManager::OnServerActivated()
{
m_bInMap = true;
HookIfNecessary();
}
void HolidayManager::Hook_LevelShutdown()
{
// GameRules is going away momentarily. Unhook before it does.
UnhookIfNecessary();
m_bInMap = false;
}
void HolidayManager::HookIfNecessary()
{
// Already hooked
if (m_iHookID)
return;
// Nothing wants us
if (m_isHolidayForward->GetFunctionCount() == 0)
return;
void *pGameRules = GetGameRules();
if (!pGameRules)
{
if (m_bInMap)
{
g_pSM->LogError(myself, "Gamerules ptr not found. TF2_OnIsHolidayActive will not be available.");
}
return;
}
static int offset = -1;
if (offset == -1)
{
if (!g_pGameConf->GetOffset("IsHolidayActive", &offset))
{
g_pSM->LogError(myself, "IsHolidayActive gamedata offset missing. TF2_OnIsHolidayActive will not be available.");
return;
}
SH_MANUALHOOK_RECONFIGURE(IsHolidayActive, offset, 0, 0);
}
m_iHookID = SH_ADD_MANUALHOOK(IsHolidayActive, pGameRules, SH_MEMBER(this, &HolidayManager::Hook_IsHolidayActive), false);
}
void HolidayManager::UnhookIfNecessary()
{
// Not hooked
if (!m_iHookID)
return;
// We're still wanted
if (m_isHolidayForward->GetFunctionCount() > 0)
return;
if (m_iHookID)
{
SH_REMOVE_HOOK_ID(m_iHookID);
m_iHookID = 0;
}
}
void HolidayManager::OnPluginLoaded(IPlugin *plugin)
{
HookIfNecessary();
}
void HolidayManager::OnPluginUnloaded(IPlugin *plugin)
{
UnhookIfNecessary();
}
bool HolidayManager::Hook_IsHolidayActive(int holiday)
{
void *pGameRules = NULL;
if (g_pSDKTools)
{
pGameRules = g_pSDKTools->GetGameRules();
}
if (pGameRules)
{
bool actualres = SH_MCALL(pGameRules, IsHolidayActive)(holiday);
if (!m_isHolidayForward)
{
g_pSM->LogMessage(myself, "Invalid Forward");
return actualres;
RETURN_META_VALUE(MRES_IGNORED, true);
}
cell_t result = 0;
cell_t newres = actualres ? 1 : 0;
g_isHolidayForward->PushCell(holiday);
g_isHolidayForward->PushCellByRef(&newres);
g_isHolidayForward->Execute(&result);
m_isHolidayForward->PushCell(holiday);
m_isHolidayForward->PushCellByRef(&newres);
m_isHolidayForward->Execute(&result);
if (result > Pl_Continue)
{
return (newres == 0) ? false : true;
RETURN_META_VALUE(MRES_SUPERCEDE, (newres == 0) ? false : true);
}
}
return actualres;
}
bool InitialiseIsHolidayDetour()
{
isHolidayDetour = DETOUR_CREATE_STATIC(IsHolidayActive, "IsHolidayActive");
if (isHolidayDetour != NULL)
{
isHolidayDetour->EnableDetour();
return true;
}
g_pSM->LogError(myself, "IsHolidayActive detour failed");
return false;
}
void RemoveIsHolidayDetour()
{
isHolidayDetour->Destroy();
RETURN_META_VALUE(MRES_IGNORED, true);
}

View File

@ -33,13 +33,46 @@
#define _INCLUDE_SOURCEMOD_HOLIDAY_H_
#include "extension.h"
#include <jit/jit_helpers.h>
#include <jit/x86/x86_macros.h>
#include "CDetour/detours.h"
#include <ISDKTools.h>
bool InitialiseIsHolidayDetour();
void RemoveIsHolidayDetour();
class HolidayManager : public IPluginsListener
{
public:
HolidayManager();
extern IForward *g_isHolidayForward;
public:
void OnSDKLoad(bool bLate);
void OnSDKUnload();
void OnServerActivated();
public: //IPluginsListener
void OnPluginLoaded(IPlugin *plugin);
void OnPluginUnloaded(IPlugin *plugin);
public:
bool Hook_IsHolidayActive(int holiday);
void Hook_LevelShutdown();
private:
bool IsHookEnabled() const { return m_iHookID != 0; }
void *GetGameRules();
void HookIfNecessary();
void UnhookIfNecessary();
private:
int m_iHookID;
IForward *m_isHolidayForward;
bool m_bInMap;
};
inline void *HolidayManager::GetGameRules()
{
if (!g_pSDKTools)
return NULL;
return g_pSDKTools->GetGameRules();
}
extern HolidayManager g_HolidayManager;
#endif //_INCLUDE_SOURCEMOD_HOLIDAY_H_

View File

@ -78,13 +78,6 @@
"linux" "@_ZN15CTFPlayerShared10StunPlayerEffiP9CTFPlayer"
"mac" "@_ZN15CTFPlayerShared10StunPlayerEffiP9CTFPlayer"
}
"IsHolidayActive"
{
"library" "server"
"windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\x78\x30\x00\x74\x04\x32\xC0"
"linux" "@_Z18TF_IsHolidayActivei"
"mac" "@_Z18TF_IsHolidayActivei"
}
"MakeBleed"
{
"library" "server"
@ -106,6 +99,15 @@
"linux" "@_ZN17CObjectTeleporter21PlayerCanBeTeleportedEP9CTFPlayer"
"mac" "@_ZN17CObjectTeleporter21PlayerCanBeTeleportedEP9CTFPlayer"
}
// Obsolete
"IsHolidayActive"
{
"library" "server"
"windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\x78\x30\x00\x74\x04\x32\xC0"
"linux" "@_Z18TF_IsHolidayActivei"
"mac" "@_Z18TF_IsHolidayActivei"
}
}
"Offsets"
{
@ -127,6 +129,14 @@
"linux" "391"
"mac" "391"
}
// CTFGameRules::IsHolidayActive
"IsHolidayActive"
{
"windows" "138"
"linux" "139"
"mac" "139"
}
}
}
}