- added bool type
- added pointer support - added three default natives - added include file for sdktools - cleaned up decoding api a bit --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40960
This commit is contained in:
parent
6c64c00f6b
commit
11ff381289
@ -23,6 +23,7 @@
|
||||
|
||||
#include "extension.h"
|
||||
#include "vcallbuilder.h"
|
||||
#include "vnatives.h"
|
||||
|
||||
/**
|
||||
* @file extension.cpp
|
||||
@ -43,6 +44,7 @@ bool SDKTools::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
{
|
||||
sharesys->AddDependency(myself, "bintools.ext", true, true);
|
||||
sharesys->AddNatives(myself, g_CallNatives);
|
||||
sharesys->AddNatives(myself, g_Natives);
|
||||
|
||||
if (!gameconfs->LoadGameConfigFile("sdktools.games", &g_pGameConf, error, maxlength))
|
||||
{
|
||||
@ -65,6 +67,15 @@ void SDKTools::OnHandleDestroy(HandleType_t type, void *object)
|
||||
|
||||
void SDKTools::SDK_OnUnload()
|
||||
{
|
||||
List<ValveCall *>::iterator iter;
|
||||
for (iter = g_RegCalls.begin();
|
||||
iter != g_RegCalls.end();
|
||||
iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
g_RegCalls.clear();
|
||||
|
||||
gameconfs->CloseGameConfigFile(g_pGameConf);
|
||||
}
|
||||
|
||||
|
@ -197,6 +197,10 @@
|
||||
RelativePath="..\vdecoder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vnatives.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
@ -215,6 +219,10 @@
|
||||
RelativePath="..\vdecoder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\vnatives.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
|
@ -8,29 +8,6 @@
|
||||
using namespace SourceMod;
|
||||
using namespace SourceHook;
|
||||
|
||||
/**
|
||||
* @brief Valve pre-defined calling types
|
||||
*/
|
||||
enum ValveCallType
|
||||
{
|
||||
ValveCall_Static, /**< Static call */
|
||||
ValveCall_Entity, /**< Thiscall (CBaseEntity implicit first parameter) */
|
||||
ValveCall_Player, /**< Thiscall (CBasePlayer implicit first parameter) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Valve parameter info
|
||||
*/
|
||||
struct ValvePassInfo
|
||||
{
|
||||
ValveType vtype; /**< IN: Valve type */
|
||||
unsigned int decflags; /**< IN: VDECODE_FLAG_* */
|
||||
unsigned int encflags; /**< IN: VENCODE_FLAG_* */
|
||||
PassType type; /**< IN: Pass information */
|
||||
unsigned int flags; /**< IN: Pass flags */
|
||||
size_t offset; /**< OUT: stack offset */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Info necessary to call a Valve function
|
||||
*/
|
||||
|
@ -29,9 +29,10 @@ inline void DecodePassMethod(ValveType vtype, SDKPassMethod method, PassType &ty
|
||||
{
|
||||
type = PassType_Basic;
|
||||
if (vtype == Valve_POD
|
||||
|| vtype == Valve_Float)
|
||||
|| vtype == Valve_Float
|
||||
|| vtype == Valve_Bool)
|
||||
{
|
||||
flags = PASSFLAG_BYREF;
|
||||
flags = PASSFLAG_ASPOINTER;
|
||||
} else {
|
||||
flags = PASSFLAG_BYVAL;
|
||||
}
|
||||
@ -169,7 +170,7 @@ static cell_t PrepSDKCall_AddParameter(IPluginContext *pContext, const cell_t *p
|
||||
ValvePassInfo *info = &s_params[s_numparams++];
|
||||
info->vtype = (ValveType)params[1];
|
||||
DecodePassMethod(info->vtype, (SDKPassMethod)params[2], info->type, info->flags);
|
||||
info->decflags = params[3];
|
||||
info->decflags = params[3] | VDECODE_FLAG_BYREF;
|
||||
info->encflags = params[4];
|
||||
|
||||
return 1;
|
||||
@ -227,9 +228,7 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
if (DecodeValveParam(pContext,
|
||||
params[startparam],
|
||||
vc->thisinfo->vtype,
|
||||
vc->thisinfo->decflags | VDECODE_FLAG_BYREF,
|
||||
vc->thisinfo->type,
|
||||
vc->thisinfo,
|
||||
ptr) == Data_Fail)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
@ -264,9 +263,7 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
}
|
||||
if (DecodeValveParam(pContext,
|
||||
params[p],
|
||||
vc->vparams[i].vtype,
|
||||
vc->vparams[i].decflags | VDECODE_FLAG_BYREF,
|
||||
vc->vparams[i].type,
|
||||
&(vc->vparams[i]),
|
||||
ptr + vc->vparams[i].offset) == Data_Fail)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
@ -290,8 +287,7 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
if (EncodeValveParam(pContext,
|
||||
startparam + i,
|
||||
vc->vparams[i].vtype,
|
||||
vc->vparams[i].type,
|
||||
&vc->vparams[i],
|
||||
ptr + vc->vparams[i].offset) == Data_Fail)
|
||||
{
|
||||
vc->stk_put(ptr);
|
||||
@ -325,7 +321,7 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
return pContext->ThrowNativeError("Expected argument (2) for Float[3] storage");
|
||||
}
|
||||
if (EncodeValveParam(pContext, params[retparam], vc->retinfo->vtype, vc->retinfo->type, vc->retbuf)
|
||||
if (EncodeValveParam(pContext, params[retparam], vc->retinfo, vc->retbuf)
|
||||
== Data_Fail)
|
||||
{
|
||||
return 0;
|
||||
@ -351,6 +347,13 @@ static cell_t SDKCall(IPluginContext *pContext, const cell_t *params)
|
||||
return -1;
|
||||
}
|
||||
return engine->IndexOfEdict(pEdict);
|
||||
} else if (vc->retinfo->vtype == Valve_Bool) {
|
||||
bool *addr = (bool *)vc->retbuf;
|
||||
if (vc->retinfo->flags & PASSFLAG_BYREF)
|
||||
{
|
||||
addr = *(bool **)addr;
|
||||
}
|
||||
return *addr ? 1 : 0;
|
||||
} else {
|
||||
cell_t *addr = (cell_t *)vc->retbuf;
|
||||
if (vc->retinfo->flags & PASSFLAG_BYREF)
|
||||
|
@ -68,12 +68,10 @@ size_t ValveParamToBinParam(ValveType type,
|
||||
}
|
||||
case Valve_CBaseEntity:
|
||||
case Valve_CBasePlayer:
|
||||
case Valve_POD:
|
||||
case Valve_Edict:
|
||||
case Valve_String:
|
||||
{
|
||||
if (pass != PassType_Basic
|
||||
|| (info->flags & PASSFLAG_BYREF))
|
||||
if (pass != PassType_Basic || (info->flags & PASSFLAG_BYREF))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -82,34 +80,65 @@ size_t ValveParamToBinParam(ValveType type,
|
||||
info->size = sizeof(void *);
|
||||
return sizeof(void *);
|
||||
}
|
||||
case Valve_POD:
|
||||
{
|
||||
info->type = PassType_Basic;
|
||||
info->flags = flags;
|
||||
if (flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
info->size = sizeof(int *);
|
||||
return sizeof(int *) + sizeof(int);
|
||||
} else {
|
||||
info->size = sizeof(int);
|
||||
return sizeof(int);
|
||||
}
|
||||
}
|
||||
case Valve_Bool:
|
||||
{
|
||||
info->type = PassType_Basic;
|
||||
info->flags = flags;
|
||||
if (flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
info->size = sizeof(bool *);
|
||||
return sizeof(bool *) + sizeof(bool);
|
||||
} else {
|
||||
info->size = sizeof(bool);
|
||||
return sizeof(bool);
|
||||
}
|
||||
}
|
||||
case Valve_Float:
|
||||
{
|
||||
info->type = PassType_Float;
|
||||
info->flags = flags;
|
||||
if (flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
info->size = sizeof(float *);
|
||||
return sizeof(float *) + sizeof(float);
|
||||
} else {
|
||||
info->size = sizeof(float);
|
||||
return sizeof(float);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataStatus EncodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
ValveType type,
|
||||
PassType pass,
|
||||
const ValvePassInfo *data,
|
||||
const void *buffer)
|
||||
{
|
||||
switch (type)
|
||||
switch (data->vtype)
|
||||
{
|
||||
case Valve_Vector:
|
||||
{
|
||||
Vector *v = NULL;
|
||||
|
||||
if (pass == PassType_Basic)
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
v = *(Vector **)((unsigned char *)buffer + sizeof(Vector *));
|
||||
} else if (pass == PassType_Object) {
|
||||
} else if (data->type == PassType_Object) {
|
||||
v = (Vector *)buffer;
|
||||
}
|
||||
|
||||
@ -126,10 +155,10 @@ DataStatus EncodeValveParam(IPluginContext *pContext,
|
||||
{
|
||||
QAngle *q = NULL;
|
||||
|
||||
if (pass == PassType_Basic)
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
q = *(QAngle **)((unsigned char *)buffer + sizeof(QAngle *));
|
||||
} else if (pass == PassType_Object) {
|
||||
} else if (data->type == PassType_Object) {
|
||||
q = (QAngle *)buffer;
|
||||
}
|
||||
|
||||
@ -180,8 +209,27 @@ DataStatus EncodeValveParam(IPluginContext *pContext,
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
buffer = (char *)buffer + sizeof(void *);
|
||||
}
|
||||
|
||||
*addr = *(cell_t *)buffer;
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_Bool:
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
buffer = (char *)buffer + sizeof(bool *);
|
||||
}
|
||||
|
||||
*addr = *(bool *)buffer ? 1 : 0;
|
||||
|
||||
return Data_Okay;
|
||||
}
|
||||
}
|
||||
@ -191,12 +239,10 @@ DataStatus EncodeValveParam(IPluginContext *pContext,
|
||||
|
||||
DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
ValveType vtype,
|
||||
unsigned int vflags,
|
||||
PassType type,
|
||||
const ValvePassInfo *data,
|
||||
void *buffer)
|
||||
{
|
||||
switch (vtype)
|
||||
switch (data->vtype)
|
||||
{
|
||||
case Valve_Vector:
|
||||
{
|
||||
@ -205,7 +251,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
err = pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
unsigned char *mem = (unsigned char *)buffer;
|
||||
if (type == PassType_Basic)
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
/* Store the object in the next N bytes, and store
|
||||
* a pointer to that object right beforehand.
|
||||
@ -214,7 +260,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
|
||||
if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
if (vflags & VDECODE_FLAG_ALLOWNULL)
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
*realPtr = NULL;
|
||||
return Data_Okay;
|
||||
@ -252,7 +298,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
err = pContext->LocalToPhysAddr(param, &addr);
|
||||
|
||||
unsigned char *mem = (unsigned char *)buffer;
|
||||
if (type == PassType_Basic)
|
||||
if (data->type == PassType_Basic)
|
||||
{
|
||||
/* Store the object in the next N bytes, and store
|
||||
* a pointer to that object right beforehand.
|
||||
@ -261,7 +307,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
|
||||
if (addr == pContext->GetNullRef(SP_NULL_VECTOR))
|
||||
{
|
||||
if (!(vflags & VDECODE_FLAG_ALLOWNULL))
|
||||
if (!(data->decflags & VDECODE_FLAG_ALLOWNULL))
|
||||
{
|
||||
pContext->ThrowNativeError("NULL not allowed");
|
||||
return Data_Fail;
|
||||
@ -295,7 +341,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
case Valve_CBasePlayer:
|
||||
{
|
||||
edict_t *pEdict;
|
||||
if (vflags & VDECODE_FLAG_BYREF)
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
@ -304,7 +350,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
if (param >= 1 && param <= playerhelpers->GetMaxClients())
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
|
||||
if ((vflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
&& !player->IsConnected())
|
||||
{
|
||||
pContext->ThrowNativeError("Client %d is not connected", param);
|
||||
@ -315,7 +361,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
}
|
||||
pEdict = player->GetEdict();
|
||||
} else if (param == -1) {
|
||||
if (vflags & VDECODE_FLAG_ALLOWNULL)
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
pEdict = NULL;
|
||||
} else {
|
||||
@ -323,7 +369,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
return Data_Fail;
|
||||
}
|
||||
} else if (param == 0) {
|
||||
if (vflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
{
|
||||
pEdict = engine->PEntityOfEntIndex(0);
|
||||
} else {
|
||||
@ -361,7 +407,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
case Valve_CBaseEntity:
|
||||
{
|
||||
edict_t *pEdict;
|
||||
if (vflags & VDECODE_FLAG_BYREF)
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
@ -370,7 +416,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
if (param >= 1 && param <= playerhelpers->GetMaxClients())
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
|
||||
if ((vflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
&& !player->IsConnected())
|
||||
{
|
||||
pContext->ThrowNativeError("Client %d is not connected", param);
|
||||
@ -381,7 +427,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
}
|
||||
pEdict = player->GetEdict();
|
||||
} else if (param == -1) {
|
||||
if (vflags & VDECODE_FLAG_ALLOWNULL)
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
pEdict = NULL;
|
||||
} else {
|
||||
@ -389,7 +435,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
return Data_Fail;
|
||||
}
|
||||
} else if (param == 0) {
|
||||
if (vflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
{
|
||||
pEdict = engine->PEntityOfEntIndex(0);
|
||||
} else {
|
||||
@ -431,7 +477,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
case Valve_Edict:
|
||||
{
|
||||
edict_t *pEdict;
|
||||
if (vflags & VDECODE_FLAG_BYREF)
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
@ -440,7 +486,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
if (param >= 1 && param <= playerhelpers->GetMaxClients())
|
||||
{
|
||||
IGamePlayer *player = playerhelpers->GetGamePlayer(param);
|
||||
if ((vflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
if ((data->decflags & VDECODE_FLAG_ALLOWNOTINGAME)
|
||||
&& !player->IsConnected())
|
||||
{
|
||||
pContext->ThrowNativeError("Client %d is not connected", param);
|
||||
@ -451,7 +497,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
}
|
||||
pEdict = player->GetEdict();
|
||||
} else if (param == -1) {
|
||||
if (vflags & VDECODE_FLAG_ALLOWNULL)
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWNULL)
|
||||
{
|
||||
pEdict = NULL;
|
||||
} else {
|
||||
@ -459,7 +505,7 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
return Data_Fail;
|
||||
}
|
||||
} else if (param == 0) {
|
||||
if (vflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
if (data->decflags & VDECODE_FLAG_ALLOWWORLD)
|
||||
{
|
||||
pEdict = engine->PEntityOfEntIndex(0);
|
||||
} else {
|
||||
@ -483,15 +529,36 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
case Valve_POD:
|
||||
case Valve_Float:
|
||||
{
|
||||
if (vflags & VDECODE_FLAG_BYREF)
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
param = *addr;
|
||||
}
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
*(void **)buffer = (char *)buffer + sizeof(void *);
|
||||
buffer = *(void **)buffer;
|
||||
}
|
||||
*(cell_t *)buffer = param;
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_Bool:
|
||||
{
|
||||
if (data->decflags & VDECODE_FLAG_BYREF)
|
||||
{
|
||||
cell_t *addr;
|
||||
pContext->LocalToPhysAddr(param, &addr);
|
||||
param = *addr;
|
||||
}
|
||||
if (data->flags & PASSFLAG_ASPOINTER)
|
||||
{
|
||||
*(bool **)buffer = (bool *)((char *)buffer + sizeof(bool *));
|
||||
buffer = *(bool **)buffer;
|
||||
}
|
||||
*(bool *)buffer = param ? true : false;
|
||||
return Data_Okay;
|
||||
}
|
||||
case Valve_String:
|
||||
{
|
||||
char *addr;
|
||||
|
@ -21,6 +21,7 @@ enum ValveType
|
||||
Valve_Float, /**< Float */
|
||||
Valve_Edict, /**< Edict */
|
||||
Valve_String, /**< String */
|
||||
Valve_Bool, /**< Boolean */
|
||||
};
|
||||
|
||||
enum DataStatus
|
||||
@ -36,6 +37,31 @@ enum DataStatus
|
||||
|
||||
#define VENCODE_FLAG_COPYBACK (1<<0) /**< Copy back data */
|
||||
|
||||
#define PASSFLAG_ASPOINTER (1<<30) /**< Not an actual passflag, used internally */
|
||||
|
||||
/**
|
||||
* @brief Valve pre-defined calling types
|
||||
*/
|
||||
enum ValveCallType
|
||||
{
|
||||
ValveCall_Static, /**< Static call */
|
||||
ValveCall_Entity, /**< Thiscall (CBaseEntity implicit first parameter) */
|
||||
ValveCall_Player, /**< Thiscall (CBasePlayer implicit first parameter) */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Valve parameter info
|
||||
*/
|
||||
struct ValvePassInfo
|
||||
{
|
||||
ValveType vtype; /**< IN: Valve type */
|
||||
unsigned int decflags; /**< IN: VDECODE_FLAG_* */
|
||||
unsigned int encflags; /**< IN: VENCODE_FLAG_* */
|
||||
PassType type; /**< IN: Pass information */
|
||||
unsigned int flags; /**< IN: Pass flags */
|
||||
size_t offset; /**< OUT: stack offset */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Converts a valve parameter to a bintools parameter.
|
||||
*
|
||||
@ -59,16 +85,12 @@ size_t ValveParamToBinParam(ValveType type,
|
||||
*
|
||||
* @param pContext Plugin context.
|
||||
* @param param Parameter value from params array.
|
||||
* @param type Valve type.
|
||||
* @param pass Pass info from bin tools.
|
||||
* @param buffer Buffer space in the virutal stack.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
ValveType type,
|
||||
unsigned int vflags,
|
||||
PassType pass,
|
||||
const ValvePassInfo *vdata,
|
||||
void *buffer);
|
||||
|
||||
/**
|
||||
@ -79,15 +101,12 @@ DataStatus DecodeValveParam(IPluginContext *pContext,
|
||||
*
|
||||
* @param pContext Plugin context.
|
||||
* @param param Parameter value from params array.
|
||||
* @param type Valve type.
|
||||
* @param pass Pass info from bin tools.
|
||||
* @param buffer Buffer space in the virutal stack.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
DataStatus EncodeValveParam(IPluginContext *pContext,
|
||||
cell_t param,
|
||||
ValveType type,
|
||||
PassType pass,
|
||||
const ValvePassInfo *vdata,
|
||||
const void *buffer);
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_VDECODER_H_
|
||||
|
182
extensions/sdktools/vnatives.cpp
Normal file
182
extensions/sdktools/vnatives.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
#include "extension.h"
|
||||
#include "vcallbuilder.h"
|
||||
#include "vnatives.h"
|
||||
|
||||
List<ValveCall *> g_RegCalls;
|
||||
|
||||
inline void InitPass(ValvePassInfo &info, ValveType vtype, PassType type, unsigned int flags)
|
||||
{
|
||||
info.decflags = 0;
|
||||
info.encflags = 0;
|
||||
info.flags = flags;
|
||||
info.type = type;
|
||||
info.vtype = vtype;
|
||||
}
|
||||
|
||||
#define START_CALL() \
|
||||
unsigned char *vptr = pCall->stk_get();
|
||||
|
||||
#define FINISH_CALL_SIMPLE(vret) \
|
||||
pCall->call->Execute(vptr, vret); \
|
||||
pCall->stk_put(vptr);
|
||||
|
||||
#define ENCODE_VALVE_PARAM(num, which, vnum) \
|
||||
if (EncodeValveParam(pContext, \
|
||||
params[num], \
|
||||
&pCall->which[vnum], \
|
||||
vptr + pCall->which[vnum].offset) \
|
||||
== Data_Fail) \
|
||||
{ \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define DECODE_VALVE_PARAM(num, which, vnum) \
|
||||
if (DecodeValveParam(pContext, \
|
||||
params[num], \
|
||||
&pCall->which[vnum], \
|
||||
vptr + pCall->which[vnum].offset) \
|
||||
== Data_Fail) \
|
||||
{ \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
bool CreateBaseCall(const char *name,
|
||||
ValveCallType vcalltype,
|
||||
const ValvePassInfo *retinfo,
|
||||
const ValvePassInfo params[],
|
||||
unsigned int numParams,
|
||||
ValveCall **vaddr)
|
||||
{
|
||||
int offset;
|
||||
ValveCall *call;
|
||||
if (g_pGameConf->GetOffset(name, &offset))
|
||||
{
|
||||
call = CreateValveVCall(offset, vcalltype, retinfo, params, numParams);
|
||||
if (call)
|
||||
{
|
||||
g_RegCalls.push_back(call);
|
||||
}
|
||||
*vaddr = call;
|
||||
return true;
|
||||
} else {
|
||||
void *addr;
|
||||
if (g_pGameConf->GetMemSig(name, &addr))
|
||||
{
|
||||
call = CreateValveCall(addr, vcalltype, retinfo, params, numParams);
|
||||
if (call)
|
||||
{
|
||||
g_RegCalls.push_back(call);
|
||||
}
|
||||
*vaddr = call;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static cell_t RemovePlayerItem(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
static ValveCall *pCall = NULL;
|
||||
if (!pCall)
|
||||
{
|
||||
ValvePassInfo pass[2];
|
||||
InitPass(pass[0], Valve_CBaseEntity, PassType_Basic, 0);
|
||||
InitPass(pass[1], Valve_Bool, PassType_Basic, 0);
|
||||
if (!CreateBaseCall("RemovePlayerItem", ValveCall_Player, &pass[1], &pass[0], 1, &pCall))
|
||||
{
|
||||
return pContext->ThrowNativeError("\"RemovePlayerItem\" not supported by this mod");
|
||||
} else if (!pCall) {
|
||||
return pContext->ThrowNativeError("\"RemovePlayerItem\" wrapper failed to initialized");
|
||||
}
|
||||
}
|
||||
|
||||
bool ret;
|
||||
START_CALL();
|
||||
DECODE_VALVE_PARAM(1, thisinfo, 0);
|
||||
DECODE_VALVE_PARAM(2, vparams, 0);
|
||||
FINISH_CALL_SIMPLE(&ret);
|
||||
return ret ? 1 : 0;
|
||||
}
|
||||
|
||||
static cell_t GiveNamedItem(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
static ValveCall *pCall = NULL;
|
||||
if (!pCall)
|
||||
{
|
||||
ValvePassInfo pass[3];
|
||||
InitPass(pass[0], Valve_String, PassType_Basic, PASSFLAG_BYVAL);
|
||||
InitPass(pass[1], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
|
||||
InitPass(pass[2], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
|
||||
if (!CreateBaseCall("GiveNamedItem", ValveCall_Player, &pass[2], pass, 2, &pCall))
|
||||
{
|
||||
return pContext->ThrowNativeError("\"GiveNamedItem\" not supported by this mod");
|
||||
} else if (!pCall) {
|
||||
return pContext->ThrowNativeError("\"GiveNamedItem\" wrapper failed to initialized");
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity *pEntity = NULL;
|
||||
START_CALL();
|
||||
DECODE_VALVE_PARAM(1, thisinfo, 0);
|
||||
DECODE_VALVE_PARAM(2, vparams, 0);
|
||||
DECODE_VALVE_PARAM(3, vparams, 1);
|
||||
FINISH_CALL_SIMPLE(&pEntity);
|
||||
|
||||
if (pEntity == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
|
||||
if (!pEdict)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return engine->IndexOfEdict(pEdict);
|
||||
}
|
||||
|
||||
static cell_t GetPlayerWeaponSlot(IPluginContext *pContext, const cell_t *params)
|
||||
{
|
||||
static ValveCall *pCall = NULL;
|
||||
if (!pCall)
|
||||
{
|
||||
ValvePassInfo pass[2];
|
||||
InitPass(pass[0], Valve_POD, PassType_Basic, PASSFLAG_BYVAL);
|
||||
InitPass(pass[1], Valve_CBaseEntity, PassType_Basic, PASSFLAG_BYVAL);
|
||||
if (!CreateBaseCall("Weapon_GetSlot", ValveCall_Player, &pass[1], pass, 1, &pCall))
|
||||
{
|
||||
return pContext->ThrowNativeError("\"Weapon_GetSlot\" not supported by this mod");
|
||||
} else if (!pCall) {
|
||||
return pContext->ThrowNativeError("\"Weapon_GetSlot\" wrapper failed to initialized");
|
||||
}
|
||||
}
|
||||
|
||||
CBaseEntity *pEntity;
|
||||
START_CALL();
|
||||
DECODE_VALVE_PARAM(1, thisinfo, 0);
|
||||
DECODE_VALVE_PARAM(2, vparams, 0);
|
||||
FINISH_CALL_SIMPLE(&pEntity);
|
||||
|
||||
if (pEntity == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
edict_t *pEdict = gameents->BaseEntityToEdict(pEntity);
|
||||
if (!pEdict)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return engine->IndexOfEdict(pEdict);
|
||||
}
|
||||
|
||||
sp_nativeinfo_t g_Natives[] =
|
||||
{
|
||||
{"RemovePlayerItem", RemovePlayerItem},
|
||||
{"GivePlayerItem", GiveNamedItem},
|
||||
{"GetPlayerWeaponSlot", GetPlayerWeaponSlot},
|
||||
{NULL, NULL},
|
||||
};
|
9
extensions/sdktools/vnatives.h
Normal file
9
extensions/sdktools/vnatives.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef _INCLUDE_SDKTOOLS_VNATIVES_H_
|
||||
#define _INCLUDE_SDKTOOLS_VNATIVES_H_
|
||||
|
||||
#include <sh_list.h>
|
||||
|
||||
extern List<ValveCall *> g_RegCalls;
|
||||
extern sp_nativeinfo_t g_Natives[];
|
||||
|
||||
#endif //_INCLUDE_SDKTOOLS_VNATIVES_H_
|
@ -14,6 +14,16 @@
|
||||
"windows" "329"
|
||||
"linux" "330"
|
||||
}
|
||||
"RemovePlayerItem"
|
||||
{
|
||||
"windows" "226"
|
||||
"linux" "227"
|
||||
}
|
||||
"Weapon_GetSlot"
|
||||
{
|
||||
"windows" "224"
|
||||
"linux" "225"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
179
plugins/include/sdktools.inc
Normal file
179
plugins/include/sdktools.inc
Normal file
@ -0,0 +1,179 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
|
||||
* ===============================================================
|
||||
*
|
||||
* This file is part of the SourceMod/SourcePawn SDK. This file may only be used
|
||||
* or modified under the Terms and Conditions of its License Agreement, which is found
|
||||
* in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins
|
||||
* may change at any time. To view the latest information, see:
|
||||
* http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#if defined _sdktools_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _sdktools_included
|
||||
|
||||
#include <core>
|
||||
#include <sdktools_functions>
|
||||
|
||||
enum SDKCallType
|
||||
{
|
||||
SDKCall_Static, /**< Static call */
|
||||
SDKCall_Entity, /**< CBaseEntity call */
|
||||
SDKCall_Player, /**< CBasePlayer call */
|
||||
};
|
||||
|
||||
enum SDKLibrary
|
||||
{
|
||||
SDKLibrary_Server, /**< server.dll/server_i486.so */
|
||||
SDKLibrary_Engine, /**< engine.dll/engine_*.so */
|
||||
};
|
||||
|
||||
enum SDKFuncConfSource
|
||||
{
|
||||
SDKConf_Virtual = 0, /**< Read a virtual index from the Offsets section */
|
||||
SDKConf_Signature = 1, /**< Read a signature from the Signatures section */
|
||||
};
|
||||
|
||||
enum SDKType
|
||||
{
|
||||
SDKType_CBaseEntity, /**< CBaseEntity (always as pointer) */
|
||||
SDKType_CBasePlayer, /**< CBasePlayer (always as pointer) */
|
||||
SDKType_Vector, /**< Vector (pointer, byval, or byref) */
|
||||
SDKType_QAngle, /**< QAngles (pointer, byval, or byref) */
|
||||
SDKType_PlainOldData, /**< Integer/generic data <=32bit (any) */
|
||||
SDKType_Float, /**< Float (any) */
|
||||
SDKType_Edict, /**< edict_t (always as pointer) */
|
||||
SDKType_String, /**< NULL-terminated string (always as pointer) */
|
||||
};
|
||||
|
||||
enum SDKPassMethod
|
||||
{
|
||||
SDKPass_Pointer, /**< Pass as a pointer */
|
||||
SDKPass_Plain, /**< Pass as plain data */
|
||||
SDKPass_ByValue, /**< Pass an object by value */
|
||||
SDKPass_ByRef, /**< Pass an object by reference */
|
||||
};
|
||||
|
||||
#define VDECODE_FLAG_ALLOWNULL (1<<0) /**< Allow NULL for pointers */
|
||||
#define VDECODE_FLAG_ALLOWNOTINGAME (1<<1) /**< Allow players not in game */
|
||||
#define VDECODE_FLAG_ALLOWWORLD (1<<2) /**< Allow World entity */
|
||||
#define VDECODE_FLAG_BYREF (1<<3) /**< Floats/ints by reference */
|
||||
|
||||
#define VENCODE_FLAG_COPYBACK (1<<0) /**< Copy back data once done */
|
||||
|
||||
/**
|
||||
* Starts the preparation of an SDK call.
|
||||
*
|
||||
* @param type Type of function call this will be.
|
||||
* @noreturn
|
||||
*/
|
||||
native StartPrepSDKCall(SDKCallType:type);
|
||||
|
||||
/**
|
||||
* Sets the virtual index of the SDK call if it is virtual.
|
||||
*
|
||||
* @param vtblidx Virtual table index.
|
||||
* @noreturn
|
||||
*/
|
||||
native PrepSDKCall_SetVirtual(vtblidx);
|
||||
|
||||
/**
|
||||
* Finds an address in a library and sets it as the address to use for the SDK call.
|
||||
*
|
||||
* @param lib Library to use.
|
||||
* @param signature Binary data to search for in the library. If it starts with '@',
|
||||
* the bytes parameter is ignored and the signature is interpreted
|
||||
* as a symbol lookup in the library.
|
||||
* @param bytes Number of bytes in the binary search string.
|
||||
* @return True on success, false if nothing was found.
|
||||
*/
|
||||
native bool:PrepSDKCall_SetSignature(SDKLibrary:lib, const String:signature[], bytes);
|
||||
|
||||
/**
|
||||
* Finds an address or virtual function index in a GameConfig file and sets it as
|
||||
* the calling information for the SDK call.
|
||||
*
|
||||
* @param gameconf GameConfig Handle, or INVALID_HANDLE to use sdktools.games.txt.
|
||||
* @param source Whether to look in Offsets or Signatures.
|
||||
* @param name Name of the property to find.
|
||||
* @return True on success, false if nothing was found.
|
||||
*/
|
||||
native bool:PrepSDKCall_SetFromConf(Handle:gameconf, SDKFuncConfSource:source, const String:name[]);
|
||||
|
||||
/**
|
||||
* Sets the return information of an SDK call. Do not call this if there is no return data.
|
||||
* This must be called if there is a return value (i.e. it is not necessarily safe to ignore
|
||||
* the data).
|
||||
*
|
||||
* @param type Data type to convert to/from.
|
||||
* @param pass How the data is passed in C++.
|
||||
* @param decflags Flags on decoding from the plugin to C++.
|
||||
* @param encflags Flags on encoding from C++ to the plugin.
|
||||
* @noreturn
|
||||
*/
|
||||
native PrepSDKCall_SetReturnInfo(SDKType:type, SDKPassMethod:pass, decflags=0, encflags=0);
|
||||
|
||||
/**
|
||||
* Adds a parameter to the calling convention. This should be called in normal ascending order.
|
||||
*
|
||||
* @param type Data type to convert to/from.
|
||||
* @param pass How the data is passed in C++.
|
||||
* @param decflags Flags on decoding from the plugin to C++.
|
||||
* @param encflags Flags on encoding from C++ to the plugin.
|
||||
* @noreturn
|
||||
*/
|
||||
native PrepSDKCall_AddParameter(SDKType:type, SDKPassMethod:pass, decflags=0, encflags=0);
|
||||
|
||||
/**
|
||||
* Finalizes an SDK call preparation and returns the resultant Handle.
|
||||
*
|
||||
* @return A new SDKCall Handle on success, or INVALID_HANDLE on failure.
|
||||
*/
|
||||
native Handle:EndPrepSDKCall();
|
||||
|
||||
/**
|
||||
* Calls an SDK function with the given parameters.
|
||||
*
|
||||
* If the call type is Entity or Player, the index MUST ALWAYS be the FIRST parameter passed.
|
||||
* If the return value is a Vector or QAngles, the SECOND parameter must be a Float[3].
|
||||
* If the return value is a string, the THIRD parameter must be a String buffer, and the
|
||||
* FOURTH parameter must be the maximum length.
|
||||
* All parameters must be passed after the above is followed. Failure to follow these
|
||||
* rules will result in crashes or wildly unexpected behavior!
|
||||
*
|
||||
* If the return value is a float or integer, the return value will be this value.
|
||||
* If the return value is a CBaseEntity, CBasePlayer, or edict, the return value will
|
||||
* always be the entity index, or -1 for NULL.
|
||||
*
|
||||
* @param call SDKCall Handle.
|
||||
* @param ... Call Parameters.
|
||||
* @return Simple return value, if any.
|
||||
* @error Invalid Handle or internal decoding error.
|
||||
*/
|
||||
native any:SDKCall(Handle:call, any:...);
|
||||
|
||||
|
||||
/**
|
||||
* Do not edit below this line!
|
||||
*/
|
||||
public Extension:__ext_sdktools =
|
||||
{
|
||||
name = "SDKTools",
|
||||
file = "sdktools.ext",
|
||||
#if defined AUTOLOAD_EXTENSIONS
|
||||
autoload = 1,
|
||||
#else
|
||||
autoload = 0,
|
||||
#endif
|
||||
#if defined REQUIRE_EXTENSIONS
|
||||
required = 1,
|
||||
#else
|
||||
required = 0,
|
||||
#endif
|
||||
};
|
51
plugins/include/sdktools_functions.inc
Normal file
51
plugins/include/sdktools_functions.inc
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* ===============================================================
|
||||
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved.
|
||||
* ===============================================================
|
||||
*
|
||||
* This file is part of the SourceMod/SourcePawn SDK. This file may only be used
|
||||
* or modified under the Terms and Conditions of its License Agreement, which is found
|
||||
* in LICENSE.txt. The Terms and Conditions for making SourceMod extensions/plugins
|
||||
* may change at any time. To view the latest information, see:
|
||||
* http://www.sourcemod.net/license.php
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#if defined _sdktools_functions_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _sdktools_functions_included
|
||||
|
||||
/**
|
||||
* Removes a player's item.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param item CBaseCombatWeapon entity index.
|
||||
* @return True on success, false otherwise.
|
||||
* @error Invalid client or entity, lack of mod support, or client not in
|
||||
* game.
|
||||
*/
|
||||
native bool:RemovePlayerItem(client, item);
|
||||
|
||||
/**
|
||||
* Gives a named item to a player.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param item Item classname (such as weapon_ak47).
|
||||
* @param iSubType Unknown.
|
||||
* @return Entity index on success, or -1 on failure.
|
||||
* @error Invalid client or client not in game, or lack of mod support.
|
||||
*/
|
||||
native GivePlayerItem(client, const String:item[], iSubType=0);
|
||||
|
||||
/**
|
||||
* Returns the weapon in a player's slot.
|
||||
*
|
||||
* @param client Client index.
|
||||
* @param slot Slot index (mod specific).
|
||||
* @return Entity index on success, -1 if no weapon existed.
|
||||
* @error Invalid client or client notin game, or lack of mod support.
|
||||
*/
|
||||
native GetPlayerWeaponSlot(client, slot);
|
Loading…
Reference in New Issue
Block a user