Important Timers

ggblade

Member
Member
Aug 14, 2014
29
0
6
ive always heard that timers on magma were weird. are those better now? (havent tested anything related to timers seeying as ive got no idea how they work)
 

DreTaX

Probably knows the answer...
Administrator
Jun 29, 2014
4,095
4,815
113
At your house.
github.com
ive always heard that timers on magma were weird. are those better now? (havent tested anything related to timers seeying as ive got no idea how they work)
Nothing specific. The only problem is that if you run a timer twice for example at the same time with the same name It will kill eachother, and Won't make an auto clone of it.

Here is one of the guy's example: (KoelKast)



JavaScript:
function On_ServerInit()
{
    Time.CreateTimer("sendServerData",10000).Start();
}
10000 = 10 secs.

And then create a function called sendServerDataCallback (Notice the name, its the timer name + Callback).

Example:

JavaScript:
function sendServerDataCallback()
{
   var players = Server.Players;
     
   var count=0, totalcount=0;
   var str = "";
   for(var pl in Server.Players) {
        totalcount++;
       if(totalcount >= 60) {
            count = 0;
           break;
       }
 
        str += pl.Name + "-"+pl.Location+"-"+pl.Ping+"-"+pl.SteamID+"-"+pl.Admin+"-"+pl.Health+"-|-";
   }
    reponse = Web.POST("http://test.com/catch.php",str);
   return reponse;
}

If you wish to add some parameters to it:


JavaScript:
var params =new ParamsList();
params.Add(Player.SteamID);
params.Add(Player.Name);
Time.CreateTimer("test",60000, params).Start();


function testCallback(params) {
       var player = Fougerite.Player.FindByName(params.Get(1));
}
If you wish to kill a timer:

Time.KillTimer("test");


If you wish to do a single timer per player @BadZombi gave me a good solution before, you may look in HomeSystem, and TpFriend

Hey magma people,

dretax14 asked me for a working example of a timer queue setup like the one I use in a few plugins.

Sooo... I made a really simple example plugin to illustrate the basic concept.

3 commands:
/extimer <phrase : optional> : this will create a new entry in the queue and start the timer if its not already running. if you enter a phrase, it is what you will see in the notice when the entry executes... if not it will just show your name.
/cleartimers : pretty obvious. this will flush the ds queue
/listtimers : will show pending timers

On first run it will create an ini file. if you want to change settings you can do so and then execute magma.reload in console.

settings:
run_timer: time between queue checks. (in seconds) this can be pretty low IMO. The timer will stop when the queue is empty and will restart when a new entry is added. Assuming you are using this for a simple delay before executing a TP home or something like that you should be ok even with a lot of players.
execute_delay: actual time in seconds before the event will trigger/execute
expiration: I added this in case there was an error. if somehow an entry is missed and goes over my this number of seconds, it will be removed and will not execute. this never happened in testing but I guess it could if the timer crashed and was restarted before the queue was empty.
example_message: Just the chat message that will pop up for the example
chatname: the name for messages and broadcasts

Hopefully this will help some people who have run into issues with multiple timers or whatever.
Hopefully that's all the explanation needed. I'll to my best to answer any questions as they come.

Here's the code: (all tested on my dev server)

JavaScript:
var ExTime = {
    name:       'ExampleTimer',
    author:   'BadZombi',
    version:   '0.1.0',
    DStable:   'ExampleTimer',
   // These config functions (createConfig, loadConfig and confSetting) are usually in my core...
    createConfig: function(data, filename, pluginname){
        Util.ConsoleLog("Config does not exist... creating "+ filename +".ini for " + pluginname, true);
        Plugin.CreateIni(filename);
       var newConf = Plugin.GetIni(filename);
       for (var x in data) {
           var section_name = x;
           var section_data = data[x];

           if(typeof(section_data) == "object"){
               for (var d in section_data) {
                   var itemName = d;
                   var itemValue = section_data[d];
                    newConf.AddSetting(section_name, itemName, itemValue);
                    Util.ConsoleLog("  --  Adding \"" + itemName + "\" = \"" + itemValue + "\" to " + section_name + " section...", true);
               }
           }
       }
        newConf.Save();
       return newConf;
   },
    loadConfig: function(file){
       if(file == undefined){ file = "Config"; }
       var readConf = Plugin.GetIni(file);
       return readConf;
   },
    confSetting: function(name, section, file) {
       if(section == undefined){ section = "Config"; }
       if(file == undefined){ file = "Config"; }
       var conf = this.loadConfig(file);
       return conf.GetSetting(section, name);
   },
    addTimer: function(P, data){
        P.MessageFrom(this.confSetting("chatname"), "Adding entry: " + data);
        P.MessageFrom(this.confSetting("chatname"), "Response should be in ~"+this.confSetting("execute_delay")+" seconds.");

       var epoch = Plugin.GetTimestamp();
       var exectime = parseInt(epoch) + parseInt(this.confSetting("execute_delay"));
        DataStore.Add(this.DStable, exectime, String(data));
       this.startTimer();
   },
    startTimer: function(){
       if(!Plugin.GetTimer("DoIt")){
            Plugin.CreateTimer("DoIt", this.confSetting("run_timer") * 1000).Start();
       }
   },
    stopTimer: function(P) {
        Plugin.KillTimer("DoIt");
   },
    clearTimers: function(P){
        P.MessageFrom(ExTime.confSetting("chatname"), "Erasing all example timers.");
        DataStore.Flush(this.DStable);
   }
}



