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:
Borja Ferrer 2007-08-03 01:53:00 +00:00
parent 8d1cb3d579
commit 2c36a434b3
5 changed files with 434 additions and 0 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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_

View File

@ -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}
};

View File

@ -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.
*