diff --git a/core/AMBuilder b/core/AMBuilder index 183cd10d..6c9e6a1e 100644 --- a/core/AMBuilder +++ b/core/AMBuilder @@ -41,6 +41,7 @@ project.sources += [ 'ConsoleDetours.cpp', 'vprof_tool.cpp', 'smn_commandline.cpp', + 'GameHooks.cpp', ] for sdk_name in SM.sdks: diff --git a/core/ConVarManager.cpp b/core/ConVarManager.cpp index 0a48289b..d566f12f 100644 --- a/core/ConVarManager.cpp +++ b/core/ConVarManager.cpp @@ -37,12 +37,6 @@ ConVarManager g_ConVarManager; -#if SOURCE_ENGINE >= SE_ORANGEBOX -SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float); -#else -SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *); -#endif - #if SOURCE_ENGINE == SE_DOTA SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *); SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, CEntityIndex, EQueryCvarValueStatus, const char *, const char *); @@ -125,12 +119,6 @@ void ConVarManager::OnSourceModAllInitialized() g_Players.AddClientListener(this); -#if SOURCE_ENGINE >= SE_ORANGEBOX - SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false); -#else - SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false); -#endif - scripts->AddPluginsListener(this); /* Add the 'convars' option to the 'sm' console command */ @@ -198,12 +186,6 @@ void ConVarManager::OnSourceModShutdown() g_Players.RemoveClientListener(this); -#if SOURCE_ENGINE >= SE_ORANGEBOX - SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false); -#else - SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false); -#endif - /* Remove the 'convars' option from the 'sm' console command */ rootmenu->RemoveRootConsoleCommand("cvars", this); @@ -696,11 +678,7 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar } } -#if SOURCE_ENGINE >= SE_ORANGEBOX void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue) -#else -void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue) -#endif { /* If the values are the same, exit early in order to not trigger callbacks */ if (strcmp(pConVar->GetString(), oldValue) == 0) @@ -720,16 +698,8 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue) if (pInfo->changeListeners.size() != 0) { - for (List::iterator i = pInfo->changeListeners.begin(); - i != pInfo->changeListeners.end(); - i++) - { -#if SOURCE_ENGINE >= SE_ORANGEBOX + for (auto i = pInfo->changeListeners.begin(); i != pInfo->changeListeners.end(); i++) (*i)->OnConVarChanged(pConVar, oldValue, flOldValue); -#else - (*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue)); -#endif - } } if (pForward != NULL) diff --git a/core/ConVarManager.h b/core/ConVarManager.h index dc21f46a..eeb3128f 100644 --- a/core/ConVarManager.h +++ b/core/ConVarManager.h @@ -147,21 +147,15 @@ public: HandleError ReadConVarHandle(Handle_t hndl, ConVar **pVar); + // Called via game hooks. + void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue); + private: /** * Adds a convar to a plugin's list. */ static void AddConVarToPluginList(IPluginContext *pContext, const ConVar *pConVar); - /** - * Static callback that Valve's ConVar object executes when the convar's value changes. - */ -#if SOURCE_ENGINE >= SE_ORANGEBOX - static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue); -#else - static void OnConVarChanged(ConVar *pConVar, const char *oldValue); -#endif - /** * Callback for when StartQueryCvarValue() has finished. */ diff --git a/core/GameHooks.cpp b/core/GameHooks.cpp new file mode 100644 index 00000000..594f386d --- /dev/null +++ b/core/GameHooks.cpp @@ -0,0 +1,68 @@ +// vim: set ts=4 sw=4 tw=99 noet : +// ============================================================================= +// 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 . +// +// 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 . +#include "GameHooks.h" +#include "sourcemod.h" +#include "ConVarManager.h" + +#if SOURCE_ENGINE >= SE_ORANGEBOX +SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float); +#else +SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallback, SH_NOATTRIB, false, ConVar *, const char *); +#endif + +GameHooks::GameHooks() +{ +} + +void GameHooks::Start() +{ +#if SOURCE_ENGINE >= SE_ORANGEBOX + SH_ADD_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false); +#else + SH_ADD_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false); +#endif +} + +void GameHooks::Shutdown() +{ +#if SOURCE_ENGINE >= SE_ORANGEBOX + SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallbacks, icvar, SH_STATIC(OnConVarChanged), false); +#else + SH_REMOVE_HOOK(ICvar, CallGlobalChangeCallback, icvar, SH_STATIC(OnConVarChanged), false); +#endif +} + +#if SOURCE_ENGINE >= SE_ORANGEBOX +void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue) +{ +#else +void GameHooks::OnConVarChanged(ConVar *pConVar, const char *oldValue) +{ + float flOldValue = atof(oldValue); +#endif + g_ConVarManager.OnConVarChanged(pConVar, oldValue, flOldValue); +} diff --git a/core/GameHooks.h b/core/GameHooks.h new file mode 100644 index 00000000..537a5912 --- /dev/null +++ b/core/GameHooks.h @@ -0,0 +1,52 @@ +// vim: set ts=4 sw=4 tw=99 noet : +// ============================================================================= +// 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 . +// +// 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 . +#ifndef _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_ +#define _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_ + +class ConVar; + +namespace SourceMod { + +class GameHooks +{ +public: + GameHooks(); + + void Start(); + void Shutdown(); + + // Static callback that Valve's ConVar object executes when the convar's value changes. +#if SOURCE_ENGINE >= SE_ORANGEBOX + static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue); +#else + static void OnConVarChanged(ConVar *pConVar, const char *oldValue); +#endif +}; + +} // namespace SourceMod + +#endif // _INCLUDE_SOURCEMOD_PROVIDER_GAME_HOOKS_H_ diff --git a/core/logic_bridge.cpp b/core/logic_bridge.cpp index 8ea1758f..f2b6b2bb 100644 --- a/core/logic_bridge.cpp +++ b/core/logic_bridge.cpp @@ -716,6 +716,16 @@ bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength) return true; } +void CoreProviderImpl::InitializeHooks() +{ + hooks_.Start(); +} + +void CoreProviderImpl::ShutdownHooks() +{ + hooks_.Shutdown(); +} + void CoreProviderImpl::ShutdownBridge() { logic_ = nullptr; diff --git a/core/provider.h b/core/provider.h index 73a89830..bfdda45a 100644 --- a/core/provider.h +++ b/core/provider.h @@ -28,6 +28,7 @@ #define _INCLUDE_SOURCEMOD_CORE_PROVIDER_IMPL_H_ #include "logic/intercom.h" +#include "GameHooks.h" #include class CoreProviderImpl : public CoreProvider @@ -40,6 +41,9 @@ public: bool LoadBridge(char *error, size_t maxlength); void ShutdownBridge(); + void InitializeHooks(); + void ShutdownHooks(); + // Provider implementation. ConVar *FindConVar(const char *name) override; const char *GetCvarString(ConVar *cvar) override; @@ -61,6 +65,7 @@ public: private: ke::Ref logic_; LogicInitFunction logic_init_; + GameHooks hooks_; }; extern CoreProviderImpl sCoreProviderImpl; diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index eb6d9e95..f484abeb 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -267,6 +267,8 @@ void SourceModBase::StartSourceMod(bool late) } g_pGameConf = logicore.GetCoreGameConfig(); + sCoreProviderImpl.InitializeHooks(); + /* Notify! */ pBase = SMGlobalClass::head; while (pBase) @@ -520,6 +522,8 @@ void SourceModBase::ShutdownServices() } m_freepacks.popall(); + sCoreProviderImpl.ShutdownHooks(); + /* Notify! */ pBase = SMGlobalClass::head; while (pBase)