AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Module Coding (https://forums.alliedmods.net/forumdisplay.php?f=9)
-   -   Make tasks inside ServerFrame loop (https://forums.alliedmods.net/showthread.php?t=319648)

^SmileY 11-12-2019 17:04

Make tasks inside ServerFrame loop
 
Hi folks, it is sane to make a class to create 'Tasks' in a metamod plugin using this:

.cpp
Code:

#include "Task.h"

cTask gTask;

cTask::cTask()
{
        this->m_Data.clear();
}

void cTask::SetTask(int iIndex,float fTime,bool bLoop)
{
        if(!this->TaskExists(iIndex))
        {
                pTaskInfo pInfo =
                {
                        iIndex,
                        fTime,
                        gpGlobals->time + fTime,
                        bLoop
                };

                this->m_Data.insert(std::pair<int, pTaskInfo>(iIndex, pInfo));
        }
}

bool cTask::TaskExists(int iIndex)
{
        return (this->m_Data.find(iIndex) != this->m_Data.end());
}

void cTask::Run() // StartFrame_Post
{
        for(auto it = this->m_Data.begin();it != this->m_Data.end();it++)
        {
                if(gpGlobals->time >= it->second.fEndTime)
                {
                        ////////////////////////////
                        // Run Function an function
                        ////////////////////////////

                        if(it->second.bLoop)
                        {
                                it->second.fEndTime += it->second.fTime;
                        }
                        else
                        {
                                it = this->m_Data.erase(it);
                        }
                }
                else
                {
                        it++;
                }
        }
}

.h
Code:

#pragma once

typedef struct
{
        int                iIndex;
        float        fTime;
        float        fEndTime;
        bool        bLoop;
} pTaskInfo, *lpTaskInfo;

class cTask
{
public:
        cTask();

        void SetTask(int iIndex,float fTime,bool bLoop);
        bool TaskExists(int iIndex);

        void Run();

private:
        std::map<int, pTaskInfo> m_Data;
};

extern cTask gTask;

Ps.
I'm using StartFrame_Post to run the ::Run of tasks.
If is a sane thing, how i pass a function as parameter to SetTask or something like else?

TheDS1337 11-13-2019 14:58

Re: Make tasks inside ServerFrame loop
 
What is not sane about it? SM (and I think AMXx too) both use OnGameFrame to check for timers (tasks). and then execute them one by one depending on plugin order. this if more than one plugin are supposed to be executed at the same time.

^SmileY 11-13-2019 16:54

Re: Make tasks inside ServerFrame loop
 
My doubt is just that, if is safe to check time inside Serverframe to do tasks.

I have created a small class, now is:

Code:

#include "Task.h"
#include "amxxmodule.h"

cTask gTask;

cTask::cTask()
{
        this->m_Data.clear();
}

void cTask::SetTask(int Index,float Time,bool Loop,void *FunctionCallback,int Param)
{
        if(!this->TaskExists(Index))
        {
                pTaskInfo Info =
                {
                        Index,
                        Time,
                        gpGlobals->time + Time,
                        Loop,
                        FunctionCallback,
                        Param
                };

                this->m_Data.insert(std::pair<int, pTaskInfo>(Index, Info));
        }
}

bool cTask::TaskExists(int Index)
{
        return (this->m_Data.find(Index) != this->m_Data.end());
}

void cTask::RemoveTask(int Index)
{
        auto it = this->m_Data.find(Index);

        if(it != this->m_Data.end())
        {
                this->m_Data.erase(it);
        }
}

void cTask::Run() // StartFrame_Post
{
        for(auto it = this->m_Data.begin();it != this->m_Data.end();it++)
        {
                if(gpGlobals->time >= it->second.EndTime)
                {
                        ((void(*)(int))it->second.FunctionCallback)(it->second.Param);

                        if(it->second.Loop)
                        {
                                it->second.EndTime += it->second.Time;
                        }
                        else
                        {
                                it = this->m_Data.erase(it);
                        }
                }
                else
                {
                        it++;
                }
        }
}

.h
Code:

#pragma once

#include <map>

typedef struct
{
        int                Index;
        float        Time;
        float        EndTime;
        bool        Loop;
        void        *FunctionCallback;
        int                Param;
} pTaskInfo, *lpTaskInfo;

class cTask
{
public:
        cTask();

        void SetTask(int Index,float Time,bool Loop,void *FunctionCallback,int Param);
        bool TaskExists(int Index);
        void RemoveTask(int Index);

        void Run();

private:
        std::map<int, pTaskInfo> m_Data;
};

extern cTask gTask;

I hope that is correct, since i never coded on amxx module before.

Thanks

TheDS1337 11-14-2019 01:47

Re: Make tasks inside ServerFrame loop
 
If the looping is what you are worried about, then it is totally safe, as both SM and AMXx does it that one.

Also,
Code:

void cTask::Run() // StartFrame_Post
{
        for(auto it = this->m_Data.begin();it != this->m_Data.end();it++)
        {
                if(gpGlobals->time >= it->second.EndTime)
                {
                        ((void(*)(int))it->second.FunctionCallback)(it->second.Param);

                        if(it->second.Loop)
                        {
                                it->second.EndTime += it->second.Time;
                        }
                        else
                        {
                                it = this->m_Data.erase(it);
                        }
                }
                else
                {
                        it++;
                }
        }
}

I don't uderstand why are you incrementing it here if the task time is yet to come? in some cases it may even increment it twice because the loop does it already:

Code:

void cTask::Run() // StartFrame_Post
{
        for(auto it = this->m_Data.begin();it != this->m_Data.end();it++)
        {
                if(gpGlobals->time >= it->second.EndTime)
                {
                        ((void(*)(int))it->second.FunctionCallback)(it->second.Param);

                        if(it->second.Loop)
                        {
                                it->second.EndTime += it->second.Time;
                        }
                        else
                        {
                                it = this->m_Data.erase(it);
                        }
                }               
        }
}

This should suffice.

^SmileY 11-14-2019 07:14

Re: Make tasks inside ServerFrame loop
 
My bad, i forgot to remove it when paste here.

Other small doubt when coding for modules or metamod, is how to check if player is connected or entity is not null:

PHP Code:

void ClientPutInServer_Post(edict_t *pEdict

Thanks for help.


All times are GMT -4. The time now is 12:37.

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