Raised This Month: $178 Target: $400
 44% 

Solved Optimized Plugin?


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
ThatKidWhoGames
Senior Member
Join Date: Jun 2013
Location: IsValidClient()
Old 06-13-2018 , 09:42   Optimized Plugin?
Reply With Quote #1

Hello all!

I have coded a plugin and I want to know your guys' input as to if it is the most optimized way to perform what I want in the plugin. As you will probably be able to tell, it is a respawn timer plugin for TF2. I also want to know if passing the UserID to the timer/frame callback is also necessary (I believe it is but I could be wrong).

PHP Code:
#pragma semicolon 1
#define PLUGIN_VERSION "1.0.0"

#include <sourcemod>
#include <tf2_stocks>

Handle hTimer[MAXPLAYERS+1];
ConVar hConVars[5];
bool bEnablebBotsbCenterbHint;
int iTimeiTimeleft[MAXPLAYERS+1];

methodmap Player {
    public 
Player(int client) {
        return 
view_as<Player>(client);
    }

    
property int Index {
        public 
get() {
            return 
view_as<int>(this);
        }
    }

    
property int UserID {
        public 
get() {
            return 
GetClientUserId(this.Index);
        }
    }
    
    
property int Time {
        public 
get() {
            return 
iTimeleft[this.Index];
        }
        public 
set(int value) {
            
iTimeleft[this.Index] = value;
        }
    }

    
property bool Alive {
        public 
get() {
            return 
IsPlayerAlive(this.Index);
        }
    }

    
property bool Valid {
        public 
get() {
            return 
IsValidClient(this.Index);
        }
    }

    
property bool Fake {
        public 
get() {
            return 
IsFakeClient(this.Index);
        }
    }

    public 
void Respawn() {
        return 
TF2_RespawnPlayer(this.Index);
    }

    public 
void PrintText(const char[] bufferany ...) {
        
int len       strlen(buffer);
        
char[] format = new char[len];
        
VFormat(formatlenbuffer2);
        if (
bCenter)
            
PrintCenterText(this.Indexformat);
        if (
bHint)
            
PrintHintText(this.Indexformat);
    }

    public 
void DelTimer() {
        
DeleteTimer(this.Index);
    }
}

public 
Plugin myinfo = {
    
name        "[TF2] Respawn Timer",
    
author      "Sgt. Gremulock",
    
description "Respawn timer for TF2.",
    
version     PLUGIN_VERSION,
    
url         "grem-co.com"
};

public 
void OnPluginStart()
{
    
CreateConVar("sm_respawntimer_version"PLUGIN_VERSION"Plugin's version."FCVAR_NOTIFY|FCVAR_DONTRECORD);
    
hConVars[0] = CreateConVar("sm_respawntimer_enable""1""Enable/disable the plugin.\n(1 = Enable, 0 = Disable)"_true0.0true1.0);
    
hConVars[1] = CreateConVar("sm_respawntimer_bots""1""Enable/disable the respawn timer for bots.\n(1 = Enable, 0 = Disable)"_true0.0true1.0);
    
hConVars[2] = CreateConVar("sm_respawntimer_time""5""Time (in seconds) until player should respawn.\n(<1 = Instant (If value is <1, center & hint text will not display regardless of ConVar value.))"_true0.0);
    
hConVars[3] = CreateConVar("sm_respawntimer_center_text""1""Display center text for seconds remaining until respawn.\n(1 = Enable, 0 = Disable)"_true0.0true1.0);
    
hConVars[4] = CreateConVar("sm_respawntimer_hint_text""1""Display hint text for seconds remaining until respawn.\n(1 = Enable, 0 = Disable)"_true0.0true1.0);
    for (
int i 0sizeof(hConVars); i++)
        
hConVars[i].AddChangeHook(ConVarUpdate);
    
AutoExecConfig(true"RespawnTimer");
    
HookEvent("player_death"Event_PlayerDeath);
}

