mirror of
https://github.com/rehlds/reapi.git
synced 2025-01-27 05:57:55 +03:00
Implemented g/set_member safe version
This commit is contained in:
parent
9e16f2769a
commit
2491fb9865
@ -1,3 +1,3 @@
|
|||||||
majorVersion=5
|
majorVersion=5
|
||||||
minorVersion=17
|
minorVersion=18
|
||||||
maintenanceVersion=0
|
maintenanceVersion=0
|
||||||
|
@ -94,6 +94,13 @@ enum members_tables_e
|
|||||||
#include <reapi_engine> // @note: only for ReHLDS
|
#include <reapi_engine> // @note: only for ReHLDS
|
||||||
#include <reapi_gamedll> // @note: only for gamedll Counter-Strike (ReGameDLL_CS)
|
#include <reapi_gamedll> // @note: only for gamedll Counter-Strike (ReGameDLL_CS)
|
||||||
|
|
||||||
|
// If you want to use s/get_member unsafe version,
|
||||||
|
// then macro MEMBER_UNSAFE must be defined before including header reapi.inc
|
||||||
|
#if !defined(MEMBER_UNSAFE)
|
||||||
|
#define set_member set_member_s
|
||||||
|
#define get_member get_member_s
|
||||||
|
#endif
|
||||||
|
|
||||||
// addons
|
// addons
|
||||||
#include <reapi_vtc>
|
#include <reapi_vtc>
|
||||||
#include <reapi_reunion>
|
#include <reapi_reunion>
|
||||||
|
@ -120,6 +120,28 @@ native set_member(const index, any:member, any:...);
|
|||||||
*/
|
*/
|
||||||
native any:get_member(const index, any:member, any:...);
|
native any:get_member(const index, any:member, any:...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets a value to an entity's member.
|
||||||
|
* Safe version, can guarantee that the present member is refers to derived class of the entity.
|
||||||
|
*
|
||||||
|
* @param index Entity index
|
||||||
|
* @param member The specified member, look at the enums with name *_Members
|
||||||
|
*
|
||||||
|
* @return 1 on success.
|
||||||
|
*/
|
||||||
|
native set_member_s(const index, any:member, any:...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a value from an entity's member.
|
||||||
|
* Safe version, can guarantee that the present member is refers to derived class of the entity.
|
||||||
|
*
|
||||||
|
* @param index Entity index
|
||||||
|
* @param member The specified member, look at the enums with name *_Members
|
||||||
|
*
|
||||||
|
* @return If an integer or boolean or one byte, array or everything else is passed via the 3rd argument and more, look at the argument list for the specified member
|
||||||
|
*/
|
||||||
|
native any:get_member_s(const index, any:member, any:...);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets playermove var.
|
* Sets playermove var.
|
||||||
*
|
*
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
#define decltypefxdot(cx, pref, mx) decltype(cx::pref.mx)
|
#define decltypefxdot(cx, pref, mx) decltype(cx::pref.mx)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CLASS_MEMBERS(cx, mx, postf) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefx(cx, , mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(cx, mx);ptr->type = getMemberType(f);ptr->name = #postf;}) : regmember(#mx)
|
#define CLASS_MEMBERS(cx, mx, postf) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefx(cx, , mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(cx, mx);ptr->type = getMemberType(f);ptr->name = #postf;ptr->pfnIsRefsToClass = [](CBaseEntity *pEntity){ return dynamic_cast<cx *>(pEntity) != nullptr;};}) : regmember(#mx)
|
||||||
#define CLASS_MEMBERS_PREF(cx, mx, postf, pref) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefx(cx, pref, mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(cx, pref##mx);ptr->type = getMemberType(f);ptr->name = #postf;}) : regmember(#pref#mx)
|
#define CLASS_MEMBERS_PREF(cx, mx, postf, pref) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefx(cx, pref, mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(cx, pref##mx);ptr->type = getMemberType(f);ptr->name = #postf;ptr->pfnIsRefsToClass = [](CBaseEntity *pEntity){ return dynamic_cast<cx *>(pEntity) != nullptr;};}) : regmember(#pref#mx)
|
||||||
#define CLASS_MEMBERS_DOT(cx, mx, postf, pref) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefxdot(cx, pref, mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(cx, pref.mx);ptr->type = getMemberType(f);ptr->name = #postf;}) : regmember(#pref"."#mx)
|
#define CLASS_MEMBERS_DOT(cx, mx, postf, pref) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefxdot(cx, pref, mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(cx, pref.mx);ptr->type = getMemberType(f);ptr->name = #postf;ptr->pfnIsRefsToClass = [](CBaseEntity *pEntity){ return dynamic_cast<cx *>(pEntity) != nullptr;};}) : regmember(#pref"."#mx)
|
||||||
|
|
||||||
#define GM_MEMBERS(mx) CLASS_MEMBERS(CHalfLifeMultiplay, mx, mx)
|
#define GM_MEMBERS(mx) CLASS_MEMBERS(CHalfLifeMultiplay, mx, mx)
|
||||||
#define GM_VOICE_MEMBERS(mx) CLASS_MEMBERS_DOT(CHalfLifeMultiplay, mx, mx, m_VoiceGameMgr)
|
#define GM_VOICE_MEMBERS(mx) CLASS_MEMBERS_DOT(CHalfLifeMultiplay, mx, mx, m_VoiceGameMgr)
|
||||||
@ -616,7 +616,7 @@ member_t memberlist_entvars[] = {
|
|||||||
EVAR_MEMBERS(euser1),
|
EVAR_MEMBERS(euser1),
|
||||||
EVAR_MEMBERS(euser2),
|
EVAR_MEMBERS(euser2),
|
||||||
EVAR_MEMBERS(euser3),
|
EVAR_MEMBERS(euser3),
|
||||||
EVAR_MEMBERS(euser4)
|
EVAR_MEMBERS(euser4),
|
||||||
};
|
};
|
||||||
|
|
||||||
member_t memberlist_playermove[] = {
|
member_t memberlist_playermove[] = {
|
||||||
@ -723,7 +723,7 @@ member_t memberlist_usercmd[] = {
|
|||||||
UCMD_MEMBERS(impulse),
|
UCMD_MEMBERS(impulse),
|
||||||
UCMD_MEMBERS(weaponselect),
|
UCMD_MEMBERS(weaponselect),
|
||||||
UCMD_MEMBERS(impact_index),
|
UCMD_MEMBERS(impact_index),
|
||||||
UCMD_MEMBERS(impact_position)
|
UCMD_MEMBERS(impact_position),
|
||||||
};
|
};
|
||||||
|
|
||||||
member_t memberlist_pmtrace[] = {
|
member_t memberlist_pmtrace[] = {
|
||||||
@ -735,7 +735,7 @@ member_t memberlist_pmtrace[] = {
|
|||||||
PMTRACE_MEMBERS(endpos),
|
PMTRACE_MEMBERS(endpos),
|
||||||
PMTRACE_MEMBERS(ent),
|
PMTRACE_MEMBERS(ent),
|
||||||
PMTRACE_MEMBERS(deltavelocity),
|
PMTRACE_MEMBERS(deltavelocity),
|
||||||
PMTRACE_MEMBERS(hitgroup)
|
PMTRACE_MEMBERS(hitgroup),
|
||||||
};
|
};
|
||||||
|
|
||||||
member_t memberlist_csplayer[] = {
|
member_t memberlist_csplayer[] = {
|
||||||
@ -790,7 +790,7 @@ member_t memberlist_baseweapon[] = {
|
|||||||
BASEWPN_MEMBERS(usFireGlock18),
|
BASEWPN_MEMBERS(usFireGlock18),
|
||||||
BASEWPN_MEMBERS(usFireFamas),
|
BASEWPN_MEMBERS(usFireFamas),
|
||||||
BASEWPN_MEMBERS(flPrevPrimaryAttack),
|
BASEWPN_MEMBERS(flPrevPrimaryAttack),
|
||||||
BASEWPN_MEMBERS(flLastFireTime)
|
BASEWPN_MEMBERS(flLastFireTime),
|
||||||
};
|
};
|
||||||
|
|
||||||
member_t memberlist_weaponbox[] = {
|
member_t memberlist_weaponbox[] = {
|
||||||
|
@ -95,6 +95,7 @@ struct member_t
|
|||||||
size_t offset;
|
size_t offset;
|
||||||
const char *name;
|
const char *name;
|
||||||
MType type;
|
MType type;
|
||||||
|
bool (*pfnIsRefsToClass)(class CBaseEntity *pEntity);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool member_t::isTypeReturnable() const
|
inline bool member_t::isTypeReturnable() const
|
||||||
|
@ -108,6 +108,131 @@ cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets a value to an entity's member.
|
||||||
|
* Safe version, can guarantee that the present member is refers to derived class of the entity.
|
||||||
|
*
|
||||||
|
* @param index Entity index
|
||||||
|
* @param member The specified member, look at the enums with name *_Members
|
||||||
|
*
|
||||||
|
* @return 1 on success.
|
||||||
|
* native set_member_safe(const index, any:member, any:...);
|
||||||
|
*/
|
||||||
|
cell AMX_NATIVE_CALL set_member_s(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
enum args_e { arg_count, arg_index, arg_member, arg_value, arg_elem };
|
||||||
|
member_t *member = memberlist[params[arg_member]];
|
||||||
|
|
||||||
|
if (unlikely(member == nullptr)) {
|
||||||
|
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: unknown member id %i", __FUNCTION__, params[arg_member]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
edict_t *pEdict = edictByIndexAmx(params[arg_index]);
|
||||||
|
if (unlikely(pEdict == nullptr || pEdict->pvPrivateData == nullptr)) {
|
||||||
|
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell* value = getAmxAddr(amx, params[arg_value]);
|
||||||
|
size_t element = (PARAMS_COUNT == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0;
|
||||||
|
CBaseEntity *pEntity = getPrivate<CBaseEntity>(pEdict);
|
||||||
|
|
||||||
|
if (!member->pfnIsRefsToClass(pEntity))
|
||||||
|
{
|
||||||
|
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: '%s' has no refs to the base class of an entity '%s'", __FUNCTION__, member->name, STRING(pEdict->v.classname));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return set_member(
|
||||||
|
get_pdata_custom(pEntity, params[arg_member]),
|
||||||
|
member,
|
||||||
|
value,
|
||||||
|
element
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a value from an entity's member.
|
||||||
|
* Safe version, can guarantee that the present member is refers to derived class of the entity.
|
||||||
|
*
|
||||||
|
* @param index Entity index
|
||||||
|
* @param member The specified member, look at the enums with name *_Members
|
||||||
|
*
|
||||||
|
* @return If an integer or boolean or one byte, array or everything else is passed via the 3rd argument and more, look at the argument list for the specified member
|
||||||
|
*
|
||||||
|
* native any:get_member_safe(const index, any:member, any:...);
|
||||||
|
*/
|
||||||
|
cell AMX_NATIVE_CALL get_member_s(AMX *amx, cell *params)
|
||||||
|
{
|
||||||
|
enum args_e { arg_count, arg_index, arg_member, arg_3, arg_4, arg_5 };
|
||||||
|
member_t *member = memberlist[params[arg_member]];
|
||||||
|
|
||||||
|
if (unlikely(member == nullptr)) {
|
||||||
|
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: unknown member id %i", __FUNCTION__, params[arg_member]);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
edict_t *pEdict = edictByIndexAmx(params[arg_index]);
|
||||||
|
if (unlikely(pEdict == nullptr || pEdict->pvPrivateData == nullptr)) {
|
||||||
|
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid or uninitialized entity", __FUNCTION__);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell* dest;
|
||||||
|
size_t element;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
switch (PARAMS_COUNT)
|
||||||
|
{
|
||||||
|
case 5:
|
||||||
|
dest = getAmxAddr(amx, params[arg_3]);
|
||||||
|
length = *getAmxAddr(amx, params[arg_4]);
|
||||||
|
element = *getAmxAddr(amx, params[arg_5]);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
dest = getAmxAddr(amx, params[arg_3]);
|
||||||
|
length = *getAmxAddr(amx, params[arg_4]);
|
||||||
|
element = 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
cell* arg3 = getAmxAddr(amx, params[arg_3]);
|
||||||
|
if (member->isTypeReturnable()) {
|
||||||
|
dest = nullptr;
|
||||||
|
element = *arg3;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dest = arg3;
|
||||||
|
element = 0;
|
||||||
|
}
|
||||||
|
length = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
dest = nullptr;
|
||||||
|
element = 0;
|
||||||
|
length = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBaseEntity *pEntity = getPrivate<CBaseEntity>(pEdict);
|
||||||
|
|
||||||
|
if (!member->pfnIsRefsToClass(pEntity))
|
||||||
|
{
|
||||||
|
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: '%s' has no refs to the base class of an entity '%s'", __FUNCTION__, member->name, STRING(pEdict->v.classname));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_member(
|
||||||
|
get_pdata_custom(pEntity, params[arg_member]),
|
||||||
|
member,
|
||||||
|
dest,
|
||||||
|
element,
|
||||||
|
length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets a value to CSGameRules_Members members.
|
* Sets a value to CSGameRules_Members members.
|
||||||
*
|
*
|
||||||
@ -617,6 +742,9 @@ AMX_NATIVE_INFO ReGameVars_Natives[] =
|
|||||||
{ "set_member", set_member },
|
{ "set_member", set_member },
|
||||||
{ "get_member", get_member },
|
{ "get_member", get_member },
|
||||||
|
|
||||||
|
{ "set_member_s", set_member_s },
|
||||||
|
{ "get_member_s", get_member_s },
|
||||||
|
|
||||||
{ "set_member_game", set_member_game },
|
{ "set_member_game", set_member_game },
|
||||||
{ "get_member_game", get_member_game },
|
{ "get_member_game", get_member_game },
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user