2
0
mirror of https://github.com/rehlds/reapi.git synced 2025-01-27 22:17:55 +03:00

Refactored member natives code

Fixed compilation under linux
This commit is contained in:
asmodai 2016-04-20 00:39:38 +03:00
parent 59be98fb6a
commit 0dd99aaf6d
14 changed files with 424 additions and 459 deletions

View File

@ -202,7 +202,8 @@
<ClInclude Include="..\src\member_list.h" />
<ClInclude Include="..\src\mod_regamedll_api.h" />
<ClInclude Include="..\src\mod_rehlds_api.h" />
<ClInclude Include="..\src\natives.h" />
<ClInclude Include="..\src\natives_hookchains.h" />
<ClInclude Include="..\src\natives_members.h" />
<ClInclude Include="..\src\precompiled.h" />
<ClInclude Include="..\src\reapi_utils.h" />
</ItemGroup>
@ -236,8 +237,8 @@
<ClCompile Include="..\src\main.cpp" />
<ClCompile Include="..\src\meta_api.cpp" />
<ClCompile Include="..\src\mod_rehlds_api.cpp" />
<ClCompile Include="..\src\natives.cpp" />
<ClCompile Include="..\src\natives_member.cpp" />
<ClCompile Include="..\src\natives_hookchains.cpp" />
<ClCompile Include="..\src\natives_members.cpp" />
<ClCompile Include="..\src\precompiled.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

View File

@ -591,9 +591,6 @@
<ClInclude Include="..\src\amxxmodule.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\natives.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\precompiled.h">
<Filter>src</Filter>
</ClInclude>
@ -621,6 +618,12 @@
<ClInclude Include="..\src\hook_manager.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\natives_hookchains.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\natives_members.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\include\cssdk\common\parsemsg.cpp">
@ -644,9 +647,6 @@
<ClCompile Include="..\src\meta_api.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\natives.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\precompiled.cpp">
<Filter>src</Filter>
</ClCompile>
@ -671,9 +671,6 @@
<ClCompile Include="..\src\member_list.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\natives_member.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\hook_manager.cpp">
<Filter>src</Filter>
</ClCompile>
@ -686,6 +683,12 @@
<ClCompile Include="..\src\h_export.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\natives_hookchains.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\natives_members.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\extra\amxmodx\scripting\include\reapi.inc">

View File

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

View File

@ -78,21 +78,6 @@ struct hookctx_t
extern hookctx_t* g_hookCtx;
#pragma optimize("ts", on)
template <typename original_t, typename ...f_args>
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 <typename original_t, typename ...f_args>
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 <typename R, typename original_t, typename ...f_args>
R callForward(size_t func, original_t original, f_args... args)
template <typename original_t, typename ...f_args>
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<R>(g_hookManager.getHook(func), original, args...);
_callVoidForward(g_hookManager.getHook(func), original, args...);
g_hookCtx = nullptr;
return ret;
}
template <typename R, typename original_t, typename ...f_args>
@ -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 <typename R, typename original_t, typename ...f_args>
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<R>(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);

View File

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

View File

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

View File

@ -3,7 +3,7 @@
struct regmember
{
template<typename T>
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<typename T>
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;

View File

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

View File

@ -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);
}

View File

@ -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();

View File