public 
void OnConfigsExecuted()
{
    
bEnable hConVars[0].BoolValue;
    
bBots    hConVars[1].BoolValue;
    
iTime    hConVars[2].IntValue;
    
bCenter hConVars[3].BoolValue;
    
bHint    hConVars[4].BoolValue;
}

public 
void ConVarUpdate(ConVar cvar, const char[] oldValue, const char[] newValue)
{
    if (
cvar == hConVars[0])
        
bEnable hConVars[0].BoolValue;
    if (
cvar == hConVars[1])
        
bBots hConVars[1].BoolValue;
    if (
cvar == hConVars[2])
        
iTime hConVars[2].IntValue;
    if (
cvar == hConVars[3])
        
bCenter hConVars[3].BoolValue;
    if (
cvar == hConVars[4])
        
bHint hConVars[4].BoolValue;
}

public 
void OnClientDisconnect(int client)
{
    
Player player Player(client);
    
player.Time   0;
    
player.DelTimer();
}

public 
void Event_PlayerDeath(Event event, const char[] namebool dontBroadcast)
{
    if (!
bEnable || event.GetInt("death_flags") & TF_DEATHFLAG_DEADRINGER)
        return;
    
Player player Player(GetClientOfUserId(event.GetInt("userid")));
    if (
player.Valid)
        if (!
iTime)
            
RequestFrame(Frame_Callbackplayer.UserID);
        else {
            
player.Time iTime;
            
player.PrintText("You will respawn in %i seconds"player.Time);
            
hTimer[player.Index] = CreateTimer(1.0Timer_Callbackplayer.UserIDTIMER_REPEAT);
        }
}

public 
Action Timer_Callback(Handle timerint userid)
{
    
Player player Player(GetClientOfUserId(userid));
    if (
player.Valid)
    {
        if (
player.Alive)
        {
            
hTimer[player.Index] = null;
            return 
Plugin_Stop;
        }

        if (!
player.Time)
        {
            
player.Respawn();
            
hTimer[player.Index] = null;
            return 
Plugin_Stop;
        }

        
player.Time--;
        
player.PrintText("You will respawn in %i seconds"player.Time);
        return 
Plugin_Continue;
    } else
        
player.DelTimer();
    return 
Plugin_Stop;
}

public 
void Frame_Callback(int userid)
{
    
Player player Player(GetClientOfUserId(userid));
    if (
player.Valid && !player.Alive)
        
player.Respawn();
}

stock bool IsValidClient(int client)
{
    return 
client && client <= MaxClients && IsClientInGame(client) && !(!bBots && IsFakeClient(client));
}