function On_PluginInit() {

   if ( !Plugin.IniExists( 'Config' ) ) {

       var Config = {};
            Config['run_timer'] = 2;
            Config['execute_delay'] = 30;
            Config['expiration'] = 40;
            Config['example_message'] = "A timer has executed! Wow!";
            Config['chatname'] = "ExTime";


       var iniData = {};
            iniData["Config"] = Config;

       var conf = ExTime.createConfig(iniData, 'Config', ExTime.name);

   }

    Util.ConsoleLog(ExTime.name + " v" + ExTime.version + " loaded.", true);
}

function On_Command(P, cmd, args) {

    cmd = Data.ToLower(cmd);
   switch(cmd) {

       case "extimer":
           if(args.Length >= 1){
               var phrase = "";
               for (var a in args){
                    phrase += a+" ";
               }
                ExTime.addTimer(P, phrase);
           } else {
                ExTime.addTimer(P, P.Name);
                P.MessageFrom(ExTime.confSetting("chatname"), "You can also enter a phrase with this command.");
                P.MessageFrom(ExTime.confSetting("chatname"), "e.g. /extimer bob likes chicken");
           }
   
       break;

       case "cleartimers":
            ExTime.clearTimers();
       break;

       case "listtimers":

            P.MessageFrom(ExTime.confSetting("chatname"), "Listing pending timer entries:");
           var dsTable = DataStore.Keys(ExTime.DStable);
           for (var x in dsTable){
                P.MessageFrom(ExTime.confSetting("chatname"), "Timer entry: " + x + " : " + DataStore.Get(ExTime.DStable, x));
           }
            P.MessageFrom(ExTime.confSetting("chatname"), "==============================");
       break;

   }
}

function DoItCallback(){
   var epoch = Plugin.GetTimestamp();
   var exp = parseInt(ExTime.confSetting("expiration") - ExTime.confSetting("execute_delay"))
   if(DataStore.Count(ExTime.DStable) >= 1){
       var pending = DataStore.Keys(ExTime.DStable);
       for (var p in pending){
           var x = parseInt(epoch - p);
           if(x < 0){
                x = x * -1;
                Server.BroadcastFrom(ExTime.confSetting("chatname"), 'One entry will execute in ' + x + ' seconds...');
           } else if(x >= 0 < exp){
                Server.BroadcastFrom(ExTime.confSetting("chatname"), ExTime.confSetting("example_message"));
                Server.BroadcastNotice( DataStore.Get(ExTime.DStable, p) );
                DataStore.Remove(ExTime.DStable, p)
           } else if(x >= exp){
                DataStore.Remove(ExTime.DStable, p)
           }
       
       }
        Server.BroadcastFrom(ExTime.confSetting("chatname"), '-----------------------------------');
   } else {
        ExTime.stopTimer();
   }

}
I should note that there is a LOT of room for optimization, better structure and whatnot. This was a quickie so don't tell me my code is shit ;)

Repo: http://code.badzombi.com/rust-plugin-development/magma-queue-timer-example/tree/master

Edit: removed a reference to a handleError function from my core. I didn't include it here so it shouldn't have been called.
 
Last edited:
  • Useful
Reactions: ggblade

ggblade

Member
Member
Aug 14, 2014
29
0
6
im going to make a plugin that protects the new players structures for e certain amount of time, but that time would be i guess 2-5 days, depending on how the testing go's. but afaik alot of timers would lag the server, and i would implement this in the next wipe. so that would be alot of timers running at the same time. is there a way to do long timers that would use less?

maybe a single timer that counts every hour/day ...

and every hour it checks a file to see if in this hour/day there should be a person removed from the list or somthing
 

Snake

Moderator
Moderator
Jul 13, 2014
288
174
28
I guess that the timers stop when server disconnects and probably your server won't be running 5 days without a disconnect so why don't use the date ?

In JavaScript -> Plugin.GetDate();

In C# -> System.DateTime.Today;
 

DreTaX

Probably knows the answer...
Administrator
Jun 29, 2014
4,095
4,815
113
At your house.
github.com
im going to make a plugin that protects the new players structures for e certain amount of time, but that time would be i guess 2-5 days, depending on how the testing go's. but afaik alot of timers would lag the server, and i would implement this in the next wipe. so that would be alot of timers running at the same time. is there a way to do long timers that would use less?

maybe a single timer that counts every hour/day ...

and every hour it checks a file to see if in this hour/day there should be a person removed from the list or somthing
Not really.

You can add a time simply in the datastore / steamid.
After that you can check in hurtevent if the entity's owner has protection in DS, then make the damage 0.

You can simply use a timer that runs every 30mins, and checks if the X amount of time passed, and if it did, you can remove the player from the datastor, or simply give another value to it to identify he already had protection.