@ -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<CBaseEntity *>(pEdict, member->offset, pEntity, element);
return TRUE;
}
case MEMBER_EHANDLE:
{
// native set_member(_index, any:_member, _value, _elem);
EHANDLE& ehandle = get_member<EHANDLE>(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<edict_t *>(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<Vector>(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<char *>(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<char *>(pEdict, member->offset);
if (dest != nullptr) {
delete [] dest;
}
dest = new char[len + 1];
strcpy(dest, source);
set_member<char *>(pEdict, member->offset, dest);
return TRUE;
}
case MEMBER_FLOAT:
case MEMBER_INTEGER:
{
// native set_member(_index, any:_member, any:_value, _elem);
set_member<int>(pEdict, member->offset, *value, element);
return TRUE;
}
case MEMBER_SHORT:
{
// native set_member(_index, any:_member, _value, _elem);
set_member<short>(pEdict, member->offset, *value, element);
return TRUE;
}
case MEMBER_BYTE:
{
// native set_member(_index, any:_member, _value, _elem);
set_member<byte>(pEdict, member->offset, *value, element);
return TRUE;
}
case MEMBER_BOOL:
{
// native set_member(_index, any:_member, bool:_value, _elem);
set_member<bool>(pEdict, member->offset, *value != 0, element);
return TRUE;
}
case MEMBER_SIGNALS:
{
// native set_member(_index, any:_member, _value);
CUnifiedSignals& signal = get_member<CUnifiedSignals>(pEdict, member->offset, element);
signal.Signal(*value);
return TRUE;
}
case MEMBER_DOUBLE:
{
// native set_member(_index, any:_member, any:_value, _elem);
set_member<double>(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<CBaseEntity *>(pEdict, member->offset, element)->entindex();
case MEMBER_EHANDLE:
{
// native any:get_member(_index, any:_member, element);
EHANDLE ehandle = get_member<EHANDLE>(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<edict_t *>(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<Vector>(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<char *>(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<char *>(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<int>(pEdict, member->offset, element);
}
case MEMBER_SHORT:
// native any:get_member(_index, any:_member, element);
return get_member<short>(pEdict, member->offset, element);
case MEMBER_BYTE:
// native any:get_member(_index, any:_member, element);
return get_member<byte>(pEdict, member->offset, element);
case MEMBER_BOOL:
// native any:get_member(_index, any:_member, element);
return get_member<bool>(pEdict, member->offset, element);
case MEMBER_SIGNALS:
{
// native any:get_member(_index, any:_member, &_signal = 0, &_state = 0);
CUnifiedSignals signal = get_member<CUnifiedSignals>(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<CBaseEntity *>((*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<int>((*g_pCSGameRules), member->offset, value, element);
return 1;
}
case MEMBER_SHORT:
{
// native set_member_game(any:_member, _value, _elem);
set_member<short>((*g_pCSGameRules), member->offset, value, element);
return 1;
}
case MEMBER_BOOL:
{
// native set_member_game(any:_member, bool:_value, _elem);
set_member<bool>((*g_pCSGameRules), member->offset, value != 0, element);
return 1;
}
case MEMBER_DOUBLE:
{
// native set_member_game(any:_member, _value);
set_member<double>((*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<CBaseEntity *>((*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<int>(&((*g_pCSGameRules)->m_VoiceGameMgr), member->offset);
}
(*g_pCSGameRules)->m_iMapVotes[5] = 1337;
return get_member<int>((*g_pCSGameRules), member->offset, element);
}
case MEMBER_SHORT:
// native any:get_member_game(any:_member);
return get_member<short>((*g_pCSGameRules), member->offset);
case MEMBER_BOOL:
// native any:get_member_game(any:_member);
return get_member<bool>((*g_pCSGameRules), member->offset);
case MEMBER_DOUBLE:
{
// native get_member_game(any:_member, _value);
float flRet = (float)get_member<double>(&((*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 }
};

View File

@ -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<CBaseEntity *>(pdata, member->offset, pEntity, element);
return TRUE;
}
case MEMBER_EHANDLE:
{
// native set_member(_index, any:_member, _value, _elem);
EHANDLE& ehandle = get_member<EHANDLE>(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<edict_t *>(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<Vector>(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<char *>(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<char *>(pdata, member->offset);
if (dest != nullptr) {
delete[] dest;
}
dest = new char[len + 1];
strcpy(dest, source);
set_member<char *>(pdata, member->offset, dest);
return TRUE;
}
case MEMBER_FLOAT:
case MEMBER_INTEGER:
{
// native set_member(_index, any:_member, any:_value, _elem);
set_member<int>(pdata, member->offset, *value, element);
return TRUE;
}
case MEMBER_SHORT:
{
// native set_member(_index, any:_member, _value, _elem);
set_member<short>(pdata, member->offset, *value, element);
return TRUE;
}
case MEMBER_BYTE:
{
// native set_member(_index, any:_member, _value, _elem);
set_member<byte>(pdata, member->offset, *value, element);
return TRUE;
}
case MEMBER_BOOL:
{
// native set_member(_index, any:_member, bool:_value, _elem);
set_member<bool>(pdata, member->offset, *value != 0, element);
return TRUE;
}
case MEMBER_SIGNALS:
{
// native set_member(_index, any:_member, _value);
CUnifiedSignals& signal = get_member<CUnifiedSignals>(pdata, member->offset, element);
signal.Signal(*value);
return TRUE;
}
case MEMBER_DOUBLE:
{
// native set_member(_index, any:_member, any:_value, _elem);
set_member<double>(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<CBaseEntity *>(pdata, member->offset, element)->entindex();
case MEMBER_EHANDLE:
{
// native any:get_member(_index, any:_member, element);
EHANDLE ehandle = get_member<EHANDLE>(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<edict_t *>(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<cell *>(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<const char *>(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<const char *>(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<int>(pdata, member->offset, element);
case MEMBER_SHORT:
// native any:get_member(_index, any:_member, element);
return get_member<short>(pdata, member->offset, element);
case MEMBER_BYTE:
// native any:get_member(_index, any:_member, element);
return get_member<byte>(pdata, member->offset, element);
case MEMBER_BOOL:
// native any:get_member(_index, any:_member, element);
return get_member<bool>(pdata, member->offset, element);
case MEMBER_DOUBLE:
// native any:get_member(_index, any:_member, element);
return get_member<double>(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<CUnifiedSignals>(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;
}
}

View File

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

View File

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