diff --git a/extensions/tf2/extension.cpp b/extensions/tf2/extension.cpp index 1f49f0ff..4aa10c47 100644 --- a/extensions/tf2/extension.cpp +++ b/extensions/tf2/extension.cpp @@ -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()) diff --git a/extensions/tf2/extension.h b/extensions/tf2/extension.h index d90903e1..cd6064da 100644 --- a/extensions/tf2/extension.h +++ b/extensions/tf2/extension.h @@ -42,6 +42,10 @@ #include #include +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; diff --git a/extensions/tf2/holiday.cpp b/extensions/tf2/holiday.cpp index a36da726..278e02d0 100644 --- a/extensions/tf2/holiday.cpp +++ b/extensions/tf2/holiday.cpp @@ -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) - { - g_pSM->LogMessage(myself, "Invalid Forward"); - return actualres; - } - - cell_t result = 0; - cell_t newres = actualres ? 1 : 0; - - g_isHolidayForward->PushCell(holiday); - g_isHolidayForward->PushCellByRef(&newres); - g_isHolidayForward->Execute(&result); - - if (result > Pl_Continue) - { - return (newres == 0) ? false : true; - } - - return actualres; } -bool InitialiseIsHolidayDetour() +void HolidayManager::OnSDKLoad(bool bLate) { - isHolidayDetour = DETOUR_CREATE_STATIC(IsHolidayActive, "IsHolidayActive"); + m_bInMap = bLate; - if (isHolidayDetour != NULL) + 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) { - isHolidayDetour->EnableDetour(); - return true; + if (m_bInMap) + { + g_pSM->LogError(myself, "Gamerules ptr not found. TF2_OnIsHolidayActive will not be available."); + } + return; } - g_pSM->LogError(myself, "IsHolidayActive detour failed"); - return false; + 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 RemoveIsHolidayDetour() +void HolidayManager::UnhookIfNecessary() { - isHolidayDetour->Destroy(); + // 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_META_VALUE(MRES_IGNORED, true); + } + + cell_t result = 0; + cell_t newres = actualres ? 1 : 0; + + m_isHolidayForward->PushCell(holiday); + m_isHolidayForward->PushCellByRef(&newres); + m_isHolidayForward->Execute(&result); + + if (result > Pl_Continue) + { + RETURN_META_VALUE(MRES_SUPERCEDE, (newres == 0) ? false : true); + } + } + + RETURN_META_VALUE(MRES_IGNORED, true); } diff --git a/extensions/tf2/holiday.h b/extensions/tf2/holiday.h index cef2f672..7457b7d6 100644 --- a/extensions/tf2/holiday.h +++ b/extensions/tf2/holiday.h @@ -33,13 +33,46 @@ #define _INCLUDE_SOURCEMOD_HOLIDAY_H_ #include "extension.h" -#include -#include -#include "CDetour/detours.h" +#include -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_ diff --git a/gamedata/sm-tf2.games.txt b/gamedata/sm-tf2.games.txt index 32e095af..bb853292 100644 --- a/gamedata/sm-tf2.games.txt +++ b/gamedata/sm-tf2.games.txt @@ -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" + } } } }