mirror of
https://github.com/alliedmodders/amxmodx.git
synced 2024-12-25 06:15:37 +03:00
rewritten
This commit is contained in:
parent
64bf40aaa3
commit
06da72658b
@ -32,49 +32,221 @@
|
|||||||
#include <extdll.h>
|
#include <extdll.h>
|
||||||
#include <meta_api.h>
|
#include <meta_api.h>
|
||||||
#include "amxmodx.h"
|
#include "amxmodx.h"
|
||||||
#include "CForward.h"
|
|
||||||
|
|
||||||
void CForwardMngr::registerForward( CPluginMngr::CPlugin* p, int func , int type ){
|
|
||||||
|
CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes)
|
||||||
CForward** a = &head[ type ];
|
{
|
||||||
while(*a) a = &(*a)->next;
|
m_FuncName = name;
|
||||||
*a = new CForward( p , func );
|
m_ExecType = et;
|
||||||
|
m_NumParams = numParams;
|
||||||
|
memcpy((void *)m_ParamTypes, paramTypes, numParams * sizeof(ForwardParam));
|
||||||
|
// find funcs
|
||||||
|
int func;
|
||||||
|
AMXForward *tmp = NULL;
|
||||||
|
for (CPluginMngr::iterator iter = g_plugins.begin(); iter; ++iter)
|
||||||
|
{
|
||||||
|
if (amx_FindPublic((*iter).getAMX(), name, &func) == AMX_ERR_NONE)
|
||||||
|
{
|
||||||
|
tmp = new AMXForward;
|
||||||
|
tmp->pPlugin = &(*iter);
|
||||||
|
tmp->func = func;
|
||||||
|
m_Funcs.put(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForwardMngr::clearForwards( CForward** a ){
|
int CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||||
while( *a ) {
|
{
|
||||||
CForward* b = (*a)->next;
|
cell realParams[FORWARD_MAX_PARAMS];
|
||||||
delete *a;
|
cell *physAddrs[FORWARD_MAX_PARAMS];
|
||||||
*a = b;
|
|
||||||
|
const STRINGEX_MAXLENGTH = 128;
|
||||||
|
|
||||||
|
int globRetVal = 0;
|
||||||
|
|
||||||
|
for (CList<AMXForward>::iterator iter = m_Funcs.begin(); iter; ++iter)
|
||||||
|
{
|
||||||
|
if ((*iter).pPlugin->isExecutable((*iter).func))
|
||||||
|
{
|
||||||
|
// handle strings & arrays
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < m_NumParams; ++i)
|
||||||
|
{
|
||||||
|
if (m_ParamTypes[i] == FP_STRING || m_ParamTypes[i] == FP_STRINGEX)
|
||||||
|
{
|
||||||
|
cell *tmp;
|
||||||
|
amx_Allot((*iter).pPlugin->getAMX(),
|
||||||
|
(m_ParamTypes[i] == FP_STRING) ? strlen(reinterpret_cast<const char*>(params[i]))+1 : STRINGEX_MAXLENGTH,
|
||||||
|
&realParams[i], &tmp);
|
||||||
|
amx_SetString(tmp, (const char *)(params[i]), 0, 0);
|
||||||
|
physAddrs[i] = tmp;
|
||||||
|
}
|
||||||
|
else if (m_ParamTypes[i] == FP_ARRAY)
|
||||||
|
{
|
||||||
|
cell *tmp;
|
||||||
|
amx_Allot((*iter).pPlugin->getAMX(), preparedArrays[params[i]].size,
|
||||||
|
&realParams[i], &tmp);
|
||||||
|
physAddrs[i] = tmp;
|
||||||
|
if (preparedArrays[params[i]].type == Type_Cell)
|
||||||
|
{
|
||||||
|
memcpy(tmp, preparedArrays[params[i]].ptr, preparedArrays[params[i]].size * sizeof(cell));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *data = (char*)preparedArrays[params[i]].ptr;
|
||||||
|
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
|
||||||
|
*tmp++ = (static_cast<cell>(*data++)) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
realParams[i] = params[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// exec
|
||||||
|
cell retVal;
|
||||||
|
amx_Execv((*iter).pPlugin->getAMX(), &retVal, (*iter).func, m_NumParams, realParams);
|
||||||
|
// cleanup strings & arrays
|
||||||
|
for (i = 0; i < m_NumParams; ++i)
|
||||||
|
{
|
||||||
|
if (m_ParamTypes[i] == FP_STRING)
|
||||||
|
{
|
||||||
|
amx_Release((*iter).pPlugin->getAMX(), realParams[i]);
|
||||||
|
}
|
||||||
|
else if (m_ParamTypes[i] == FP_STRINGEX)
|
||||||
|
{
|
||||||
|
// copy back
|
||||||
|
amx_GetString(reinterpret_cast<char*>(params[i]), physAddrs[i], 0);
|
||||||
|
amx_Release((*iter).pPlugin->getAMX(), realParams[i]);
|
||||||
|
}
|
||||||
|
else if (m_ParamTypes[i] == FP_ARRAY)
|
||||||
|
{
|
||||||
|
// copy back
|
||||||
|
cell *tmp = physAddrs[i];
|
||||||
|
if (preparedArrays[params[i]].type == Type_Cell)
|
||||||
|
{
|
||||||
|
memcpy(preparedArrays[params[i]].ptr, tmp, preparedArrays[params[i]].size * sizeof(cell));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *data = (char*)preparedArrays[params[i]].ptr;
|
||||||
|
for (unsigned int j = 0; j < preparedArrays[params[i]].size; ++j)
|
||||||
|
*data++ = static_cast<char>(*tmp++ & 0xFF);
|
||||||
|
}
|
||||||
|
amx_Release((*iter).pPlugin->getAMX(), realParams[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decide what to do (based on exectype and retval)
|
||||||
|
switch (m_ExecType)
|
||||||
|
{
|
||||||
|
case ET_IGNORE:
|
||||||
|
break;
|
||||||
|
case ET_STOP:
|
||||||
|
if (retVal > 0)
|
||||||
|
return retVal;
|
||||||
|
case ET_STOP2:
|
||||||
|
if (retVal == 1)
|
||||||
|
return 1;
|
||||||
|
else if (retVal > globRetVal)
|
||||||
|
globRetVal = retVal;
|
||||||
|
break;
|
||||||
|
case ET_CONTINUE:
|
||||||
|
if (retVal > globRetVal)
|
||||||
|
globRetVal = retVal;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return globRetVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CForwardMngr::registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam * paramTypes)
|
||||||
|
{
|
||||||
|
int retVal = m_Forwards.size();
|
||||||
|
m_Forwards.push_back(new CForward(funcName, et, numParams, paramTypes));
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CForwardMngr::isIdValid(int id) const
|
||||||
|
{
|
||||||
|
return (id >= 0) && (static_cast<size_t>(id) < m_Forwards.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int CForwardMngr::executeForwards(int id, cell *params)
|
||||||
|
{
|
||||||
|
int retVal = m_Forwards[id]->execute(params, m_TmpArrays);
|
||||||
|
m_TmpArraysNum = 0;
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CForwardMngr::getParamsNum(int id) const
|
||||||
|
{
|
||||||
|
return m_Forwards[id]->getParamsNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForwardMngr::clear()
|
void CForwardMngr::clear()
|
||||||
{
|
{
|
||||||
for ( int a = 0; a < FORWARD_NUM; ++a )
|
for (ForwardVec::iterator iter = m_Forwards.begin(); iter != m_Forwards.end(); ++iter)
|
||||||
clearForwards( &head[ a ] );
|
{
|
||||||
|
delete (*iter);
|
||||||
|
}
|
||||||
|
m_Forwards.clear();
|
||||||
|
m_TmpArraysNum = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CForwardMngr::executeForwards( int type , int num , int player ) {
|
int registerForward(const char *funcName, ForwardExecType et, ...)
|
||||||
|
{
|
||||||
cell ret = 0;
|
int curParam = 0;
|
||||||
int err;
|
va_list argptr;
|
||||||
CForward* a = head[ type ];
|
va_start(argptr, et);
|
||||||
|
ForwardParam params[FORWARD_MAX_PARAMS];
|
||||||
while ( a )
|
ForwardParam tmp;
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
if ( a->getPlugin()->isExecutable( a->getFunction() ) )
|
if (curParam == FORWARD_MAX_PARAMS)
|
||||||
{
|
break;
|
||||||
|
tmp = va_arg(argptr, ForwardParam);
|
||||||
if ((err = amx_Exec(a->getPlugin()->getAMX(), &ret, a->getFunction() , num, player)) != AMX_ERR_NONE)
|
if (tmp == FP_DONE)
|
||||||
AMXXLOG_Log("[AMXX] Run time error %d on line %ld (plugin \"%s\")", err,a->getPlugin()->getAMX()->curline,a->getPlugin()->getName());
|
break;
|
||||||
|
params[curParam] = tmp;
|
||||||
if ( ret )
|
++curParam;
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
a = a->next;
|
|
||||||
}
|
}
|
||||||
|
va_end(argptr);
|
||||||
|
return g_forwards.registerForward(funcName, et, curParam, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
int executeForwards(int id, ...)
|
||||||
|
{
|
||||||
|
if (!g_forwards.isIdValid(id))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cell params[FORWARD_MAX_PARAMS];
|
||||||
|
int paramsNum = g_forwards.getParamsNum(id);
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, id);
|
||||||
|
for (int i = 0; i < paramsNum && i < FORWARD_MAX_PARAMS; ++i)
|
||||||
|
{
|
||||||
|
params[i] = va_arg(argptr, cell);
|
||||||
|
}
|
||||||
|
va_end(argptr);
|
||||||
|
return g_forwards.executeForwards(id, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell CForwardMngr::prepareArray(void *ptr, unsigned int size, ForwardArrayElemType type)
|
||||||
|
{
|
||||||
|
m_TmpArrays[m_TmpArraysNum].ptr = ptr;
|
||||||
|
m_TmpArrays[m_TmpArraysNum].size = size;
|
||||||
|
m_TmpArrays[m_TmpArraysNum].type = type;
|
||||||
|
return m_TmpArraysNum++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell prepareCellArray(cell *ptr, unsigned int size)
|
||||||
|
{
|
||||||
|
return g_forwards.prepareArray((void*)ptr, size, Type_Cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell prepareCharArray(char *ptr, unsigned int size)
|
||||||
|
{
|
||||||
|
return g_forwards.prepareArray((void*)ptr, size, Type_Char);
|
||||||
}
|
}
|
@ -36,80 +36,94 @@
|
|||||||
// class CmdMngr
|
// class CmdMngr
|
||||||
// *****************************************************
|
// *****************************************************
|
||||||
|
|
||||||
#define FORWARD_NUM 12
|
const int FORWARD_MAX_PARAMS = 16;
|
||||||
|
|
||||||
enum {
|
enum ForwardExecType
|
||||||
FF_ClientCommand,
|
{
|
||||||
FF_ClientConnect,
|
ET_IGNORE = 0, // Ignore return vaue
|
||||||
FF_ClientDisconnect,
|
ET_STOP, // Stop on PLUGIN_HANDLED
|
||||||
FF_ClientInfoChanged,
|
ET_STOP2, // Stop on PLUGIN_HANDLED, continue on other values, return biggest return value
|
||||||
FF_ClientPutInServer,
|
ET_CONTINUE, // Continue; return biggest return value
|
||||||
FF_PluginInit,
|
|
||||||
FF_PluginCfg,
|
|
||||||
FF_PluginPrecache,
|
|
||||||
FF_PluginLog,
|
|
||||||
FF_PluginEnd,
|
|
||||||
FF_InconsistentFile,
|
|
||||||
FF_ClientAuthorized,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CForwardMngr
|
enum ForwardParam
|
||||||
{
|
{
|
||||||
public:
|
FP_DONE = -1, // specify this as the last argument
|
||||||
|
// only tells the function that there are no more arguments
|
||||||
class iterator;
|
FP_CELL, // normal cell
|
||||||
|
FP_FLOAT, // float; used as normal cell though
|
||||||
|
FP_STRING, // string
|
||||||
|
FP_STRINGEX, // string; will be updated to the last function's value
|
||||||
|
FP_ARRAY, // array; use the return value of prepareArray.
|
||||||
|
};
|
||||||
|
|
||||||
class CForward
|
enum ForwardArrayElemType
|
||||||
|
{
|
||||||
|
Type_Cell = 0,
|
||||||
|
Type_Char
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ForwardPreparedArray
|
||||||
|
{
|
||||||
|
|
||||||
|
void *ptr;
|
||||||
|
ForwardArrayElemType type;
|
||||||
|
unsigned int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CForward
|
||||||
|
{
|
||||||
|
const char *m_FuncName;
|
||||||
|
ForwardExecType m_ExecType;
|
||||||
|
int m_NumParams;
|
||||||
|
struct AMXForward
|
||||||
{
|
{
|
||||||
|
CPluginMngr::CPlugin *pPlugin;
|
||||||
friend class iterator;
|
int func;
|
||||||
friend class CForwardMngr;
|
|
||||||
|
|
||||||
CPluginMngr::CPlugin* plugin;
|
|
||||||
int function;
|
|
||||||
CForward* next;
|
|
||||||
CForward( CPluginMngr::CPlugin* p, int func ) : plugin(p) , function(func) {next=0;}
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline CPluginMngr::CPlugin* getPlugin() { return plugin; }
|
|
||||||
inline int getFunction() { return function; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
typedef CList<AMXForward> AMXForwardList;
|
||||||
|
AMXForwardList m_Funcs;
|
||||||
|
ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS];
|
||||||
private:
|
|
||||||
CForward *head[ FORWARD_NUM ];
|
|
||||||
void clearForwards( CForward** a );
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CForwardMngr() {memset( head, 0, sizeof(head));}
|
CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam * paramTypes);
|
||||||
~CForwardMngr() { clear(); }
|
CForward()
|
||||||
|
{ } // leaves everything unitialized
|
||||||
|
int execute(cell *params, ForwardPreparedArray *preparedArrays);
|
||||||
|
int getParamsNum() const
|
||||||
|
{
|
||||||
|
return m_NumParams;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CForwardMngr
|
||||||
|
{
|
||||||
|
typedef CVector<CForward*> ForwardVec;
|
||||||
|
ForwardVec m_Forwards;
|
||||||
|
ForwardPreparedArray m_TmpArrays[FORWARD_MAX_PARAMS]; // used by prepareArray
|
||||||
|
int m_TmpArraysNum;
|
||||||
|
public:
|
||||||
|
|
||||||
|
CForwardMngr()
|
||||||
|
{ m_TmpArraysNum = 0; }
|
||||||
|
~CForwardMngr()
|
||||||
|
{ }
|
||||||
|
|
||||||
// Interface
|
// Interface
|
||||||
|
int registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam *paramTypes);
|
||||||
void registerForward( CPluginMngr::CPlugin* p, int func , int type );
|
int executeForwards(int id, cell *params);
|
||||||
void executeForwards( int type , int num = 0, int player = 0 );
|
void clear(); // delete all forwards
|
||||||
void clear();
|
bool isIdValid(int id) const;
|
||||||
|
int getParamsNum(int id) const;
|
||||||
|
cell prepareArray(void *ptr, unsigned int size, ForwardArrayElemType type);
|
||||||
class iterator {
|
|
||||||
CForward *a;
|
|
||||||
public:
|
|
||||||
iterator(CForward*aa) : a(aa) {}
|
|
||||||
iterator& operator++() { a = a->next; return *this; }
|
|
||||||
bool operator==(const iterator& b) const { return a == b.a; }
|
|
||||||
bool operator!=(const iterator& b) const { return !operator==(b); }
|
|
||||||
operator bool () const { return a ? true : false; }
|
|
||||||
CForward& operator*() { return *a; }
|
|
||||||
};
|
|
||||||
inline iterator begin( int type ) const { return iterator(head[(int)type]); }
|
|
||||||
inline iterator end() const { return iterator(0); }
|
|
||||||
inline bool forwardsExist( int type ) {return head[(int)type]?true:false;}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// register forward
|
||||||
|
int registerForward(const char *funcName, ForwardExecType et, ...);
|
||||||
|
// execute forwards
|
||||||
|
int executeForwards(int id, ...);
|
||||||
|
// prepare array
|
||||||
|
cell prepareCellArray(cell *ptr, unsigned int size);
|
||||||
|
cell prepareCharArray(char *ptr, unsigned int size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user