stock void DeleteTimer(int client)
{
    if (
hTimer[client])
    {
        
KillTimer(hTimer[client]);
        
hTimer[client] = null;
    }

Thanks!
Grant
__________________


I take custom plugin requests, add me on Steam for details.

Last edited by ThatKidWhoGames; 06-13-2018 at 15:29. Reason: OCD
ThatKidWhoGames is offline
Neuro Toxin
Veteran Member
Join Date: Oct 2013
Location: { closing the void; }
Old 06-13-2018 , 12:40   Re: Optimized Plugin?
Reply With Quote #2

I would start off by noting you dont need ConVarUpdate anymore.

ConVar caches it's value and updates automatically.
__________________
Neuro Toxin is offline
Peace-Maker
SourceMod Plugin Approver
Join Date: Aug 2008
Location: Germany
Old 06-13-2018 , 13:33   Re: Optimized Plugin?
Reply With Quote #3

Quote:
Originally Posted by Neuro Toxin View Post
I would start off by noting you dont need ConVarUpdate anymore.

ConVar caches it's value and updates automatically.
What makes you think that? ConVar.BoolValue is still a native call just like GetConVarBool which might be expensive when done in a loop in a critical callback.

You can get rid of the DeleteTimer function and just do "delete hTimer[client];". "KillTimer" does exactly the same as "CloseHandle"/"delete" if you don't use its optional "autoClose" parameter. "delete" ignores null handles and sets the variable to null afterwards - all in one go!
__________________
Peace-Maker is offline
ddhoward
Veteran Member
Join Date: May 2012
Location: California
Old 06-13-2018 , 14:53   Re: Optimized Plugin?
Reply With Quote #4

Quote:
Originally Posted by Peace-Maker View Post
What makes you think that?
https://forums.alliedmods.net/showth...63#post2316163
__________________
ddhoward is offline
akcaliberg
Senior Member
Join Date: Nov 2011
Location: Istanbul
Old 06-13-2018 , 15:18   Re: Optimized Plugin?
Reply With Quote #5

Since a variable can only have a single value at a time, you should not keep comparing it with other values once you find a match.

So instead of doing:

PHP Code:
if(something == a) ...
if(
something == b) ...
if(
something == c) ... 
You should do:

PHP Code:
if(something == a) ...
else if(
something == b) ...
else if(
something == c) ... 
It will be even better if you use the switch statement:

PHP Code:
switch(something) {
   case 
a: {
      ...
   }
   case 
b: {
      ...
   }
   case 
c: {
      ...
   }

akcaliberg is online now
ThatKidWhoGames
Senior Member
Join Date: Jun 2013
Location: IsValidClient()
Old 06-13-2018 , 15:29   Re: Optimized Plugin?
Reply With Quote #6

Thanks guys!!
__________________


I take custom plugin requests, add me on Steam for details.
ThatKidWhoGames is offline
Crasher_3637
AlliedModders Donor
Join Date: May 2012
Old 06-13-2018 , 19:02   Re: Optimized Plugin?
Reply With Quote #7

Yeah you really don't need to assign all the convar changes to booleans, cells, etc.

This:
PHP Code:
bool g_bEnabled;
ConVar g_cvEnabled[5];
g_bEnabled g_cvEnabled[0].BoolValue;
...
if (
g_bEnabled
Can be simplified to:
PHP Code:
ConVar g_cvEnabled[5];
...
if (
g_cvEnabled[0].BoolValue
As said on psychonic's post that ddhoward linked, convar values are already cached internally and do not need to be recached when their values are changed.
__________________

Last edited by Crasher_3637; 06-13-2018 at 19:03.
Crasher_3637 is offline
ThatKidWhoGames
Senior Member
Join Date: Jun 2013
Location: IsValidClient()
Old 06-13-2018 , 20:02   Re: Optimized Plugin?
Reply With Quote #8

Quote:
Originally Posted by Crasher_3637 View Post
Yeah you really don't need to assign all the convar changes to booleans, cells, etc.

This:
PHP Code:
bool g_bEnabled;
ConVar g_cvEnabled[5];
g_bEnabled g_cvEnabled[0].BoolValue;
...
if (
g_bEnabled
Can be simplified to:
PHP Code:
ConVar g_cvEnabled[5];
...
if (
g_cvEnabled[0].BoolValue
As said on psychonic's post that ddhoward linked, convar values are already cached internally and do not need to be recached when their values are changed.
Thanks!
__________________


I take custom plugin requests, add me on Steam for details.
ThatKidWhoGames is offline
Peace-Maker
SourceMod Plugin Approver
Join Date: Aug 2008
Location: Germany
Old 06-13-2018 , 20:22   Re: Optimized Plugin?
Reply With Quote #9

Quote:
Originally Posted by ddhoward View Post
We're still talking about little optimizations here and switching to C++ code by calling the ConVar.IntValue native instead of just reading a variable in the vm memory is technically still more expensive. Native calls are pretty fast though and since the native is just returning a cached value this isn't really worth the effort. You just need to make a difference between "ConVar" (the sourcepawn methodmap) caching its value and the c++ structure backing it up in the SDK. sourcepawn isn't caching the value.
__________________
Peace-Maker is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 04:24.


Powered by vBulletin®
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Theme made by Freecode