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
|