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
This commit is contained in:
parent
8d1cb3d579
commit
2c36a434b3
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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<IPluginFunction *> 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<TEHookInfo *> m_HookInfo;
|
||||
size_t m_HookCount;
|
||||
};
|
||||
|
||||
extern TempEntityManager g_TEManager;
|
||||
extern TempEntHooks s_TempEntHooks;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TEMPENTS_H_
|
||||
|
@ -32,9 +32,166 @@
|
||||
|
||||
#include "tempents.h"
|
||||
#include "CellRecipientFilter.h"
|
||||
#include <IForwardSys.h>
|
||||
|
||||
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<TEHookInfo *>::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<size_t>(pFilter->GetRecipientCount());
|
||||
|
||||
for (size_t i=0; i<size; i++)
|
||||
{
|
||||
pl_array[i] = pFilter->GetRecipientIndex(i);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
bool TempEntHooks::AddHook(const char *name, IPluginFunction *pFunc)
|
||||
{
|
||||
TEHookInfo *pInfo;
|
||||
|
||||
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&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<void *>(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<void **>(&pInfo)))
|
||||
{
|
||||
List<IPluginFunction *>::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<void *>(pSender));
|
||||
|
||||
if (m_TEHooks->Retrieve(name, reinterpret_cast<void **>(&pInfo)))
|
||||
{
|
||||
List<IPluginFunction *>::iterator iter;
|
||||
IPluginFunction *pFunc;
|
||||
size_t size;
|
||||
cell_t res = static_cast<ResultType>(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}
|
||||
};
|
||||
|
@ -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.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user