Move dhookparam/return natives to its own file

This commit is contained in:
Kenzzer 2025-09-19 13:47:50 +00:00
parent c3f798d065
commit 600e07fafb
No known key found for this signature in database
GPG Key ID: 64C3FD4332686DC1
5 changed files with 739 additions and 727 deletions

View File

@ -5,7 +5,8 @@ sources = [
'src/capsule.cpp',
'src/globals.cpp',
'src/handle.cpp',
'src/register.cpp'
'src/register.cpp',
'src/natives/dhookparam.cpp'
]
for cxx in builder.targets:

View File

@ -4,8 +4,10 @@
#include <IExtensionSys.h>
#include <IGameHelpers.h>
#include <ISourceMod.h>
#include <sp_vm_types.h>
#include <thread>
#include <vector>
namespace dhooks::globals {
@ -14,6 +16,7 @@ extern SourceMod::IHandleSys* handlesys;
extern SourceMod::IGameHelpers* gamehelpers;
extern SourceMod::IExtension* myself;
extern SourceMod::ISourceMod* sourcemod;
extern std::vector<sp_nativeinfo_t> natives;
void init();

View File

@ -1,26 +1,15 @@
#include "handle.hpp"
#include "globals.hpp"
#include "capsule.hpp"
#include "sdk_types.hpp"
#include <cstdlib>
namespace dhooks::globals {
SourceMod::HandleType_t param_return_handle;
}
namespace dhooks::handle {
void init() {
SourceMod::HandleAccess security;
globals::handlesys->InitAccessDefaults(nullptr, &security);
// Do not allow cloning, the struct self-manage its handle
security.access[SourceMod::HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY;
globals::param_return_handle = globals::handlesys->CreateType("DHookParamReturn", nullptr, 0, nullptr, &security, globals::myself->GetIdentity(), nullptr);
}
SourceMod::HandleType_t ParamReturn::HANDLE_TYPE = 0;
ParamReturn::ParamReturn(const Capsule* capsule, GeneralRegister* generalregs, FloatRegister* floatregs, void* return_ptr) :
_handle(globals::handlesys->CreateHandle(globals::param_return_handle, this, globals::myself->GetIdentity(), globals::myself->GetIdentity(), nullptr)),
_handle(globals::handlesys->CreateHandle(handle::ParamReturn::HANDLE_TYPE, this, globals::myself->GetIdentity(), globals::myself->GetIdentity(), nullptr)),
_capsule(capsule),
_general_registers(generalregs),
_float_registers(floatregs),
@ -69,719 +58,12 @@ void* ParamReturn::_Get(size_t index) const {
}
}
inline ParamReturn* Get(SourcePawn::IPluginContext* context, const cell_t param) {
SourceMod::HandleSecurity security;
security.pOwner = globals::myself->GetIdentity();
security.pIdentity = globals::myself->GetIdentity();
SourceMod::Handle_t hndl = static_cast<SourceMod::Handle_t>(param);
ParamReturn* obj = nullptr;
SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, globals::param_return_handle, &security, (void **)&obj);
if (chnderr != SourceMod::HandleError_None) {
context->ThrowNativeError("Invalid Handle %x (error %i: %s)", hndl, chnderr, globals::HandleErrorToString(chnderr));
return nullptr;
void init() {
SourceMod::HandleAccess security;
globals::handlesys->InitAccessDefaults(nullptr, &security);
// Do not allow cloning, the struct self-manage its handle
security.access[SourceMod::HandleAccess_Clone] = HANDLE_RESTRICT_IDENTITY;
ParamReturn::HANDLE_TYPE = globals::handlesys->CreateType("DHookParamReturn", nullptr, 0, nullptr, &security, globals::myself->GetIdentity(), nullptr);
}
return obj;
}
inline cell_t GetParam(SourcePawn::IPluginContext* context, ParamReturn* obj, const cell_t param) {
int index = param - 1;
if (obj->GetCapsule()->GetCallConv() == sp::CallConv_THISCALL) {
// Skip the |this| ptr parameter
index += 1;
}
if (param <= 0 || index >= obj->GetCapsule()->GetParameters().size()) {
context->ThrowNativeError("Invalid param number %i max params is %i", param, obj->GetCapsule()->GetParameters().size() - ((obj->GetCapsule()->GetCallConv() == sp::CallConv_THISCALL) ? 1 : 0));
return -1;
}
return index;
}
cell_t DHookReturn_GetReturn(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
switch (ret.dhook_type) {
case sp::ReturnType_Int:
return *obj->GetReturn<int>();
case sp::ReturnType_Bool:
return (*obj->GetReturn<bool>()) ? 1 : 0;
case sp::ReturnType_CBaseEntity:
return globals::gamehelpers->EntityToBCompatRef(*obj->GetReturn<CBaseEntity*>());
case sp::ReturnType_Edict:
return globals::gamehelpers->IndexOfEdict(*obj->GetReturn<edict_t*>());
case sp::ReturnType_Float:
return sp_ftoc(*obj->GetReturn<float>());
default:
return context->ThrowNativeError("Invalid param type (%i) to get", ret.dhook_type);
}
return 0;
}
cell_t DHookReturn_SetReturn(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
switch (ret.dhook_type) {
case sp::ReturnType_Int:
*obj->GetReturn<int>() = params[2];
break;
case sp::ReturnType_Bool:
*obj->GetReturn<bool>() = params[2] != 0;
break;
case sp::ReturnType_CBaseEntity: {
CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[2]);
if (entity == nullptr) {
return context->ThrowNativeError("Invalid entity index passed for return value");
}
*obj->GetReturn<CBaseEntity*>() = entity;
break;
}
case sp::ReturnType_Edict: {
sdk::edict_t* edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->EdictOfIndex(params[2]));
if (edict == nullptr || edict->IsFree()) {
return context->ThrowNativeError("Invalid entity index passed for return value");
}
*obj->GetReturn<sdk::edict_t*>() = edict;
break;
}
case sp::ReturnType_Float:
*obj->GetReturn<float>() = sp_ctof(params[2]);
break;
default:
return context->ThrowNativeError("Invalid param type (%i) to get", ret.dhook_type);
}
return 0;
}
cell_t DHookReturn_GetReturnVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
cell_t *buffer;
context->LocalToPhysAddr(params[2], &buffer);
const auto& ret = obj->GetCapsule()->GetReturn();
sdk::Vector* vector = nullptr;
if (ret.dhook_type == sp::ReturnType_Vector) {
vector = obj->GetReturn<sdk::Vector>();
} else if(ret.dhook_type == sp::ReturnType_VectorPtr) {
auto pvector = obj->GetReturn<sdk::Vector*>();
if (*pvector == nullptr) {
return context->ThrowNativeError("Vector pointer is null");
}
vector = *pvector;
} else {
return context->ThrowNativeError("Return type is not a vector type");
}
buffer[0] = sp_ftoc(vector->x);
buffer[1] = sp_ftoc(vector->y);
buffer[2] = sp_ftoc(vector->z);
return 0;
}
static void FreeChangedVector(void* data) {
delete (sdk::Vector*)data;
}
cell_t DHookReturn_SetReturnVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
cell_t *buffer;
context->LocalToPhysAddr(params[2], &buffer);
const auto& ret = obj->GetCapsule()->GetReturn();
if (ret.dhook_type == sp::ReturnType_Vector) {
*(obj->GetReturn<sdk::Vector>()) = sdk::Vector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2]));
}
else if (ret.dhook_type == sp::ReturnType_VectorPtr) {
// Lazily free the vector a frame later
auto vector = new sdk::Vector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2]));
*(obj->GetReturn<sdk::Vector*>()) = vector;
globals::sourcemod->AddFrameAction(FreeChangedVector, vector);
} else {
return context->ThrowNativeError("Return type is not a vector type");
}
return 0;
}
cell_t DHookReturn_GetReturnString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
switch (ret.dhook_type) {
case sp::ReturnType_String:
context->StringToLocal(params[2], params[3], obj->GetReturn<sdk::string_t>()->ToCStr());
return 1;
case sp::ReturnType_StringPtr:
context->StringToLocal(params[2], params[3], (obj->GetReturn<sdk::string_t*>() != nullptr) ? (*obj->GetReturn<sdk::string_t*>())->ToCStr() : "");
return 1;
case sp::ReturnType_CharPtr:
context->StringToLocal(params[2], params[3], (*(obj->GetReturn<const char*>()) == nullptr) ? "" : *(obj->GetReturn<const char*>()));
return 1;
default:
return context->ThrowNativeError("Invalid param type to get. Param is not a string.");
}
}
static void FreeChangedCharPtr(void* data) {
delete[] (const char*)data;
}
cell_t DHookReturn_SetReturnString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
char *value;
context->LocalToString(params[2], &value);
switch (ret.dhook_type) {
case sp::ReturnType_CharPtr: {
auto new_str = new char[strlen(value) + 1];
strcpy(new_str, value);
*(obj->GetReturn<const char*>()) = new_str;
// Free it later (cheaply) after the function returned.
globals::sourcemod->AddFrameAction(FreeChangedCharPtr, new_str);
return 1;
}
default:
return context->ThrowNativeError("Invalid param type to get. Param is not a char pointer.");
}
}
cell_t DHookParam_GetParam(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
if (params[2] == 0) {
return obj->GetCapsule()->GetParameters().size();
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (sp::HookParamTypeIsPtr(var.dhook_type) && *obj->Get<void*>(index) == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
switch(var.dhook_type) {
case sp::HookParamType_Int:
return *obj->Get<int>(index);
case sp::HookParamType_Bool:
return (*obj->Get<bool>(index)) ? 1 : 0;
case sp::HookParamType_CBaseEntity:
return globals::gamehelpers->EntityToBCompatRef(*obj->Get<CBaseEntity*>(index));
case sp::HookParamType_Edict:
return globals::gamehelpers->IndexOfEdict(*obj->Get<edict_t*>(index));
case sp::HookParamType_Float:
return sp_ftoc(*obj->Get<float>(index));
default:
return context->ThrowNativeError("Invalid param type (%i) to get", var.dhook_type);
}
}
cell_t DHookParam_SetParam(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
switch (var.dhook_type) {
case sp::HookParamType_Int:
*obj->Get<int>(index) = params[3];
break;
case sp::HookParamType_Bool:
*obj->Get<bool>(index) = (params[3] ? true : false);
break;
case sp::HookParamType_CBaseEntity: {
CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[3]);
if (params[3] != -1 && entity == nullptr) {
return context->ThrowNativeError("Invalid entity reference passed for param value");
}
*obj->Get<CBaseEntity*>(index) = entity;
break;
}
case sp::HookParamType_Edict: {
sdk::edict_t* edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->EdictOfIndex(params[3]));
if (params[3] != -1 && (edict == nullptr || edict->IsFree())) {
return context->ThrowNativeError("Invalid edict index passed for param value");
}
*obj->Get<sdk::edict_t*>(index) = edict;
break;
}
case sp::HookParamType_Float:
*obj->Get<float>(index) = sp_ctof(params[3]);
break;
default:
return context->ThrowNativeError("Invalid param type (%i) to set", var.dhook_type);
}
return 0;
}
cell_t DHookParam_GetParamVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type == sp::HookParamType_VectorPtr) {
cell_t* buffer;
context->LocalToPhysAddr(params[3], &buffer);
auto vec = *obj->Get<sdk::Vector*>(index);
if (vec == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
buffer[0] = sp_ftoc(vec->x);
buffer[1] = sp_ftoc(vec->y);
buffer[2] = sp_ftoc(vec->z);
} else {
return context->ThrowNativeError("Invalid param type to get. Param is not a vector.");
}
return 0;
}
cell_t DHookParam_SetParamVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type == sp::HookParamType_VectorPtr) {
cell_t* buffer;
context->LocalToPhysAddr(params[3], &buffer);
auto vec = *obj->Get<sdk::Vector*>(index);
if (vec == nullptr) {
vec = new sdk::Vector;
globals::sourcemod->AddFrameAction(FreeChangedVector, vec);
*obj->Get<sdk::Vector*>(index) = vec;
}
vec->x = sp_ctof(buffer[0]);
vec->y = sp_ctof(buffer[1]);
vec->z = sp_ctof(buffer[2]);
} else {
return context->ThrowNativeError("Invalid param type to set. Param is not a vector.");
}
return 0;
}
cell_t DHookParam_GetParamString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (sp::HookParamTypeIsPtr(var.dhook_type) && *obj->Get<void*>(index) == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
switch (var.dhook_type) {
case sp::HookParamType_CharPtr: {
auto str = *obj->Get<const char*>(index);
context->StringToLocal(params[3], params[4], str);
break;
}
case sp::HookParamType_String: {
auto str = *obj->Get<sdk::string_t>(index);
context->StringToLocal(params[3], params[4], str.ToCStr());
break;
}
case sp::HookParamType_StringPtr: {
auto str = *obj->Get<sdk::string_t*>(index);
context->StringToLocal(params[3], params[4], str->ToCStr());
break;
}
default:
return context->ThrowNativeError("Invalid param type to get. Param is not a string.");
}
return 0;
}
cell_t DHookParam_SetParamString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
char* value;
context->LocalToString(params[3], &value);
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type == sp::HookParamType_CharPtr) {
auto str = new char[strlen(value) + 1];
strcpy(str, value);
*obj->Get<const char*>(index) = str;
// Free it later (cheaply) after the function returned.
globals::sourcemod->AddFrameAction(FreeChangedCharPtr, str);
} else if (var.dhook_type == sp::HookParamType_String || var.dhook_type == sp::HookParamType_StringPtr) {
return context->ThrowNativeError("DHooks currently lacks support for setting string_t. Pull requests are welcome!");
} else {
return context->ThrowNativeError("Invalid param type to set. Param is not a string.");
}
return 0;
}
cell_t Native_GetParamObjectPtrVar(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
switch((sp::ObjectValueType)params[4]) {
case sp::ObjectValueType_Int:
return *(int *)(object + params[3]);
case sp::ObjectValueType_Bool:
return (*(bool *)(object + params[3])) ? 1 : 0;
case sp::ObjectValueType_Ehandle: {
auto edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->GetHandleEntity(*(CBaseHandle *)(object + params[3])));
if (edict == nullptr || edict->IsFree()) {
return -1;
}
return globals::gamehelpers->IndexOfEdict(reinterpret_cast<edict_t*>(edict));
}
case sp::ObjectValueType_EhandlePtr: {
auto edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->GetHandleEntity(**(CBaseHandle **)(object + params[3])));
if (edict == nullptr || edict->IsFree()) {
return -1;
}
return globals::gamehelpers->IndexOfEdict(reinterpret_cast<edict_t*>(edict));
}
case sp::ObjectValueType_Float:
return sp_ftoc(*(float *)(object + params[3]));
// This is technically incorrect and doesn't follow the "convention" that CBaseEntity is always a pointer for plugins
// Therefore this should be a pointer of pointer (i.e a triple pointer when offseted to it). But it isn't....
case sp::ObjectValueType_CBaseEntityPtr:
return globals::gamehelpers->EntityToBCompatRef(*(CBaseEntity **)(object + params[3]));
case sp::ObjectValueType_IntPtr:
return **(int **)(object + params[3]);
case sp::ObjectValueType_BoolPtr:
return (**(bool **)(object + params[3])) ? 1 : 0;
case sp::ObjectValueType_FloatPtr:
return sp_ftoc(**(float **)(object + params[3]));
default:
return context->ThrowNativeError("Invalid Object value type");
}
}
cell_t DHookParam_SetParamObjectPtrVar(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
switch((sp::ObjectValueType)params[4]) {
case sp::ObjectValueType_Int:
*(int *)(object + params[3]) = params[5];
break;
case sp::ObjectValueType_Bool:
*(bool *)(object + params[3]) = params[5] != 0;
break;
case sp::ObjectValueType_Ehandle:
globals::gamehelpers->SetHandleEntity(*(CBaseHandle *)(object + params[3]), globals::gamehelpers->EdictOfIndex(params[5]));
break;
case sp::ObjectValueType_EhandlePtr:
globals::gamehelpers->SetHandleEntity(**(CBaseHandle **)(object + params[3]), globals::gamehelpers->EdictOfIndex(params[5]));
break;
case sp::ObjectValueType_Float:
*(float *)(object + params[3]) = sp_ctof(params[5]);
break;
// This is technically incorrect and doesn't follow the "convention" that CBaseEntity is always a pointer for plugins
// Therefore this should be a pointer of pointer (i.e a triple pointer when offseted to it). But it isn't....
case sp::ObjectValueType_CBaseEntityPtr: {
CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[5]);
if (params[5] != -1 && entity == nullptr) {
return context->ThrowNativeError("Invalid entity passed");
}
*(CBaseEntity **)(object + params[3]) = entity;
break;
}
case sp::ObjectValueType_IntPtr:
**(int **)(object + params[3]) = params[5];
break;
case sp::ObjectValueType_BoolPtr:
**(int **)(object + params[3]) = params[5] != 0;
break;
case sp::ObjectValueType_FloatPtr:
**(float **)(object + params[3]) = sp_ctof(params[5]);
break;
default:
return context->ThrowNativeError("Invalid Object value type");
}
return 0;
}
cell_t DHookParam_GetParamObjectPtrVarVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
cell_t *buffer;
context->LocalToPhysAddr(params[5], &buffer);
if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr || (sp::ObjectValueType)params[4] == sp::ObjectValueType_Vector) {
sdk::Vector* vec = (sdk::Vector*)(object + params[3]);
if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr) {
vec = *(sdk::Vector**)vec;
if (vec == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
}
buffer[0] = sp_ftoc(vec->x);
buffer[1] = sp_ftoc(vec->y);
buffer[2] = sp_ftoc(vec->z);
return 1;
}
return context->ThrowNativeError("Invalid Object value type (not a type of vector)");
}
cell_t DHookParam_SetParamObjectPtrVarVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
cell_t *buffer;
context->LocalToPhysAddr(params[5], &buffer);
if((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr || (sp::ObjectValueType)params[4] == sp::ObjectValueType_Vector) {
sdk::Vector* vec = (sdk::Vector*)(object + params[3]);
if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr) {
vec = *(sdk::Vector**)vec;
if (vec == nullptr) {
return context->ThrowNativeError("Trying to set value for null pointer.");
}
}
vec->x = sp_ctof(buffer[0]);
vec->y = sp_ctof(buffer[1]);
vec->z = sp_ctof(buffer[2]);
return 0;
}
return context->ThrowNativeError("Invalid Object value type (not a type of vector)");
}
cell_t DHookParam_GetParamObjectPtrString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
switch((sp::ObjectValueType)params[4]) {
case sp::ObjectValueType_CharPtr: {
char *ptr = *(char **)(object + params[3]);
context->StringToLocal(params[5], params[6], ptr == NULL ? "" : (const char *)ptr);
break;
}
case sp::ObjectValueType_String: {
auto str = *(sdk::string_t *)(object + params[3]);
context->StringToLocal(params[5], params[6], str.ToCStr());
break;
}
default:
return context->ThrowNativeError("Invalid Object value type (not a type of string)");
}
return 0;
}
cell_t DHookParam_IsNullParam(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (sp::HookParamTypeIsPtr(var.dhook_type)) {
return (*obj->Get<void*>(index) != nullptr) ? 1 : 0;
}
return context->ThrowNativeError("Param is not a pointer!");
}
/*void foo() {
{
{"DHookGetParam", DHookParam_GetParam},
{"DHookSetParam", DHookParam_SetParam},
{"DHookGetParamVector", DHookParam_GetParamVector},
{"DHookSetParamVector", DHookParam_SetParamVector},
{"DHookGetParamString", DHookParam_GetParamString},
{"DHookSetParamString", DHookParam_SetParamString},
{"DHookGetParamObjectPtrVar", DHookParam_GetParamObjectPtrVar},
{"DHookSetParamObjectPtrVar", DHookParam_SetParamObjectPtrVar},
{"DHookGetParamObjectPtrVarVector", DHookParam_GetParamObjectPtrVarVector},
{"DHookSetParamObjectPtrVarVector", DHookParam_SetParamObjectPtrVarVector},
{"DHookGetParamObjectPtrString", DHookParam_GetParamObjectPtrString},
{"DHookIsNullParam", DHookParam_IsNullParam}
{"DHookParam.Get", DHookParam_GetParam},
{"DHookParam.Set", DHookParam_SetParam},
{"DHookParam.GetVector", DHookParam_GetParamVector},
{"DHookParam.SetVector", DHookParam_SetParamVector},
{"DHookParam.GetString", DHookParam_GetParamString},
{"DHookParam.SetString", DHookParam_SetParamString},
{"DHookParam.GetObjectVar", DHookParam_GetParamObjectPtrVar},
{"DHookParam.SetObjectVar", DHookParam_SetParamObjectPtrVar},
{"DHookParam.GetObjectVarVector", DHookParam_GetParamObjectPtrVarVector},
{"DHookParam.SetObjectVarVector", DHookParam_SetParamObjectPtrVarVector},
{"DHookParam.GetObjectVarString", DHookParam_GetParamObjectPtrString},
{"DHookParam.IsNull", DHookParam_IsNullParam},
{"DHookGetReturn", DHookReturn_GetReturn},
{"DHookSetReturn", DHookReturn_SetReturn},
{"DHookGetReturnVector", DHookReturn_GetReturnVector},
{"DHookSetReturnVector", DHookReturn_SetReturnVector},
{"DHookGetReturnString", DHookReturn_GetReturnString},
{"DHookSetReturnString", DHookReturn_SetReturnString},
{"DHookReturn.Value.get", DHookReturn_GetReturn},
{"DHookReturn.Value.set", DHookReturn_SetReturn},
{"DHookReturn.GetVector", DHookReturn_GetReturnVector},
{"DHookReturn.SetVector", DHookReturn_SetReturnVector},
{"DHookReturn.GetString", DHookReturn_GetReturnString},
{"DHookReturn.SetString", DHookReturn_SetReturnString}
}
}*/
}

