diff --git a/amxmodx/messages.cpp b/amxmodx/messages.cpp new file mode 100755 index 00000000..e54049a1 --- /dev/null +++ b/amxmodx/messages.cpp @@ -0,0 +1,564 @@ +#include "amxmodx.h" +#include "messages.h" + +Message Msg; +CVector msgHooks[256]; +int msgBlocks[256] = {BLOCK_NOT}; +int msgDest; +int msgType; +float *msgOrigin; +edict_t *msgpEntity; +bool inhook = false; +bool inblock = false; + +void ClearMessages() +{ + for (size_t i=0; i= m_Params.size()) + { + pParam = new msgparam; + m_Params.push_back(pParam); + } else { + pParam = m_Params[m_CurParam]; + } + + return pParam; +} + +void Message::AddParam(const char *data, msgtype type) +{ + msgparam *pParam = AdvPtr(); + + pParam->szData.assign(data); + pParam->type = type; +} + +void Message::AddParam(int data, msgtype type) +{ + msgparam *pParam = AdvPtr(); + + pParam->v.iData = data; + pParam->type = type; +} + +void Message::AddParam(float data, msgtype type) +{ + msgparam *pParam = AdvPtr(); + + pParam->v.fData = data; + pParam->type = type; +} + +msgtype Message::GetParamType(size_t index) +{ + if (index < 1 || index > m_CurParam) + return static_cast(0); + + return m_Params[index]->type; +} + +float Message::GetParamFloat(size_t index) +{ + if (index < 1 || index > m_CurParam) + return 0; + + return m_Params[index]->v.fData; +} + +const char *Message::GetParamString(size_t index) +{ + if (index < 1 || index > m_CurParam) + return 0; + + return m_Params[index]->szData.c_str(); +} + +int Message::GetParamInt(size_t index) +{ + if (index < 1 || index > m_CurParam) + return 0; + + return m_Params[index]->v.iData; +} + +void Message::SetParam(size_t index, float data) +{ + if (index < 1 || index > m_CurParam) + return; + + m_Params[index]->v.fData = data; +} + +void Message::SetParam(size_t index, int data) +{ + if (index < 1 || index > m_CurParam) + return; + + m_Params[index]->v.iData = data; +} + +void Message::SetParam(size_t index, const char *data) +{ + if (index < 1 || index > m_CurParam) + return; + + m_Params[index]->szData.assign(data); +} + +void Message::Reset() +{ + m_CurParam = 0; +} + +size_t Message::Params() +{ + return m_CurParam; +} + +void Message::Send() +{ + msgparam *pParam = NULL; + + for (size_t i=1; i<=m_CurParam; i++) + { + pParam = m_Params[i]; + switch (pParam->type) + { + case arg_byte: + WRITE_BYTE(pParam->v.iData); + break; + case arg_char: + WRITE_CHAR(pParam->v.iData); + break; + case arg_short: + WRITE_SHORT(pParam->v.iData); + break; + case arg_long: + WRITE_LONG(pParam->v.iData); + break; + case arg_angle: + WRITE_ANGLE(pParam->v.fData); + break; + case arg_coord: + WRITE_COORD(pParam->v.fData); + break; + case arg_string: + WRITE_STRING(pParam->szData.c_str()); + break; + case arg_entity: + WRITE_ENTITY(pParam->v.iData); + break; + } + } +} + +void C_MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed) +{ + if (msgBlocks[msg_type]) + { + inblock = true; + msgType = msg_type; + RETURN_META(MRES_SUPERCEDE); + } else if (msgHooks[msg_type].size()) { + inhook = true; + msgDest = msg_dest; + msgType = msg_type; + msgOrigin = (float *)pOrigin; + msgpEntity = ed; + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteByte(int iValue) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(iValue, arg_byte); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteChar(int iValue) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(iValue, arg_char); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteShort(int iValue) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(iValue, arg_short); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteLong(int iValue) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(iValue, arg_long); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteAngle(float flValue) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(flValue, arg_angle); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteCoord(float flValue) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(flValue, arg_coord); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteString(const char *sz) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(sz, arg_string); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_WriteEntity(int iValue) +{ + if (inblock) + { + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + Msg.AddParam(iValue, arg_entity); + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +void C_MessageEnd(void) +{ + int mres = 0, mresB = 0; + unsigned int i = 0; + if (inblock) + { + inblock = false; + if (msgBlocks[msgType] == BLOCK_ONCE) + { + msgBlocks[msgType] = BLOCK_NOT; + } + RETURN_META(MRES_SUPERCEDE); + } else if (inhook) { + for (i=0; i mres) + mres = mresB; + } + inhook = false; + if (mres & 1) + { + Msg.Reset(); + RETURN_META(MRES_SUPERCEDE); + } + + /* send the real message */ + MESSAGE_BEGIN(msgDest, msgType, msgOrigin, msgpEntity); + Msg.Send(); + MESSAGE_END(); + + /* reset */ + Msg.Reset(); + + RETURN_META(MRES_SUPERCEDE); + } + + RETURN_META(MRES_IGNORED); +} + +static cell AMX_NATIVE_CALL register_message(AMX *amx, cell *params) +{ + int len; + char *name = get_amxstring(amx, params[2], 0, len); + + if (!Msg.Ready()) + Msg.Init(); + + if (params[1]>0 && params[1] < 256) + { + int id = registerSPForwardByName(amx, name, FP_CELL, FP_CELL, FP_CELL, FP_CELL, FP_DONE); + if (id != -1) + { + msgHooks[params[1]].push_back(id); + return id; + } else { + LogError(amx, AMX_ERR_NOTFOUND, "Could not find function \"%s\"", name); + return -1; + } + } + + return 0; +} + +static cell AMX_NATIVE_CALL set_msg_block(AMX *amx, cell *params) +{ + int msgid = params[1]; + int block = params[2]; + + if (msgid < 1 || msgid > 255) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message id"); + return 0; + } + + msgBlocks[msgid] = block; + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_block(AMX *amx, cell *params) +{ + int msgid = params[1]; + + if (msgid < 1 || msgid > 255) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message id"); + return 0; + } + + return msgBlocks[msgid]; +} + +static cell AMX_NATIVE_CALL get_msg_args(AMX *amx, cell *params) +{ + return Msg.Params(); +} + +static cell AMX_NATIVE_CALL get_msg_argtype(AMX *amx, cell *params) +{ + size_t argn = static_cast(params[1]); + + if (!inhook || argn > Msg.Params()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message argument %d", argn); + return 0; + } + + return Msg.GetParamType(argn); +} + +static cell AMX_NATIVE_CALL get_msg_arg_int(AMX *amx, cell *params) +{ + size_t argn = static_cast(params[1]); + + if (!inhook || argn > Msg.Params()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message argument %d", argn); + return 0; + } + + return Msg.GetParamInt(argn); +} + +static cell AMX_NATIVE_CALL set_msg_arg_int(AMX *amx, cell *params) +{ + size_t argn = static_cast(params[1]); + + if (!inhook || argn > Msg.Params()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message argument %d", argn); + return 0; + } + + Msg.SetParam(argn, (int)params[3]); + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_arg_float(AMX *amx, cell *params) +{ + size_t argn = static_cast(params[1]); + + if (!inhook || argn > Msg.Params()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message argument %d", argn); + return 0; + } + + REAL f = (REAL)Msg.GetParamFloat(argn); + return amx_ftoc(f); +} + +static cell AMX_NATIVE_CALL set_msg_arg_float(AMX *amx, cell *params) +{ + size_t argn = static_cast(params[1]); + + if (!inhook || argn > Msg.Params()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message argument %d", argn); + return 0; + } + + REAL fVal = amx_ctof(params[3]); + + Msg.SetParam(argn, (float)fVal); + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_arg_string(AMX *amx, cell *params) +{ + size_t argn = static_cast(params[1]); + + if (!inhook || argn > Msg.Params()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message argument %d", argn); + return 0; + } + + const char *szVal = Msg.GetParamString(argn); + + return set_amxstring(amx, params[2], szVal, params[3]); +} + +static cell AMX_NATIVE_CALL set_msg_arg_string(AMX *amx, cell *params) +{ + size_t argn = static_cast(params[1]); + int iLen; + + if (!inhook || argn > Msg.Params()) + { + LogError(amx, AMX_ERR_NATIVE, "Invalid message argument %d", argn); + return 0; + } + + char *szVal = get_amxstring(amx, params[2], 0, iLen); + + Msg.SetParam(argn, szVal); + + return 1; +} + +static cell AMX_NATIVE_CALL get_msg_origin(AMX *amx, cell *params) +{ + if (!inhook) + { + LogError(amx, AMX_ERR_NATIVE, "Not in a message hook"); + return 0; + } + + cell *cAddr = get_amxaddr(amx, params[1]); + + if (msgDest >= MSG_PVS && msgDest <= MSG_PAS_R) + { + vec3_t vRet = (Vector)msgOrigin; + cAddr[0] = amx_ftoc(vRet.x); + cAddr[1] = amx_ftoc(vRet.y); + cAddr[2] = amx_ftoc(vRet.z); + } else { + cAddr[0] = 0; + cAddr[1] = 0; + cAddr[2] = 0; + } + + return 1; +} + +AMX_NATIVE_INFO msg_Natives[] = +{ + {"register_message", register_message}, + + {"set_msg_block", set_msg_block}, + {"get_msg_block", get_msg_block}, + + {"get_msg_args", get_msg_args}, + {"get_msg_argtype", get_msg_argtype}, + {"get_msg_arg_int", get_msg_arg_int}, + {"set_msg_arg_int", set_msg_arg_int}, + {"get_msg_arg_float", get_msg_arg_float}, + {"set_msg_arg_float", set_msg_arg_float}, + {"get_msg_arg_string", get_msg_arg_string}, + {"set_msg_arg_string", set_msg_arg_string}, + {"get_msg_origin", get_msg_origin}, + + {NULL, NULL}, +}; diff --git a/amxmodx/messages.h b/amxmodx/messages.h new file mode 100755 index 00000000..2061d2bd --- /dev/null +++ b/amxmodx/messages.h @@ -0,0 +1,84 @@ +#ifndef _MSGS_INCLUDE_H +#define _MSGS_INCLUDE_H + +#include +#include +#include "amx.h" +#include "CVector.h" +#include "CString.h" + +#define MAX_MESSAGES 255 + +#define BLOCK_NOT 0 +#define BLOCK_ONCE 1 +#define BLOCK_SET 2 + +enum msgtype +{ + arg_byte = 1, + arg_char, + arg_short, + arg_long, + arg_angle, + arg_coord, + arg_string, + arg_entity, +}; + +struct msgparam +{ + msgtype type; + union + { + REAL fData; + int iData; + } v; + String szData; +}; + +class Message +{ +public: + Message(); + ~Message(); + void AddParam(float data, msgtype type); + void AddParam(int data, msgtype type); + void AddParam(const char *data, msgtype type); + void SetParam(size_t index, float data); + void SetParam(size_t index, int data); + void SetParam(size_t index, const char *data); + const char *GetParamString(size_t index); + float GetParamFloat(size_t index); + bool Ready(); + void Init(); + int GetParamInt(size_t index); + msgtype GetParamType(size_t index); + void Reset(); + void Send(); + size_t Params(); +private: + msgparam *AdvPtr(); +private: + CVector m_Params; + size_t m_CurParam; +}; + +void C_MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed); +void C_WriteByte(int iValue); +void C_WriteChar(int iValue); +void C_WriteShort(int iValue); +void C_WriteLong(int iValue); +void C_WriteAngle(float flValue); +void C_WriteCoord(float flValue); +void C_WriteString(const char *sz); +void C_WriteEntity(int iValue); +void C_MessageEnd(void); + +extern AMX_NATIVE_INFO msg_Natives[]; +extern CVector msgHooks[256]; +extern int msgBlocks[256]; + +void ClearMessages(); + +#endif //_MSGS_INCLUDE_H + diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index 1d468d41..2082420d 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -42,6 +42,7 @@ #include "binlog.h" #include "optimizer.h" #include "libraries.h" +#include "messages.h" plugin_info_t Plugin_info = { @@ -511,6 +512,8 @@ void C_ServerDeactivate_Post() g_plugins.clear(); ClearPluginLibraries(); modules_callPluginsUnloaded(); + + ClearMessages(); for (unsigned int i=0; i g_modules; CList g_loadedscripts; @@ -540,6 +541,7 @@ int set_amxnatives(AMX* amx, char error[128]) amx_Register(amx, g_NewMenuNatives, -1); amx_Register(amx, g_NativeNatives, -1); amx_Register(amx, g_DebugNatives, -1); + amx_Register(amx, msg_Natives, -1); //we're not actually gonna check these here anymore amx->flags |= AMX_FLAG_PRENIT; diff --git a/amxmodx/msvc/amxmodx_mm.vcproj b/amxmodx/msvc/amxmodx_mm.vcproj index cde93f3e..8f45c5c9 100755 --- a/amxmodx/msvc/amxmodx_mm.vcproj +++ b/amxmodx/msvc/amxmodx_mm.vcproj @@ -421,6 +421,9 @@ + + @@ -554,6 +557,9 @@ + +