2
0
mirror of https://github.com/rehlds/reapi.git synced 2025-01-29 23:17:57 +03:00

Enhanced natives SetThink, SetTouch, SetUse, SetBlocked, SetMoveDone

This commit is contained in:
s1lent 2017-10-03 18:37:11 +07:00
parent e636819f02
commit 9cedc733b7
No known key found for this signature in database
GPG Key ID: 0FE401DC73916B5C
7 changed files with 165 additions and 76 deletions

View File

@ -1195,3 +1195,11 @@ enum InfoMapBuyParam
BUYING_ONLY_TERRORISTS,
BUYING_NO_ONE,
};
enum USE_TYPE
{
USE_OFF,
USE_ON,
USE_SET,
USE_TOGGLE
};

View File

@ -7,60 +7,70 @@
#include <reapi_gamedll_const>
/*
* Sets callback for entity
* Sets Think callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Think_Callback(const ent)"
*
* @noreturn
*/
native SetThink(const ent, const callback[]);
native SetThink(const ent, const callback[], const params[] = "", const len = 0);
/*
* Sets callback for entity
* Sets Touch callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Touch_Callback(const ent, const other)"
*
* @noreturn
*/
native SetTouch(const ent, const callback[]);
native SetTouch(const ent, const callback[], const params[] = "", const len = 0);
/*
* Sets callback for entity
* Sets Use callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Use_Callback(const ent, const activator, const caller, USE_TYPE:useType, Float:value)"
*
* @noreturn
*/
native SetUse(const ent, const callback[]);
native SetUse(const ent, const callback[], const params[] = "", const len = 0);
/*
* Sets callback for entity
* Sets Blocked callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Blocked_Callback(const ent, const other)"
*
* @noreturn
*/
native SetBlocked(const ent, const callback[]);
native SetBlocked(const ent, const callback[], const params[] = "", const len = 0);
/*
* Sets callback for entity
* Sets MoveDone callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Entity should be inherited from CBaseToggle, otherwise server can crash
*
* @param entity Entity index
* @param callback The forward to call
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public MoveDone_Callback(const ent, const other)"
*
* @noreturn
*/
native SetMoveDone(const ent, const callback[]);
native SetMoveDone(const ent, const callback[], const params[] = "", const len = 0);
/*
* Sets a value to CSGameRules_Members members.

View File

@ -8,7 +8,7 @@ enum fwdstate
FSTATE_STOPPED
};
template <typename T = int>
template <typename T = void>
class CAmxxHook
{
public:
@ -18,9 +18,11 @@ public:
g_amxxapi.UnregisterSPForward(m_index);
m_index = -1;
}
delete m_uniqueData;
}
CAmxxHook(AMX *amx, const char *funcname, int index, T data = (T)0) :
CAmxxHook(AMX *amx, const char *funcname, int index, T *data = nullptr) :
m_index(index),
m_state(FSTATE_ENABLED),
m_amx(amx),
@ -29,7 +31,7 @@ public:
Q_strlcpy(m_CallbackName, funcname);
};
T GetUnique() const;
T *GetUnique() const;
int GetIndex() const;
fwdstate GetState() const;
AMX *GetAmx() const;
@ -38,7 +40,7 @@ public:
void SetState(fwdstate st);
private:
T m_uniqueData;
T *m_uniqueData;
int m_index;
char m_CallbackName[64];
fwdstate m_state;
@ -47,7 +49,7 @@ private:
// Inlines
template <typename T>
inline T CAmxxHook<T>::GetUnique() const
inline T *CAmxxHook<T>::GetUnique() const
{
return m_uniqueData;
}

View File

@ -7,10 +7,10 @@ void CEntityCallback::PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type)
auto it = m_callbacks.begin();
while (it != m_callbacks.end())
{
EntityCallback_t data = (*it)->GetUnique();
eCallback_t *pUnique = (*it)->GetUnique();
// this callback was already sets, need to unregister the current forward
if (data.m_callbackType == type && data.m_entity == pEntity) {
if (pUnique->m_callbackType == type && pUnique->m_entity == pEntity) {
delete (*it);
it = m_callbacks.erase(it);
} else {
@ -26,8 +26,8 @@ void CEntityCallback::Clear(CBaseEntity *pEntity)
auto it = m_callbacks.begin();
while (it != m_callbacks.end())
{
EntityCallback_t data = (*it)->GetUnique();
if (data.m_entity == pEntity) {
eCallback_t *pUnique = (*it)->GetUnique();
if (pUnique->m_entity == pEntity) {
delete (*it);
it = m_callbacks.erase(it);
} else {
@ -45,82 +45,107 @@ void CEntityCallback::Clear(CBaseEntity *pEntity)
}
}
bool CEntityCallback::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback)
bool CEntityCallback::SetThink(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{
PurgeCallbacks(pEntity, CType_Think);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE);
int fwdid;
if (iParamsLen > 0) {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE);
} else {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE);
}
if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false;
}
EntityCallback_t entry(pEntity, CType_Think);
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Think)));
pEntity->SetThink(&CBaseEntity::SUB_Think);
return true;
}
bool CEntityCallback::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback)
bool CEntityCallback::SetTouch(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{
PurgeCallbacks(pEntity, CType_Touch);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE);
int fwdid;
if (iParamsLen > 0) {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE);
} else {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE);
}
if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false;
}
EntityCallback_t entry(pEntity, CType_Touch);
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Touch)));
pEntity->SetTouch(&CBaseEntity::SUB_Touch);
return true;
}
bool CEntityCallback::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback)
bool CEntityCallback::SetUse(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{
PurgeCallbacks(pEntity, CType_Use);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_DONE);
int fwdid;
if (iParamsLen > 0) {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_ARRAY, FP_DONE);
} else {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_FLOAT, FP_DONE);
}
if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false;
}
EntityCallback_t entry(pEntity, CType_Use);
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Use)));
pEntity->SetUse(&CBaseEntity::SUB_Use);
return true;
}
bool CEntityCallback::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback)
bool CEntityCallback::SetBlocked(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{
PurgeCallbacks(pEntity, CType_Blocked);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE);
int fwdid;
if (iParamsLen > 0) {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_ARRAY, FP_DONE);
} else {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_CELL, FP_DONE);
}
if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false;
}
EntityCallback_t entry(pEntity, CType_Blocked);
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_Blocked)));
pEntity->SetTouch(&CBaseEntity::SUB_Blocked);
return true;
}
bool CEntityCallback::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback)
bool CEntityCallback::SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen)
{
PurgeCallbacks(pEntity, CType_MoveDone);
int fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE);
int fwdid;
if (iParamsLen > 0) {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_ARRAY, FP_DONE);
} else {
fwdid = g_amxxapi.RegisterSPForwardByName(amx, pszCallback, FP_CELL, FP_DONE);
}
if (fwdid == -1) {
MF_LogError(amx, AMX_ERR_NATIVE, "%s: failed to register forward.", __FUNCTION__);
return false;
}
EntityCallback_t entry(pEntity, CType_MoveDone);
m_callbacks.push_back(new CAmxxHook<EntityCallback_t>(amx, pszCallback, fwdid, entry));
m_callbacks.push_back(new CAmxxHook<eCallback_t>(amx, pszCallback, fwdid, new eCallback_t(pEntity, pParams, iParamsLen, CType_MoveDone)));
// TODO: Make sure that the entity actually inherited from CBaseToggle
((CBaseToggle *)pEntity)->SetMoveDone(&CBaseToggle::SUB_MoveDone);

View File

@ -7,11 +7,11 @@ class CEntityCallback
public:
void Clear(CBaseEntity *pEntity = nullptr);
bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback);
bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback);
bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback);
bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback);
bool SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback);
bool SetThink (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetTouch (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetUse (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetBlocked (AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
bool SetMoveDone(AMX *amx, CBaseEntity *pEntity, const char *pszCallback, const cell *pParams, size_t iParamsLen);
enum CallbackType_e
{
@ -26,24 +26,53 @@ public:
void FireCallbacks(CBaseEntity *pEntity, CallbackType_e type, volatile f_args... args)
{
for (auto fwd : m_callbacks) {
if (fwd->GetUnique().m_entity == pEntity && fwd->GetUnique().m_callbackType == type) {
g_amxxapi.ExecuteForward(fwd->GetIndex(), args...);
auto data = fwd->GetUnique();
if (data->m_entity == pEntity && data->m_callbackType == type)
{
if (data->m_iParamLen > 0) {
g_amxxapi.ExecuteForward(fwd->GetIndex(), args..., g_amxxapi.PrepareCellArrayA(data->m_pParams, data->m_iParamLen, true));
} else {
g_amxxapi.ExecuteForward(fwd->GetIndex(), args...);
}
}
}
}
private:
void PurgeCallbacks(CBaseEntity *pEntity, CallbackType_e type);
struct EntityCallback_t
struct eCallback_t
{
EntityCallback_t(CBaseEntity *pEntity, CallbackType_e type) :
m_entity(pEntity), m_callbackType(type) {};
eCallback_t(CBaseEntity *pEntity, const cell *pParams, size_t iParamsLen, CallbackType_e type) :
m_entity(pEntity), m_callbackType(type)
{
if (iParamsLen > 0) {
m_iParamLen = iParamsLen + 1;
m_pParams = new cell[m_iParamLen];
Q_memcpy(m_pParams, pParams, sizeof(cell) * iParamsLen);
m_pParams[iParamsLen] = 0;
} else {
m_iParamLen = 0;
m_pParams = nullptr;
}
};
~eCallback_t()
{
if (m_pParams) {
delete[] m_pParams;
m_pParams = nullptr;
}
m_iParamLen = 0;
}
CBaseEntity *m_entity;
CallbackType_e m_callbackType;
cell *m_pParams;
size_t m_iParamLen;
};
std::vector<CAmxxHook<EntityCallback_t> *> m_callbacks;
std::vector<CAmxxHook<eCallback_t> *> m_callbacks;
};
extern CEntityCallback g_entCallback;

View File

@ -33,7 +33,7 @@ META_FUNCTIONS gMetaFunctionTable =
NULL, // pfnGetEntityAPI_Post META; called after game DLL
GetEntityAPI2, // pfnGetEntityAPI2 HL SDK2; called before game DLL
GetEntityAPI2_Post, // pfnGetEntityAPI2_Post META; called after game DLL
NULL, // pfnGetNewDLLFunctions HL SDK2; called before game DLL
GetNewDLLFunctions, // pfnGetNewDLLFunctions HL SDK2; called before game DLL
NULL, // pfnGetNewDLLFunctions_Post META; called after game DLL
NULL, // pfnGetEngineFunctions META; called before HL engine
NULL, // pfnGetEngineFunctions_Post META; called after HL engine

View File

@ -256,19 +256,21 @@ cell AMX_NATIVE_CALL amx_GetAttachment(AMX *amx, cell *params)
}
/*
* Sets callback for entity
* Sets Think callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Think_Callback(const ent)"
*
* @noreturn
*
* native SetThink(const ent, const callback[]);
* native SetThink(const ent, const callback[], const params[] = "", const len = 0);
*/
cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_handler };
enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index);
@ -290,23 +292,26 @@ cell AMX_NATIVE_CALL amx_SetThink(AMX *amx, cell *params)
return FALSE;
}
return (cell)g_entCallback.SetThink(amx, pEntity, funcname);
cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetThink(amx, pEntity, funcname, pParams, params[arg_len]);
}
/*
* Sets callback for entity
* Sets Touch callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Touch_Callback(const ent, const other)"
*
* @noreturn
*
* native SetTouch(const ent, const callback[]);
* native SetTouch(const ent, const callback[], const params[] = "", const len = 0);
*/
cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_handler };
enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index);
@ -328,23 +333,26 @@ cell AMX_NATIVE_CALL amx_SetTouch(AMX *amx, cell *params)
return FALSE;
}
return (cell)g_entCallback.SetTouch(amx, pEntity, funcname);
cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetTouch(amx, pEntity, funcname, pParams, params[arg_len]);
}
/*
* Sets callback for entity
* Sets Use callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Use_Callback(const ent, const activator, const caller, USE_TYPE:useType, Float:value)"
*
* @noreturn
*
* native SetUse(const ent, const callback[]);
* native SetUse(const ent, const callback[], const params[] = "", const len = 0);
*/
cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_handler };
enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index);
@ -366,23 +374,26 @@ cell AMX_NATIVE_CALL amx_SetUse(AMX *amx, cell *params)
return FALSE;
}
return (cell)g_entCallback.SetUse(amx, pEntity, funcname);
cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetUse(amx, pEntity, funcname, pParams, params[arg_len]);
}
/*
* Sets callback for entity
* Sets Blocked callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Callback should be contains passing arguments as "public Blocked_Callback(const ent, const other)"
*
* @noreturn
*
* native SetBlocked(const ent, const callback[]);
* native SetBlocked(const ent, const callback[], const params[] = "", const len = 0);
*/
cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_handler };
enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index);
@ -404,24 +415,27 @@ cell AMX_NATIVE_CALL amx_SetBlocked(AMX *amx, cell *params)
return FALSE;
}
return (cell)g_entCallback.SetBlocked(amx, pEntity, funcname);
cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetBlocked(amx, pEntity, funcname, pParams, params[arg_len]);
}
/*
* Sets callback for entity
* @note Entity should be inherited from CBaseToggle, otherwise server can crash
* Sets MoveDone callback for entity
*
* @param entity Entity index
* @param callback The forward to call
*
* @note Use "" to reset callback
* @note Entity should be inherited from CBaseToggle, otherwise server can crash
* @note Callback should be contains passing arguments as "public MoveDone_Callback(const ent, const other)"
*
* @noreturn
*
* native SetMoveDone(const ent, const callback[]);
* native SetMoveDone(const ent, const callback[], const params[] = "", const len = 0);
*/
cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params)
{
enum args_e { arg_count, arg_index, arg_handler };
enum args_e { arg_count, arg_index, arg_handler, arg_params, arg_len };
CHECK_ISENTITY(arg_index);
@ -443,7 +457,8 @@ cell AMX_NATIVE_CALL amx_SetMoveDone(AMX *amx, cell *params)
return FALSE;
}
return (cell)g_entCallback.SetMoveDone(amx, pEntity, funcname);
cell *pParams = (PARAMS_COUNT >= 3) ? getAmxAddr(amx, params[arg_params]) : nullptr;
return (cell)g_entCallback.SetMoveDone(amx, pEntity, funcname, pParams, params[arg_len]);
}
AMX_NATIVE_INFO Natives_Common[] =