2
0
mirror of https://github.com/rehlds/reapi.git synced 2025-03-25 19:59:02 +03:00
reapi/reapi/src/hook_callback.h
2016-04-07 01:34:18 +03:00

209 lines
6.7 KiB
C++

#pragma once
// hookchain return type
enum HookChainState
{
HC_CONTINUE = 0,
HC_OVERRIDE,
HC_SUPERCEDE,
HC_BREAK
};
// api types
enum AType : uint8
{
ATYPE_INTEGER = 0,
ATYPE_FLOAT,
ATYPE_STRING,
ATYPE_CLASSPTR
};
struct retval_t
{
bool set;
AType type;
union
{
char* _string;
float _float;
int _interger;
CBaseEntity* _classptr;
};
};
inline AType getApiType(int) { return ATYPE_INTEGER; }
inline AType getApiType(unsigned) { return ATYPE_INTEGER; }
inline AType getApiType(cvar_s *) { return ATYPE_INTEGER; }
inline AType getApiType(float) { return ATYPE_FLOAT; }
inline AType getApiType(const char *) { return ATYPE_STRING; }
inline AType getApiType(CBaseEntity *) { return ATYPE_CLASSPTR; }
template<size_t current>
void setupArgTypes(AType args_type[])
{
}
#define MAX_ARGS 10u
template<size_t current, typename T, typename ...t_args>
void setupArgTypes(AType args_type[MAX_ARGS], T arg, t_args... args)
{
args_type[current] = getApiType(arg);
if (sizeof...(args) && current + 1 < MAX_ARGS)
setupArgTypes<current + 1>(args_type, args...);
}
struct hookctx_t
{
template<typename ...t_args>
hookctx_t(size_t count, size_t ptr, t_args... args)
{
args_count = min(count, MAX_ARGS);
args_ptr = ptr;
setupArgTypes<0>(this->args_type, args...);
}
retval_t retVal;
size_t args_count;
size_t args_ptr;
AType args_type[MAX_ARGS];
};
extern hookctx_t* g_hookCtx;
template <typename original_t, typename ...f_args>
void callVoidForward(int func, original_t original, f_args... args)
{
hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...);
hookCtx.retVal.set = false;
g_hookCtx = &hookCtx;
int hc_state = HC_CONTINUE;
auto hook = g_hookManager.getHook(func);
for (auto& fwd : hook->pre)
{
if (fwd->GetState() == FSTATE_ENABLED)
{
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
if (ret == HC_BREAK) {
g_hookCtx = nullptr;
return;
}
if (ret > hc_state)
hc_state = ret;
}
}
if (hc_state != HC_SUPERCEDE)
original(args...);
for (auto& fwd : hook->post)
{
if (fwd->GetState() == FSTATE_ENABLED)
{
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
if (ret == HC_BREAK)
break;
}
}
g_hookCtx = nullptr;
}
template <typename R, typename original_t, typename ...f_args>
R callForward(int func, original_t original, f_args... args)
{
hookctx_t hookCtx(sizeof...(args), size_t(&original) + sizeof(original), args...);
hookCtx.retVal.set = false;
hookCtx.retVal.type = getApiType(R());
g_hookCtx = &hookCtx;
int hc_state = HC_CONTINUE;
auto hook = g_hookManager.getHook(func);
for (auto& fwd : hook->pre)
{
if (fwd->GetState() == FSTATE_ENABLED)
{
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
if (ret == HC_CONTINUE)
continue;
if (!hookCtx.retVal.set)
{
g_amxxapi.LogError(fwd->GetAmx(), AMX_ERR_CALLBACK, "%s", "can't suppress original function call without new return value set");
continue;
}
if (ret == HC_BREAK) {
g_hookCtx = nullptr;
return (R)hookCtx.retVal._interger;
}
if (ret > hc_state)
hc_state = ret;
}
}
if (hc_state != HC_SUPERCEDE)
{
auto retVal = original(args...);
if (hc_state != HC_OVERRIDE)
hookCtx.retVal._interger = *(int *)&retVal;
}
for (auto& fwd : hook->post) {
if (fwd->GetState() == FSTATE_ENABLED) {
auto ret = g_amxxapi.ExecuteForward(fwd->m_forward, args...);
if (ret == HC_BREAK)
break;
}
}
g_hookCtx = nullptr;
return (R)hookCtx.retVal._interger;
}
// rehlds functions
void SV_StartSound(IRehldsHook_SV_StartSound *chain, int recipients, edict_t *entity, int channel, const char *sample, int volume, float attenuation, int fFlags, int pitch);
void SV_DropClient(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *fmt);
void SV_ActivateServer(IRehldsHook_SV_ActivateServer *chain, int runPhysics);
void Cvar_DirectSet(IRehldsHook_Cvar_DirectSet *chain, cvar_t *var, const char *value);
// regamedll functions
int GetForceCamera(IReGameHook_GetForceCamera *chain, CBasePlayer *pObserver);
// regamedll functions - player
void CBasePlayer_Spawn(IReGameHook_CBasePlayer_Spawn *chain, CBasePlayer *pthis);
void CBasePlayer_Precache(IReGameHook_CBasePlayer_Precache *chain, CBasePlayer *pthis);
int CBasePlayer_ObjectCaps(IReGameHook_CBasePlayer_ObjectCaps *chain, CBasePlayer *pthis);
int CBasePlayer_Classify(IReGameHook_CBasePlayer_Classify *chain, CBasePlayer *pthis);
void CBasePlayer_TraceAttack(IReGameHook_CBasePlayer_TraceAttack *chain, CBasePlayer *pthis, entvars_t *pevAttacker, float flDamage, Vector& vecDir, TraceResult *ptr, int bitsDamageType);
int CBasePlayer_TakeDamage(IReGameHook_CBasePlayer_TakeDamage *chain, CBasePlayer *pthis, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType);
int CBasePlayer_TakeHealth(IReGameHook_CBasePlayer_TakeHealth *chain, CBasePlayer *pthis, float flHealth, int bitsDamageType);
void CBasePlayer_Killed(IReGameHook_CBasePlayer_Killed *chain, CBasePlayer *pthis, entvars_t *pevAttacker, int iGib);
void CBasePlayer_AddPoints(IReGameHook_CBasePlayer_AddPoints *chain, CBasePlayer *pthis, int score, BOOL bAllowNegativeScore);
void CBasePlayer_AddPointsToTeam(IReGameHook_CBasePlayer_AddPointsToTeam *chain, CBasePlayer *pthis, int score, BOOL bAllowNegativeScore);
BOOL CBasePlayer_AddPlayerItem(IReGameHook_CBasePlayer_AddPlayerItem *chain, CBasePlayer *pthis, CBasePlayerItem *pItem);
BOOL CBasePlayer_RemovePlayerItem(IReGameHook_CBasePlayer_RemovePlayerItem *chain, CBasePlayer *pthis, CBasePlayerItem *pItem);
int CBasePlayer_GiveAmmo(IReGameHook_CBasePlayer_GiveAmmo *chain, CBasePlayer *pthis, int iAmount, char *szName, int iMax);
void CBasePlayer_ResetMaxSpeed(IReGameHook_CBasePlayer_ResetMaxSpeed *chain, CBasePlayer *pthis);
void CBasePlayer_Jump(IReGameHook_CBasePlayer_Jump *chain, CBasePlayer *pthis);
void CBasePlayer_Duck(IReGameHook_CBasePlayer_Duck *chain, CBasePlayer *pthis);
void CBasePlayer_PreThink(IReGameHook_CBasePlayer_PreThink *chain, CBasePlayer *pthis);
void CBasePlayer_PostThink(IReGameHook_CBasePlayer_PostThink *chain, CBasePlayer *pthis);
void CBasePlayer_UpdateClientData(IReGameHook_CBasePlayer_UpdateClientData *chain, CBasePlayer *pthis);
void CBasePlayer_ImpulseCommands(IReGameHook_CBasePlayer_ImpulseCommands *chain, CBasePlayer *pthis);
void CBasePlayer_RoundRespawn(IReGameHook_CBasePlayer_RoundRespawn *chain, CBasePlayer *pthis);
void CBasePlayer_Blind(IReGameHook_CBasePlayer_Blind *chain, CBasePlayer *pthis, float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha);
CBaseEntity *CBasePlayer_Observer_IsValidTarget(IReGameHook_CBasePlayer_Observer_IsValidTarget *chain, CBasePlayer *pthis, int iPlayerIndex, bool bSameTeam);