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 <meta_api.h>
|
||||
#include "amxmodx.h"
|
||||
#include "CForward.h"
|
||||
|
||||
void CForwardMngr::registerForward( CPluginMngr::CPlugin* p, int func , int type ){
|
||||
|
||||
CForward** a = &head[ type ];
|
||||
while(*a) a = &(*a)->next;
|
||||
*a = new CForward( p , func );
|
||||
|
||||
CForward::CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam *paramTypes)
|
||||
{
|
||||
m_FuncName = name;
|
||||
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 ){
|
||||
while( *a ) {
|
||||
CForward* b = (*a)->next;
|
||||
delete *a;
|
||||
*a = b;
|
||||
int CForward::execute(cell *params, ForwardPreparedArray *preparedArrays)
|
||||
{
|
||||
cell realParams[FORWARD_MAX_PARAMS];
|
||||
cell *physAddrs[FORWARD_MAX_PARAMS];
|
||||
|
||||
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()
|
||||
{
|
||||
for ( int a = 0; a < FORWARD_NUM; ++a )
|
||||
clearForwards( &head[ a ] );
|
||||
}
|
||||
|
||||
void CForwardMngr::executeForwards( int type , int num , int player ) {
|
||||
|
||||
cell ret = 0;
|
||||
int err;
|
||||
CForward* a = head[ type ];
|
||||
|
||||
while ( a )
|
||||
for (ForwardVec::iterator iter = m_Forwards.begin(); iter != m_Forwards.end(); ++iter)
|
||||
{
|
||||
if ( a->getPlugin()->isExecutable( a->getFunction() ) )
|
||||
{
|
||||
|
||||
if ((err = amx_Exec(a->getPlugin()->getAMX(), &ret, a->getFunction() , num, player)) != AMX_ERR_NONE)
|
||||
AMXXLOG_Log("[AMXX] Run time error %d on line %ld (plugin \"%s\")", err,a->getPlugin()->getAMX()->curline,a->getPlugin()->getName());
|
||||
|
||||
if ( ret )
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
a = a->next;
|
||||
delete (*iter);
|
||||
}
|
||||
m_Forwards.clear();
|
||||
m_TmpArraysNum = 0;
|
||||
}
|
||||
|
||||
int registerForward(const char *funcName, ForwardExecType et, ...)
|
||||
{
|
||||
int curParam = 0;
|
||||
va_list argptr;
|
||||
va_start(argptr, et);
|
||||
ForwardParam params[FORWARD_MAX_PARAMS];
|
||||
ForwardParam tmp;
|
||||
while (true)
|
||||
{
|
||||
if (curParam == FORWARD_MAX_PARAMS)
|
||||
break;
|
||||
tmp = va_arg(argptr, ForwardParam);
|
||||
if (tmp == FP_DONE)
|
||||
break;
|
||||
params[curParam] = tmp;
|
||||
++curParam;
|
||||
}
|
||||
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
|
||||
// *****************************************************
|
||||
|
||||
#define FORWARD_NUM 12
|
||||
const int FORWARD_MAX_PARAMS = 16;
|
||||
|
||||
enum {
|
||||
FF_ClientCommand,
|
||||
FF_ClientConnect,
|
||||
FF_ClientDisconnect,
|
||||
FF_ClientInfoChanged,
|
||||
FF_ClientPutInServer,
|
||||
FF_PluginInit,
|
||||
FF_PluginCfg,
|
||||
FF_PluginPrecache,
|
||||
FF_PluginLog,
|
||||
FF_PluginEnd,
|
||||
FF_InconsistentFile,
|
||||
FF_ClientAuthorized,
|
||||
enum ForwardExecType
|
||||
{
|
||||
ET_IGNORE = 0, // Ignore return vaue
|
||||
ET_STOP, // Stop on PLUGIN_HANDLED
|
||||
ET_STOP2, // Stop on PLUGIN_HANDLED, continue on other values, return biggest return value
|
||||
ET_CONTINUE, // Continue; return biggest return value
|
||||
};
|
||||
|
||||
enum ForwardParam
|
||||
{
|
||||
FP_DONE = -1, // specify this as the last argument
|
||||
// only tells the function that there are no more arguments
|
||||
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.
|
||||
};
|
||||
|
||||
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;
|
||||
int func;
|
||||
};
|
||||
typedef CList<AMXForward> AMXForwardList;
|
||||
AMXForwardList m_Funcs;
|
||||
ForwardParam m_ParamTypes[FORWARD_MAX_PARAMS];
|
||||
public:
|
||||
CForward(const char *name, ForwardExecType et, int numParams, const ForwardParam * paramTypes);
|
||||
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:
|
||||
|
||||
class iterator;
|
||||
|
||||
class CForward
|
||||
{
|
||||
|
||||
friend class iterator;
|
||||
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; }
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
private:
|
||||
CForward *head[ FORWARD_NUM ];
|
||||
void clearForwards( CForward** a );
|
||||
|
||||
public:
|
||||
CForwardMngr() {memset( head, 0, sizeof(head));}
|
||||
~CForwardMngr() { clear(); }
|
||||
CForwardMngr()
|
||||
{ m_TmpArraysNum = 0; }
|
||||
~CForwardMngr()
|
||||
{ }
|
||||
|
||||
// Interface
|
||||
|
||||
void registerForward( CPluginMngr::CPlugin* p, int func , int type );
|
||||
void executeForwards( int type , int num = 0, int player = 0 );
|
||||
void clear();
|
||||
|
||||
|
||||
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;}
|
||||
int registerForward(const char *funcName, ForwardExecType et, int numParams, const ForwardParam *paramTypes);
|
||||
int executeForwards(int id, cell *params);
|
||||
void clear(); // delete all forwards
|
||||
bool isIdValid(int id) const;
|
||||
int getParamsNum(int id) const;
|
||||
cell prepareArray(void *ptr, unsigned int size, ForwardArrayElemType type);
|
||||
};
|
||||
|
||||
// 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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user