View File

@ -3,6 +3,7 @@
#include "register.hpp"
#include <sp_vm_types.h>
#include <IHandleSys.h>
namespace dhooks {
class Capsule;
@ -29,6 +30,8 @@ public:
template<typename T>
inline T* GetReturn() const { return reinterpret_cast<T*>(_return); };
inline const Capsule* GetCapsule() const { return _capsule; };
static SourceMod::HandleType_t HANDLE_TYPE;
private:
void* _Get(size_t index) const;

View File

@ -0,0 +1,723 @@
#include "../globals.hpp"
#include "../sdk_types.hpp"
#include "../handle.hpp"
#include "../capsule.hpp"
namespace dhooks::natives::dhookparam {
inline handle::ParamReturn* Get(SourcePawn::IPluginContext* context, const cell_t param) {
SourceMod::HandleSecurity security;
security.pOwner = globals::myself->GetIdentity();
security.pIdentity = globals::myself->GetIdentity();
SourceMod::Handle_t hndl = static_cast<SourceMod::Handle_t>(param);
handle::ParamReturn* obj = nullptr;
SourceMod::HandleError chnderr = globals::handlesys->ReadHandle(hndl, handle::ParamReturn::HANDLE_TYPE, &security, (void **)&obj);
if (chnderr != SourceMod::HandleError_None) {
context->ThrowNativeError("Invalid Handle %x (error %i: %s)", hndl, chnderr, globals::HandleErrorToString(chnderr));
return nullptr;
}
return obj;
}
inline cell_t GetParam(SourcePawn::IPluginContext* context, handle::ParamReturn* obj, const cell_t param) {
int index = param - 1;
if (obj->GetCapsule()->GetCallConv() == sp::CallConv_THISCALL) {
// Skip the |this| ptr parameter
index += 1;
}
if (param <= 0 || index >= obj->GetCapsule()->GetParameters().size()) {
context->ThrowNativeError("Invalid param number %i max params is %i", param, obj->GetCapsule()->GetParameters().size() - ((obj->GetCapsule()->GetCallConv() == sp::CallConv_THISCALL) ? 1 : 0));
return -1;
}
return index;
}
cell_t DHookReturn_GetReturn(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
switch (ret.dhook_type) {
case sp::ReturnType_Int:
return *obj->GetReturn<int>();
case sp::ReturnType_Bool:
return (*obj->GetReturn<bool>()) ? 1 : 0;
case sp::ReturnType_CBaseEntity:
return globals::gamehelpers->EntityToBCompatRef(*obj->GetReturn<CBaseEntity*>());
case sp::ReturnType_Edict:
return globals::gamehelpers->IndexOfEdict(*obj->GetReturn<edict_t*>());
case sp::ReturnType_Float:
return sp_ftoc(*obj->GetReturn<float>());
default:
return context->ThrowNativeError("Invalid param type (%i) to get", ret.dhook_type);
}
return 0;
}
cell_t DHookReturn_SetReturn(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
switch (ret.dhook_type) {
case sp::ReturnType_Int:
*obj->GetReturn<int>() = params[2];
break;
case sp::ReturnType_Bool:
*obj->GetReturn<bool>() = params[2] != 0;
break;
case sp::ReturnType_CBaseEntity: {
CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[2]);
if (entity == nullptr) {
return context->ThrowNativeError("Invalid entity index passed for return value");
}
*obj->GetReturn<CBaseEntity*>() = entity;
break;
}
case sp::ReturnType_Edict: {
sdk::edict_t* edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->EdictOfIndex(params[2]));
if (edict == nullptr || edict->IsFree()) {
return context->ThrowNativeError("Invalid entity index passed for return value");
}
*obj->GetReturn<sdk::edict_t*>() = edict;
break;
}
case sp::ReturnType_Float:
*obj->GetReturn<float>() = sp_ctof(params[2]);
break;
default:
return context->ThrowNativeError("Invalid param type (%i) to get", ret.dhook_type);
}
return 0;
}
cell_t DHookReturn_GetReturnVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
cell_t *buffer;
context->LocalToPhysAddr(params[2], &buffer);
const auto& ret = obj->GetCapsule()->GetReturn();
sdk::Vector* vector = nullptr;
if (ret.dhook_type == sp::ReturnType_Vector) {
vector = obj->GetReturn<sdk::Vector>();
} else if(ret.dhook_type == sp::ReturnType_VectorPtr) {
auto pvector = obj->GetReturn<sdk::Vector*>();
if (*pvector == nullptr) {
return context->ThrowNativeError("Vector pointer is null");
}
vector = *pvector;
} else {
return context->ThrowNativeError("Return type is not a vector type");
}
buffer[0] = sp_ftoc(vector->x);
buffer[1] = sp_ftoc(vector->y);
buffer[2] = sp_ftoc(vector->z);
return 0;
}
static void FreeChangedVector(void* data) {
delete (sdk::Vector*)data;
}
cell_t DHookReturn_SetReturnVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
cell_t *buffer;
context->LocalToPhysAddr(params[2], &buffer);
const auto& ret = obj->GetCapsule()->GetReturn();
if (ret.dhook_type == sp::ReturnType_Vector) {
*(obj->GetReturn<sdk::Vector>()) = sdk::Vector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2]));
}
else if (ret.dhook_type == sp::ReturnType_VectorPtr) {
// Lazily free the vector a frame later
auto vector = new sdk::Vector(sp_ctof(buffer[0]), sp_ctof(buffer[1]), sp_ctof(buffer[2]));
*(obj->GetReturn<sdk::Vector*>()) = vector;
globals::sourcemod->AddFrameAction(FreeChangedVector, vector);
} else {
return context->ThrowNativeError("Return type is not a vector type");
}
return 0;
}
cell_t DHookReturn_GetReturnString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
switch (ret.dhook_type) {
case sp::ReturnType_String:
context->StringToLocal(params[2], params[3], obj->GetReturn<sdk::string_t>()->ToCStr());
return 1;
case sp::ReturnType_StringPtr:
context->StringToLocal(params[2], params[3], (obj->GetReturn<sdk::string_t*>() != nullptr) ? (*obj->GetReturn<sdk::string_t*>())->ToCStr() : "");
return 1;
case sp::ReturnType_CharPtr:
context->StringToLocal(params[2], params[3], (*(obj->GetReturn<const char*>()) == nullptr) ? "" : *(obj->GetReturn<const char*>()));
return 1;
default:
return context->ThrowNativeError("Invalid param type to get. Param is not a string.");
}
}
static void FreeChangedCharPtr(void* data) {
delete[] (const char*)data;
}
cell_t DHookReturn_SetReturnString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
const auto& ret = obj->GetCapsule()->GetReturn();
char *value;
context->LocalToString(params[2], &value);
switch (ret.dhook_type) {
case sp::ReturnType_CharPtr: {
auto new_str = new char[strlen(value) + 1];
strcpy(new_str, value);
*(obj->GetReturn<const char*>()) = new_str;
// Free it later (cheaply) after the function returned.
globals::sourcemod->AddFrameAction(FreeChangedCharPtr, new_str);
return 1;
}
default:
return context->ThrowNativeError("Invalid param type to get. Param is not a char pointer.");
}
}
cell_t DHookParam_GetParam(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
if (params[2] == 0) {
return obj->GetCapsule()->GetParameters().size();
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (sp::HookParamTypeIsPtr(var.dhook_type) && *obj->Get<void*>(index) == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
switch(var.dhook_type) {
case sp::HookParamType_Int:
return *obj->Get<int>(index);
case sp::HookParamType_Bool:
return (*obj->Get<bool>(index)) ? 1 : 0;
case sp::HookParamType_CBaseEntity:
return globals::gamehelpers->EntityToBCompatRef(*obj->Get<CBaseEntity*>(index));
case sp::HookParamType_Edict:
return globals::gamehelpers->IndexOfEdict(*obj->Get<edict_t*>(index));
case sp::HookParamType_Float:
return sp_ftoc(*obj->Get<float>(index));
default:
return context->ThrowNativeError("Invalid param type (%i) to get", var.dhook_type);
}
}
cell_t DHookParam_SetParam(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
switch (var.dhook_type) {
case sp::HookParamType_Int:
*obj->Get<int>(index) = params[3];
break;
case sp::HookParamType_Bool:
*obj->Get<bool>(index) = (params[3] ? true : false);
break;
case sp::HookParamType_CBaseEntity: {
CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[3]);
if (params[3] != -1 && entity == nullptr) {
return context->ThrowNativeError("Invalid entity reference passed for param value");
}
*obj->Get<CBaseEntity*>(index) = entity;
break;
}
case sp::HookParamType_Edict: {
sdk::edict_t* edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->EdictOfIndex(params[3]));
if (params[3] != -1 && (edict == nullptr || edict->IsFree())) {
return context->ThrowNativeError("Invalid edict index passed for param value");
}
*obj->Get<sdk::edict_t*>(index) = edict;
break;
}
case sp::HookParamType_Float:
*obj->Get<float>(index) = sp_ctof(params[3]);
break;
default:
return context->ThrowNativeError("Invalid param type (%i) to set", var.dhook_type);
}
return 0;
}
cell_t DHookParam_GetParamVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type == sp::HookParamType_VectorPtr) {
cell_t* buffer;
context->LocalToPhysAddr(params[3], &buffer);
auto vec = *obj->Get<sdk::Vector*>(index);
if (vec == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
buffer[0] = sp_ftoc(vec->x);
buffer[1] = sp_ftoc(vec->y);
buffer[2] = sp_ftoc(vec->z);
} else {
return context->ThrowNativeError("Invalid param type to get. Param is not a vector.");
}
return 0;
}
cell_t DHookParam_SetParamVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type == sp::HookParamType_VectorPtr) {
cell_t* buffer;
context->LocalToPhysAddr(params[3], &buffer);
auto vec = *obj->Get<sdk::Vector*>(index);
if (vec == nullptr) {
vec = new sdk::Vector;
globals::sourcemod->AddFrameAction(FreeChangedVector, vec);
*obj->Get<sdk::Vector*>(index) = vec;
}
vec->x = sp_ctof(buffer[0]);
vec->y = sp_ctof(buffer[1]);
vec->z = sp_ctof(buffer[2]);
} else {
return context->ThrowNativeError("Invalid param type to set. Param is not a vector.");
}
return 0;
}
cell_t DHookParam_GetParamString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (sp::HookParamTypeIsPtr(var.dhook_type) && *obj->Get<void*>(index) == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
switch (var.dhook_type) {
case sp::HookParamType_CharPtr: {
auto str = *obj->Get<const char*>(index);
context->StringToLocal(params[3], params[4], str);
break;
}
case sp::HookParamType_String: {
auto str = *obj->Get<sdk::string_t>(index);
context->StringToLocal(params[3], params[4], str.ToCStr());
break;
}
case sp::HookParamType_StringPtr: {
auto str = *obj->Get<sdk::string_t*>(index);
context->StringToLocal(params[3], params[4], str->ToCStr());
break;
}
default:
return context->ThrowNativeError("Invalid param type to get. Param is not a string.");
}
return 0;
}
cell_t DHookParam_SetParamString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
char* value;
context->LocalToString(params[3], &value);
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type == sp::HookParamType_CharPtr) {
auto str = new char[strlen(value) + 1];
strcpy(str, value);
*obj->Get<const char*>(index) = str;
// Free it later (cheaply) after the function returned.
globals::sourcemod->AddFrameAction(FreeChangedCharPtr, str);
} else if (var.dhook_type == sp::HookParamType_String || var.dhook_type == sp::HookParamType_StringPtr) {
return context->ThrowNativeError("DHooks currently lacks support for setting string_t. Pull requests are welcome!");
} else {
return context->ThrowNativeError("Invalid param type to set. Param is not a string.");
}
return 0;
}
cell_t DHookParam_GetParamObjectPtrVar(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
switch((sp::ObjectValueType)params[4]) {
case sp::ObjectValueType_Int:
return *(int *)(object + params[3]);
case sp::ObjectValueType_Bool:
return (*(bool *)(object + params[3])) ? 1 : 0;
case sp::ObjectValueType_Ehandle: {
auto edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->GetHandleEntity(*(CBaseHandle *)(object + params[3])));
if (edict == nullptr || edict->IsFree()) {
return -1;
}
return globals::gamehelpers->IndexOfEdict(reinterpret_cast<edict_t*>(edict));
}
case sp::ObjectValueType_EhandlePtr: {
auto edict = reinterpret_cast<sdk::edict_t*>(globals::gamehelpers->GetHandleEntity(**(CBaseHandle **)(object + params[3])));
if (edict == nullptr || edict->IsFree()) {
return -1;
}
return globals::gamehelpers->IndexOfEdict(reinterpret_cast<edict_t*>(edict));
}
case sp::ObjectValueType_Float:
return sp_ftoc(*(float *)(object + params[3]));
// This is technically incorrect and doesn't follow the "convention" that CBaseEntity is always a pointer for plugins
// Therefore this should be a pointer of pointer (i.e a triple pointer when offseted to it). But it isn't....
case sp::ObjectValueType_CBaseEntityPtr:
return globals::gamehelpers->EntityToBCompatRef(*(CBaseEntity **)(object + params[3]));
case sp::ObjectValueType_IntPtr:
return **(int **)(object + params[3]);
case sp::ObjectValueType_BoolPtr:
return (**(bool **)(object + params[3])) ? 1 : 0;
case sp::ObjectValueType_FloatPtr:
return sp_ftoc(**(float **)(object + params[3]));
default:
return context->ThrowNativeError("Invalid Object value type");
}
}
cell_t DHookParam_SetParamObjectPtrVar(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
switch((sp::ObjectValueType)params[4]) {
case sp::ObjectValueType_Int:
*(int *)(object + params[3]) = params[5];
break;
case sp::ObjectValueType_Bool:
*(bool *)(object + params[3]) = params[5] != 0;
break;
case sp::ObjectValueType_Ehandle:
globals::gamehelpers->SetHandleEntity(*(CBaseHandle *)(object + params[3]), globals::gamehelpers->EdictOfIndex(params[5]));
break;
case sp::ObjectValueType_EhandlePtr:
globals::gamehelpers->SetHandleEntity(**(CBaseHandle **)(object + params[3]), globals::gamehelpers->EdictOfIndex(params[5]));
break;
case sp::ObjectValueType_Float:
*(float *)(object + params[3]) = sp_ctof(params[5]);
break;
// This is technically incorrect and doesn't follow the "convention" that CBaseEntity is always a pointer for plugins
// Therefore this should be a pointer of pointer (i.e a triple pointer when offseted to it). But it isn't....
case sp::ObjectValueType_CBaseEntityPtr: {
CBaseEntity* entity = globals::gamehelpers->ReferenceToEntity(params[5]);
if (params[5] != -1 && entity == nullptr) {
return context->ThrowNativeError("Invalid entity passed");
}
*(CBaseEntity **)(object + params[3]) = entity;
break;
}
case sp::ObjectValueType_IntPtr:
**(int **)(object + params[3]) = params[5];
break;
case sp::ObjectValueType_BoolPtr:
**(int **)(object + params[3]) = params[5] != 0;
break;
case sp::ObjectValueType_FloatPtr:
**(float **)(object + params[3]) = sp_ctof(params[5]);
break;
default:
return context->ThrowNativeError("Invalid Object value type");
}
return 0;
}
cell_t DHookParam_GetParamObjectPtrVarVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
cell_t *buffer;
context->LocalToPhysAddr(params[5], &buffer);
if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr || (sp::ObjectValueType)params[4] == sp::ObjectValueType_Vector) {
sdk::Vector* vec = (sdk::Vector*)(object + params[3]);
if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr) {
vec = *(sdk::Vector**)vec;
if (vec == nullptr) {
return context->ThrowNativeError("Trying to get value for null pointer.");
}
}
buffer[0] = sp_ftoc(vec->x);
buffer[1] = sp_ftoc(vec->y);
buffer[2] = sp_ftoc(vec->z);
return 1;
}
return context->ThrowNativeError("Invalid Object value type (not a type of vector)");
}
cell_t DHookParam_SetParamObjectPtrVarVector(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
cell_t *buffer;
context->LocalToPhysAddr(params[5], &buffer);
if((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr || (sp::ObjectValueType)params[4] == sp::ObjectValueType_Vector) {
sdk::Vector* vec = (sdk::Vector*)(object + params[3]);
if ((sp::ObjectValueType)params[4] == sp::ObjectValueType_VectorPtr) {
vec = *(sdk::Vector**)vec;
if (vec == nullptr) {
return context->ThrowNativeError("Trying to set value for null pointer.");
}
}
vec->x = sp_ctof(buffer[0]);
vec->y = sp_ctof(buffer[1]);
vec->z = sp_ctof(buffer[2]);
return 0;
}
return context->ThrowNativeError("Invalid Object value type (not a type of vector)");
}
cell_t DHookParam_GetParamObjectPtrString(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (var.dhook_type != sp::HookParamType_ObjectPtr && var.dhook_type != sp::HookParamType_Object) {
return context->ThrowNativeError("Invalid object value type %i", var.dhook_type);
}
std::uint8_t* object = obj->Get<std::uint8_t>(index);
if (var.dhook_type == sp::HookParamType_ObjectPtr) {
object = *(std::uint8_t**)object;
}
switch((sp::ObjectValueType)params[4]) {
case sp::ObjectValueType_CharPtr: {
char *ptr = *(char **)(object + params[3]);
context->StringToLocal(params[5], params[6], ptr == NULL ? "" : (const char *)ptr);
break;
}
case sp::ObjectValueType_String: {
auto str = *(sdk::string_t *)(object + params[3]);
context->StringToLocal(params[5], params[6], str.ToCStr());
break;
}
default:
return context->ThrowNativeError("Invalid Object value type (not a type of string)");
}
return 0;
}
cell_t DHookParam_IsNullParam(SourcePawn::IPluginContext* context, const cell_t* params) {
auto obj = Get(context, params[1]);
if (obj == nullptr) {
return 0;
}
int index = GetParam(context, obj, params[2]);
if (index == -1) {
return 0;
}
const auto& var = obj->GetCapsule()->GetParameters()[index];
if (sp::HookParamTypeIsPtr(var.dhook_type)) {
return (*obj->Get<void*>(index) != nullptr) ? 1 : 0;
}
return context->ThrowNativeError("Param is not a pointer!");
}
void init(std::vector<sp_nativeinfo_t>& natives) {
sp_nativeinfo_t list[] = {
{"DHookGetParam", DHookParam_GetParam},
{"DHookSetParam", DHookParam_SetParam},
{"DHookGetParamVector", DHookParam_GetParamVector},
{"DHookSetParamVector", DHookParam_SetParamVector},
{"DHookGetParamString", DHookParam_GetParamString},
{"DHookSetParamString", DHookParam_SetParamString},
{"DHookGetParamObjectPtrVar", DHookParam_GetParamObjectPtrVar},
{"DHookSetParamObjectPtrVar", DHookParam_SetParamObjectPtrVar},
{"DHookGetParamObjectPtrVarVector", DHookParam_GetParamObjectPtrVarVector},
{"DHookSetParamObjectPtrVarVector", DHookParam_SetParamObjectPtrVarVector},
{"DHookGetParamObjectPtrString", DHookParam_GetParamObjectPtrString},
{"DHookIsNullParam", DHookParam_IsNullParam},
{"DHookParam.Get", DHookParam_GetParam},
{"DHookParam.Set", DHookParam_SetParam},
{"DHookParam.GetVector", DHookParam_GetParamVector},
{"DHookParam.SetVector", DHookParam_SetParamVector},
{"DHookParam.GetString", DHookParam_GetParamString},
{"DHookParam.SetString", DHookParam_SetParamString},
{"DHookParam.GetObjectVar", DHookParam_GetParamObjectPtrVar},
{"DHookParam.SetObjectVar", DHookParam_SetParamObjectPtrVar},
{"DHookParam.GetObjectVarVector", DHookParam_GetParamObjectPtrVarVector},
{"DHookParam.SetObjectVarVector", DHookParam_SetParamObjectPtrVarVector},
{"DHookParam.GetObjectVarString", DHookParam_GetParamObjectPtrString},
{"DHookParam.IsNull", DHookParam_IsNullParam},
{"DHookGetReturn", DHookReturn_GetReturn},
{"DHookSetReturn", DHookReturn_SetReturn},
{"DHookGetReturnVector", DHookReturn_GetReturnVector},
{"DHookSetReturnVector", DHookReturn_SetReturnVector},
{"DHookGetReturnString", DHookReturn_GetReturnString},
{"DHookSetReturnString", DHookReturn_SetReturnString},
{"DHookReturn.Value.get", DHookReturn_GetReturn},
{"DHookReturn.Value.set", DHookReturn_SetReturn},
{"DHookReturn.GetVector", DHookReturn_GetReturnVector},
{"DHookReturn.SetVector", DHookReturn_SetReturnVector},
{"DHookReturn.GetString", DHookReturn_GetReturnString},
{"DHookReturn.SetString", DHookReturn_SetReturnString}
};
natives.insert(natives.end(), std::begin(list), std::end(list));
}
}