From 11ff3812893ff06b55d8f693403eafe786d80a7a Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 16 Jun 2007 18:03:05 +0000 Subject: [PATCH] - 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 --- extensions/sdktools/extension.cpp | 11 ++ extensions/sdktools/msvc8/sdktools.vcproj | 8 + extensions/sdktools/vcallbuilder.h | 23 --- extensions/sdktools/vcaller.cpp | 27 ++-- extensions/sdktools/vdecoder.cpp | 133 ++++++++++++---- extensions/sdktools/vdecoder.h | 37 +++-- extensions/sdktools/vnatives.cpp | 182 ++++++++++++++++++++++ extensions/sdktools/vnatives.h | 9 ++ gamedata/sdktools.games.txt | 10 ++ plugins/include/sdktools.inc | 179 +++++++++++++++++++++ plugins/include/sdktools_functions.inc | 51 ++++++ 11 files changed, 593 insertions(+), 77 deletions(-) create mode 100644 extensions/sdktools/vnatives.cpp create mode 100644 extensions/sdktools/vnatives.h create mode 100644 plugins/include/sdktools.inc create mode 100644 plugins/include/sdktools_functions.inc diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp index c762db5e..7aea3839 100644 --- a/extensions/sdktools/extension.cpp +++ b/extensions/sdktools/extension.cpp @@ -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::iterator iter; + for (iter = g_RegCalls.begin(); + iter != g_RegCalls.end(); + iter++) + { + delete (*iter); + } + g_RegCalls.clear(); + gameconfs->CloseGameConfigFile(g_pGameConf); } diff --git a/extensions/sdktools/msvc8/sdktools.vcproj b/extensions/sdktools/msvc8/sdktools.vcproj index 560fbd36..4edbf0a9 100644 --- a/extensions/sdktools/msvc8/sdktools.vcproj +++ b/extensions/sdktools/msvc8/sdktools.vcproj @@ -197,6 +197,10 @@ RelativePath="..\vdecoder.cpp" > + + + + 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) diff --git a/extensions/sdktools/vdecoder.cpp b/extensions/sdktools/vdecoder.cpp index 4764a206..92783f20 100644 --- a/extensions/sdktools/vdecoder.cpp +++ b/extensions/sdktools/vdecoder.cpp @@ -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,12 +80,44 @@ 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; - info->size = sizeof(float); - return sizeof(float); + if (flags & PASSFLAG_ASPOINTER) + { + info->size = sizeof(float *); + return sizeof(float *) + sizeof(float); + } else { + info->size = sizeof(float); + return sizeof(float); + } } } @@ -96,20 +126,19 @@ size_t ValveParamToBinParam(ValveType type, 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; diff --git a/extensions/sdktools/vdecoder.h b/extensions/sdktools/vdecoder.h index 05355f18..94f9321e 100644 --- a/extensions/sdktools/vdecoder.h +++ b/extensions/sdktools/vdecoder.h @@ -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_ diff --git a/extensions/sdktools/vnatives.cpp b/extensions/sdktools/vnatives.cpp new file mode 100644 index 00000000..3c6d1b4b --- /dev/null +++ b/extensions/sdktools/vnatives.cpp @@ -0,0 +1,182 @@ +#include "extension.h" +#include "vcallbuilder.h" +#include "vnatives.h" + +List 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}, +}; diff --git a/extensions/sdktools/vnatives.h b/extensions/sdktools/vnatives.h new file mode 100644 index 00000000..8c235644 --- /dev/null +++ b/extensions/sdktools/vnatives.h @@ -0,0 +1,9 @@ +#ifndef _INCLUDE_SDKTOOLS_VNATIVES_H_ +#define _INCLUDE_SDKTOOLS_VNATIVES_H_ + +#include + +extern List g_RegCalls; +extern sp_nativeinfo_t g_Natives[]; + +#endif //_INCLUDE_SDKTOOLS_VNATIVES_H_ diff --git a/gamedata/sdktools.games.txt b/gamedata/sdktools.games.txt index 8f2d7ce0..52fcc011 100644 --- a/gamedata/sdktools.games.txt +++ b/gamedata/sdktools.games.txt @@ -14,6 +14,16 @@ "windows" "329" "linux" "330" } + "RemovePlayerItem" + { + "windows" "226" + "linux" "227" + } + "Weapon_GetSlot" + { + "windows" "224" + "linux" "225" + } } } } diff --git a/plugins/include/sdktools.inc b/plugins/include/sdktools.inc new file mode 100644 index 00000000..78a964d5 --- /dev/null +++ b/plugins/include/sdktools.inc @@ -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 +#include + +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 +}; diff --git a/plugins/include/sdktools_functions.inc b/plugins/include/sdktools_functions.inc new file mode 100644 index 00000000..1ecdcf3e --- /dev/null +++ b/plugins/include/sdktools_functions.inc @@ -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); \ No newline at end of file