Raised This Month: $ Target: $400
 0% 

Safer Timers


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
zeroibis
Veteran Member
Join Date: Jun 2007
Old 03-27-2013 , 23:29   Safer Timers
Reply With Quote #1

So is it recommended that we use clientid for timer tracking or are we fine just using client?

CLIENT:
In Variable Declaration:
Code:
//timers
new Handle:NewTimer[MAXPLAYERS+1];

In Program Include this Method
: Must be included to remove the timer to prevent errors
Code:
//CLEAR TIMERS
public OnClientDisconnect(client)
{
    new Handle:Timer;
    Timer = NewTimer[client];
    if(Timer != INVALID_HANDLE)
    {
        KillTimer(NewTimer);
        Timer = INVALID_HANDLE;
    }
}

In Method Using Timer
: This is used to create the timer
Code:
NewTimer[client] = CreateTimer(LENGTH_OF_TIMER,NAME_OF_METHOD,client);

In Program Include this Method
: Place code to run when timer ends within this method too
Code:
public Action:NAME_OF_METHOD(Handle:timer,any:client)
{
    //Code to run when timer ends
    Timer[client] = INVALID_HANDLE;
}

CLIENTID:

In Variable Declaration:
Code:
//timers
new Handle:NewTimer[MAXPLAYERS+1];

In Program Include this Method
: Must be included to remove the timer to prevent errors
Code:
//CLEAR TIMERS
public OnClientDisconnect(client)
{
    new Handle:Timer;
    Timer = NewTimer[client];
    if(Timer != INVALID_HANDLE)
    {
        KillTimer(NewTimer);
        Timer = INVALID_HANDLE;
    }
}

In Method Using Timer
: This is used to create the timer
Code:
NewTimer[client] = CreateTimer(LENGTH_OF_TIMER,NAME_OF_METHOD,GetClientUserId(client));

In Program Include this Method
: Place code to run when timer ends within this method too
Code:
public Action:NAME_OF_METHOD(Handle:timer,any:userid)
{
    //Get the current client of the target userid
    new client = GetClientOfUserId(userid);
    
    //Code to run when timer ends
    Timer[client] = INVALID_HANDLE;
    
    //If client is a valid player
    if(client!=0)
    {
        
    }
}
So is it advisable to use userid instead of client for timers or does it not really matter. Also in the example here should the timers be cleared manually at map end in addition to client disconnect if they are not supposed to carry over?
__________________

Last edited by zeroibis; 03-27-2013 at 23:30.
zeroibis is offline
friagram
Veteran Member
Join Date: Sep 2012
Location: Silicon Valley
Old 03-28-2013 , 00:07   Re: Safer Timers
Reply With Quote #2

Just use client. You do not need to store the handle of the timer unless you know you will need to close it later. Timers will close their own handles when they complete. If you use datapacks, you can pass a flag to have the timer close that as well. If you are sure the timer will complete, and it won't have to be canceled don't store the handle generally. Likewise, if you know whe the timer will become invalid, as is the case usually with repeating client timers, you can return a plugin_stop from within the plugin if the client becomes invalid, or if a global variable changes.

Times when you would want to store the handle is if you need to kill the timer at some other point and may risk having multipe timers up at the same time, like you applied some effect to a player, and need to renew it.. Like spawn protection or something of that sort, you would want to start a new timer if they changed class instantly and you just needed to renew the timer.

Make sure if you use really long timers, or if you use repeating timers, you make sure they will finish before the map changes, or use the flag which prevents the timer from continuing on mapchange.

TIMER_REPEAT > your timer repeats until you return plugin stop or closehandle/killtimer
TIMER_FLAG_NO_MAPCHANGE > kills your timer on map change for you
TIMER_DATA_HNDL_CLOSE > closes the handle of a datapck for you when the timer ends
__________________
Profile - Plugins
Add me on steam if you are seeking sp/map/model commissions.

Last edited by friagram; 03-28-2013 at 00:18.
friagram is offline
thetwistedpanda
Good Little Panda
Join Date: Sep 2008
Old 03-28-2013 , 00:27   Re: Safer Timers
Reply With Quote #3

If the timer does not need to be closed early, say at the end of a round, does not need to be tracked, and will not repeat itself under most circumstancs, you can pass the client's userid and simply verify the userid when the timer executes. If the opposite is true, it's recommended to track the Handle. Usage varies on the situation.
__________________
thetwistedpanda is offline
TnTSCS
AlliedModders Donor
Join Date: Oct 2010
Location: Undisclosed...
Old 03-28-2013 , 00:28   Re: Safer Timers
Reply With Quote #4

