diff --git a/reapi/msvc/reapi.vcxproj b/reapi/msvc/reapi.vcxproj index f17084f..dbb2b59 100644 --- a/reapi/msvc/reapi.vcxproj +++ b/reapi/msvc/reapi.vcxproj @@ -202,7 +202,8 @@ - + + @@ -236,8 +237,8 @@ - - + + Create Create diff --git a/reapi/msvc/reapi.vcxproj.filters b/reapi/msvc/reapi.vcxproj.filters index b8be123..66991e9 100644 --- a/reapi/msvc/reapi.vcxproj.filters +++ b/reapi/msvc/reapi.vcxproj.filters @@ -591,9 +591,6 @@ src - - src - src @@ -621,6 +618,12 @@ src + + src + + + src + @@ -644,9 +647,6 @@ src - - src - src @@ -671,9 +671,6 @@ src - - src - src @@ -686,6 +683,12 @@ src + + src + + + src + diff --git a/reapi/src/amxxmodule.cpp b/reapi/src/amxxmodule.cpp index 9e3a74d..05911cf 100644 --- a/reapi/src/amxxmodule.cpp +++ b/reapi/src/amxxmodule.cpp @@ -159,7 +159,8 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) *(void **)((unsigned long)&g_amxxapi + g_funcrequests[i].offset) = fptr; } - RegisterNatives(); + RegisterNatives_HookChains(); + RegisterNatives_Members(); return AMXX_OK; } diff --git a/reapi/src/hook_callback.h b/reapi/src/hook_callback.h index 69b2007..67a0c88 100644 --- a/reapi/src/hook_callback.h +++ b/reapi/src/hook_callback.h @@ -78,21 +78,6 @@ struct hookctx_t extern hookctx_t* g_hookCtx; -#pragma optimize("ts", on) - -template -void callVoidForward(size_t func, original_t original, f_args... args) -{ -#ifndef _WIN32 - static -#endif - hookctx_t hookCtx(sizeof...(args), args...); - - g_hookCtx = &hookCtx; - _callVoidForward(g_hookManager.getHook(func), original, args...); - g_hookCtx = nullptr; -} - template NOINLINE void DLLEXPORT _callVoidForward(const hook_t* hook, original_t original, volatile f_args... args) { @@ -129,8 +114,8 @@ NOINLINE void DLLEXPORT _callVoidForward(const hook_t* hook, original_t original } } -template -R callForward(size_t func, original_t original, f_args... args) +template +void callVoidForward(size_t func, original_t original, f_args... args) { #ifndef _WIN32 static @@ -138,10 +123,8 @@ R callForward(size_t func, original_t original, f_args... args) hookctx_t hookCtx(sizeof...(args), args...); g_hookCtx = &hookCtx; - auto ret = _callForward(g_hookManager.getHook(func), original, args...); + _callVoidForward(g_hookManager.getHook(func), original, args...); g_hookCtx = nullptr; - - return ret; } template @@ -194,7 +177,20 @@ NOINLINE R DLLEXPORT _callForward(const hook_t* hook, original_t original, volat return *(R *)&hookCtx.retVal._interger; } -#pragma optimize("", on) +template +R callForward(size_t func, original_t original, f_args... args) +{ +#ifndef _WIN32 + static +#endif + hookctx_t hookCtx(sizeof...(args), args...); + + g_hookCtx = &hookCtx; + auto ret = _callForward(g_hookManager.getHook(func), original, args...); + g_hookCtx = nullptr; + + return ret; +} // 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); diff --git a/reapi/src/hook_list.cpp b/reapi/src/hook_list.cpp index 8daafba..28651d0 100644 --- a/reapi/src/hook_list.cpp +++ b/reapi/src/hook_list.cpp @@ -41,22 +41,6 @@ hook_t hooklist_player[] = { DLL(CBasePlayer_Observer_IsValidTarget), }; -/*hook_t *hooklist_t::getHook(size_t hook) -{ - #define CASE(h) case ht_##h: if (index < arraysize(hooklist_##h)) return &hooklist_##h[index]; else break; - - const auto table = hooks_tables_e(hook / MAX_REGION_RANGE); - const auto index = hook & (MAX_REGION_RANGE - 1); - - switch (table) { - CASE(engine) - CASE(gamedll) - CASE(player) - } - - return nullptr; -}*/ - const size_t hooklist_engine_size = arraysize(hooklist_engine); const size_t hooklist_gamedll_size = arraysize(hooklist_gamedll); const size_t hooklist_player_size = arraysize(hooklist_player); diff --git a/reapi/src/hook_list.h b/reapi/src/hook_list.h index ed4c191..6de9107 100644 --- a/reapi/src/hook_list.h +++ b/reapi/src/hook_list.h @@ -124,20 +124,8 @@ struct hooklist_t } return nullptr; - /*const auto table = hooks_tables_e(hook / MAX_REGION_RANGE); - const auto index = hook & (MAX_REGION_RANGE - 1); - - switch (table) { - case ht_engine: return &hooklist_engine[index]; - case ht_gamedll: return &hooklist_gamedll[index]; - case ht_player: return &hooklist_player[index]; - } - - return nullptr;*/ } - //static hook_t *getHook(size_t hook); - enum hooks_tables_e { ht_engine, diff --git a/reapi/src/member_list.cpp b/reapi/src/member_list.cpp index 168bc52..f7e10df 100644 --- a/reapi/src/member_list.cpp +++ b/reapi/src/member_list.cpp @@ -3,7 +3,7 @@ struct regmember { template - regmember(T& type, size_t maxsize, size_t offset, enum_membertypes member_type) + regmember(T& type, size_t maxsize, size_t offset, MType member_type) { member.size = sizeof(T); member.max_size = sizeof(T); @@ -11,7 +11,7 @@ struct regmember member.type = member_type; } template - regmember(T type[], size_t maxsize, size_t offset, enum_membertypes member_type) + regmember(T type[], size_t maxsize, size_t offset, MType member_type) { member.size = sizeof(T); member.max_size = maxsize; diff --git a/reapi/src/member_list.h b/reapi/src/member_list.h index 70c51ec..760ec36 100644 --- a/reapi/src/member_list.h +++ b/reapi/src/member_list.h @@ -2,7 +2,8 @@ #define BEGIN_MEMBER_REGION(x) (MAX_REGION_RANGE * memberlist_t::members_tables_e::ht_##x) -enum enum_membertypes +// member types +enum MType { MEMBER_FLOAT = 0, // Any floating point value MEMBER_DOUBLE, // double value @@ -27,7 +28,7 @@ struct member_t uint16 size; uint16 max_size; uint32 offset; - enum_membertypes type; + MType type; }; struct memberlist_t diff --git a/reapi/src/natives.cpp b/reapi/src/natives_hookchains.cpp similarity index 98% rename from reapi/src/natives.cpp rename to reapi/src/natives_hookchains.cpp index 5dcf42d..584166f 100644 --- a/reapi/src/natives.cpp +++ b/reapi/src/natives_hookchains.cpp @@ -265,7 +265,7 @@ static cell AMX_NATIVE_CALL SetHookChainArg(AMX *amx, cell *params) return TRUE; } -AMX_NATIVE_INFO Func_Natives[] = +AMX_NATIVE_INFO HookChain_Natives[] = { { "RegisterHookChain", RegisterHookChain }, @@ -280,8 +280,7 @@ AMX_NATIVE_INFO Func_Natives[] = { nullptr, nullptr } }; -void RegisterNatives() +void RegisterNatives_HookChains() { - g_amxxapi.AddNatives(Func_Natives); - g_amxxapi.AddNatives(Member_Natives); + g_amxxapi.AddNatives(HookChain_Natives); } diff --git a/reapi/src/natives.h b/reapi/src/natives_hookchains.h similarity index 86% rename from reapi/src/natives.h rename to reapi/src/natives_hookchains.h index ca270c5..f7a47ce 100644 --- a/reapi/src/natives.h +++ b/reapi/src/natives_hookchains.h @@ -4,6 +4,4 @@ #define PARAMS_REQUIRE(x) if (params[0] != x * sizeof(cell)) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid parameters count in %s", __FUNCTION__); return nullptr; } #define NATIVE_MEMBER_REQUIRE(a,x) if (!api_cfg.has##x()) { MF_LogError(amx, AMX_ERR_NATIVE, "Member (%s) is not available, required %s", memberlist[a]->member_name, #x); return 0; } -extern AMX_NATIVE_INFO Member_Natives[]; - -void RegisterNatives(); +void RegisterNatives_HookChains(); diff --git a/reapi/src/natives_member.cpp b/reapi/src/natives_member.cpp deleted file mode 100644 index 3378951..0000000 --- a/reapi/src/natives_member.cpp +++ /dev/null @@ -1,385 +0,0 @@ -#include "precompiled.h" - -// native set_member(_index, any:_member, any:...); -static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) -{ - enum args_member_e { arg_count, arg_index, arg_member, arg_value, arg_elem }; - member_t *member = memberlist[params[arg_member]]; - - if (member == nullptr) { - MF_LogError(amx, AMX_ERR_NATIVE, "set_member: unknown member id %i", params[arg_member]); - return FALSE; - } - - edict_t *pEdict = INDEXENT(params[arg_index]); - if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) { - MF_LogError(amx, AMX_ERR_NATIVE, "set_member: invalid or uninitialized entity", params[arg_member]); - return FALSE; - } - - cell* value = getAmxAddr(amx, params[arg_value]); - size_t element = (params[arg_count] == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0; - - switch (member->type) - { - case MEMBER_ENTITY: - return FALSE; - case MEMBER_CLASSPTR: - { - // native set_member(_index, any:_member, _value, _elem); - CBaseEntity *pEntity = nullptr; - edict_t *pEdictValue = INDEXENT(*value); - - if (pEdictValue != nullptr) { - pEntity = CBaseEntity::Instance(pEdictValue); - } - set_member(pEdict, member->offset, pEntity, element); - return TRUE; - } - case MEMBER_EHANDLE: - { - // native set_member(_index, any:_member, _value, _elem); - EHANDLE& ehandle = get_member(pEdict, member->offset, element); - edict_t *pEdictValue = INDEXENT(*value); - ehandle.Set(pEdictValue); - return TRUE; - } - case MEMBER_EVARS: - return FALSE; - case MEMBER_EDICT: - { - // native set_member(_index, any:_member, _value, _elem); - edict_t *pEdictValue = INDEXENT(*value); - set_member(pEdict, member->offset, pEdictValue, element); - return TRUE; - } - case MEMBER_VECTOR: - { - // native set_member(_index, any:_member, Float:_value[3], _elem); - Vector *pSource = (Vector *)getAmxAddr(amx, params[arg_value]); - set_member(pEdict, member->offset, *pSource, element); - return TRUE; - } - case MEMBER_CHAR_ARRAY: - { - // native set_member(_index, any:_member, const source[]); - size_t len; - char *source = getAmxString(value, &len); - char *dest = get_member_direct(pEdict, member->offset); - strncpy(dest, source, member->max_size - 1); - dest[member->max_size - 1] = '\0'; - return TRUE; - } - case MEMBER_CHAR_POINTER: - { - // native set_member(_index, any:_member, const source[]); - size_t len; - char *source = getAmxString(value, &len); - char *&dest = get_member(pEdict, member->offset); - - if (dest != nullptr) { - delete [] dest; - } - - dest = new char[len + 1]; - strcpy(dest, source); - - set_member(pEdict, member->offset, dest); - return TRUE; - } - case MEMBER_FLOAT: - case MEMBER_INTEGER: - { - // native set_member(_index, any:_member, any:_value, _elem); - set_member(pEdict, member->offset, *value, element); - return TRUE; - } - case MEMBER_SHORT: - { - // native set_member(_index, any:_member, _value, _elem); - set_member(pEdict, member->offset, *value, element); - return TRUE; - } - case MEMBER_BYTE: - { - // native set_member(_index, any:_member, _value, _elem); - set_member(pEdict, member->offset, *value, element); - return TRUE; - } - case MEMBER_BOOL: - { - // native set_member(_index, any:_member, bool:_value, _elem); - set_member(pEdict, member->offset, *value != 0, element); - return TRUE; - } - case MEMBER_SIGNALS: - { - // native set_member(_index, any:_member, _value); - CUnifiedSignals& signal = get_member(pEdict, member->offset, element); - signal.Signal(*value); - return TRUE; - } - case MEMBER_DOUBLE: - { - // native set_member(_index, any:_member, any:_value, _elem); - set_member(pEdict, member->offset, *(float *)value, element); - return TRUE; - } - case MEBMER_REBUYSTRUCT: - return FALSE; - } - - return FALSE; -} - -// native any:get_member(_index = 0, any:_member, any:...); -static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) -{ - enum args_member_e { arg_count, arg_index, arg_member, arg_elem }; - member_t *member = memberlist[params[arg_member]]; - - if (member == nullptr) { - MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]); - return FALSE; - } - - edict_t *pEdict = INDEXENT(params[arg_index]); - - if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) { - return FALSE; - } - - size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]); - - switch (member->type) - { - case MEMBER_ENTITY: - return FALSE; - case MEMBER_CLASSPTR: - // native any:get_member(_index, any:_member, element); - return get_member(pEdict, member->offset, element)->entindex(); - case MEMBER_EHANDLE: - { - // native any:get_member(_index, any:_member, element); - EHANDLE ehandle = get_member(pEdict, member->offset, element); - edict_t *pEntity = ehandle.Get(); - if (pEntity != nullptr) { - return ((CBaseEntity *)ehandle)->entindex(); - } - return FALSE; - } - case MEMBER_EVARS: - return -1; - case MEMBER_EDICT: - { - // native any:get_member(_index, any:_member, element); - edict_t *pEntity = get_member(pEdict, member->offset, element); - if (pEntity != nullptr) { - return indexOfEdict(pEntity); - } - - return FALSE; - } - case MEMBER_VECTOR: - { - // native any:get_member(_index, any:_member, any:output[], element); - cell *pOutput = g_amxxapi.GetAmxAddr(amx, params[3]); - Vector vecDest = get_member(pEdict, member->offset, *g_amxxapi.GetAmxAddr(amx, params[4])); - - pOutput[0] = *(cell *)&vecDest.x; - pOutput[1] = *(cell *)&vecDest.y; - pOutput[2] = *(cell *)&vecDest.z; - - return 1; - } - case MEMBER_CHAR_ARRAY: - { - // native any:get_member(_index, any:_member, any:output[], maxlength); - char *dest = get_member_direct(pEdict, member->offset); - g_amxxapi.SetAmxString(amx, params[3], dest, *g_amxxapi.GetAmxAddr(amx, params[4])); - return 1; - } - case MEMBER_CHAR_POINTER: - { - // native any:get_member(_index, any:_member, any:output[], maxlength); - char *dest = get_member(pEdict, member->offset); - if (dest != nullptr) { - g_amxxapi.SetAmxString(amx, params[3], dest, *g_amxxapi.GetAmxAddr(amx, params[4])); - return 1; - } - return FALSE; - } - case MEMBER_FLOAT: - case MEMBER_INTEGER: - { - // native any:get_member(_index, any:_member, element); - return get_member(pEdict, member->offset, element); - } - case MEMBER_SHORT: - // native any:get_member(_index, any:_member, element); - return get_member(pEdict, member->offset, element); - case MEMBER_BYTE: - // native any:get_member(_index, any:_member, element); - return get_member(pEdict, member->offset, element); - case MEMBER_BOOL: - // native any:get_member(_index, any:_member, element); - return get_member(pEdict, member->offset, element); - case MEMBER_SIGNALS: - { - // native any:get_member(_index, any:_member, &_signal = 0, &_state = 0); - CUnifiedSignals signal = get_member(pEdict, member->offset); - cell *pSignal = g_amxxapi.GetAmxAddr(amx, params[3]); - cell *pState = g_amxxapi.GetAmxAddr(amx, params[4]); - - *pSignal = signal.GetSignal(); - *pState = signal.GetState(); - - return 1; - } - case MEMBER_DOUBLE: - { - return 1; - } - case MEBMER_REBUYSTRUCT: - return -1; - } - - return FALSE; -} - -// native set_member_game(any:_member, any:...); -static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params) -{ - enum args_member_e { arg_count, arg_member, arg_value, arg_elem }; - member_t *member = memberlist[params[arg_member]]; - - if (member == nullptr) { - MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]); - return FALSE; - } - - size_t value = *g_amxxapi.GetAmxAddr(amx, params[arg_value]); - size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]); - - switch (member->type) - { - case MEMBER_ENTITY: - case MEMBER_EHANDLE: - case MEMBER_EVARS: - case MEMBER_EDICT: - case MEMBER_VECTOR: - case MEMBER_CHAR_ARRAY: - case MEMBER_CHAR_POINTER: - case MEMBER_BYTE: - case MEMBER_SIGNALS: - case MEBMER_REBUYSTRUCT: - return FALSE; - case MEMBER_CLASSPTR: - { - // native set_member_game(any:_member, _value, _elem); - CBaseEntity *pEntity = NULL; - edict_t *pEdictValue = INDEXENT(value); - - if (pEdictValue != nullptr) { - pEntity = CBaseEntity::Instance(pEdictValue); - } - set_member((*g_pCSGameRules), member->offset, pEntity, element); - return 1; - } - case MEMBER_FLOAT: - case MEMBER_INTEGER: - { - // native set_member_game(any:_member, any:_value, _elem); - set_member((*g_pCSGameRules), member->offset, value, element); - return 1; - } - case MEMBER_SHORT: - { - // native set_member_game(any:_member, _value, _elem); - set_member((*g_pCSGameRules), member->offset, value, element); - return 1; - } - case MEMBER_BOOL: - { - // native set_member_game(any:_member, bool:_value, _elem); - set_member((*g_pCSGameRules), member->offset, value != 0, element); - return 1; - } - case MEMBER_DOUBLE: - { - // native set_member_game(any:_member, _value); - set_member((*g_pCSGameRules), member->offset, value); - return 1; - } - } - - return FALSE; -} - -// native get_member_game(any:_member, any:...); -static cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params) -{ - enum args_member_e { arg_count, arg_member, arg_elem }; - member_t *member = memberlist[params[arg_member]]; - - if (member == nullptr) { - MF_LogError(amx, AMX_ERR_NATIVE, "Member (%d) is unknown", params[arg_member]); - return FALSE; - } - - size_t element = *g_amxxapi.GetAmxAddr(amx, params[arg_elem]); - - switch (member->type) - { - case MEMBER_ENTITY: - case MEMBER_EHANDLE: - case MEMBER_EVARS: - case MEMBER_EDICT: - case MEMBER_VECTOR: - case MEMBER_CHAR_ARRAY: - case MEMBER_CHAR_POINTER: - case MEMBER_BYTE: - case MEMBER_SIGNALS: - case MEBMER_REBUYSTRUCT: - return -1; - case MEMBER_CLASSPTR: - // native any:get_member_game(any:_member, element); - return get_member((*g_pCSGameRules), member->offset, element)->entindex(); - case MEMBER_FLOAT: - case MEMBER_INTEGER: - { - // native any:get_member_game(any:_member, element); - // members for m_VoiceGameMgr - if (params[arg_member] >= m_msgPlayerVoiceMask && params[arg_member] <= m_nMaxPlayers) { - return get_member(&((*g_pCSGameRules)->m_VoiceGameMgr), member->offset); - } - (*g_pCSGameRules)->m_iMapVotes[5] = 1337; - return get_member((*g_pCSGameRules), member->offset, element); - } - case MEMBER_SHORT: - // native any:get_member_game(any:_member); - return get_member((*g_pCSGameRules), member->offset); - case MEMBER_BOOL: - // native any:get_member_game(any:_member); - return get_member((*g_pCSGameRules), member->offset); - case MEMBER_DOUBLE: - { - // native get_member_game(any:_member, _value); - float flRet = (float)get_member(&((*g_pCSGameRules)->m_VoiceGameMgr), member->offset); - return *(cell *)&flRet; - } - } - - return FALSE; -} - -AMX_NATIVE_INFO Member_Natives[] = -{ - { "set_member", set_member }, - { "get_member", get_member }, - - { "set_member_game", set_member_game }, - { "get_member_game", get_member_game }, - - { nullptr, nullptr } -}; diff --git a/reapi/src/natives_members.cpp b/reapi/src/natives_members.cpp new file mode 100644 index 0000000..37b526b --- /dev/null +++ b/reapi/src/natives_members.cpp @@ -0,0 +1,370 @@ +#include "precompiled.h" + +// native set_member(_index, any:_member, any:...); +static cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) +{ + enum args_member_e { arg_count, arg_index, arg_member, arg_value, arg_elem }; + member_t *member = memberlist[params[arg_member]]; + + if (member == nullptr) { + MF_LogError(amx, AMX_ERR_NATIVE, "set_member: unknown member id %i", params[arg_member]); + return FALSE; + } + + edict_t *pEdict = INDEXENT(params[arg_index]); + if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) { + MF_LogError(amx, AMX_ERR_NATIVE, "set_member: invalid or uninitialized entity", params[arg_member]); + return FALSE; + } + + cell* value = getAmxAddr(amx, params[arg_value]); + size_t element = (params[arg_count] == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0; + + return set_member(pEdict->pvPrivateData, member, element, value); +} + +// native any:get_member(_index = 0, any:_member, any:...); +static cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) +{ + enum args_member_e { arg_count, arg_index, arg_member, arg_3, arg_4 }; + member_t *member = memberlist[params[arg_member]]; + + if (member == nullptr) { + MF_LogError(amx, AMX_ERR_NATIVE, "get_member: unknown member id %i", params[arg_member]); + return FALSE; + } + + edict_t *pEdict = INDEXENT(params[arg_index]); + if (pEdict == nullptr || pEdict->pvPrivateData == nullptr) { + MF_LogError(amx, AMX_ERR_NATIVE, "get_member: invalid or uninitialized entity", params[arg_member]); + return FALSE; + } + + cell* dest; + size_t element; + + if (params[arg_count] == 4) { + dest = getAmxAddr(amx, params[arg_3]); + element = *getAmxAddr(amx, params[arg_4]); + } + else if (params[arg_count] == 3) { + cell* arg3 = getAmxAddr(amx, params[arg_3]); + + if (isTypeReturnable(member->type)) { + dest = nullptr; + element = *arg3; + } + else { + dest = arg3; + element = 0; + } + } + else { + dest = nullptr; + element = 0; + } + + return get_member(pEdict->pvPrivateData, member, element, dest); +} + +// native set_member_game(any:_member, any:...); +static cell AMX_NATIVE_CALL set_member_game(AMX *amx, cell *params) +{ + enum args_member_e { arg_count, arg_member, arg_value, arg_elem }; + member_t *member = memberlist[params[arg_member]]; + + if (member == nullptr) { + MF_LogError(amx, AMX_ERR_NATIVE, "set_member_game: unknown member id %i", params[arg_member]); + return FALSE; + } + + cell* value = getAmxAddr(amx, params[arg_value]); + size_t element = (params[arg_count] == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0; + + return set_member(*g_pCSGameRules, member, element, value); +} + +// native get_member_game(any:_member, any:...); +static cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params) +{ + enum args_member_e { arg_count, arg_member, arg_3, arg_4 }; + member_t *member = memberlist[params[arg_member]]; + + if (member == nullptr) { + MF_LogError(amx, AMX_ERR_NATIVE, "get_member_game: unknown member id %i", params[arg_member]); + return 0; + } + + cell* dest; + size_t element; + + if (params[arg_count] == 4) { + dest = getAmxAddr(amx, params[arg_3]); + element = *getAmxAddr(amx, params[arg_4]); + } + else if (params[arg_count] == 3) { + cell* arg3 = getAmxAddr(amx, params[arg_3]); + + if (isTypeReturnable(member->type)) { + dest = nullptr; + element = *arg3; + } + else { + dest = arg3; + element = 0; + } + } + else { + dest = nullptr; + element = 0; + } + + return get_member(*g_pCSGameRules, member, element, dest); +} + +AMX_NATIVE_INFO Member_Natives[] = +{ + { "set_member", set_member }, + { "get_member", get_member }, + + { "set_member_game", set_member_game }, + { "get_member_game", get_member_game }, + + { nullptr, nullptr } +}; + +void RegisterNatives_Members() +{ + g_amxxapi.AddNatives(Member_Natives); +} + +BOOL set_member(void* pdata, const member_t *member, size_t element, cell* value) +{ + switch (member->type) { + case MEMBER_CLASSPTR: + { + // native set_member(_index, any:_member, _value, _elem); + CBaseEntity *pEntity = CBaseEntity::Instance(INDEXENT(*value)); + set_member(pdata, member->offset, pEntity, element); + return TRUE; + } + case MEMBER_EHANDLE: + { + // native set_member(_index, any:_member, _value, _elem); + EHANDLE& ehandle = get_member(pdata, member->offset, element); + edict_t *pEdictValue = INDEXENT(*value); + ehandle.Set(pEdictValue); + return TRUE; + } + case MEMBER_EDICT: + { + // native set_member(_index, any:_member, _value, _elem); + edict_t *pEdictValue = INDEXENT(*value); + set_member(pdata, member->offset, pEdictValue, element); + return TRUE; + } + case MEMBER_VECTOR: + { + // native set_member(_index, any:_member, Float:_value[3], _elem); + Vector *pSource = (Vector *)value; + set_member(pdata, member->offset, *pSource, element); + return TRUE; + } + case MEMBER_CHAR_ARRAY: + { + // native set_member(_index, any:_member, const source[]); + size_t len; + char *source = getAmxString(value, &len); + char *dest = get_member_direct(pdata, member->offset); + strncpy(dest, source, member->max_size - 1); + dest[member->max_size - 1] = '\0'; + return TRUE; + } + case MEMBER_CHAR_POINTER: + { + // native set_member(_index, any:_member, const source[]); + size_t len; + char *source = getAmxString(value, &len); + char *&dest = get_member(pdata, member->offset); + + if (dest != nullptr) { + delete[] dest; + } + + dest = new char[len + 1]; + strcpy(dest, source); + + set_member(pdata, member->offset, dest); + return TRUE; + } + case MEMBER_FLOAT: + case MEMBER_INTEGER: + { + // native set_member(_index, any:_member, any:_value, _elem); + set_member(pdata, member->offset, *value, element); + return TRUE; + } + case MEMBER_SHORT: + { + // native set_member(_index, any:_member, _value, _elem); + set_member(pdata, member->offset, *value, element); + return TRUE; + } + case MEMBER_BYTE: + { + // native set_member(_index, any:_member, _value, _elem); + set_member(pdata, member->offset, *value, element); + return TRUE; + } + case MEMBER_BOOL: + { + // native set_member(_index, any:_member, bool:_value, _elem); + set_member(pdata, member->offset, *value != 0, element); + return TRUE; + } + case MEMBER_SIGNALS: + { + // native set_member(_index, any:_member, _value); + CUnifiedSignals& signal = get_member(pdata, member->offset, element); + signal.Signal(*value); + return TRUE; + } + case MEMBER_DOUBLE: + { + // native set_member(_index, any:_member, any:_value, _elem); + set_member(pdata, member->offset, *(float *)value, element); + return TRUE; + } + + case MEMBER_ENTITY: + case MEMBER_EVARS: + case MEBMER_REBUYSTRUCT: + return FALSE; + } + + return FALSE; +} + +cell get_member(void* pdata, const member_t *member, size_t element, cell* dest) +{ + switch (member->type) + { + case MEMBER_CLASSPTR: + // native any:get_member(_index, any:_member, element); + return get_member(pdata, member->offset, element)->entindex(); + case MEMBER_EHANDLE: + { + // native any:get_member(_index, any:_member, element); + EHANDLE ehandle = get_member(pdata, member->offset, element); + edict_t *pEntity = ehandle.Get(); + if (pEntity != nullptr) { + return ENTINDEX(pEntity); + } + return -1; + } + case MEMBER_EDICT: + { + // native any:get_member(_index, any:_member, element); + edict_t *pEntity = get_member(pdata, member->offset, element); + if (pEntity != nullptr) { + return ENTINDEX(pEntity); + } + + return -1; + } + case MEMBER_VECTOR: + { + // native any:get_member(_index, any:_member, any:output[], element); + if (!dest) + return 0; + + cell* vecSrc = get_member_direct(pdata, member->offset, element); + + dest[0] = vecSrc[0]; + dest[1] = vecSrc[1]; + dest[2] = vecSrc[2]; + return 1; + } + case MEMBER_CHAR_ARRAY: + { + // native any:get_member(_index, any:_member, any:output[], maxlength); + if (!dest) + return 0; + + const char *src = get_member_direct(pdata, member->offset); + setAmxString(dest, src, element); + return 1; + } + case MEMBER_CHAR_POINTER: + { + // native any:get_member(_index, any:_member, any:output[], maxlength); + if (!dest) + return 0; + + const char *src = get_member(pdata, member->offset); + if (src != nullptr) { + setAmxString(dest, src, element); + return 1; + } + setAmxString(dest, "", 1); + return 0; + } + case MEMBER_FLOAT: + case MEMBER_INTEGER: + // native any:get_member(_index, any:_member, element); + return get_member(pdata, member->offset, element); + case MEMBER_SHORT: + // native any:get_member(_index, any:_member, element); + return get_member(pdata, member->offset, element); + case MEMBER_BYTE: + // native any:get_member(_index, any:_member, element); + return get_member(pdata, member->offset, element); + case MEMBER_BOOL: + // native any:get_member(_index, any:_member, element); + return get_member(pdata, member->offset, element); + case MEMBER_DOUBLE: + // native any:get_member(_index, any:_member, element); + return get_member(pdata, member->offset, element); + case MEMBER_SIGNALS: + { + enum {_Signal, _State}; + + // native any:get_member(_index, any:_member, signals[2]); + if (!dest) + return 0; + + CUnifiedSignals& signal = get_member(pdata, member->offset); + + int *pSignals = dest; + pSignals[_Signal] = signal.GetSignal(); + pSignals[_State] = signal.GetState(); + return 1; + } + + case MEMBER_ENTITY: + case MEMBER_EVARS: + case MEBMER_REBUYSTRUCT: + return 0; + } + + return 0; +} + +bool isTypeReturnable(MType type) +{ + switch (type) { + case MEMBER_FLOAT: + case MEMBER_DOUBLE: + case MEMBER_ENTITY: + case MEMBER_CLASSPTR: + case MEMBER_EDICT: + case MEMBER_INTEGER: + case MEMBER_SHORT: + case MEMBER_BYTE: + case MEMBER_BOOL: + return true; + + default: + return false; + } +} diff --git a/reapi/src/natives_members.h b/reapi/src/natives_members.h new file mode 100644 index 0000000..60f0088 --- /dev/null +++ b/reapi/src/natives_members.h @@ -0,0 +1,8 @@ +#pragma once + +void RegisterNatives_Members(); + +BOOL set_member(void* pdata, const member_t *member, size_t element, cell* value); +cell get_member(void* pdata, const member_t *member, size_t element, cell* dest); + +bool isTypeReturnable(MType type); diff --git a/reapi/src/precompiled.h b/reapi/src/precompiled.h index 19363c9..3877e92 100644 --- a/reapi/src/precompiled.h +++ b/reapi/src/precompiled.h @@ -36,7 +36,8 @@ #include "hook_manager.h" #include "hook_callback.h" #include "member_list.h" -#include "natives.h" +#include "natives_hookchains.h" +#include "natives_members.h" #undef DLLEXPORT #ifdef _WIN32