AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   To hook or not to hook, that is the question. (https://forums.alliedmods.net/showthread.php?t=314151)

PatriotGames 02-05-2019 14:52

To hook or not to hook, that is the question.
 
Please help a new coder understand the current recommended practice for tracking convar changes in both transitional and methodmap syntax.

In this example we have several different approaches:
PHP Code:

ConVar g_cvMyCvar;
bool g_bMyCvar;

public 
void OnPluginStart()
{
    
g_cvMyCvar CreateConVar("my_cvar""0""This cvar does something. 0 = Disable, 1 = Enable"FCVAR_NOTIFY);
    
    
g_bMyCvar GetConVarBool(g_cvMyCvar); //set bool var to cvar value
    
HookConvarChange(g_cvMyCvar CvarsChanged); // transitional hook cvar change function
    
    
g_cvMyCvar.AddChangeHook(CvarsChanged); //methodmap hook cvar change property
    
}

public 
void CvarsChanged(Handle convar, const char oldValue[], const char newValue[])
{
    
GetCvars();
}

public 
void GetCvars()
{
    
g_bMyCvar GetConVarBool(g_cvMyCvar); //transitional syntax
    
g_bMyCvar g_cvMyCvar.BoolValue;    //methodmap property
}

void MyCvarFunction()
{
    if (
GetConvarBool(g_cvMyCvar)); //does not use a cvar hook at all. Is this sub-optimal?
    
{
        
//code
    
}
}

void MyCvarBoolFunction()
{
    If (
g_bMyCvar//transitional syntax and methodmap property use the bool var for g_cvMyCvar. Any advantage of one over the other?
    
{
        
// code
    
}

void MyCvarMethodMapFunction()
{
    If (
g_cvMyCvar.BoolValue))    // A methodmap that uses the cvar directly without the hook property. Is this ok?
    
{
        
// code
    
}


What is the recommended practice?

Bonus question: what's the optimal method for using cvars to calculate another cvars new value?

Exmple:
PHP Code:

void SomeFunction()
{
    
SetConVarInt(g_cvSomeCvar, (g_iAnotherCvar + (g_iYetAnotherCvar g_iSomeConstant)));


Thanks,
PG

Neuro Toxin 02-05-2019 15:48

Re: To hook or not to hook, that is the question.
 
It is my understanding that it's now better practise to not hook convar changes. When using the new ConVar methodmap, it apparently caches the values and updates itself.

Im sure a dev will jump in if anything stated is wrong.

impossible_cc 02-05-2019 16:36

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by PatriotGames (Post 2638317)
Bonus question: what's the optimal method for using cvars to calculate another cvars new value?

Exmple:
PHP Code:

void SomeFunction()
{
    
SetConVarInt(g_cvSomeCvar, (g_iAnotherCvar + (g_iYetAnotherCvar g_iSomeConstant)));


Thanks,
PG


PHP Code:

void SomeFunction()
{
    
g_cvSomeCvar.IntValue g_iAnotherCvar.IntValue g_iYetAnotherCvar.IntValue g_iSomeConstant;
    
//If g_iSomeConstant is also a cvar, then you need g_iSomeConstant.IntValue


Edit:
if all of that is int, not convar, then do like this
PHP Code:

void SomeFunction()
{
    
g_cvSomeCvar.IntValue =  g_iAnotherCvar g_iYetAnotherCvar g_iSomeConstant;



asherkin 02-05-2019 19:04

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by Neuro Toxin (Post 2638330)
It is my understanding that it's now better practise to not hook convar changes. When using the new ConVar methodmap, it apparently caches the values and updates itself.

Im sure a dev will jump in if anything stated is wrong.

There is no difference pre- or post-methodmaps, convar handles have always been cached, and convars do the value conversions when they're set so getting values is just copying memory.

PatriotGames 02-05-2019 21:37

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by impossible_cc (Post 2638339)
Edit:
if all of that is int, not convar, then do like this
PHP Code:

void SomeFunction()
{
    
g_cvSomeCvar.IntValue =  g_iAnotherCvar g_iYetAnotherCvar g_iSomeConstant;



Thank you, impossible_cc. So the IntValue methodmap property can work like both GetConVarInt and SetConVarInt functions even in the same statement. Interesting...

Quote:

Originally Posted by asherkin (Post 2638345)
There is no difference pre- or post-methodmaps, convar handles have always been cached, and convars do the value conversions when they're set so getting values is just copying memory.

So there's no performance advantage to hooking cvar change and creating a var (bool, int, float) to track it over simply calling the cvar value? And...
PHP Code:

void SomeFunction()
{
    
g_cvSomeCvar.IntValue g_iAnotherCvar.IntValue g_iYetAnotherCvar.IntValue g_iSomeConstant;

    
// and...
    
    
SetConVarInt(g_cvSomeCvar) = (GetConVarInt(g_iAnotherCvar) + GetConVarInt(g_iYetAnotherCvar) * g_iSomeConstant);

    
// are equivalent and one has no performance advantage over the other?


So, when and why would we use:
PHP Code:

g_cvMyCvar.AddChangeHook(MyCallback); 

Thank you for the help,
PG

Dragokas 02-10-2019 13:33

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by PatriotGames (Post 2638354)
So, when and why would we use:
PHP Code:

g_cvMyCvar.AddChangeHook(MyCallback); 

PG

When you need instantly execute some method, e.g. change player color when cvarColor is changed.

PatriotGames 02-11-2019 14:32

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by Dragokas (Post 2639048)
When you need instantly execute some method, e.g. change player color when cvarColor is changed.

Thanks, Dragokas, that makes sense.

PG

Psyk0tik 02-13-2019 03:46

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by PatriotGames (Post 2639220)
Thanks, Dragokas, that makes sense.

PG

To add more to this, we hook a cvar handle to a changehook if we want something to happen as soon as the value of that cvar is changed. (i.e. g_cvIsOn.AddChangeHook(vIsOnHook) or HookConVarChange(g_hIsOn, vIsOnHook))

If we just want to check the current value of the cvar, we can just call it when we need it (or cache it to a variable if you prefer that). (i.e. bIsOn = g_cvIsOn.BoolValue or bIsOn = GetConVarBool(g_hIsOn))

In this example, we're going to check the initial value of the "mp_gamemode" cvar and then hook it so we can check for the value whenever it changes:

PHP Code:

ConVar g_cvMPGameMode;
bool g_bIsCampaign;

public 
void OnPluginStart()
{
    
g_cvMPGameMode FindConVar("mp_gamemode");

    if (
g_cvMPGameMode != null)
    {
        
g_cvMPGameMode.AddChangeHook(vMPGameModeHook);
    }
}

public 
void OnMapStart()
{
    if (
g_cvMPGameMode != null)
    {
        
char sGameMode[32];
        
g_cvMPGameMode.GetString(sGameModesizeof(sGameMode));

        if (
StrEqual(sGameMode"versus"))
        {
            
g_bIsCampaign false;
        }
    }
}

public 
void vMPGameModeHook(ConVar convar, const char[] oldVal, const char[] newVal)
{
    if (
StrEqual(newVal"versus"))
    {
        
g_bIsCampaign false;
    }
    else
    {
        
g_bIsCampaign true;
    }


I assume you've made this thread due to the changes I made to your plugin last week. I'm sorry for not explaining it to you or adding comments in the code to help you. If you want, we can discuss any other questions you may have in private chat or on Discord.

Ilusion9 02-13-2019 05:35

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by Crasher_3637 (Post 2639421)
To add more to this, we hook a cvar handle to a changehook if we want something to happen as soon as the value of that cvar is changed.

Or to block that change to happen.

PHP Code:


public void OnPluginStart() 

    
g_cvMPGameMode FindConVar("mp_gamemode"); 

    if (
g_cvMPGameMode != null
    { 
        
g_cvMPGameMode.AddChangeHook(vMPGameModeHook); 
    } 



public 
void vMPGameModeHook(ConVar convar, const char[] oldVal, const char[] newVal

    if (!
StrEqual(newVal"versus")) 
    { 
        
g_cvMPGameMode.SetString("versus"));
    } 



PatriotGames 02-15-2019 20:41

Re: To hook or not to hook, that is the question.
 
Quote:

Originally Posted by Crasher_3637 (Post 2639421)
To add more to this, we hook a cvar handle to a changehook if we want something to happen as soon as the value of that cvar is changed. (i.e. g_cvIsOn.AddChangeHook(vIsOnHook) or HookConVarChange(g_hIsOn, vIsOnHook))

If we just want to check the current value of the cvar, we can just call it when we need it (or cache it to a variable if you prefer that). (i.e. bIsOn = g_cvIsOn.BoolValue or bIsOn = GetConVarBool(g_hIsOn))

In this example, we're going to check the initial value of the "mp_gamemode" cvar and then hook it so we can check for the value whenever it changes:

PHP Code:

ConVar g_cvMPGameMode;
bool g_bIsCampaign;

public 
void OnPluginStart()
{
    
g_cvMPGameMode FindConVar("mp_gamemode");

    if (
g_cvMPGameMode != null)
    {
        
g_cvMPGameMode.AddChangeHook(vMPGameModeHook);
    }
}

public 
void OnMapStart()
{
    if (
g_cvMPGameMode != null)
    {
        
char sGameMode[32];
        
g_cvMPGameMode.GetString(sGameModesizeof(sGameMode));

        if (
StrEqual(sGameMode"versus"))
        {
            
g_bIsCampaign false;
        }
    }
}

public 
void vMPGameModeHook(ConVar convar, const char[] oldVal, const char[] newVal)
{
    if (
StrEqual(newVal"versus"))
    {
        
g_bIsCampaign false;
    }
    else
    {
        
g_bIsCampaign true;
    }


I assume you've made this thread due to the changes I made to your plugin last week. I'm sorry for not explaining it to you or adding comments in the code to help you. If you want, we can discuss any other questions you may have in private chat or on Discord.

Thanks for the explanation, Crasher_3637, and no need to apologize. I just appreciated your taking the time to review my code and offer suggested changes. Sure, comments would have been helpful, but I don't feel comfortable pressing someone for more effort when they're already graciously giving their time to help me.

This thread was made in part due to your removing the convar hook and check section from the early version of my plugin, but also because of comments (not necessarily yours) made in other threads which gave the impression that hooking cvars is really not needed except in very specific cases, such as the one you've detailed here and in Ilusion9's example.

That revelation was perplexing because of the number of plugins from very competent authors that include large cvar hook sections. For me, understanding why something is done is as important as learning how it is done. I'm not comfortable applying practices or using code if I don't understand the "why" behind it. Your above example and explanation has helped my understanding of when to hook or not to hook cvars and why.

Thanks again for your help and if the need arises, I will definitely contact you to discuss this topic further.

Kind regards,
Patriot


All times are GMT -4. The time now is 01:18.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.