- rewrote internal convar hooking mechanism to prevent crashes and potential "race conditions"
- sharesys is now the first thing to run, so g_pCoreIdent is valid EVERYWHERE - added internal convar hooking funcs for timersys --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401776
This commit is contained in:
parent
9ab9eba5d7
commit
d78d7ab960
@ -41,6 +41,16 @@
|
||||
|
||||
ConVarManager g_ConVarManager;
|
||||
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
|
||||
#endif
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
||||
#else
|
||||
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
|
||||
#endif
|
||||
|
||||
SH_DECL_HOOK5_void(IServerGameDLL, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
||||
SH_DECL_HOOK5_void(IServerPluginCallbacks, OnQueryCvarValueFinished, SH_NOATTRIB, 0, QueryCvarCookie_t, edict_t *, EQueryCvarValueStatus, const char *, const char *);
|
||||
|
||||
@ -56,6 +66,19 @@ ConVarManager::~ConVarManager()
|
||||
{
|
||||
}
|
||||
|
||||
void ConVarManager::OnSourceModStartup(bool late)
|
||||
{
|
||||
HandleAccess sec;
|
||||
|
||||
/* Set up access rights for the 'ConVar' handle type */
|
||||
sec.access[HandleAccess_Read] = 0;
|
||||
sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||
|
||||
/* Create the 'ConVar' handle type */
|
||||
m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
}
|
||||
|
||||
void ConVarManager::OnSourceModAllInitialized()
|
||||
{
|
||||
/**
|
||||
@ -69,15 +92,7 @@ void ConVarManager::OnSourceModAllInitialized()
|
||||
}
|
||||
#endif
|
||||
|
||||
HandleAccess sec;
|
||||
|
||||
/* Set up access rights for the 'ConVar' handle type */
|
||||
sec.access[HandleAccess_Read] = 0;
|
||||
sec.access[HandleAccess_Delete] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||
sec.access[HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY | HANDLE_RESTRICT_OWNER;
|
||||
|
||||
/* Create the 'ConVar' handle type */
|
||||
m_ConVarType = g_HandleSys.CreateType("ConVar", this, 0, NULL, &sec, g_pCoreIdent, NULL);
|
||||
SH_ADD_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
||||
|
||||
/* Add the 'convars' option to the 'sm' console command */
|
||||
g_RootMenu.AddRootConsoleCommand("cvars", "View convars created by a plugin", this);
|
||||
@ -138,6 +153,8 @@ void ConVarManager::OnSourceModShutdown()
|
||||
m_bIsVSPQueryHooked = false;
|
||||
}
|
||||
|
||||
SH_REMOVE_HOOK_STATICFUNC(ICvar, CallGlobalChangeCallbacks, icvar, OnConVarChanged, false);
|
||||
|
||||
/* Remove the 'convars' option from the 'sm' console command */
|
||||
g_RootMenu.RemoveRootConsoleCommand("cvars", this);
|
||||
|
||||
@ -243,7 +260,7 @@ void ConVarManager::OnHandleDestroy(HandleType_t type, void *object)
|
||||
|
||||
bool ConVarManager::GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize)
|
||||
{
|
||||
*pSize = sizeof(ConVar);
|
||||
*pSize = sizeof(ConVar) + sizeof(ConVarInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -321,7 +338,6 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
||||
pInfo = new ConVarInfo();
|
||||
pInfo->sourceMod = false;
|
||||
pInfo->pChangeForward = NULL;
|
||||
pInfo->origCallback = pConVar->GetCallback();
|
||||
pInfo->pVar = pConVar;
|
||||
|
||||
/* If we don't, then create a new handle from the convar */
|
||||
@ -361,7 +377,6 @@ Handle_t ConVarManager::CreateConVar(IPluginContext *pContext, const char *name,
|
||||
pInfo->handle = hndl;
|
||||
pInfo->sourceMod = true;
|
||||
pInfo->pChangeForward = NULL;
|
||||
pInfo->origCallback = NULL;
|
||||
|
||||
/* Create a handle from the new convar */
|
||||
hndl = g_HandleSys.CreateHandle(m_ConVarType, pInfo, NULL, g_pCoreIdent, NULL);
|
||||
@ -412,7 +427,6 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
||||
pInfo = new ConVarInfo();
|
||||
pInfo->sourceMod = false;
|
||||
pInfo->pChangeForward = NULL;
|
||||
pInfo->origCallback = pConVar->GetCallback();
|
||||
pInfo->pVar = pConVar;
|
||||
|
||||
/* If we don't have a handle, then create a new one */
|
||||
@ -433,6 +447,33 @@ Handle_t ConVarManager::FindConVar(const char *name)
|
||||
return hndl;
|
||||
}
|
||||
|
||||
void ConVarManager::AddConVarChangeListener(const char *name, IConVarChangeListener *pListener)
|
||||
{
|
||||
ConVarInfo *pInfo;
|
||||
|
||||
if (FindConVar(name) == BAD_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the convar in the lookup trie */
|
||||
if (convar_cache_lookup(name, &pInfo))
|
||||
{
|
||||
pInfo->changeListeners.push_back(pListener);
|
||||
}
|
||||
}
|
||||
|
||||
void ConVarManager::RemoveConVarChangeListener(const char *name, IConVarChangeListener *pListener)
|
||||
{
|
||||
ConVarInfo *pInfo;
|
||||
|
||||
/* Find the convar in the lookup trie */
|
||||
if (convar_cache_lookup(name, &pInfo))
|
||||
{
|
||||
pInfo->changeListeners.remove(pListener);
|
||||
}
|
||||
}
|
||||
|
||||
void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction)
|
||||
{
|
||||
ConVarInfo *pInfo;
|
||||
@ -449,9 +490,6 @@ void ConVarManager::HookConVarChange(ConVar *pConVar, IPluginFunction *pFunction
|
||||
{
|
||||
pForward = g_Forwards.CreateForwardEx(NULL, ET_Ignore, 3, CONVARCHANGE_PARAMS);
|
||||
pInfo->pChangeForward = pForward;
|
||||
|
||||
/* Install our own callback */
|
||||
pConVar->InstallChangeCallback(OnConVarChanged);
|
||||
}
|
||||
|
||||
/* Add function to forward's list */
|
||||
@ -491,9 +529,6 @@ void ConVarManager::UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFuncti
|
||||
/* Free this forward */
|
||||
g_Forwards.ReleaseForward(pForward);
|
||||
pInfo->pChangeForward = NULL;
|
||||
|
||||
/* Put back the original convar callback */
|
||||
pConVar->InstallChangeCallback(pInfo->origCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -561,15 +596,12 @@ void ConVarManager::AddConVarToPluginList(IPluginContext *pContext, const ConVar
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
void ConVarManager::OnConVarChanged(IConVar *pIConVar, const char *oldValue, float flOldValue)
|
||||
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 defined ORANGEBOX_BUILD
|
||||
ConVar *pConVar = (ConVar *)pIConVar;
|
||||
#endif
|
||||
if (strcmp(pConVar->GetString(), oldValue) == 0)
|
||||
{
|
||||
return;
|
||||
@ -583,24 +615,30 @@ void ConVarManager::OnConVarChanged(ConVar *pConVar, const char *oldValue)
|
||||
return;
|
||||
}
|
||||
|
||||
FnChangeCallback_t origCallback = pInfo->origCallback;
|
||||
IChangeableForward *pForward = pInfo->pChangeForward;
|
||||
|
||||
/* If there was a change callback installed previously, call it */
|
||||
if (origCallback)
|
||||
if (pInfo->changeListeners.size() != 0)
|
||||
{
|
||||
for (List<IConVarChangeListener *>::iterator i = pInfo->changeListeners.begin();
|
||||
i != pInfo->changeListeners.end();
|
||||
i++)
|
||||
{
|
||||
#if defined ORANGEBOX_BUILD
|
||||
origCallback(pConVar, oldValue, flOldValue);
|
||||
(*i)->OnConVarChanged(pConVar, oldValue, flOldValue);
|
||||
#else
|
||||
origCallback(pConVar, oldValue);
|
||||
(*i)->OnConVarChanged(pConVar, oldValue, atof(oldValue));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Now call forwards in plugins that have hooked this */
|
||||
pForward->PushCell(pInfo->handle);
|
||||
pForward->PushString(oldValue);
|
||||
pForward->PushString(reinterpret_cast<ConVar *>(pConVar)->GetString());
|
||||
pForward->Execute(NULL);
|
||||
if (pForward != NULL)
|
||||
{
|
||||
/* Now call forwards in plugins that have hooked this */
|
||||
pForward->PushCell(pInfo->handle);
|
||||
pForward->PushString(oldValue);
|
||||
pForward->PushString(pConVar->GetString());
|
||||
pForward->Execute(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool ConVarManager::IsQueryingSupported()
|
||||
@ -815,14 +853,10 @@ void _IntExt_EnableYamagrams()
|
||||
}
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
void _IntExt_OnHostnameChanged(IConVar *pConVar, const char *oldValue, float flOldValue)
|
||||
#else
|
||||
void _IntExt_OnHostnameChanged(ConVar *pConVar, char const *oldValue)
|
||||
#endif
|
||||
void _IntExt_OnHostnameChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
||||
{
|
||||
if (strcmp(oldValue, "Good morning, DS-san.") == 0
|
||||
&& strcmp(reinterpret_cast<ConVar *>(pConVar)->GetString(), "Good night, talking desk lamp.") == 0)
|
||||
&& strcmp(pConVar->GetString(), "Good night, talking desk lamp.") == 0)
|
||||
{
|
||||
_IntExt_EnableYamagrams();
|
||||
}
|
||||
|
@ -44,6 +44,12 @@
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
class IConVarChangeListener
|
||||
{
|
||||
public:
|
||||
virtual void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue) =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds SourceMod-specific information about a convar
|
||||
*/
|
||||
@ -52,8 +58,8 @@ struct ConVarInfo
|
||||
Handle_t handle; /**< Handle to self */
|
||||
bool sourceMod; /**< Determines whether or not convar was created by a SourceMod plugin */
|
||||
IChangeableForward *pChangeForward; /**< Forward associated with convar */
|
||||
FnChangeCallback_t origCallback; /**< The original callback function */
|
||||
ConVar *pVar; /**< The actual convar */
|
||||
List<IConVarChangeListener *> changeListeners;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -77,6 +83,7 @@ public:
|
||||
ConVarManager();
|
||||
~ConVarManager();
|
||||
public: // SMGlobalClass
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
void OnSourceModVSPReceived();
|
||||
@ -111,6 +118,9 @@ public:
|
||||
*/
|
||||
void UnhookConVarChange(ConVar *pConVar, IPluginFunction *pFunction);
|
||||
|
||||
void AddConVarChangeListener(const char *name, IConVarChangeListener *pListener);
|
||||
void RemoveConVarChangeListener(const char *name, IConVarChangeListener *pListener);
|
||||
|
||||
/**
|
||||
* Starts a query to find the value of a client convar.
|
||||
*/
|
||||
@ -131,7 +141,7 @@ private:
|
||||
* Static callback that Valve's ConVar object executes when the convar's value changes.
|
||||
*/
|
||||
#if defined ORANGEBOX_BUILD
|
||||
static void OnConVarChanged(IConVar *pConVar, const char *oldValue, float flOldValue);
|
||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue);
|
||||
#else
|
||||
static void OnConVarChanged(ConVar *pConVar, const char *oldValue);
|
||||
#endif
|
||||
|
@ -34,19 +34,10 @@
|
||||
#include "ForwardSys.h"
|
||||
#include "sourcemm_api.h"
|
||||
#include "frame_hooks.h"
|
||||
#include "ConVarManager.h"
|
||||
|
||||
#define TIMER_MIN_ACCURACY 0.1
|
||||
|
||||
#if !defined ORANGEBOX_BUILD
|
||||
#define CallGlobalChangeCallbacks CallGlobalChangeCallback
|
||||
#endif
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
SH_DECL_HOOK3_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *, float);
|
||||
#else
|
||||
SH_DECL_HOOK2_void(ICvar, CallGlobalChangeCallbacks, SH_NOATTRIB, false, ConVar *, const char *);
|
||||
#endif
|
||||
|
||||
TimerSystem g_Timers;
|
||||
double g_fUniversalTime = 0.0f;
|
||||
float g_fGameStartTime = 0.0f; /* Game game start time, non-universal */
|
||||
@ -74,7 +65,8 @@ time_t GetAdjustedTime(time_t *buf)
|
||||
|
||||
class DefaultMapTimer :
|
||||
public IMapTimer,
|
||||
public SMGlobalClass
|
||||
public SMGlobalClass,
|
||||
public IConVarChangeListener
|
||||
{
|
||||
public:
|
||||
DefaultMapTimer()
|
||||
@ -118,34 +110,20 @@ public:
|
||||
mp_timelimit->SetValue(mp_timelimit->GetInt() + extra_time);
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
void GlobalChangeCallback(ConVar *pVar, const char *old_value, float flOldValue)
|
||||
#else
|
||||
void GlobalChangeCallback(ConVar *pVar, const char *old_value)
|
||||
#endif
|
||||
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
||||
{
|
||||
if (pVar != mp_timelimit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (atoi(old_value) == pVar->GetInt())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_Timers.MapTimeLeftChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
void Enable()
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(ICvar, CallGlobalChangeCallbacks, icvar, this, &DefaultMapTimer::GlobalChangeCallback, false);
|
||||
g_ConVarManager.AddConVarChangeListener("mp_timelimit", this);
|
||||
}
|
||||
|
||||
void Disable()
|
||||
{
|
||||
SH_REMOVE_HOOK_MEMFUNC(ICvar, CallGlobalChangeCallbacks, icvar, this, &DefaultMapTimer::GlobalChangeCallback, false);
|
||||
g_ConVarManager.RemoveConVarChangeListener("mp_timelimit", this);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "sm_stringutil.h"
|
||||
#include "HandleSys.h"
|
||||
#include "CoreConfig.h"
|
||||
#include "ConVarManager.h"
|
||||
|
||||
RootConsoleMenu g_RootMenu;
|
||||
|
||||
@ -57,11 +58,16 @@ RootConsoleMenu::~RootConsoleMenu()
|
||||
m_Menu.clear();
|
||||
}
|
||||
|
||||
#if defined ORANGEBOX_BUILD
|
||||
extern void _IntExt_OnHostnameChanged(IConVar *var, const char *pOldValue, float flOldValue);
|
||||
#else
|
||||
extern void _IntExt_OnHostnameChanged(ConVar *pConVar, char const *oldValue);
|
||||
#endif
|
||||
extern void _IntExt_OnHostnameChanged(ConVar *var, const char *pOldValue, float flOldValue);
|
||||
|
||||
class DetectHostNameChanges : public IConVarChangeListener
|
||||
{
|
||||
public:
|
||||
void OnConVarChanged(ConVar *pConVar, const char *oldValue, float flOldValue)
|
||||
{
|
||||
_IntExt_OnHostnameChanged(pConVar, oldValue, flOldValue);
|
||||
}
|
||||
} s_HostnameChangeDetector;
|
||||
|
||||
void RootConsoleMenu::OnSourceModStartup(bool late)
|
||||
{
|
||||
@ -71,13 +77,16 @@ void RootConsoleMenu::OnSourceModStartup(bool late)
|
||||
CONVAR_REGISTER(this);
|
||||
AddRootConsoleCommand("version", "Display version information", this);
|
||||
AddRootConsoleCommand("credits", "Display credits listing", this);
|
||||
}
|
||||
|
||||
ConVar *pHost = icvar->FindVar("hostname");
|
||||
pHost->InstallChangeCallback(_IntExt_OnHostnameChanged);
|
||||
void RootConsoleMenu::OnSourceModAllInitialized()
|
||||
{
|
||||
g_ConVarManager.AddConVarChangeListener("hostname", &s_HostnameChangeDetector);
|
||||
}
|
||||
|
||||
void RootConsoleMenu::OnSourceModShutdown()
|
||||
{
|
||||
g_ConVarManager.RemoveConVarChangeListener("hostname", &s_HostnameChangeDetector);
|
||||
RemoveRootConsoleCommand("credits", this);
|
||||
RemoveRootConsoleCommand("version", this);
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ public: //IConCommandBaseAccessor
|
||||
bool RegisterConCommandBase(ConCommandBase *pCommand);
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModStartup(bool late);
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IRootConsoleCommand
|
||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||
|
@ -281,6 +281,11 @@ void SourceModBase::StartSourceMod(bool late)
|
||||
enginePatch = SH_GET_CALLCLASS(engine);
|
||||
gamedllPatch = SH_GET_CALLCLASS(gamedll);
|
||||
|
||||
g_ShareSys.Initialize();
|
||||
|
||||
/* Make the global core identity */
|
||||
g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
|
||||
|
||||
/* Notify! */
|
||||
SMGlobalClass *pBase = SMGlobalClass::head;
|
||||
while (pBase)
|
||||
@ -289,9 +294,6 @@ void SourceModBase::StartSourceMod(bool late)
|
||||
pBase = pBase->m_pGlobalClassNext;
|
||||
}
|
||||
|
||||
/* Make the global core identity */
|
||||
g_pCoreIdent = g_ShareSys.CreateCoreIdentity();
|
||||
|
||||
/* Notify! */
|
||||
pBase = SMGlobalClass::head;
|
||||
while (pBase)
|
||||
|
@ -54,7 +54,7 @@ IdentityToken_t *ShareSystem::CreateCoreIdentity()
|
||||
return CreateIdentity(m_CoreType, this);
|
||||
}
|
||||
|
||||
void ShareSystem::OnSourceModStartup(bool late)
|
||||
void ShareSystem::Initialize()
|
||||
{
|
||||
TypeAccess sec;
|
||||
|
||||
|
@ -84,7 +84,7 @@ public: //IShareSys
|
||||
void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives);
|
||||
public: //SMGlobalClass
|
||||
/* Pre-empt in case anything tries to register idents early */
|
||||
void OnSourceModStartup(bool late);
|
||||
void Initialize();
|
||||
void OnSourceModShutdown();
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object);
|
||||
|
Loading…
Reference in New Issue
Block a user