From 2446ff49f270894517495a184a4f3a0202de88de Mon Sep 17 00:00:00 2001 From: Arkshine Date: Wed, 14 Jan 2015 09:28:40 +0100 Subject: [PATCH 1/5] Add cs_create_entity native --- dlls/cstrike/cstrike/CstrikeDatas.h | 14 ++++++++------ dlls/cstrike/cstrike/CstrikeNatives.cpp | 23 +++++++++++++++++++++++ dlls/cstrike/cstrike/amxx_api.cpp | 6 ++++++ plugins/include/cstrike.inc | 16 ++++++++++++++++ 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index 59d955e1..4c2b3e89 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -140,23 +140,23 @@ #define CS_CLICMD_OFFS_BOTARGS 22 #endif -/** - * CS_OnBuy forward - */ #if defined(__linux__) - #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" - #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" - #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" + #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" // CS_OnBuy forward + #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" // CS_OnBuy forward + #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" // CS_OnBuy forward + #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" // cs_create_entity #define CS_IDENT_HIDDEN_STATE false #elif defined(__APPLE__) #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" + #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" #define CS_IDENT_HIDDEN_STATE true #elif defined(WIN32) #define CS_IDENT_GIVENSHIELD "\\x56\\x8B\\x2A\\x57\\x33\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\xB0" #define CS_IDENT_GIVENAMEDITEM "\\x8B\\x2A\\x2A\\x2A\\x56\\x57\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x2B" #define CS_IDENT_ADDACCOUNT "\\x8B\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x03" + #define CS_IDENT_CREATENAMEDENTITY "\\x56\\x57\\x8B\\x2A\\x2A\\x2A\\x57\\xFF\\x2A\\x2A\\x2A\\x2A\\x2A\\x8B" #define CS_IDENT_HIDDEN_STATE false #endif @@ -349,4 +349,6 @@ typedef enum } Menu; +typedef edict_t* (*CreateNamedEntityFunc)(string_t); + #endif // CSTRIKE_DATA_H diff --git a/dlls/cstrike/cstrike/CstrikeNatives.cpp b/dlls/cstrike/cstrike/CstrikeNatives.cpp index e494bfb0..902019d5 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.cpp +++ b/dlls/cstrike/cstrike/CstrikeNatives.cpp @@ -1707,6 +1707,28 @@ static cell AMX_NATIVE_CALL cs_set_c4_defusing(AMX* amx, cell* params) return 1; } +extern CreateNamedEntityFunc CS_CreateNamedEntity; + +// cs_create_entity(const classname[]) +static cell AMX_NATIVE_CALL cs_create_entity(AMX* amx, cell* params) +{ + if (CS_CreateNamedEntity > 0) + { + int len; + int iszClass = ALLOC_STRING(MF_GetAmxString(amx, params[1], 0, &len)); + + edict_t *pEnt = CS_CreateNamedEntity(iszClass); + + if (!FNullEnt(pEnt)) + { + return ENTINDEX(pEnt); + } + } + + return 0; +} + + #else static cell AMX_NATIVE_CALL not_on_64(AMX* amx, cell* params) @@ -1791,6 +1813,7 @@ AMX_NATIVE_INFO CstrikeNatives[] = { {"cs_set_c4_explode_time", cs_set_c4_explode_time}, {"cs_get_c4_defusing", cs_get_c4_defusing}, {"cs_set_c4_defusing", cs_set_c4_defusing}, + {"cs_create_entity", cs_create_entity }, {NULL, NULL} }; diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index 17dfd227..e0499675 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -13,6 +13,7 @@ #include "amxxmodule.h" #include "CstrikeUtils.h" +#include "CstrikeDatas.h" extern AMX_NATIVE_INFO CstrikeNatives[]; @@ -25,6 +26,7 @@ void ShutdownHacks(); void ToggleDetour_ClientCommands(bool enable); void ToggleDetour_BuyCommands(bool enable); +CreateNamedEntityFunc CS_CreateNamedEntity = NULL; int AmxxCheckGame(const char *game) { @@ -39,7 +41,11 @@ int AmxxCheckGame(const char *game) void OnAmxxAttach() { MF_AddNatives(CstrikeNatives); + InitializeHacks(); + + // cs_create_entity(). + CS_CreateNamedEntity = reinterpret_cast(UTIL_FindAddressFromEntry(CS_IDENT_CREATENAMEDENTITY, CS_IDENT_HIDDEN_STATE)); } void OnPluginsLoaded() diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 6c404eda..6d41267b 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -350,6 +350,22 @@ native bool:cs_get_c4_defusing(c4index); native cs_set_c4_defusing(c4index, bool:defusing); +/** + * Creates an entity. + * + * @note Similar as create_entity() native from engine module, with the difference that in Counter-Strike + * to improve lookup performance on entities, the classname is hashed and saved in a global list. + * This means for classname, game uses a custom function which checks that list instead of calling pfnFindEntityByString. + * You would want to use this native if you want having custom entities to be known by the game. + * E.g. By creating a "weaponbox" entity, this will be automatically deleted by game on map restart. + * With engine version, you would have to remove it manually. + * + * @param classname Entity class name + * + * @return Index of the created entity, 0 otherwise. + */ +native cs_create_entity(const classname[]); + /** * Called when CS internally fires a command to a player. It does this for a few * functions, most notably rebuy/autobuy functionality. This is also used to pass From c87d46ad5bdc23559fc2b54b11b5e6b9b87ff63a Mon Sep 17 00:00:00 2001 From: Arkshine Date: Fri, 30 Jan 2015 15:53:25 +0100 Subject: [PATCH 2/5] Add cs_find_ent_by_class and fix documentation --- dlls/cstrike/cstrike/AMBuilder | 1 + dlls/cstrike/cstrike/CstrikeDatas.h | 36 +++--- .../cstrike/CstrikeHLTypeConversion.cpp | 118 ++++++++++++++++++ .../cstrike/cstrike/CstrikeHLTypeConversion.h | 49 ++++++++ dlls/cstrike/cstrike/CstrikeNatives.cpp | 23 ++++ dlls/cstrike/cstrike/Makefile | 2 +- dlls/cstrike/cstrike/amxx_api.cpp | 12 +- plugins/include/cstrike.inc | 39 ++++-- 8 files changed, 254 insertions(+), 26 deletions(-) create mode 100644 dlls/cstrike/cstrike/CstrikeHLTypeConversion.cpp create mode 100644 dlls/cstrike/cstrike/CstrikeHLTypeConversion.h diff --git a/dlls/cstrike/cstrike/AMBuilder b/dlls/cstrike/cstrike/AMBuilder index aaffd58f..bae60bed 100644 --- a/dlls/cstrike/cstrike/AMBuilder +++ b/dlls/cstrike/cstrike/AMBuilder @@ -14,6 +14,7 @@ binary.sources = [ 'CstrikeNatives.cpp', 'CstrikeHacks.cpp', 'CstrikeUtils.cpp', + 'CstrikeHLTypeConversion.cpp', '../../../public/memtools/MemoryUtils.cpp', '../../../public/memtools/CDetour/detours.cpp', '../../../public/memtools/CDetour/asm/asm.c', diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index 4c2b3e89..070b1581 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -141,23 +141,26 @@ #endif #if defined(__linux__) - #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" // CS_OnBuy forward - #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" // CS_OnBuy forward - #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" // CS_OnBuy forward - #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" // cs_create_entity - #define CS_IDENT_HIDDEN_STATE false + #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" // CS_OnBuy forward + #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" // CS_OnBuy forward + #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" // CS_OnBuy forward + #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" // cs_create_entity + #define CS_IDENTI_UTIL_FINDENTITYBYSTRING "_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_" // cs_create_entity + #define CS_IDENT_HIDDEN_STATE false #elif defined(__APPLE__) - #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" - #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" - #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" - #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" - #define CS_IDENT_HIDDEN_STATE true + #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" + #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" + #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" + #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" + #define CS_IDENTI_UTIL_FINDENTITYBYSTRING "_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_" + #define CS_IDENT_HIDDEN_STATE true #elif defined(WIN32) - #define CS_IDENT_GIVENSHIELD "\\x56\\x8B\\x2A\\x57\\x33\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\xB0" - #define CS_IDENT_GIVENAMEDITEM "\\x8B\\x2A\\x2A\\x2A\\x56\\x57\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x2B" - #define CS_IDENT_ADDACCOUNT "\\x8B\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x03" - #define CS_IDENT_CREATENAMEDENTITY "\\x56\\x57\\x8B\\x2A\\x2A\\x2A\\x57\\xFF\\x2A\\x2A\\x2A\\x2A\\x2A\\x8B" - #define CS_IDENT_HIDDEN_STATE false + #define CS_IDENT_GIVENSHIELD "\\x56\\x8B\\x2A\\x57\\x33\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\xB0" + #define CS_IDENT_GIVENAMEDITEM "\\x8B\\x2A\\x2A\\x2A\\x56\\x57\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x2B" + #define CS_IDENT_ADDACCOUNT "\\x8B\\x2A\\x2A\\x2A\\x56\\x8B\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\x03" + #define CS_IDENT_CREATENAMEDENTITY "\\x56\\x57\\x8B\\x2A\\x2A\\x2A\\x57\\xFF\\x2A\\x2A\\x2A\\x2A\\x2A\\x8B" + #define CS_IDENT_UTIL_FINDENTITYBYSTRING "\\x51\\x8B\\x2A\\x2A\\x2A\\x53\\x55\\x56\\x85\\x2A\\x57" + #define CS_IDENT_HIDDEN_STATE false #endif #define CSI_P228 CSW_P228 @@ -349,6 +352,7 @@ typedef enum } Menu; -typedef edict_t* (*CreateNamedEntityFunc)(string_t); +typedef edict_t* (*CreateNamedEntityFunc)(string_t iszClassname); +typedef void* (*UTIL_FindEntityByStringFunc)(void* pStartEntity, const char *szKeyword, const char *szValue); #endif // CSTRIKE_DATA_H diff --git a/dlls/cstrike/cstrike/CstrikeHLTypeConversion.cpp b/dlls/cstrike/cstrike/CstrikeHLTypeConversion.cpp new file mode 100644 index 00000000..3b971af3 --- /dev/null +++ b/dlls/cstrike/cstrike/CstrikeHLTypeConversion.cpp @@ -0,0 +1,118 @@ +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +// +// Counter-Strike Module +// + +#include "CstrikeHLTypeConversion.h" + +OffsetHandler* G_OffsetHandler; +HL_TypeConversion G_HL_TypeConversion; + +void OffsetHandler::search_pev() +{ + edict_t* edict = INDEXENT(0); + entvars_t* entvars = &edict->v; + + byte* private_c = (byte*)edict->pvPrivateData; + + for (int i = 0; i < 0xFFF; i++) + { + uintptr_t val = *((uintptr_t*)(private_c + i)); + + if (val == (uintptr_t)entvars) + { + this->pev = i; + return; + } + } + + // This should not happen. + this->pev = 0; +} + +inline edict_t* HL_TypeConversion::INDEXENT2(int iEdictNum) +{ + if (iEdictNum >= 1 && iEdictNum <= gpGlobals->maxClients) + { + return MF_GetPlayerEdict(iEdictNum); + } + else + { + return (*g_engfuncs.pfnPEntityOfEntIndex)(iEdictNum); + } +} + +edict_t* HL_TypeConversion::entvar_to_edict(entvars_t *pev) +{ + if (!pev) + { + return nullptr; + } + + return pev->pContainingEntity; +} + +int HL_TypeConversion::entvar_to_id(entvars_t *pev) +{ + if (!pev) + { + return -1; + } + + if (!pev->pContainingEntity) + { + return -1; + } + + return ENTINDEX(pev->pContainingEntity); +} + +void* HL_TypeConversion::id_to_cbase(int index) +{ + edict_t* edict = INDEXENT2(index); + return edict ? edict->pvPrivateData : nullptr; +} + +entvars_t* HL_TypeConversion::id_to_entvar(int index) +{ + return &(INDEXENT2(index)->v); +} + +entvars_t* HL_TypeConversion::cbase_to_entvar(void* cbase) +{ + if (!cbase) + { + return nullptr; + } + + return *(entvars_t **)((char *)(cbase) + G_OffsetHandler->pev); +} + +int HL_TypeConversion::cbase_to_id(void *cbase) +{ + if (!cbase) + { + return -1; + } + + entvars_t* pev = this->cbase_to_entvar(cbase); + + if (!pev) + { + return -1; + } + + if (!pev->pContainingEntity || FNullEnt(pev->pContainingEntity)) + { + return -1; + } + + return ENTINDEX(pev->pContainingEntity); +} diff --git a/dlls/cstrike/cstrike/CstrikeHLTypeConversion.h b/dlls/cstrike/cstrike/CstrikeHLTypeConversion.h new file mode 100644 index 00000000..327878e3 --- /dev/null +++ b/dlls/cstrike/cstrike/CstrikeHLTypeConversion.h @@ -0,0 +1,49 @@ +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +// +// Counter-Strike Module +// + +#ifndef HL_TYPE_CONVERSION_H +#define HL_TYPE_CONVERSION_H + +#include "amxxmodule.h" + +struct OffsetHandler +{ + int pev; + + void search_pev(); + + OffsetHandler() + { + search_pev(); + } +}; + +class HL_TypeConversion +{ + public: + + inline edict_t* INDEXENT2(int iEdictNum); + + edict_t* entvar_to_edict(entvars_t *pev); + int entvar_to_id(entvars_t *pev); + + void* id_to_cbase(int index); + int cbase_to_id(void *cbase); + + entvars_t* id_to_entvar(int index); + entvars_t* cbase_to_entvar(void* cbase); +}; + +extern OffsetHandler* G_OffsetHandler; +extern HL_TypeConversion G_HL_TypeConversion; + +#endif // HL_TYPE_CONVERSION_H diff --git a/dlls/cstrike/cstrike/CstrikeNatives.cpp b/dlls/cstrike/cstrike/CstrikeNatives.cpp index 902019d5..004e941b 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.cpp +++ b/dlls/cstrike/cstrike/CstrikeNatives.cpp @@ -14,6 +14,7 @@ #include "CstrikeDatas.h" #include "CstrikePlayer.h" #include "CstrikeUtils.h" +#include "CstrikeHLTypeConversion.h" CCstrikePlayer g_players[33]; int g_zooming[33] = {0}; @@ -1708,6 +1709,7 @@ static cell AMX_NATIVE_CALL cs_set_c4_defusing(AMX* amx, cell* params) } extern CreateNamedEntityFunc CS_CreateNamedEntity; +extern UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString; // cs_create_entity(const classname[]) static cell AMX_NATIVE_CALL cs_create_entity(AMX* amx, cell* params) @@ -1728,6 +1730,26 @@ static cell AMX_NATIVE_CALL cs_create_entity(AMX* amx, cell* params) return 0; } +// cs_find_ent_by_class(start_index, const classname[]) +static cell AMX_NATIVE_CALL cs_find_ent_by_class(AMX* amx, cell* params) +{ + if (CS_UTIL_FindEntityByString > 0) + { + int len; + void* pEntity = G_HL_TypeConversion.id_to_cbase(params[1]); + const char* value = MF_GetAmxString(amx, params[2], 0, &len); + + int index = G_HL_TypeConversion.cbase_to_id(CS_UTIL_FindEntityByString(pEntity, "classname", value)); + + if (index != -1) + { + return index; + } + } + + return 0; +} + #else @@ -1814,6 +1836,7 @@ AMX_NATIVE_INFO CstrikeNatives[] = { {"cs_get_c4_defusing", cs_get_c4_defusing}, {"cs_set_c4_defusing", cs_set_c4_defusing}, {"cs_create_entity", cs_create_entity }, + {"cs_find_ent_by_class", cs_find_ent_by_class }, {NULL, NULL} }; diff --git a/dlls/cstrike/cstrike/Makefile b/dlls/cstrike/cstrike/Makefile index a56c9de2..d4397e2f 100755 --- a/dlls/cstrike/cstrike/Makefile +++ b/dlls/cstrike/cstrike/Makefile @@ -15,7 +15,7 @@ PUBLIC_ROOT = ../../../public PROJECT = cstrike -OBJECTS = amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp CstrikeNatives.cpp CstrikeHacks.cpp CstrikeUtils.cpp \ +OBJECTS = amxxmodule.cpp amxx_api.cpp CstrikePlayer.cpp CstrikeNatives.cpp CstrikeHacks.cpp CstrikeUtils.cpp CstrikeHLTypeConversion.cpp \ MemoryUtils.cpp detours.cpp asm.c ############################################## diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index e0499675..9d059c32 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -14,6 +14,7 @@ #include "amxxmodule.h" #include "CstrikeUtils.h" #include "CstrikeDatas.h" +#include "CstrikeHLTypeConversion.h" extern AMX_NATIVE_INFO CstrikeNatives[]; @@ -26,7 +27,8 @@ void ShutdownHacks(); void ToggleDetour_ClientCommands(bool enable); void ToggleDetour_BuyCommands(bool enable); -CreateNamedEntityFunc CS_CreateNamedEntity = NULL; +CreateNamedEntityFunc CS_CreateNamedEntity = nullptr; +UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString = nullptr; int AmxxCheckGame(const char *game) { @@ -44,8 +46,14 @@ void OnAmxxAttach() InitializeHacks(); - // cs_create_entity(). + // cs_create_entity() CS_CreateNamedEntity = reinterpret_cast(UTIL_FindAddressFromEntry(CS_IDENT_CREATENAMEDENTITY, CS_IDENT_HIDDEN_STATE)); + + // cs_find_ent_by_class() + CS_UTIL_FindEntityByString = reinterpret_cast(UTIL_FindAddressFromEntry(CS_IDENT_UTIL_FINDENTITYBYSTRING, CS_IDENT_HIDDEN_STATE)); + + // Search pev offset automatically. + G_OffsetHandler = new OffsetHandler; } void OnPluginsLoaded() diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index 6d41267b..dbb52938 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -351,14 +351,20 @@ native bool:cs_get_c4_defusing(c4index); native cs_set_c4_defusing(c4index, bool:defusing); /** - * Creates an entity. + * Creates an entity using Counter-Strike's custom CreateNamedEntity wrapper. * - * @note Similar as create_entity() native from engine module, with the difference that in Counter-Strike - * to improve lookup performance on entities, the classname is hashed and saved in a global list. - * This means for classname, game uses a custom function which checks that list instead of calling pfnFindEntityByString. - * You would want to use this native if you want having custom entities to be known by the game. - * E.g. By creating a "weaponbox" entity, this will be automatically deleted by game on map restart. - * With engine version, you would have to remove it manually. + * @note Unlike other mods CS keeps track of entities using a custom hashtable. + * This function will add entities to this hashtable, providing benefits + * over the default engine functions (used by create_entity() for example): + * - Storing entities in a hashtable allows CS to improve classname lookup + * performance compared to functions like FindEntityByString that usually + * have to loop incrementally through all entities. + * - As CS exclusively uses the hashtable for classname lookup, entities + * created using the default engine functions will not be found by the + * game. For example "weaponbox" entities are supposed to be + * automatically cleaned up on round restart but are not considered if + * they have not been added to the hashtable. + * @note CS's faster hashtable lookup can be utilized with cs_find_ent_by_class() * * @param classname Entity class name * @@ -366,6 +372,25 @@ native cs_set_c4_defusing(c4index, bool:defusing); */ native cs_create_entity(const classname[]); +/** + * Finds an entity in the world using Counter-Strike's custom FindEntityByString + * wrapper. + * + * @note Unlike other mods CS keeps track of entities using a custom hashtable. + * This function utilizes the custom hasthable and allows for considerably + * faster classname lookup compared to the default engine functions (used + * by find_ent_by_class() for example). + * @note This exclusively considers entities in the hashtable, created by the + * game itself or using cs_create_entity(). + * + * @param start_index Entity index to start searching from. -1 to start from + * the first entity + * @param classname Classname to search for + * + * @return Entity index > 0 if found, 0 otherwise + */ +native cs_find_ent_by_class(start_index, const classname[]); + /** * Called when CS internally fires a command to a player. It does this for a few * functions, most notably rebuy/autobuy functionality. This is also used to pass From e0426f10b2ce5bb0fbd44295f6909145411eb94c Mon Sep 17 00:00:00 2001 From: Arkshine Date: Fri, 30 Jan 2015 16:01:26 +0100 Subject: [PATCH 3/5] Fix typo --- dlls/cstrike/cstrike/CstrikeDatas.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeDatas.h b/dlls/cstrike/cstrike/CstrikeDatas.h index 070b1581..f65af4e1 100644 --- a/dlls/cstrike/cstrike/CstrikeDatas.h +++ b/dlls/cstrike/cstrike/CstrikeDatas.h @@ -145,14 +145,14 @@ #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" // CS_OnBuy forward #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" // CS_OnBuy forward #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" // cs_create_entity - #define CS_IDENTI_UTIL_FINDENTITYBYSTRING "_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_" // cs_create_entity + #define CS_IDENT_UTIL_FINDENTITYBYSTRING "_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_" // cs_create_entity #define CS_IDENT_HIDDEN_STATE false #elif defined(__APPLE__) #define CS_IDENT_GIVENSHIELD "_ZN11CBasePlayer10GiveShieldEb" #define CS_IDENT_GIVENAMEDITEM "_ZN11CBasePlayer13GiveNamedItemEPKc" #define CS_IDENT_ADDACCOUNT "_ZN11CBasePlayer10AddAccountEib" #define CS_IDENT_CREATENAMEDENTITY "_Z19CREATE_NAMED_ENTITYj" - #define CS_IDENTI_UTIL_FINDENTITYBYSTRING "_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_" + #define CS_IDENT_UTIL_FINDENTITYBYSTRING "_Z23UTIL_FindEntityByStringP11CBaseEntityPKcS2_" #define CS_IDENT_HIDDEN_STATE true #elif defined(WIN32) #define CS_IDENT_GIVENSHIELD "\\x56\\x8B\\x2A\\x57\\x33\\x2A\\x8B\\x2A\\x2A\\x2A\\x2A\\x2A\\xB0" From 4ceb767022f02d6955a69166015be3b9daa73f62 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Sat, 31 Jan 2015 14:45:37 +0100 Subject: [PATCH 4/5] Add error messages and fix documentation --- dlls/cstrike/cstrike/CstrikeHacks.cpp | 23 +++++++++++--- dlls/cstrike/cstrike/CstrikeNatives.cpp | 42 ++++++++++++++----------- dlls/cstrike/cstrike/amxx_api.cpp | 12 ++++++- plugins/include/cstrike.inc | 19 +++++------ 4 files changed, 64 insertions(+), 32 deletions(-) diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 094e88d5..926d37a1 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -251,9 +251,9 @@ void CtrlDetours_ClientCommand(bool set) #endif ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, target); - if (ClientCommandDetour == NULL) + if (!ClientCommandDetour) { - MF_Log("No Client Commands detour could be initialized - Disabled Client Command forward."); + MF_Log("ClientCommand is not available - forward client_command has been disabled"); } } else @@ -337,9 +337,24 @@ void CtrlDetours_BuyCommands(bool set) GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, giveNamedItemAddress); AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, addAccountAddress); - if (GiveNamedItemDetour == NULL || AddAccountDetour == NULL) + if (!GiveShieldDetour || !GiveNamedItemDetour || !AddAccountDetour) { - MF_Log("No Buy Commands detours could be initialized - Disabled Buy forward."); + if (!GiveNamedItemDetour) + { + MF_Log("GiveShield is not available"); + } + + if (!GiveNamedItemDetour) + { + MF_Log("GiveNamedItem is not available"); + } + + if (!AddAccountDetour) + { + MF_Log("AddAccount is not available"); + } + + MF_Log("Some functions are not available - forward CS_OnBuyAttempt and CS_OnBuy have been disabled"); } } else diff --git a/dlls/cstrike/cstrike/CstrikeNatives.cpp b/dlls/cstrike/cstrike/CstrikeNatives.cpp index 004e941b..4d84c3ca 100644 --- a/dlls/cstrike/cstrike/CstrikeNatives.cpp +++ b/dlls/cstrike/cstrike/CstrikeNatives.cpp @@ -1714,17 +1714,20 @@ extern UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString; // cs_create_entity(const classname[]) static cell AMX_NATIVE_CALL cs_create_entity(AMX* amx, cell* params) { - if (CS_CreateNamedEntity > 0) + if (CS_CreateNamedEntity <= 0) { - int len; - int iszClass = ALLOC_STRING(MF_GetAmxString(amx, params[1], 0, &len)); + MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_create_entity() is disabled"); + return 0; + } - edict_t *pEnt = CS_CreateNamedEntity(iszClass); + int len; + int iszClass = ALLOC_STRING(MF_GetAmxString(amx, params[1], 0, &len)); - if (!FNullEnt(pEnt)) - { - return ENTINDEX(pEnt); - } + edict_t *pEnt = CS_CreateNamedEntity(iszClass); + + if (!FNullEnt(pEnt)) + { + return ENTINDEX(pEnt); } return 0; @@ -1733,18 +1736,21 @@ static cell AMX_NATIVE_CALL cs_create_entity(AMX* amx, cell* params) // cs_find_ent_by_class(start_index, const classname[]) static cell AMX_NATIVE_CALL cs_find_ent_by_class(AMX* amx, cell* params) { - if (CS_UTIL_FindEntityByString > 0) + if (CS_UTIL_FindEntityByString <= 0) { - int len; - void* pEntity = G_HL_TypeConversion.id_to_cbase(params[1]); - const char* value = MF_GetAmxString(amx, params[2], 0, &len); + MF_LogError(amx, AMX_ERR_NATIVE, "Native cs_find_ent_by_class() is disabled"); + return 0; + } - int index = G_HL_TypeConversion.cbase_to_id(CS_UTIL_FindEntityByString(pEntity, "classname", value)); + int len; + void* pEntity = G_HL_TypeConversion.id_to_cbase(params[1]); + const char* value = MF_GetAmxString(amx, params[2], 0, &len); - if (index != -1) - { - return index; - } + int index = G_HL_TypeConversion.cbase_to_id(CS_UTIL_FindEntityByString(pEntity, "classname", value)); + + if (index != -1) + { + return index; } return 0; @@ -1836,7 +1842,7 @@ AMX_NATIVE_INFO CstrikeNatives[] = { {"cs_get_c4_defusing", cs_get_c4_defusing}, {"cs_set_c4_defusing", cs_set_c4_defusing}, {"cs_create_entity", cs_create_entity }, - {"cs_find_ent_by_class", cs_find_ent_by_class }, + {"cs_find_ent_by_class", cs_find_ent_by_class}, {NULL, NULL} }; diff --git a/dlls/cstrike/cstrike/amxx_api.cpp b/dlls/cstrike/cstrike/amxx_api.cpp index 9d059c32..1cf5c169 100644 --- a/dlls/cstrike/cstrike/amxx_api.cpp +++ b/dlls/cstrike/cstrike/amxx_api.cpp @@ -48,9 +48,19 @@ void OnAmxxAttach() // cs_create_entity() CS_CreateNamedEntity = reinterpret_cast(UTIL_FindAddressFromEntry(CS_IDENT_CREATENAMEDENTITY, CS_IDENT_HIDDEN_STATE)); - + + if (CS_CreateNamedEntity <= 0) + { + MF_Log("CREATE_NAMED_ENITTY is not available - native cs_create_entity() has been disabled"); + } + // cs_find_ent_by_class() CS_UTIL_FindEntityByString = reinterpret_cast(UTIL_FindAddressFromEntry(CS_IDENT_UTIL_FINDENTITYBYSTRING, CS_IDENT_HIDDEN_STATE)); + + if (CS_UTIL_FindEntityByString <= 0) + { + MF_Log("UTIL_FindEntByString is not available - native cs_find_ent_by_class() has been disabled"); + } // Search pev offset automatically. G_OffsetHandler = new OffsetHandler; diff --git a/plugins/include/cstrike.inc b/plugins/include/cstrike.inc index dbb52938..6bd2846d 100755 --- a/plugins/include/cstrike.inc +++ b/plugins/include/cstrike.inc @@ -354,17 +354,18 @@ native cs_set_c4_defusing(c4index, bool:defusing); * Creates an entity using Counter-Strike's custom CreateNamedEntity wrapper. * * @note Unlike other mods CS keeps track of entities using a custom hashtable. - * This function will add entities to this hashtable, providing benefits - * over the default engine functions (used by create_entity() for example): + * This function adds entities to this hashtable, providing benefits over + * the default CreateNamedEntity (used by create_entity() for example): * - Storing entities in a hashtable allows CS to improve classname lookup - * performance compared to functions like FindEntityByString that usually - * have to loop incrementally through all entities. + * performance compared to functions like FindEntityByString (used by + * find_ent_by_class() for example) that usually have to loop + * through all entities incrementally. * - As CS exclusively uses the hashtable for classname lookup, entities * created using the default engine functions will not be found by the * game. For example "weaponbox" entities are supposed to be * automatically cleaned up on round restart but are not considered if * they have not been added to the hashtable. - * @note CS's faster hashtable lookup can be utilized with cs_find_ent_by_class() + * @note The faster hashtable lookup can be utilized with cs_find_ent_by_class() * * @param classname Entity class name * @@ -372,14 +373,14 @@ native cs_set_c4_defusing(c4index, bool:defusing); */ native cs_create_entity(const classname[]); -/** +/** * Finds an entity in the world using Counter-Strike's custom FindEntityByString * wrapper. * * @note Unlike other mods CS keeps track of entities using a custom hashtable. - * This function utilizes the custom hasthable and allows for considerably - * faster classname lookup compared to the default engine functions (used - * by find_ent_by_class() for example). + * This function utilizes the hasthable and allows for considerably faster + * classname lookup compared to the default FindEntityByString (used by + * find_ent_by_class() for example). * @note This exclusively considers entities in the hashtable, created by the * game itself or using cs_create_entity(). * From 30ee4df0fab4a911c41181462722394fc845b407 Mon Sep 17 00:00:00 2001 From: Arkshine Date: Sat, 31 Jan 2015 15:38:35 +0100 Subject: [PATCH 5/5] Fix typo --- dlls/cstrike/cstrike/CstrikeHacks.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/cstrike/cstrike/CstrikeHacks.cpp b/dlls/cstrike/cstrike/CstrikeHacks.cpp index 926d37a1..29ee8c82 100644 --- a/dlls/cstrike/cstrike/CstrikeHacks.cpp +++ b/dlls/cstrike/cstrike/CstrikeHacks.cpp @@ -339,7 +339,7 @@ void CtrlDetours_BuyCommands(bool set) if (!GiveShieldDetour || !GiveNamedItemDetour || !AddAccountDetour) { - if (!GiveNamedItemDetour) + if (!GiveShieldDetour) { MF_Log("GiveShield is not available"); }