rewritten
This commit is contained in:
parent
59bb24e791
commit
a6f7742e86
|
@ -32,173 +32,214 @@
|
||||||
#include "amxmodx.h"
|
#include "amxmodx.h"
|
||||||
#include "CTask.h"
|
#include "CTask.h"
|
||||||
|
|
||||||
|
/*********************** CTask ***********************/
|
||||||
CTaskMngr::CTask::CTask( CPluginMngr::CPlugin* p, int f, int flags,
|
int CTaskMngr::CTask::getTaskId() const
|
||||||
int i, float base, float exec, int parlen ,
|
|
||||||
const cell* par, int r){
|
|
||||||
plugin = p;
|
|
||||||
func = f;
|
|
||||||
id = i;
|
|
||||||
next = 0;
|
|
||||||
prev = 0;
|
|
||||||
param_len = 0;
|
|
||||||
param = 0;
|
|
||||||
base_time = base;
|
|
||||||
exec_time = exec;
|
|
||||||
repeat = (flags & 1) ? r : 0;
|
|
||||||
loop = (flags & 2) ? true : false;
|
|
||||||
afterstart = (flags & 4) ? true : false;
|
|
||||||
beforeend = (flags & 8) ? true : false;
|
|
||||||
|
|
||||||
if ( parlen )
|
|
||||||
{
|
{
|
||||||
param = new cell[ parlen + 1 ];
|
return m_iId;
|
||||||
|
}
|
||||||
|
|
||||||
if ( param ){
|
CPluginMngr::CPlugin *CTaskMngr::CTask::getPlugin() const
|
||||||
param_len = parlen + 1;
|
{
|
||||||
memcpy( param , par , sizeof( cell ) * parlen );
|
return m_pPlugin;
|
||||||
param[ parlen ] = 0;
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::CTask::set(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, int iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat, float fCurrentTime)
|
||||||
|
{
|
||||||
|
m_bFree = false;
|
||||||
|
|
||||||
|
m_pPlugin = pPlugin;
|
||||||
|
m_iFunc = iFunc;
|
||||||
|
m_iId = iId;
|
||||||
|
m_fBase = fBase;
|
||||||
|
|
||||||
|
m_iRepeat = (iFlags & 1) ? iRepeat : 0;
|
||||||
|
m_bLoop = (iFlags & 2) ? true : false;
|
||||||
|
m_bAfterStart = (iFlags & 4) ? true : false;
|
||||||
|
m_bBeforeEnd = (iFlags & 8) ? true : false;
|
||||||
|
|
||||||
|
m_fNextExecTime = fCurrentTime + m_fBase;
|
||||||
|
|
||||||
|
if (iParamsLen)
|
||||||
|
{
|
||||||
|
// also add a cell to the back with the value 0
|
||||||
|
m_iParamLen = iParamsLen + 1;
|
||||||
|
m_pParams = new cell[m_iParamLen];
|
||||||
|
memcpy(m_pParams, pParams, sizeof(cell)*iParamsLen);
|
||||||
|
m_pParams[iParamsLen] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_iParamLen = 0;
|
||||||
|
m_pParams = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::CTask::clear()
|
||||||
|
{
|
||||||
|
m_bFree = true;
|
||||||
|
if (m_pParams)
|
||||||
|
delete [] m_pParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTaskMngr::CTask::isFree() const
|
||||||
|
{
|
||||||
|
return m_bFree;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::CTask::changeBase(float fNewBase)
|
||||||
|
{
|
||||||
|
m_fBase = fNewBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::CTask::resetNextExecTime(float fCurrentTime)
|
||||||
|
{
|
||||||
|
m_fNextExecTime = fCurrentTime + m_fBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::CTask::executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft)
|
||||||
|
{
|
||||||
|
bool execute=false;
|
||||||
|
if (m_bAfterStart)
|
||||||
|
{
|
||||||
|
if (fCurrentTime - fTimeLeft + 1.0f >= m_fBase)
|
||||||
|
execute = true;
|
||||||
|
}
|
||||||
|
else if (m_bBeforeEnd)
|
||||||
|
{
|
||||||
|
if (fTimeLimit != 0.0f && (fTimeLeft + fTimeLimit * 60.0f) - fCurrentTime - 1.0f <= m_fBase)
|
||||||
|
execute = true;
|
||||||
|
}
|
||||||
|
else if (m_fNextExecTime <= fCurrentTime)
|
||||||
|
execute = true;
|
||||||
|
|
||||||
|
if (execute)
|
||||||
|
{
|
||||||
|
if (m_pPlugin->isExecutable(m_iFunc))
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if (m_iParamLen) // call with parameters
|
||||||
|
{
|
||||||
|
cell amx_addr, *phys_addr;
|
||||||
|
if (amx_Allot(m_pPlugin->getAMX(), m_iParamLen, &amx_addr, &phys_addr) != AMX_ERR_NONE)
|
||||||
|
AMXXLOG_Log("[AMXX] Failed to allocate AMX memory (task \"%d\") (plugin \"%s\")", m_iId, m_pPlugin->getName());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copy_amxmemory(phys_addr, m_pParams, m_iParamLen);
|
||||||
|
if ((err = amx_Exec(m_pPlugin->getAMX(), NULL, m_iFunc, 2, amx_addr, m_iId)) != AMX_ERR_NONE)
|
||||||
|
AMXXLOG_Log("[AMXX] Run time error %d on line %ld (task \"%d\") (plugin \"%s\")", err, m_pPlugin->getAMX()->curline, m_iId, m_pPlugin->getName());
|
||||||
|
|
||||||
|
amx_Release(m_pPlugin->getAMX(), amx_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((err = amx_Exec(m_pPlugin->getAMX(), NULL, m_iFunc, 1, m_iId)) != AMX_ERR_NONE)
|
||||||
|
AMXXLOG_Log("[AMXX] Run time error %d on line %ld (task \"%d\") (plugin \"%s\")", err, m_pPlugin->getAMX()->curline, m_iId, m_pPlugin->getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set new exec time OR remove the task if needed
|
||||||
|
if (m_bLoop || (--m_iRepeat > 0))
|
||||||
|
{
|
||||||
|
m_fNextExecTime += m_fBase;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_bFree = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CTaskMngr::CTask* CTaskMngr::getFirstValidTask(CTask* h){
|
CTaskMngr::CTask::CTask()
|
||||||
CTask* a = h;
|
{
|
||||||
while( a ) {
|
m_bFree = true;
|
||||||
if ( a->isRemoved() ) {
|
|
||||||
CTask* b = a->next;
|
|
||||||
unlink( a );
|
|
||||||
delete a;
|
|
||||||
a = b;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if ( a->afterstart ){
|
|
||||||
if ( *m_timer - *m_timeleft + 1 < a->base_time ) {
|
|
||||||
a = a->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( a->beforeend ){
|
|
||||||
if ( *m_timelimit == 0 ){
|
|
||||||
a = a->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( (*m_timeleft + *m_timelimit * 60.0) - *m_timer - 1 >
|
|
||||||
a->base_time ){
|
|
||||||
a = a->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( a->exec_time > *m_timer ) {
|
|
||||||
a = a->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CTaskMngr::CTask* CTaskMngr::getNextTask(CTask* a) {
|
CTaskMngr::CTask::~CTask()
|
||||||
if ( a->isRemoved() )
|
{
|
||||||
return a->next;
|
|
||||||
if ( a->loop || a->isToReply() ){
|
|
||||||
a->exec_time = *m_timer + a->base_time;
|
|
||||||
return a->next;
|
|
||||||
}
|
|
||||||
a->setToRemove();
|
|
||||||
return a->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CTaskMngr::CTaskMngr() {
|
|
||||||
head = 0;
|
|
||||||
tail = 0;
|
|
||||||
m_timer = 0;
|
|
||||||
m_timelimit = 0;
|
|
||||||
m_timeleft = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CTaskMngr::~CTaskMngr() {
|
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTaskMngr::clear() {
|
/*********************** CTaskMngr ***********************/
|
||||||
while ( head ) {
|
CTaskMngr::CTaskMngr()
|
||||||
tail = head->next;
|
|
||||||
delete head;
|
|
||||||
head = tail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTaskMngr::registerTimers( float* timer , float* timelimit, float* timeleft ) {
|
|
||||||
m_timer = timer;
|
|
||||||
m_timelimit = timelimit;
|
|
||||||
m_timeleft = timeleft;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTaskMngr::registerTask( CPluginMngr::CPlugin* plugin, int func,
|
|
||||||
int flags, int i, float base, float exec,
|
|
||||||
int parlen , const cell* par, int repeat ){
|
|
||||||
|
|
||||||
CTask* a = new CTask(plugin,func,flags,i,base,exec,parlen,par,repeat );
|
|
||||||
|
|
||||||
if ( a == 0 ) return;
|
|
||||||
|
|
||||||
if ( tail )
|
|
||||||
{
|
{
|
||||||
tail->next = a;
|
m_pTmr_CurrentTime = NULL;
|
||||||
a->prev = tail;
|
m_pTmr_TimeLimit = NULL;
|
||||||
tail = a;
|
m_pTmr_TimeLeft = NULL;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
head = a;
|
void CTaskMngr::registerTimers(float *pCurrentTime, float *pTimeLimit, float *pTimeLeft)
|
||||||
tail = a;
|
{
|
||||||
|
m_pTmr_CurrentTime = pCurrentTime;
|
||||||
|
m_pTmr_TimeLimit = pTimeLimit;
|
||||||
|
m_pTmr_TimeLeft = pTimeLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::registerTask(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, int iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat)
|
||||||
|
{
|
||||||
|
// first, search for free tasks
|
||||||
|
TaskListIter iter = m_Tasks.find(CTaskDescriptor(0, NULL, true));
|
||||||
|
if (iter)
|
||||||
|
{
|
||||||
|
// found: reuse it
|
||||||
|
iter->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// not found: make a new one
|
||||||
|
CTask *pTmp = new CTask;
|
||||||
|
if (!pTmp)
|
||||||
|
return;
|
||||||
|
pTmp->set(pPlugin, iFunc, iFlags, iId, fBase, iParamsLen, pParams, iRepeat, *m_pTmr_CurrentTime);
|
||||||
|
m_Tasks.put(pTmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CTaskMngr::CTask* CTaskMngr::findTask( int id , AMX* amx )
|
int CTaskMngr::removeTasks(int iId, AMX *pAmx)
|
||||||
{
|
{
|
||||||
for (CTask* a = head; a ; a = a->next)
|
CTaskDescriptor descriptor(iId, pAmx);
|
||||||
{
|
TaskListIter iter = m_Tasks.find(descriptor);
|
||||||
if ( !a->isRemoved() && (a->getTaskId() == id) && (!amx ||
|
|
||||||
(a->getPlugin()->getAMX() == amx)) )
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CTaskMngr::changeTask(int id, AMX *amx, float flNewTime)
|
|
||||||
{
|
|
||||||
CTask *a;
|
|
||||||
int i=0;
|
int i=0;
|
||||||
|
while (iter)
|
||||||
while ( (a=findTask(id, amx)) != 0)
|
|
||||||
{
|
{
|
||||||
a->changeTime(flNewTime > 0.1 ? flNewTime : 0.1);
|
iter->clear();
|
||||||
++i;
|
++i;
|
||||||
|
iter = m_Tasks.find(++iter, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTaskMngr::unlink(CTask* a){
|
int CTaskMngr::changeTasks(int iId, AMX *pAmx, float fNewBase)
|
||||||
if ( a->prev ) a->prev->next = a->next;
|
|
||||||
else head = a->next;
|
|
||||||
if ( a->next ) a->next->prev = a->prev;
|
|
||||||
else tail = a->prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CTaskMngr::removeTasks( int id , AMX* amx )
|
|
||||||
{
|
{
|
||||||
CTask* a;
|
CTaskDescriptor descriptor(iId, pAmx);
|
||||||
|
TaskListIter iter = m_Tasks.find(descriptor);
|
||||||
int i=0;
|
int i=0;
|
||||||
|
while (iter)
|
||||||
while ( (a = findTask(id, amx )) != 0 ) {
|
{
|
||||||
a->setToRemove();
|
iter->changeBase(fNewBase);
|
||||||
|
iter->resetNextExecTime(*m_pTmr_CurrentTime);
|
||||||
++i;
|
++i;
|
||||||
|
iter = m_Tasks.find(++iter, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CTaskMngr::taskExists(int iId, AMX *pAmx)
|
||||||
|
{
|
||||||
|
return m_Tasks.find(CTaskDescriptor(iId, pAmx));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::startFrame()
|
||||||
|
{
|
||||||
|
for (TaskListIter iter = m_Tasks.begin(); iter; ++iter)
|
||||||
|
{
|
||||||
|
if (iter->isFree())
|
||||||
|
continue;
|
||||||
|
iter->executeIfRequired(*m_pTmr_CurrentTime, *m_pTmr_TimeLimit, *m_pTmr_TimeLeft);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTaskMngr::clear()
|
||||||
|
{
|
||||||
|
m_Tasks.clear();
|
||||||
|
}
|
147
amxmodx/CTask.h
147
amxmodx/CTask.h
|
@ -32,97 +32,88 @@
|
||||||
#ifndef CTASK_H
|
#ifndef CTASK_H
|
||||||
#define CTASK_H
|
#define CTASK_H
|
||||||
|
|
||||||
// *****************************************************
|
|
||||||
// class CTaskMngr
|
|
||||||
// *****************************************************
|
|
||||||
|
|
||||||
class CTaskMngr
|
class CTaskMngr
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
|
/*** class CTask ***/
|
||||||
class iterator;
|
|
||||||
|
|
||||||
class CTask
|
class CTask
|
||||||
{
|
{
|
||||||
|
// task settings
|
||||||
|
CPluginMngr::CPlugin *m_pPlugin;
|
||||||
|
int m_iId;
|
||||||
|
int m_iFunc;
|
||||||
|
int m_iRepeat;
|
||||||
|
bool m_bLoop;
|
||||||
|
bool m_bAfterStart;
|
||||||
|
bool m_bBeforeEnd;
|
||||||
|
float m_fBase; // for normal tasks, stores the interval, for the others, stores the amount of time before start / after end
|
||||||
|
int m_iParamLen;
|
||||||
|
cell *m_pParams;
|
||||||
|
bool m_bFree;
|
||||||
|
|
||||||
friend class iterator;
|
// execution
|
||||||
friend class CTaskMngr;
|
float m_fNextExecTime;
|
||||||
|
|
||||||
CPluginMngr::CPlugin* plugin;
|
|
||||||
int id;
|
|
||||||
int func;
|
|
||||||
int repeat;
|
|
||||||
bool loop;
|
|
||||||
bool afterstart;
|
|
||||||
bool beforeend;
|
|
||||||
float base_time;
|
|
||||||
float exec_time;
|
|
||||||
int param_len;
|
|
||||||
cell* param;
|
|
||||||
CTask* next;
|
|
||||||
CTask* prev;
|
|
||||||
inline void setToRemove() { exec_time = -1.0f; }
|
|
||||||
inline void changeTime(float flNewTime) { exec_time = flNewTime; }
|
|
||||||
inline bool isToReply() { return (repeat-- > 0); }
|
|
||||||
inline bool isRemoved() { return (exec_time == -1.0f); }
|
|
||||||
CTask( CPluginMngr::CPlugin* p, int f, int flags, int i,
|
|
||||||
float base, float exec, int parlen , const cell* par, int r );
|
|
||||||
~CTask() { if ( param_len ) delete[] param; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
inline void set(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, int iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat, float fCurrentTime);
|
||||||
|
inline void clear();
|
||||||
|
inline bool isFree() const;
|
||||||
|
|
||||||
inline int getParamLen() { return param_len; }
|
inline CPluginMngr::CPlugin *getPlugin() const;
|
||||||
inline int getTaskId() { return id; }
|
inline int getTaskId() const;
|
||||||
inline int getFunction() { return func; }
|
|
||||||
cell* getParam() { return param; }
|
inline void executeIfRequired(float fCurrentTime, float fTimeLimit, float fTimeLeft); // also removes the task if needed
|
||||||
CPluginMngr::CPlugin* getPlugin() { return plugin; }
|
|
||||||
|
inline void changeBase(float fNewBase);
|
||||||
|
inline void resetNextExecTime(float fCurrentTime);
|
||||||
|
|
||||||
|
inline bool shouldRepeat();
|
||||||
|
|
||||||
|
CTask();
|
||||||
|
~CTask();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CTaskDescriptor
|
||||||
|
{
|
||||||
private:
|
|
||||||
|
|
||||||
friend class iterator;
|
|
||||||
CTask *head;
|
|
||||||
CTask *tail;
|
|
||||||
float* m_timer;
|
|
||||||
float* m_timelimit;
|
|
||||||
float* m_timeleft;
|
|
||||||
CTask* getFirstValidTask(CTask* a);
|
|
||||||
CTask* getNextTask(CTask* a);
|
|
||||||
CTask* findTask( int id , AMX* amx );
|
|
||||||
void unlink(CTask* a);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int m_iId;
|
||||||
|
AMX *m_pAmx;
|
||||||
|
bool m_bFree;
|
||||||
|
|
||||||
CTaskMngr();
|
CTaskDescriptor(int iId, AMX *pAmx, bool bFree = false)
|
||||||
~CTaskMngr();
|
{
|
||||||
|
m_iId = iId;
|
||||||
// Interface
|
m_pAmx = pAmx;
|
||||||
|
m_bFree = bFree;
|
||||||
|
|
||||||
void registerTimers( float* timer , float* timelimit, float* timeleft );
|
|
||||||
void registerTask( CPluginMngr::CPlugin* plugin, int func, int flags, int i, float base, float exec, int parlen , const cell* par, int repeat );
|
|
||||||
inline int taskExists( int id ,AMX* amx) { return findTask(id,amx ) ? 1 : 0; }
|
|
||||||
int changeTask(int id, AMX *amx, float flNewTime);
|
|
||||||
int removeTasks( int id , AMX* amx );
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
class iterator {
|
|
||||||
CTask* a;
|
|
||||||
CTaskMngr* b;
|
|
||||||
public:
|
|
||||||
iterator(CTask*aa,CTaskMngr* bb) : a(aa), b(bb) {}
|
|
||||||
iterator& operator++() {
|
|
||||||
a = b->getNextTask( a );
|
|
||||||
a = b->getFirstValidTask( a );
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
CTask& operator*() { return *a; }
|
|
||||||
operator bool ( ) const { return a ? true : false; }
|
|
||||||
};
|
|
||||||
inline iterator begin() { return iterator(getFirstValidTask(head),this); }
|
|
||||||
|
|
||||||
|
friend bool operator == (const CTask &left, const CTaskDescriptor &right)
|
||||||
|
{
|
||||||
|
if (right.m_bFree)
|
||||||
|
return left.isFree();
|
||||||
|
|
||||||
|
return !left.isFree() &&
|
||||||
|
(right.m_pAmx ? left.getPlugin()->getAMX() == right.m_pAmx : true) &&
|
||||||
|
left.getTaskId() == right.m_iId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** CTaskMngr priv members ***/
|
||||||
|
typedef CList<CTask, CTaskDescriptor> TaskList;
|
||||||
|
typedef TaskList::iterator TaskListIter;
|
||||||
|
TaskList m_Tasks;
|
||||||
|
float *m_pTmr_CurrentTime;
|
||||||
|
float *m_pTmr_TimeLimit;
|
||||||
|
float *m_pTmr_TimeLeft;
|
||||||
|
public:
|
||||||
|
CTaskMngr();
|
||||||
|
|
||||||
|
void registerTimers(float *pCurrentTime, float *pTimeLimit, float *pTimeLeft); // The timers will always point to the right value
|
||||||
|
void registerTask(CPluginMngr::CPlugin *pPlugin, int iFunc, int iFlags, int iId, float fBase, int iParamsLen, const cell *pParams, int iRepeat);
|
||||||
|
int removeTasks(int iId, AMX *pAmx); // remove all tasks that match the id and amx
|
||||||
|
int changeTasks(int iId, AMX *pAmx, float fNewBase); // change all tasks that match the id and amx
|
||||||
|
bool taskExists(int iId, AMX *pAmx);
|
||||||
|
void startFrame();
|
||||||
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user