Implement raw entity handle accessors (#1830)

* Implement raw entity handle accessors

* Fix FromPseudoAddress calls on 64-bit

* fixup: Remove unnecessary ent deref

* fixup: Correct param index in thrown error
This commit is contained in:
nosoop 2022-12-28 19:57:47 -08:00 committed by GitHub
parent ecb707e38d
commit 2130c60fd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 86 additions and 0 deletions

View File

@ -706,6 +706,36 @@ static cell_t GetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
return g_HL2.EntityToBCompatRef(pHandleEntity);
}
//memory addresses below 0x10000 are automatically considered invalid for dereferencing
//this is copied over from smn_core.cpp
#define VALID_MINIMUM_MEMORY_ADDRESS 0x10000
static cell_t LoadEntityFromHandleAddress(IPluginContext *pContext, const cell_t *params)
{
#ifdef PLATFORM_X86
void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = g_SourceMod.FromPseudoAddress(params[1]);
#endif
if (addr == NULL)
{
return pContext->ThrowNativeError("Address cannot be null");
}
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
}
CBaseHandle &hndl = *reinterpret_cast<CBaseHandle*>(addr);
CBaseEntity *pHandleEntity = g_HL2.ReferenceToEntity(hndl.GetEntryIndex());
if (!pHandleEntity || hndl != reinterpret_cast<IHandleEntity *>(pHandleEntity)->GetRefEHandle())
return -1;
return g_HL2.EntityToBCompatRef(pHandleEntity);
}
/* THIS GUY IS DEPRECATED. */
static cell_t SetEntDataEnt(IPluginContext *pContext, const cell_t *params)
{
@ -791,6 +821,44 @@ static cell_t SetEntDataEnt2(IPluginContext *pContext, const cell_t *params)
return 1;
}
static cell_t StoreEntityToHandleAddress(IPluginContext *pContext, const cell_t *params)
{
#ifdef PLATFORM_X86
void *addr = reinterpret_cast<void*>(params[1]);
#else
void *addr = g_SourceMod.FromPseudoAddress(params[1]);
#endif
if (addr == NULL)
{
return pContext->ThrowNativeError("Address cannot be null");
}
else if (reinterpret_cast<uintptr_t>(addr) < VALID_MINIMUM_MEMORY_ADDRESS)
{
return pContext->ThrowNativeError("Invalid address 0x%x is pointing to reserved memory.", addr);
}
CBaseHandle &hndl = *reinterpret_cast<CBaseHandle*>(addr);
if ((unsigned)params[2] == INVALID_EHANDLE_INDEX)
{
hndl.Set(NULL);
}
else
{
CBaseEntity *pOther = GetEntity(params[2]);
if (!pOther)
{
return pContext->ThrowNativeError("Entity %d (%d) is invalid", g_HL2.ReferenceToIndex(params[2]), params[2]);
}
IHandleEntity *pHandleEnt = (IHandleEntity *)pOther;
hndl.Set(pHandleEnt);
}
return 1;
}
static cell_t ChangeEdictState(IPluginContext *pContext, const cell_t *params)
{
edict_t *pEdict = GetEdict(params[1]);
@ -2752,5 +2820,7 @@ REGISTER_NATIVES(entityNatives)
{"SetEntPropVector", SetEntPropVector},
{"GetEntityAddress", GetEntityAddress},
{"FindDataMapInfo", FindDataMapInfo},
{"LoadEntityFromHandleAddress", LoadEntityFromHandleAddress},
{"StoreEntityToHandleAddress", StoreEntityToHandleAddress},
{NULL, NULL}
};

View File

@ -767,3 +767,19 @@ stock bool GetEntityClassname(int entity, char[] clsname, int maxlength)
{
return !!GetEntPropString(entity, Prop_Data, "m_iClassname", clsname, maxlength);
}
/**
* Interprets the address as an entity handle and returns the associated entity.
*
* @param addr Address to a memory location.
* @return Entity index at the given location. If there is no entity, or the stored entity is invalid, then -1 is returned.
*/
native int LoadEntityFromHandleAddress(Address addr);
/**
* Interprets the address as an entity handle and sets the entity.
*
* @param addr Address to a memory location.
* @param entity Entity index to set, or -1 to clear.
*/
native void StoreEntityToHandleAddress(Address addr, int entity);