From 2c36a434b309fae98319b5a0e1671d7eb4c09b82 Mon Sep 17 00:00:00 2001 From: Borja Ferrer Date: Fri, 3 Aug 2007 01:53:00 +0000 Subject: [PATCH] added amb719, added TE hooks and read prop natives to read props before transmission --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401261 --- extensions/sdktools/extension.cpp | 3 + extensions/sdktools/tempents.cpp | 63 ++++++ extensions/sdktools/tempents.h | 29 +++ extensions/sdktools/tenatives.cpp | 278 ++++++++++++++++++++++++++ plugins/include/sdktools_tempents.inc | 61 ++++++ 5 files changed, 434 insertions(+) diff --git a/extensions/sdktools/extension.cpp b/extensions/sdktools/extension.cpp index eae9bd95..e6b28486 100644 --- a/extensions/sdktools/extension.cpp +++ b/extensions/sdktools/extension.cpp @@ -119,6 +119,7 @@ void SDKTools::SDK_OnUnload() ShutdownHelpers(); g_TEManager.Shutdown(); + s_TempEntHooks.Shutdown(); gameconfs->CloseGameConfigFile(g_pGameConf); playerhelpers->RemoveClientListener(&g_SdkTools); @@ -143,6 +144,7 @@ void SDKTools::SDK_OnAllLoaded() SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools); g_TEManager.Initialize(); + s_TempEntHooks.Initialize(); InitializeValveGlobals(); } @@ -176,6 +178,7 @@ void SDKTools::NotifyInterfaceDrop(SMInterface *pInterface) ShutdownHelpers(); g_TEManager.Shutdown(); + s_TempEntHooks.Shutdown(); } bool SDKTools::RegisterConCommandBase(ConCommandBase *pVar) diff --git a/extensions/sdktools/tempents.cpp b/extensions/sdktools/tempents.cpp index d6a64ee6..4b7214f5 100644 --- a/extensions/sdktools/tempents.cpp +++ b/extensions/sdktools/tempents.cpp @@ -143,6 +143,31 @@ bool TempEntityInfo::TE_SetEntData(const char *name, int value) return true; } +bool TempEntityInfo::TE_GetEntData(const char *name, int *value) +{ + /* Search for our offset */ + int size; + int offset = _FindOffset(name, &size); + + if (offset < 0) + { + return false; + } + + if (size <= 8) + { + *value = *((uint8_t *)m_Me + offset); + } else if (size <= 16) { + *value = *(short *)((uint8_t *)m_Me + offset); + } else if (size <= 32) { + *value = *(int *)((uint8_t *)m_Me + offset); + } else { + return false; + } + + return true; +} + bool TempEntityInfo::TE_SetEntDataFloat(const char *name, float value) { /* Search for our offset */ @@ -158,6 +183,21 @@ bool TempEntityInfo::TE_SetEntDataFloat(const char *name, float value) return true; } +bool TempEntityInfo::TE_GetEntDataFloat(const char *name, float *value) +{ + /* Search for our offset */ + int offset = _FindOffset(name); + + if (offset < 0) + { + return false; + } + + *value = *(float *)((uint8_t *)m_Me + offset); + + return true; +} + bool TempEntityInfo::TE_SetEntDataVector(const char *name, float vector[3]) { /* Search for our offset */ @@ -176,6 +216,24 @@ bool TempEntityInfo::TE_SetEntDataVector(const char *name, float vector[3]) return true; } +bool TempEntityInfo::TE_GetEntDataVector(const char *name, float vector[3]) +{ + /* Search for our offset */ + int offset = _FindOffset(name); + + if (offset < 0) + { + return false; + } + + Vector *v = (Vector *)((uint8_t *)m_Me + offset); + vector[0] = v->x; + vector[1] = v->y; + vector[2] = v->z; + + return true; +} + bool TempEntityInfo::TE_SetEntDataFloatArray(const char *name, cell_t *array, int size) { /* Search for our offset */ @@ -314,6 +372,11 @@ TempEntityInfo *TempEntityManager::GetTempEntityInfo(const char *name) return te; } +const char *TempEntityManager::GetNameFromThisPtr(void *me) +{ + return *(const char **)((unsigned char *)me + m_NameOffs); +} + void TempEntityManager::DumpList() { unsigned int index = 0; diff --git a/extensions/sdktools/tempents.h b/extensions/sdktools/tempents.h index bd383f61..cb9a98bd 100644 --- a/extensions/sdktools/tempents.h +++ b/extensions/sdktools/tempents.h @@ -53,6 +53,9 @@ public: bool TE_SetEntDataFloat(const char *name, float value); bool TE_SetEntDataVector(const char *name, float vector[3]); bool TE_SetEntDataFloatArray(const char *name, cell_t *array, int size); + bool TE_GetEntData(const char *name, int *value); + bool TE_GetEntDataFloat(const char *name, float *value); + bool TE_GetEntDataVector(const char *name, float vector[3]); void Send(IRecipientFilter &filter, float delay); private: int _FindOffset(const char *name, int *size=NULL); @@ -72,6 +75,7 @@ public: void Shutdown(); public: TempEntityInfo *GetTempEntityInfo(const char *name); + const char *GetNameFromThisPtr(void *me); public: void DumpList(); void DumpProps(FILE *fp); @@ -85,6 +89,31 @@ private: bool m_Loaded; }; +struct TEHookInfo +{ + TempEntityInfo *te; + List lst; +}; + +class TempEntHooks +{ +public: + void Initialize(); + void Shutdown(); + bool AddHook(const char *name, IPluginFunction *pFunc); + bool RemoveHook(const char *name, IPluginFunction *pFunc); + void OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID); +private: + void _IncRefCounter(); + void _DecRefCounter(); + size_t _FillInPlayers(int *pl_array, IRecipientFilter *pFilter); +private: + IBasicTrie *m_TEHooks; + List m_HookInfo; + size_t m_HookCount; +}; + extern TempEntityManager g_TEManager; +extern TempEntHooks s_TempEntHooks; #endif //_INCLUDE_SOURCEMOD_TEMPENTS_H_ diff --git a/extensions/sdktools/tenatives.cpp b/extensions/sdktools/tenatives.cpp index cbe3ea0b..b840dde1 100644 --- a/extensions/sdktools/tenatives.cpp +++ b/extensions/sdktools/tenatives.cpp @@ -32,9 +32,166 @@ #include "tempents.h" #include "CellRecipientFilter.h" +#include + +SH_DECL_HOOK5_void(IVEngineServer, PlaybackTempEntity, SH_NOATTRIB, 0, IRecipientFilter &, float, const void *, const SendTable *, int); CellRecipientFilter g_TERecFilter; TempEntityInfo *g_CurrentTE = NULL; +int g_TEPlayers[256]; + +/************************* +* * +* Temp Entity Hook Class * +* * +**************************/ + +void TempEntHooks::Initialize() +{ + m_TEHooks = adtfactory->CreateBasicTrie(); +} + +void TempEntHooks::Shutdown() +{ + List::iterator iter; + for (iter=m_HookInfo.begin(); iter!=m_HookInfo.end(); iter++) + { + delete (*iter); + } + if (m_HookCount) + { + m_HookCount = 1; + _DecRefCounter(); + } + m_TEHooks->Destroy(); +} + +void TempEntHooks::_IncRefCounter() +{ + if (m_HookCount++ == 0) + { + SH_ADD_HOOK_MEMFUNC(IVEngineServer, PlaybackTempEntity, engine, this, &TempEntHooks::OnPlaybackTempEntity, false); + } +} + +void TempEntHooks::_DecRefCounter() +{ + if (--m_HookCount == 0) + { + SH_REMOVE_HOOK_MEMFUNC(IVEngineServer, PlaybackTempEntity, engine, this, &TempEntHooks::OnPlaybackTempEntity, false); + } +} + +size_t TempEntHooks::_FillInPlayers(int *pl_array, IRecipientFilter *pFilter) +{ + size_t size = static_cast(pFilter->GetRecipientCount()); + + for (size_t i=0; iGetRecipientIndex(i); + } + + return size; +} + +bool TempEntHooks::AddHook(const char *name, IPluginFunction *pFunc) +{ + TEHookInfo *pInfo; + + if (m_TEHooks->Retrieve(name, reinterpret_cast(&pInfo))) + { + pInfo->lst.push_back(pFunc); + } else { + TempEntityInfo *te; + if (!(te=g_TEManager.GetTempEntityInfo(name))) + { + return false; + } + + pInfo = new TEHookInfo; + pInfo->te = te; + pInfo->lst.push_back(pFunc); + + m_TEHooks->Insert(name, reinterpret_cast(pInfo)); + m_HookInfo.push_back(pInfo); + } + + _IncRefCounter(); + + return true; +} + +bool TempEntHooks::RemoveHook(const char *name, IPluginFunction *pFunc) +{ + TEHookInfo *pInfo; + + if (m_TEHooks->Retrieve(name, reinterpret_cast(&pInfo))) + { + List::iterator iter; + if ((iter=pInfo->lst.find(pFunc)) != pInfo->lst.end()) + { + pInfo->lst.erase(iter); + if (pInfo->lst.empty()) + { + m_HookInfo.remove(pInfo); + m_TEHooks->Delete(name); + delete pInfo; + } + _DecRefCounter(); + } else { + return false; + } + } else { + return false; + } + + return true; +} + +void TempEntHooks::OnPlaybackTempEntity(IRecipientFilter &filter, float delay, const void *pSender, const SendTable *pST, int classID) +{ + TEHookInfo *pInfo; + const char *name = g_TEManager.GetNameFromThisPtr(const_cast(pSender)); + + if (m_TEHooks->Retrieve(name, reinterpret_cast(&pInfo))) + { + List::iterator iter; + IPluginFunction *pFunc; + size_t size; + cell_t res = static_cast(Pl_Continue); + + TempEntityInfo *oldinfo = g_CurrentTE; + g_CurrentTE = pInfo->te; + size = _FillInPlayers(g_TEPlayers, &filter); + + for (iter=pInfo->lst.begin(); iter!=pInfo->lst.end(); iter++) + { + pFunc = (*iter); + pFunc->PushString(name); + pFunc->PushArray(g_TEPlayers, size); + pFunc->PushCell(size); + pFunc->PushFloat(delay); + pFunc->Execute(&res); + + if (res != Pl_Continue) + { + g_CurrentTE = oldinfo; + RETURN_META(MRES_SUPERCEDE); + } + } + + g_CurrentTE = oldinfo; + RETURN_META(MRES_IGNORED); + } +} + +/********************** +* * +* Temp Entity Natives * +* * +***********************/ + +TempEntHooks s_TempEntHooks; static cell_t smn_TEStart(IPluginContext *pContext, const cell_t *params) { @@ -77,6 +234,29 @@ static cell_t smn_TEWriteNum(IPluginContext *pContext, const cell_t *params) return 1; } +static cell_t smn_TEReadNum(IPluginContext *pContext, const cell_t *params) +{ + if (!g_TEManager.IsAvailable()) + { + return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report"); + } + if (!g_CurrentTE) + { + return pContext->ThrowNativeError("No TempEntity call is in progress"); + } + + char *prop; + int val; + pContext->LocalToString(params[1], &prop); + + if (!g_CurrentTE->TE_GetEntData(prop, &val)) + { + return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop); + } + + return val; +} + static cell_t smn_TE_WriteFloat(IPluginContext *pContext, const cell_t *params) { if (!g_TEManager.IsAvailable()) @@ -99,6 +279,29 @@ static cell_t smn_TE_WriteFloat(IPluginContext *pContext, const cell_t *params) return 1; } +static cell_t smn_TE_ReadFloat(IPluginContext *pContext, const cell_t *params) +{ + if (!g_TEManager.IsAvailable()) + { + return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report"); + } + if (!g_CurrentTE) + { + return pContext->ThrowNativeError("No TempEntity call is in progress"); + } + + char *prop; + float val; + pContext->LocalToString(params[1], &prop); + + if (!g_CurrentTE->TE_GetEntDataFloat(prop, &val)) + { + return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop); + } + + return sp_ftoc(val); +} + static cell_t smn_TEWriteVector(IPluginContext *pContext, const cell_t *params) { if (!g_TEManager.IsAvailable()) @@ -125,6 +328,36 @@ static cell_t smn_TEWriteVector(IPluginContext *pContext, const cell_t *params) return 1; } +static cell_t smn_TEReadVector(IPluginContext *pContext, const cell_t *params) +{ + if (!g_TEManager.IsAvailable()) + { + return pContext->ThrowNativeError("TempEntity System unsupported or not available, file a bug report"); + } + if (!g_CurrentTE) + { + return pContext->ThrowNativeError("No TempEntity call is in progress"); + } + + char *prop; + pContext->LocalToString(params[1], &prop); + + cell_t *addr; + float vec[3]; + pContext->LocalToPhysAddr(params[2], &addr); + + if (!g_CurrentTE->TE_GetEntDataVector(prop, vec)) + { + return pContext->ThrowNativeError("Temp entity property \"%s\" not found", prop); + } + + addr[0] = sp_ftoc(vec[0]); + addr[1] = sp_ftoc(vec[1]); + addr[2] = sp_ftoc(vec[2]); + + return 1; +} + static cell_t smn_TEWriteFloatArray(IPluginContext *pContext, const cell_t *params) { if (!g_TEManager.IsAvailable()) @@ -190,15 +423,60 @@ static cell_t smn_TEIsValidProp(IPluginContext *pContext, const cell_t *params) return g_CurrentTE->IsValidProp(prop) ? 1 : 0; } +static cell_t smn_AddTempEntHook(IPluginContext *pContext, const cell_t *params) +{ + char *name; + IPluginFunction *pFunc; + + pContext->LocalToString(params[1], &name); + pFunc = pContext->GetFunctionById(params[2]); + if (!pFunc) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); + } + + if (!s_TempEntHooks.AddHook(name, pFunc)) + { + return pContext->ThrowNativeError("Invalid TempEntity name: \"%s\"", name); + } + + return 1; +} + +static cell_t smn_RemoveTempEntHook(IPluginContext *pContext, const cell_t *params) +{ + char *name; + IPluginFunction *pFunc; + + pContext->LocalToString(params[1], &name); + pFunc = pContext->GetFunctionById(params[2]); + if (!pFunc) + { + return pContext->ThrowNativeError("Invalid function id (%X)", params[2]); + } + + if (!s_TempEntHooks.RemoveHook(name, pFunc)) + { + return pContext->ThrowNativeError("Invalid hooked TempEntity name or function"); + } + + return 1; +} + sp_nativeinfo_t g_TENatives[] = { {"TE_Start", smn_TEStart}, {"TE_WriteNum", smn_TEWriteNum}, + {"TE_ReadNum", smn_TEReadNum}, {"TE_WriteFloat", smn_TE_WriteFloat}, + {"TE_ReadFloat", smn_TE_ReadFloat}, {"TE_WriteVector", smn_TEWriteVector}, + {"TE_ReadVector", smn_TEReadVector}, {"TE_WriteAngles", smn_TEWriteVector}, {"TE_Send", smn_TESend}, {"TE_IsValidProp", smn_TEIsValidProp}, {"TE_WriteFloatArray", smn_TEWriteFloatArray}, + {"AddTempEntHook", smn_AddTempEntHook}, + {"RemoveTempEntHook", smn_RemoveTempEntHook}, {NULL, NULL} }; diff --git a/plugins/include/sdktools_tempents.inc b/plugins/include/sdktools_tempents.inc index 2079216d..f91afc40 100644 --- a/plugins/include/sdktools_tempents.inc +++ b/plugins/include/sdktools_tempents.inc @@ -18,6 +18,37 @@ #endif #define _sdktools_tempents_included +/** + * Called when a temp entity is going to be sent. + * + * @param te_name TE name. + * @param Players Array containing target player indexes. + * @param numClients Number of players in the array. + * @param delay Delay in seconds to send the TE. + * @return Plugin_Continue to allow the transmission of the TE, Plugin_Stop to block it. + */ +functag TEHook Action:public(const String:te_name[], const Players[], numClients, Float:delay); + +/** + * Hooks a temp entity. + * + * @param te_name TE name to hook. + * @param hook Function to use as a hook. + * @noreturn + * @error Temp Entity name not available or invalid function hook. + */ +native AddTempEntHook(const String:te_name[], TEHook:hook); + +/** + * Removes a temp entity. + * + * @param te_name TE name to unhook. + * @param hook Function used for the hook. + * @noreturn + * @error Temp Entity name not available or invalid function hook. + */ +native RemoveTempEntHook(const String:te_name[], TEHook:hook); + /** * Starts a temp entity transmission. * @@ -45,6 +76,16 @@ native bool:TE_IsValidProp(const String:prop[]); */ native TE_WriteNum(const String:prop[], value); +/** + * Reads an integer value in the current temp entity. + * + * @param prop Property to use. + * @param value Integer value to read. + * @return Property value. + * @error Property not found. + */ +native TE_ReadNum(const String:prop[]); + /** * Sets a floating point number in the current temp entity. * @@ -55,6 +96,16 @@ native TE_WriteNum(const String:prop[], value); */ native TE_WriteFloat(const String:prop[], Float:value); +/** + * Reads a floating point number in the current temp entity. + * + * @param prop Property to use. + * @param value Floating point number to read. + * @noreturn Property value. + * @error Property not found. + */ +native Float:TE_ReadFloat(const String:prop[]); + /** * Sets a vector in the current temp entity. * @@ -65,6 +116,16 @@ native TE_WriteFloat(const String:prop[], Float:value); */ native TE_WriteVector(const String:prop[], const Float:vector[3]); +/** + * Reads a vector in the current temp entity. + * + * @param prop Property to use. + * @param vector Vector to read. + * @noreturn + * @error Property not found. + */ +native TE_ReadVector(const String:prop[], Float:vector[3]); + /** * Sets a QAngle in the current temp entity. *