rewritten

This commit is contained in:
Pavol Marko 2004-04-03 19:14:03 +00:00
parent 64bf40aaa3
commit 06da72658b
2 changed files with 281 additions and 95 deletions

View File

@ -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 ] );
for (ForwardVec::iterator iter = m_Forwards.begin(); iter != m_Forwards.end(); ++iter)
{
delete (*iter);
}
m_Forwards.clear();
m_TmpArraysNum = 0;
}
void CForwardMngr::executeForwards( int type , int num , int player ) {
cell ret = 0;
int err;
CForward* a = head[ type ];
while ( a )
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 ( 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 )
if (curParam == FORWARD_MAX_PARAMS)
break;
}
a = a->next;
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);
}

View File

@ -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