I've switched to use the client's serial (GetClientSerial and then to validate, GetClientFromSerial)
__________________
View my Plugins | Donate
TnTSCS is offline
zeroibis
Veteran Member
Join Date: Jun 2007
Old 03-28-2013 , 01:31   Re: Safer Timers
Reply With Quote #5

Quote:
Originally Posted by TnTSCS View Post
I've switched to use the client's serial (GetClientSerial and then to validate, GetClientFromSerial)
Ah very cool.

In my case I am dealing with war3 related timers so you want to ensure that the intended target client does not change as invalid is one thing but if the wrong player got something applied to them you can get a crash really fast. Obviously something like this is not common or likely but I am not sure how safe using client is in order to ensure that a given method is run on the intended target 100% of the time.
__________________
zeroibis is offline
friagram
Veteran Member
Join Date: Sep 2012
Location: Silicon Valley
Old 03-28-2013 , 07:37   Re: Safer Timers
Reply With Quote #6

I never really see entity references used with clients. Usually what i see is the client passed, and people just check to see if the client is still connected, ingame, alive or whatever when the timer executes. I can see that it would make sense though to make sure that the id is the same, but do client ids get recycled that frequently? I can think of a few plugins that i have run for a long time now that pass client to timers, and have never applied effects to the wrong person to my knowledge.

I see entity references used fairly frequently when destroying entities, though another method is to test the entities' classname and then destroy it (this is probably not as good as a reference). The rest of the time plugins just check if the entity is valid, and assume that it is what it should be, and don't bother with references, like if some random property of an entity is going to be modified after a second or two of it being spawned.

I can think of a hale mod we have that rarely will bug out a bit with some TE effects on a timer, where an entity index will change as the round resets, so a light will teleport to some random map entity like a info particle system or door on the map and send out TE effects and continue the timer.. I happens mabye once every few months, and is harmless, but it does happen.
__________________
Profile - Plugins
Add me on steam if you are seeking sp/map/model commissions.

Last edited by friagram; 03-28-2013 at 07:42.
friagram is offline
thetwistedpanda
Good Little Panda
Join Date: Sep 2008
Old 03-28-2013 , 08:39   Re: Safer Timers
Reply With Quote #7

Timers that don't have their handle saved should always pass their clients / entities in a safe manner, i.e. GetCilentSerial / GetClientUserId / GetEntityRefIndex. For clients, indexes are recycled on connection where as userids are only recycled after 65,000ish - incremental by one each connection. For example:
- Say you want to ban someone after 30 seconds; you want to scare them or whatever. You pass a timer of 30.0 and forget to cache the handle. That player disconnects, and your favorite donator joins right after. 30.0 seconds later, your favorite donator gets banned. Passing via userid would have failed when getting GetClientOfUserId, saving your donator.
The same concept applies to entities, but there's only ~2048-~4096 (varies on game) indexes and things get deleted/reused often depending on the game, map, and plugins. A very common mistake is issuing RemoveEdict / AcceptEntityInput "Kill" on entities without passing their reference, so server crashes, missing weapons, etc start to occur.

Plugins that don't cache, but don't pass data correctly, are doing it wrong.
__________________

Last edited by thetwistedpanda; 03-28-2013 at 09:40.
thetwistedpanda is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 03-28-2013 , 09:35   Re: Safer Timers
Reply With Quote #8

Quote:
Originally Posted by thetwistedpanda View Post
but there's only 2048 indexes
I thought we were up to 4096 in Source games.
__________________
Not currently working on SourceMod plugin development.
Powerlord is offline
Bacardi
Veteran Member
Join Date: Jan 2010
Location: mom's basement
Old 03-28-2013 , 09:36   Re: Safer Timers
Reply With Quote #9

Quote:
Originally Posted by TnTSCS View Post
I've switched to use the client's serial (GetClientSerial and then to validate, GetClientFromSerial)
Those serial numbers change even on map change, not like players userid.
Can't see how this is usefull...
Bacardi is offline
thetwistedpanda
Good Little Panda
Join Date: Sep 2008
Old 03-28-2013 , 09:39   Re: Safer Timers
Reply With Quote #10

Quote:
Originally Posted by Powerlord View Post
I thought we were up to 4096 in Source games.
It varies by game, maybe TF2 has 4096, but a good majority of them have 2048. Edited for posterity sake though.

Quote:
Originally Posted by Bacardi View Post
Those serial numbers change even on map change, not like players userid.
Can't see how this is usefull...
Any timer with TIMER_FLAG_NO_MAPCHANGE.
__________________

Last edited by thetwistedpanda; 03-28-2013 at 09:40.
thetwistedpanda is offline
Reply



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 05:49.


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