mirror of
https://github.com/rehlds/reapi.git
synced 2024-12-28 07:35:31 +03:00
Rework message hook/natives
This commit is contained in:
parent
06743d6eb9
commit
ab14d37b0a
@ -280,8 +280,13 @@ enum MessageHook
|
||||
* @param callback The name of the callback function.
|
||||
* @param post Whether the callback should be invoked before or after processing the message. (optional)
|
||||
*
|
||||
* @note You can modify the message content using SetMessageParam native before the original function is invoked.
|
||||
* Also can reading the message content using GetMessageParam native.
|
||||
* @note The callback arguments have:
|
||||
* msg_id - Message id
|
||||
* msg_dest - Destination type (see MSG_* constants in messages_const.inc)
|
||||
* msg_entity - Entity receiving the message
|
||||
*
|
||||
* @note You can modify the message content using SetMessageData native before the original function is invoked.
|
||||
* Also can reading the message content using GetMessageData native.
|
||||
*
|
||||
* In the callback function, use the return values from Hookchain return types, such as HC_CONTINUE, HC_SUPERCEDE, etc.
|
||||
* to control the flow of message processing.
|
||||
@ -318,56 +323,50 @@ native bool:EnableHookMessage(const MessageHook:handle);
|
||||
native bool:DisableHookMessage(const MessageHook:handle);
|
||||
|
||||
/**
|
||||
* Sets the parameter value for the specified index in the current game message.
|
||||
* Sets the message data in the current game message.
|
||||
*
|
||||
* @param index The index of the parameter to set.
|
||||
* @param value The value to set for the parameter.
|
||||
* @param type The type of the message data that can be changed
|
||||
* @param ... Additional args depending on the type of the message argument being retrieved (For more details, look at the enum MsgArgType)
|
||||
*
|
||||
* @return Returns true if the parameter value is successfully set, otherwise false.
|
||||
* @return Returns true if the message data is successfully set, otherwise false.
|
||||
*/
|
||||
native bool:SetMessageParam(const number, any:...);
|
||||
native bool:SetMessageData(const MsgDataType:type, any:...);
|
||||
|
||||
/**
|
||||
* Retrieves the parameter value for the specified index in the current game message.
|
||||
* Gets the message data value in the current game message
|
||||
*
|
||||
* @param index The index of the parameter to retrieve.
|
||||
* @param ... Additional parameters depending on the type of the parameter being retrieved.
|
||||
* @param type The type of message data that can be get
|
||||
* @param ... Additional args depending on the type of the message argument being retrieved (For more details, look at the enum MsgArgType)
|
||||
*
|
||||
* @return Returns the retrieved parameter value.
|
||||
* @return Returns value of argument in the current message
|
||||
*/
|
||||
native any:GetMessageParam(const number, any:...);
|
||||
native any:GetMessageData(const MsgDataType:type, any:...);
|
||||
|
||||
/**
|
||||
* Retrieves the type of the parameter at the specified index in the current game message.
|
||||
* Gets the message data original value in the current game message.
|
||||
*
|
||||
* @param index The index of the parameter to retrieve the type for.
|
||||
* @param type The type of message data that can be get
|
||||
* @param ... Additional args depending on the type of the message argument being retrieved (For more details, look at the enum MsgArgType)
|
||||
*
|
||||
* @return Returns the type of the parameter, look at the enum MsgParamType
|
||||
* @return Returns original value of argument in the current message
|
||||
*/
|
||||
native MsgParamType:GetMessageParamType(const number);
|
||||
native any:GetMessageOrigData(const MsgDataType:type, any:...);
|
||||
|
||||
/**
|
||||
* Retrieves the number of parameters in the current game message.
|
||||
* Retrieves the type of the argument at the specified number in the current game message.
|
||||
*
|
||||
* @return Returns the number of parameters in the current game message.
|
||||
* @param number The number of the argument to retrieve the type for.
|
||||
*
|
||||
* @return Returns the type of the argument, look at the enum MsgArgType
|
||||
*/
|
||||
native GetMessageParamCount();
|
||||
native MsgArgType:GetMessageArgType(const number);
|
||||
|
||||
/**
|
||||
* Retrieves the origin of the current game message.
|
||||
* Retrieves the number of argument in the current game message.
|
||||
*
|
||||
* @param origin An array to store the origin coordinates of the game message.
|
||||
*
|
||||
* @return Returns true if the origin is successfully retrieved, otherwise false.
|
||||
* @return Returns the number of argument in the current game message.
|
||||
*/
|
||||
native bool:GetMessageOrigin(Float:origin[3]);
|
||||
|
||||
/**
|
||||
* Retrieves the destination of the current message.
|
||||
*
|
||||
* @return Returns the destination of the current message.
|
||||
*/
|
||||
native GetMessageDest();
|
||||
native GetMessageArgsNum();
|
||||
|
||||
/**
|
||||
* Sets the block type for the specified message ID.
|
||||
@ -387,3 +386,44 @@ native bool:SetMessageBlock(const msgid, MsgBlockType:type);
|
||||
* @return Returns the block type of the specified message, look at the enum MsgBlockType
|
||||
*/
|
||||
native MsgBlockType:GetMessageBlock(const msgid);
|
||||
|
||||
/**
|
||||
* Checks if the specified type of message data has been modified
|
||||
*
|
||||
* This native allows you to check if any part of the message data, such as its
|
||||
* destination, type, origin, receiver, or any the specific argument of the message, has been modified
|
||||
*
|
||||
* @param type The type of the data to check for modification
|
||||
* This can be one of the following:
|
||||
* - MsgAny: Check if any part of the message has been modified
|
||||
* - MsgDest: Check if the destination has been modified
|
||||
* - MsgIndex: Check if the message ID has been modified
|
||||
* - MsgOrigin: Check if the origin has been modified
|
||||
* - MsgTargetId: Check if the index of the recipient client has been modified
|
||||
* - MsgArg: Check if a specific argument of the message has been modified
|
||||
*
|
||||
* @param number The number of the argument to check for modification (used only when type is MsgDataType:MsgArg)
|
||||
* Default value is -1, which means the argument number is not applicable
|
||||
*
|
||||
* @return Returns true if the specified data type has been modified, false otherwise
|
||||
*/
|
||||
native bool:IsMessageDataModified(MsgDataType:type = MsgAny, const number = -1);
|
||||
|
||||
/**
|
||||
* Resets a specific type of message data to its original value
|
||||
*
|
||||
* @param type The type of the data to check for modification
|
||||
* This can be one of the following:
|
||||
* - MsgAny: Reset all modified message data to its original values
|
||||
* - MsgDest: Reset the destination to its original value
|
||||
* - MsgIndex: Reset the message ID to its original value
|
||||
* - MsgOrigin: Reset the origin to its original value
|
||||
* - MsgTargetId: Reset the index of the recipient client to its original value
|
||||
* - MsgArg: Reset a specific argument of the message to its original value
|
||||
*
|
||||
* @param number The number of the argument to reset (used only when type is MsgDataType:MsgArg)
|
||||
* Default value is -1, which means all arguments will be reset.
|
||||
*
|
||||
* @return Returns true if the modified data type was reset, otherwise false.
|
||||
*/
|
||||
native bool:ResetModifiedMessageData(MsgDataType:type = MsgAny, const number = -1);
|
||||
|
@ -1323,18 +1323,79 @@ enum NetAdrVars
|
||||
};
|
||||
|
||||
/**
|
||||
* Message param types used with GetMessageParamType()
|
||||
* Message argument types used with GetMessageArgType()
|
||||
*/
|
||||
enum MsgParamType
|
||||
enum MsgArgType
|
||||
{
|
||||
ParamByte,
|
||||
ParamChar,
|
||||
ParamShort,
|
||||
ParamLong,
|
||||
ParamAngle,
|
||||
ParamCoord,
|
||||
ParamString,
|
||||
ParamEntity,
|
||||
ArgByte,
|
||||
ArgChar,
|
||||
ArgShort,
|
||||
ArgLong,
|
||||
ArgAngle,
|
||||
ArgCoord,
|
||||
ArgString,
|
||||
ArgEntity,
|
||||
};
|
||||
|
||||
/**
|
||||
* Message data types used with SetMessageData()/GetMessageData()
|
||||
* HasModifiedMessageData()/ResetModifiedMessageData()
|
||||
*/
|
||||
enum MsgDataType
|
||||
{
|
||||
/*
|
||||
* Description: Any part of the message
|
||||
*/
|
||||
MsgAny,
|
||||
|
||||
/*
|
||||
* Description: The destination of the message
|
||||
* Return type: integer
|
||||
* Get params: new dest = GetMessageData(MsgDest);
|
||||
* Set params: SetMessageData(MsgDest, MSG_ALL);
|
||||
*/
|
||||
MsgDest,
|
||||
|
||||
/*
|
||||
* Description: The index of the message
|
||||
* Return type: integer
|
||||
* Get params: new msg_id = GetMessageData(MsgMsgId);
|
||||
* Set params: SetMessageData(MsgMsgId, const msg_id);
|
||||
*/
|
||||
MsgMsgId,
|
||||
|
||||
/*
|
||||
* Description: The origin of the message
|
||||
* Return type: float [3]
|
||||
* Get params: GetMessageData(MsgOrigin, Float:dstVector[3]);
|
||||
* Set params: SetMessageData(MsgOrigin, Float:srcVector[3]);
|
||||
*/
|
||||
MsgOrigin,
|
||||
|
||||
/*
|
||||
* Description: The index of the recipient client
|
||||
* Return type: integer
|
||||
* Get params: new targetId = GetMessageData(MsgTargetId);
|
||||
* Set params: SetMessageData(MsgTargetId, const targetId); (acceptable indexes 0-32, 0 index also as -1 means NULLENT)
|
||||
*/
|
||||
MsgTargetId,
|
||||
|
||||
/*
|
||||
* Description: The arguments of the message
|
||||
*
|
||||
* Arg type: string (MSG_ARG_String)
|
||||
* Get params: bool:GetMessageData(MsgArg, const argnumber, value[], const maxlen);
|
||||
* Set params: bool:SetMessageData(MsgArg, const argnumber, const value[]);
|
||||
*
|
||||
* Arg type: float (MSG_ARG_Angle, MSG_ARG_Coord)
|
||||
* Get params: Float:GetMessageData(MsgArg, const argnumber, &Float:value = 0.0);
|
||||
* Set params: bool:SetMessageData(MsgArg, const argnumber, const Float:value);
|
||||
*
|
||||
* Arg type: integer (MSG_ARG_Byte, MSG_ARG_Char, MSG_ARG_Short, MSG_ARG_Long, MSG_ARG_Entity)
|
||||
* Get params: GetMessageData(MsgArg, const argnumber);
|
||||
* Set params: bool:SetMessageData(MsgArg, const argnumber, const value);
|
||||
*/
|
||||
MsgArg
|
||||
};
|
||||
|
||||
/**
|
||||
|
210
reapi/extra/amxmodx/scripting/message_test.sma
Normal file
210
reapi/extra/amxmodx/scripting/message_test.sma
Normal file
@ -0,0 +1,210 @@
|
||||
#include <amxmodx>
|
||||
#include <reapi>
|
||||
|
||||
public plugin_init()
|
||||
{
|
||||
register_plugin("ReAPI MessageHook Test", "1.0", "s1lent");
|
||||
RegisterMessage(get_user_msgid("SayText"), "MessageSayText_Pre", .post = false);
|
||||
RegisterMessage(get_user_msgid("SayText"), "MessageSayText_Post", .post = true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destination types for message hook
|
||||
*/
|
||||
new const g_MsgDestination[][] =
|
||||
{
|
||||
"MSG_BROADCAST", // Unreliable to all
|
||||
"MSG_ONE", // Reliable to one (msg_entity)
|
||||
"MSG_ALL", // Reliable to all
|
||||
"MSG_INIT", // Write to the init string
|
||||
"MSG_PVS", // Ents in PVS of org
|
||||
"MSG_PAS", // Ents in PAS of org
|
||||
"MSG_PVS_R", // Reliable to PVS
|
||||
"MSG_PAS_R", // Reliable to PAS
|
||||
"MSG_ONE_UNRELIABLE", // Send to one client, but don't put in reliable stream, put in unreliable datagram (could be dropped)
|
||||
"MSG_SPEC" // Sends to all spectator proxies
|
||||
};
|
||||
|
||||
/**
|
||||
* Message argument types used with GetMessageArgType()
|
||||
*/
|
||||
new const g_MsgArgType[][] =
|
||||
{
|
||||
"Byte",
|
||||
"Char",
|
||||
"Short",
|
||||
"Long",
|
||||
"Angle",
|
||||
"Coord",
|
||||
"String",
|
||||
"Entity",
|
||||
};
|
||||
|
||||
/**
|
||||
* Blocking behavior types for messages used with SetMessageBlock()/GetMessageBlock()
|
||||
*/
|
||||
new const g_MsgBlockType[][] =
|
||||
{
|
||||
"MSG_BLOCK_NOT", // Not a block
|
||||
"MSG_BLOCK_ONCE", // Block once
|
||||
"MSG_BLOCK_SET" // Set block
|
||||
};
|
||||
|
||||
public MessageSayText_Pre(const msg_id, const msg_dest, const id)
|
||||
{
|
||||
server_print("^nMessageSayText_Pre");
|
||||
|
||||
DumpMessageArgs(msg_id);
|
||||
|
||||
static bool:recursive_guard = false;
|
||||
if (!recursive_guard)
|
||||
{
|
||||
recursive_guard = true; // avoid deadlock
|
||||
|
||||
// Modify original text message in chat
|
||||
SetMessageData(MsgDest, MSG_ALL); // send text messages in the chat to everyone
|
||||
SetMessageData(MsgTargetId, NULLENT);
|
||||
SetMessageData(MsgArg, 2, "^4(Test) ^3%s1^1 @ ^4%s3^1 : %s2"); // change format
|
||||
|
||||
if (is_user_connected(id))
|
||||
{
|
||||
// Send another chat message, test deadlock
|
||||
new szPlayerName[32];
|
||||
get_user_name(id, szPlayerName, charsmax(szPlayerName));
|
||||
|
||||
new szTextMsg[256];
|
||||
GetMessageData(MsgArg, 4, szTextMsg, charsmax(szTextMsg));
|
||||
|
||||
message_begin(MSG_ONE, msg_id, .player = id);
|
||||
write_byte(id);
|
||||
write_string("^3%s1^1 @ ^4%s3^1 : %s2");
|
||||
write_string(szPlayerName);
|
||||
write_string(szTextMsg);
|
||||
write_string("Courtyard");
|
||||
message_end();
|
||||
|
||||
// Send another text message, but on screen in center
|
||||
message_begin(MSG_ONE, get_user_msgid("TextMsg"), .player = id);
|
||||
write_byte(print_center);
|
||||
|
||||
for (new i = 1; i <= GetMessageArgsNum(); i++)
|
||||
{
|
||||
new MsgArgType:type = GetMessageArgType(i);
|
||||
if (type == ArgString)
|
||||
{
|
||||
new szBuffer[256];
|
||||
GetMessageOrigData(MsgArg, i, szBuffer, charsmax(szBuffer));
|
||||
write_string(szBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
message_end();
|
||||
}
|
||||
|
||||
recursive_guard = false;
|
||||
}
|
||||
}
|
||||
|
||||
public MessageSayText_Post(const msg_id, const msg_dest, const id)
|
||||
{
|
||||
server_print("^nMessageSayText_Post");
|
||||
DumpMessageArgs(msg_id);
|
||||
}
|
||||
|
||||
stock Float:fabs(Float:x)
|
||||
{
|
||||
return x > 0 ? x : -x;
|
||||
}
|
||||
|
||||
stock DumpMessageArgs(const msg_id)
|
||||
{
|
||||
// indicates that the message data has been modified
|
||||
new const symbolIndicateModified[] = "+";
|
||||
|
||||
if (IsMessageDataModified(MsgDest))
|
||||
server_print("Dest = %s (%d) > changed to > %s (%d)", g_MsgDestination[GetMessageOrigData(MsgDest)], GetMessageOrigData(MsgDest), g_MsgDestination[GetMessageData(MsgDest)], GetMessageData(MsgDest));
|
||||
else
|
||||
server_print("Dest = %s (%d)", g_MsgDestination[GetMessageData(MsgDest)], GetMessageData(MsgDest));
|
||||
|
||||
new Float:vecOrigin[3];
|
||||
GetMessageData(MsgOrigin, vecOrigin);
|
||||
|
||||
if (IsMessageDataModified(MsgOrigin))
|
||||
{
|
||||
new Float:vecSourceOrigin[3];
|
||||
GetMessageOrigData(MsgOrigin, vecSourceOrigin);
|
||||
server_print("Origin = (%0.2f, %0.2f, %0.2f) > changed to > (%0.2f, %0.2f, %0.2f)", vecSourceOrigin[0], vecSourceOrigin[1], vecSourceOrigin[2], vecOrigin[0], vecOrigin[1], vecOrigin[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
server_print("Origin = (%0.2f, %0.2f, %0.2f)", vecOrigin[0], vecOrigin[1], vecOrigin[2]);
|
||||
}
|
||||
|
||||
if (IsMessageDataModified(MsgTargetId))
|
||||
server_print("Receiver = %d > changed to > %d", GetMessageOrigData(MsgTargetId), GetMessageData(MsgTargetId));
|
||||
else
|
||||
server_print("Receiver = %d", GetMessageData(MsgTargetId));
|
||||
|
||||
server_print("Block state = %s", g_MsgBlockType[any:GetMessageBlock(msg_id)]);
|
||||
server_print("Args count = %d", GetMessageArgsNum());
|
||||
server_print("Message modified %s", IsMessageDataModified() ? symbolIndicateModified : "-");
|
||||
|
||||
// Iterate over all arguments of current message
|
||||
for (new i = 1; i <= GetMessageArgsNum(); i++)
|
||||
{
|
||||
new MsgArgType:type = GetMessageArgType(i);
|
||||
new bool:isModified = IsMessageDataModified(MsgArg, i);
|
||||
|
||||
// Print string values of argument
|
||||
if (type == ArgString)
|
||||
{
|
||||
new curString[256], origString[256];
|
||||
GetMessageData(MsgArg, i, curString, charsmax(curString));
|
||||
GetMessageOrigData(MsgArg, i, origString, charsmax(origString));
|
||||
|
||||
replace_all(curString, charsmax(curString), "^n", "");
|
||||
replace_all(origString, charsmax(origString), "^n", "");
|
||||
|
||||
if (!equal(origString, curString) || isModified)
|
||||
{
|
||||
server_print(" %-2d %-13s %s ^"%s^" > changed to > ^"%s^"", i, g_MsgArgType[any:type], isModified ? symbolIndicateModified : "-", origString, curString);
|
||||
}
|
||||
else
|
||||
{
|
||||
server_print(" %-2d %-13s %s ^"%s^"", i, g_MsgArgType[any:type], isModified ? symbolIndicateModified : "-", curString);
|
||||
}
|
||||
}
|
||||
// Print float point values of argument
|
||||
else if (type == ArgAngle || type == ArgCoord)
|
||||
{
|
||||
new Float:flCurValue = Float:GetMessageData(MsgArg, i);
|
||||
new Float:flOrigValue = Float:GetMessageOrigData(MsgArg, i);
|
||||
|
||||
if (fabs(flCurValue - flOrigValue) > 0.1 || isModified)
|
||||
{
|
||||
server_print(" %-2d %-13s %s ^"%f^" > changed to > ^"%f^"", i, g_MsgArgType[any:type], isModified ? symbolIndicateModified : "-", flOrigValue, flCurValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
server_print(" %-2d %-13s %s ^"%f^"", i, g_MsgArgType[any:type], isModified ? symbolIndicateModified : "-", flCurValue);
|
||||
}
|
||||
}
|
||||
// Print integer values of argument
|
||||
else
|
||||
{
|
||||
new iCurValue = GetMessageData(MsgArg, i);
|
||||
new iOrigValue = GetMessageOrigData(MsgArg, i);
|
||||
|
||||
if (iCurValue != iOrigValue || isModified)
|
||||
{
|
||||
server_print(" %-2d %-13s %s ^"%i^" > changed to > ^"%i^"", i, g_MsgArgType[any:type], isModified ? symbolIndicateModified : "-", iOrigValue, iCurValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
server_print(" %-2d %-13s %s ^"%i^"", i, g_MsgArgType[any:type], isModified ? symbolIndicateModified : "-", iCurValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server_print("^n");
|
||||
}
|
@ -44,9 +44,9 @@ public:
|
||||
*/
|
||||
enum class BlockType : uint8
|
||||
{
|
||||
Not, // Not a block
|
||||
Once, // Block once
|
||||
Set // Set block
|
||||
Not, // Not a block
|
||||
Once, // Block once
|
||||
Set // Set block
|
||||
};
|
||||
|
||||
/**
|
||||
@ -66,99 +66,213 @@ public:
|
||||
SPEC, // Sends to all spectator proxies
|
||||
};
|
||||
|
||||
virtual ~IMessage() {};
|
||||
/**
|
||||
* @brief Data types for message data
|
||||
*/
|
||||
enum class DataType : uint8_t
|
||||
{
|
||||
Any, // Any part of the message
|
||||
Dest, // Destination of the message
|
||||
Index, // Index of the message
|
||||
Origin, // Origin of the message
|
||||
Edict, // Pointer to the edict of the recipient client
|
||||
Param, // Parameter of the message
|
||||
Max
|
||||
};
|
||||
|
||||
virtual ~IMessage() = default;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of parameters in the message
|
||||
* @return The number of parameters
|
||||
*/
|
||||
virtual int getParamCount() const = 0;
|
||||
virtual int getParamCount() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the type of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @return The type of the parameter
|
||||
*/
|
||||
virtual ParamType getParamType(size_t index) const = 0;
|
||||
virtual ParamType getParamType(size_t index) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the integer value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @return The integer value of the parameter
|
||||
*/
|
||||
virtual int getParamInt(size_t index) const = 0;
|
||||
virtual int getParamInt(size_t index) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the float value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @return The float value of the parameter
|
||||
*/
|
||||
virtual float getParamFloat(size_t index) const = 0;
|
||||
virtual float getParamFloat(size_t index) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the string value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @return The string value of the parameter
|
||||
*/
|
||||
virtual const char* getParamString(size_t index) const = 0;
|
||||
virtual const char* getParamString(size_t index) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the integer value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @param value The integer value to set
|
||||
*/
|
||||
virtual void setParamInt(size_t index, int value) = 0;
|
||||
virtual void setParamInt(size_t index, int value) = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the float value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @param value The float value to set
|
||||
*/
|
||||
virtual void setParamFloat(size_t index, float value) = 0;
|
||||
virtual void setParamFloat(size_t index, float value) = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the vector value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @param pos The vector value to set
|
||||
*/
|
||||
virtual void setParamVec(size_t index, const float *pos) = 0;
|
||||
virtual void setParamVec(size_t index, const float *pos) = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the string value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
* @param string The string value to set
|
||||
*/
|
||||
virtual void setParamString(size_t index, const char *string) = 0;
|
||||
virtual void setParamString(size_t index, const char *string) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the destination of the message
|
||||
* @return The destination of the message
|
||||
*/
|
||||
virtual Dest getDest() const = 0;
|
||||
virtual Dest getDest() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the type of the message
|
||||
* @return The type of the message
|
||||
*/
|
||||
virtual int getType() const = 0;
|
||||
/**
|
||||
* @brief Returns the index of the message
|
||||
* @return The index of the message
|
||||
*/
|
||||
virtual int getId() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the origin of the message
|
||||
* @return The origin of the message
|
||||
*/
|
||||
virtual const float* getOrigin() const = 0;
|
||||
/**
|
||||
* @brief Returns the origin of the message
|
||||
* @return The origin of the message
|
||||
*/
|
||||
virtual const float* getOrigin() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the edict associated with the message
|
||||
* @return The edict associated with the message
|
||||
*/
|
||||
/**
|
||||
* @brief Returns the edict associated with the message
|
||||
* @return The edict associated with the message
|
||||
*/
|
||||
virtual struct edict_s* getEdict() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns whether the message has been modified
|
||||
* @return True if the message has been modified, false otherwise
|
||||
*/
|
||||
virtual bool isModified() const = 0;
|
||||
/**
|
||||
* @brief Checks if the specified type of message data has been modified
|
||||
*
|
||||
* This function allows you to check if any part of the message data, such as its
|
||||
* destination, type, origin, edict, or any specific parameter, has been modified
|
||||
*
|
||||
* @param type The type of the data to check for modification
|
||||
* This can be one of the following:
|
||||
* - DataType::Any: Check if any part of the message has been modified
|
||||
* - DataType::Dest: Check if the destination has been modified
|
||||
* - DataType::Index: Check if the message ID has been modified
|
||||
* - DataType::Origin: Check if the origin has been modified
|
||||
* - DataType::Edict: Check if the edict pointer has been modified
|
||||
* - DataType::Param: Check if a specific parameter has been modified
|
||||
*
|
||||
* @param index The index of the parameter to check for modification (used only when type is DataType::Param)
|
||||
* Default value is -1, which means the parameter index is not applicable
|
||||
*
|
||||
* @return True if the specified data type has been modified, false otherwise
|
||||
*/
|
||||
virtual bool isDataModified(DataType type = DataType::Any, size_t index = -1) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Resets a specific type of message data to its original value
|
||||
*
|
||||
* @param type The type of data to reset to its original value
|
||||
* This can be one of the following:
|
||||
* - DataType::Any: Reset all modified message data to its original values
|
||||
* - DataType::Dest: Reset the destination to its original value
|
||||
* - DataType::Index: Reset the message ID to its original value
|
||||
* - DataType::Origin: Reset the origin to its original value
|
||||
* - DataType::Edict: Reset the edict pointer of the recipient client to its original value
|
||||
* - DataType::Param: Reset a specific parameter to its original value
|
||||
*
|
||||
* @param index The index of the parameter to reset (used only when type is DataType::Param)
|
||||
* Default value is -1, which means the parameter index is not applicable
|
||||
*
|
||||
* @return True if the modified data type was reset, false otherwise
|
||||
*/
|
||||
virtual bool resetModifiedData(DataType type = DataType::Any, size_t index = -1) = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the destination of the message
|
||||
*/
|
||||
virtual void setDest(Dest dest) = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the index of the message
|
||||
*/
|
||||
virtual void setId(int msg_id) = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the origin of the message
|
||||
*/
|
||||
virtual void setOrigin(const float *origin) = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the edict associated with the message
|
||||
*/
|
||||
virtual void setEdict(struct edict_s *pEdict) = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the original destination of the message before any modifications
|
||||
* @return The original destination of the message
|
||||
*/
|
||||
virtual Dest getOriginalDest() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the original type of the message before any modifications
|
||||
* @return The original type of the message
|
||||
*/
|
||||
virtual int getOriginalId() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the original origin of the message before any modifications
|
||||
* @return The original origin of the message
|
||||
*/
|
||||
virtual const float* getOriginalOrigin() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the original edict associated with the message before any modifications
|
||||
* @return The original edict associated with the message
|
||||
*/
|
||||
virtual struct edict_s* getOriginalEdict() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the original integer value of the parameter at the given index before any modifications
|
||||
* @param index The index of the parameter
|
||||
* @return The original integer value of the parameter
|
||||
*/
|
||||
virtual int getOriginalParamInt(size_t index) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the original float value of the parameter at the given index before any modifications
|
||||
* @param index The index of the parameter
|
||||
* @return The original float value of the parameter
|
||||
*/
|
||||
virtual float getOriginalParamFloat(size_t index) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Returns the original string value of the parameter at the given index before any modifications
|
||||
* @param index The index of the parameter
|
||||
* @return The original string value of the parameter
|
||||
*/
|
||||
virtual const char* getOriginalParamString(size_t index) const = 0;
|
||||
|
||||
// This must be the last virtual function in class
|
||||
#ifdef REHLDS_SELF
|
||||
@ -167,7 +281,7 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
#define MESSAGEMNGR_VERSION_MAJOR 1
|
||||
#define MESSAGEMNGR_VERSION_MAJOR 2
|
||||
#define MESSAGEMNGR_VERSION_MINOR 0
|
||||
|
||||
/**
|
||||
@ -178,7 +292,7 @@ class IMessageManager
|
||||
public:
|
||||
using hookfunc_t = void (*)(IVoidHookChain<IMessage *> *chain, IMessage *msg);
|
||||
|
||||
virtual ~IMessageManager() {};
|
||||
virtual ~IMessageManager() = default;
|
||||
|
||||
/**
|
||||
* @brief Returns the major version of the MessageManager
|
||||
@ -194,30 +308,30 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Returns the blocking behavior for the given message type
|
||||
* @param msgType The message type
|
||||
* @param msg_id The message type
|
||||
* @return The blocking behavior for the given message type
|
||||
*/
|
||||
virtual IMessage::BlockType getMessageBlock(int msgType) const = 0;
|
||||
virtual IMessage::BlockType getMessageBlock(int msg_id) const = 0;
|
||||
|
||||
/**
|
||||
* @brief Sets the blocking behavior for the given message type
|
||||
* @param msgType The message type
|
||||
* @param msg_id The message type
|
||||
* @param blockType The blocking behavior to set
|
||||
*/
|
||||
virtual void setMessageBlock(int msgType, IMessage::BlockType blockType) = 0;
|
||||
virtual void setMessageBlock(int msg_id, IMessage::BlockType blockType) = 0;
|
||||
|
||||
/**
|
||||
* @brief Registers a hook function for the given message type
|
||||
* @param msgType The message type to register the hook for
|
||||
* @param msg_id The message type to register the hook for
|
||||
* @param handler The hook function to register
|
||||
* @param priority The priority of the hook function (see enum HookChainPriority)
|
||||
*/
|
||||
virtual void registerHook(int msgType, hookfunc_t handler, int priority = HC_PRIORITY_DEFAULT) = 0;
|
||||
virtual void registerHook(int msg_id, hookfunc_t handler, int priority = HC_PRIORITY_DEFAULT) = 0;
|
||||
|
||||
/**
|
||||
* @brief Unregisters a hook function for the given message type
|
||||
* @param msgType The message type to unregister the hook for
|
||||
* @param msg_id The message type to unregister the hook for
|
||||
* @param handler The hook function to unregister
|
||||
*/
|
||||
virtual void unregisterHook(int msgType, hookfunc_t handler) = 0;
|
||||
virtual void unregisterHook(int msg_id, hookfunc_t handler) = 0;
|
||||
};
|
||||
|
@ -15,24 +15,20 @@ IMessage *g_activeMessageContext = nullptr;
|
||||
* @param chain Pointer to the hook chain for the message
|
||||
* @param message Pointer to the message parameters
|
||||
*/
|
||||
void MessageHookManager::DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *params)
|
||||
void MessageHookManager::DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *message)
|
||||
{
|
||||
// Get the hook associated with the given message type
|
||||
MessageHook *msg = getHook(params->getType());
|
||||
MessageHook *msg = getHook(message->getId());
|
||||
|
||||
// If somehow no hook is found, just continue hookchain
|
||||
if (!msg) {
|
||||
chain->callNext(params);
|
||||
chain->callNext(message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the current message context and set the new one
|
||||
IMessage *savedContext = g_activeMessageContext;
|
||||
g_activeMessageContext = params;
|
||||
|
||||
// Get the entity index of the message (if applicable)
|
||||
edict_t *entityEdict = params->getEdict();
|
||||
int entityIndex = entityEdict ? indexOfEdict(entityEdict) : 0;
|
||||
g_activeMessageContext = message;
|
||||
|
||||
int hookState = HC_CONTINUE;
|
||||
|
||||
@ -41,7 +37,7 @@ void MessageHookManager::DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IM
|
||||
{
|
||||
if (likely(fwd->GetState() == FSTATE_ENABLED))
|
||||
{
|
||||
int ret = g_amxxapi.ExecuteForward(fwd->GetFwdIndex(), entityIndex, (cell)params);
|
||||
int ret = g_amxxapi.ExecuteForward(fwd->GetFwdIndex(), message->getId(), message->getDest(), indexOfEdictAmx(message->getEdict(), 0 /* most friendly to use 0 as invalid index for message */));
|
||||
if (unlikely(ret == HC_BREAK)) {
|
||||
g_activeMessageContext = savedContext;
|
||||
return;
|
||||
@ -55,8 +51,8 @@ void MessageHookManager::DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IM
|
||||
// If the hook state is not superseded, continue hookchain
|
||||
if (hookState != HC_SUPERCEDE) {
|
||||
g_activeMessageContext = nullptr;
|
||||
chain->callNext(params);
|
||||
g_activeMessageContext = savedContext;
|
||||
chain->callNext(message);
|
||||
g_activeMessageContext = message;
|
||||
}
|
||||
|
||||
// Execute post-hooks
|
||||
@ -64,7 +60,7 @@ void MessageHookManager::DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IM
|
||||
{
|
||||
if (likely(fwd->GetState() == FSTATE_ENABLED))
|
||||
{
|
||||
int ret = g_amxxapi.ExecuteForward(fwd->GetFwdIndex(), entityIndex, (cell)params);
|
||||
int ret = g_amxxapi.ExecuteForward(fwd->GetFwdIndex(), message->getId(), message->getDest(), indexOfEdictAmx(message->getEdict(), 0 /* most friendly to use 0 as invalid index for message */));
|
||||
if (unlikely(ret == HC_BREAK))
|
||||
break;
|
||||
}
|
||||
@ -87,7 +83,7 @@ void MessageHookManager::DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IM
|
||||
*/
|
||||
cell MessageHookManager::addHook(AMX *amx, int msg_id, const char *funcname, bool post)
|
||||
{
|
||||
int fwid = g_amxxapi.RegisterSPForwardByName(amx, funcname, FP_CELL, FP_DONE);
|
||||
int fwid = g_amxxapi.RegisterSPForwardByName(amx, funcname, FP_CELL, FP_CELL, FP_CELL, FP_DONE);
|
||||
if (unlikely(fwid == -1)) {
|
||||
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: register forward failed.", __FUNCTION__);
|
||||
return 0;
|
||||
@ -224,7 +220,7 @@ void MessageHookManager::Clear()
|
||||
/**
|
||||
* @brief Dispatches the message callbacks as a routine
|
||||
*/
|
||||
void MessageHookManager::RoutineMessageCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *params)
|
||||
void MessageHookManager::RoutineMessageCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *message)
|
||||
{
|
||||
g_messageHookManager.DispatchCallbacks(chain, params);
|
||||
g_messageHookManager.DispatchCallbacks(chain, message);
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ private:
|
||||
};
|
||||
|
||||
// Dispatches the callbacks for the message hooks
|
||||
void DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *params);
|
||||
void DispatchCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *message);
|
||||
|
||||
// Routine function for dispatching message callbacks
|
||||
static void RoutineMessageCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *params);
|
||||
static void RoutineMessageCallbacks(IVoidHookChain<IMessage *> *chain, IMessage *message);
|
||||
|
||||
// Getter the message hook by ID
|
||||
MessageHook *getHook(size_t id);
|
||||
|
@ -7,6 +7,8 @@ IRehldsHookchains* g_RehldsHookchains;
|
||||
IRehldsServerStatic* g_RehldsSvs;
|
||||
IMessageManager* g_RehldsMessageManager;
|
||||
|
||||
void RehldsMessageMngr_Init();
|
||||
|
||||
bool RehldsApi_Init()
|
||||
{
|
||||
#ifdef WIN32
|
||||
@ -79,14 +81,43 @@ bool RehldsApi_Init()
|
||||
|
||||
// message manager is available in "ReHLDS API" >= 3.14
|
||||
if (majorVersion >= 3 && minorVersion >= 14)
|
||||
{
|
||||
IMessageManager *messageManager = g_RehldsApi->GetMessageManager();
|
||||
if (messageManager->getMajorVersion() == MESSAGEMNGR_VERSION_MAJOR &&
|
||||
messageManager->getMinorVersion() >= MESSAGEMNGR_VERSION_MINOR)
|
||||
{
|
||||
g_RehldsMessageManager = messageManager;
|
||||
}
|
||||
}
|
||||
RehldsMessageMngr_Init();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RehldsMessageMngr_Init()
|
||||
{
|
||||
IMessageManager *messageManager = g_RehldsApi->GetMessageManager();
|
||||
|
||||
int majorMessageMngrVersion = messageManager->getMajorVersion();
|
||||
int minorMessageMngrVersion = messageManager->getMinorVersion();
|
||||
|
||||
if (majorMessageMngrVersion != MESSAGEMNGR_VERSION_MAJOR)
|
||||
{
|
||||
UTIL_ServerPrint("[%s]: ReHLDS MessageMngr API major version mismatch; expected %d.%d, real %d.%d\n", Plugin_info.logtag, MESSAGEMNGR_VERSION_MAJOR, MESSAGEMNGR_VERSION_MINOR, majorMessageMngrVersion, minorMessageMngrVersion);
|
||||
|
||||
// need to notify that it is necessary to update the ReHLDS
|
||||
if (majorMessageMngrVersion < MESSAGEMNGR_VERSION_MAJOR)
|
||||
{
|
||||
UTIL_ServerPrint("[%s]: Please update ReHLDS to a newer version for the required MessageMngr API %d.%d\n", Plugin_info.logtag, MESSAGEMNGR_VERSION_MAJOR, MESSAGEMNGR_VERSION_MINOR);
|
||||
}
|
||||
|
||||
// need to notify that it is necessary to update the module
|
||||
else if (majorMessageMngrVersion > MESSAGEMNGR_VERSION_MAJOR)
|
||||
{
|
||||
UTIL_ServerPrint("[%s]: Please update the %s to a newer version for the required MessageMngr API %d.%d\n", Plugin_info.logtag, Plugin_info.logtag, MESSAGEMNGR_VERSION_MAJOR, MESSAGEMNGR_VERSION_MINOR);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (minorMessageMngrVersion < MESSAGEMNGR_VERSION_MINOR)
|
||||
{
|
||||
UTIL_ServerPrint("[%s]: ReHLDS MessageMngr API minor version mismatch; expected at least %d.%d, real %d.%d\n", Plugin_info.logtag, MESSAGEMNGR_VERSION_MAJOR, MESSAGEMNGR_VERSION_MINOR, majorMessageMngrVersion, minorMessageMngrVersion);
|
||||
UTIL_ServerPrint("[%s]: Please update ReHLDS to a newer version for the required MessageMngr API %d.%d\n", Plugin_info.logtag, MESSAGEMNGR_VERSION_MAJOR, MESSAGEMNGR_VERSION_MINOR);
|
||||
return;
|
||||
}
|
||||
|
||||
g_RehldsMessageManager = messageManager;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#define CHECK_PARAMBOUNDS(x, y) if (unlikely(x > (size_t)y)) { AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid message argument %d/max:%d", __FUNCTION__, x, y); }
|
||||
|
||||
enum MessageHook
|
||||
{
|
||||
INVALID_MESSAGEHOOK = 0
|
||||
@ -12,8 +14,13 @@ enum MessageHook
|
||||
* @param callback The name of the callback function.
|
||||
* @param post Whether the callback should be invoked before or after processing the message. (optional)
|
||||
*
|
||||
* @note You can modify the message content using SetMessageParam native before the original function is invoked.
|
||||
* Also can reading the message content using GetMessageParam native.
|
||||
* @note The callback arguments have:
|
||||
* msg_id - Message id
|
||||
* msg_dest - Destination type (see MSG_* constants in messages_const.inc)
|
||||
* msg_entity - Entity receiving the message
|
||||
*
|
||||
* @note You can modify the message content using SetMessageData native before the original function is invoked.
|
||||
* Also can reading the message content using GetMessageData native.
|
||||
*
|
||||
* In the callback function, use the return values from Hookchain return types, such as HC_CONTINUE, HC_SUPERCEDE, etc.
|
||||
* to control the flow of message processing.
|
||||
@ -24,11 +31,11 @@ enum MessageHook
|
||||
*/
|
||||
cell AMX_NATIVE_CALL RegisterMessage(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_id, arg_handler, arg_post };
|
||||
enum args_e { arg_count, arg_msgid, arg_handler, arg_post };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
int msg_id = params[arg_id];
|
||||
int msg_id = params[arg_msgid];
|
||||
|
||||
// svc_bad (0) is not allowed for hook
|
||||
if (msg_id <= 0 || msg_id >= MAX_USERMESSAGES)
|
||||
@ -127,18 +134,18 @@ cell AMX_NATIVE_CALL DisableHookMessage(AMX *amx, cell *params)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameter value for the specified index in the current game message.
|
||||
* Sets the message data in the current game message.
|
||||
*
|
||||
* @param index The index of the parameter to set.
|
||||
* @param value The value to set for the parameter.
|
||||
* @param type The type of the message data that can be changed
|
||||
* @param ... Additional args depending on the type of the message argument being retrieved (For more details, look at the enum MsgArgType)
|
||||
*
|
||||
* @return Returns true if the parameter value is successfully set, otherwise false.
|
||||
* @return Returns true if the message data is successfully set, otherwise false.
|
||||
*
|
||||
* native bool:SetMessageParam(const number, any:...);
|
||||
* native bool:SetMessageData(const MsgDataType:type, any:...);
|
||||
*/
|
||||
cell AMX_NATIVE_CALL SetMessageParam(AMX *amx, cell *params)
|
||||
cell AMX_NATIVE_CALL SetMessageData(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_number, arg_value };
|
||||
enum args_e { arg_count, arg_type, arg_value, arg_param_value };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
@ -148,41 +155,74 @@ cell AMX_NATIVE_CALL SetMessageParam(AMX *amx, cell *params)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size_t number = params[arg_number] - 1;
|
||||
|
||||
IMessage::DataType type = static_cast<IMessage::DataType>(params[arg_type]);
|
||||
cell *value = getAmxAddr(amx, params[arg_value]);
|
||||
|
||||
switch (g_activeMessageContext->getParamType(number))
|
||||
switch (type)
|
||||
{
|
||||
case IMessage::ParamType::String:
|
||||
char stringbuf[256];
|
||||
g_activeMessageContext->setParamString(number, getAmxString(amx, params[arg_value], stringbuf));
|
||||
case IMessage::DataType::Dest:
|
||||
g_activeMessageContext->setDest(static_cast<IMessage::Dest>(*value));
|
||||
break;
|
||||
case IMessage::ParamType::Angle:
|
||||
case IMessage::ParamType::Coord:
|
||||
g_activeMessageContext->setParamFloat(number, *(float *)value);
|
||||
case IMessage::DataType::Index:
|
||||
g_activeMessageContext->setId(*value);
|
||||
break;
|
||||
case IMessage::DataType::Origin:
|
||||
g_activeMessageContext->setOrigin(*(Vector *)value);
|
||||
break;
|
||||
case IMessage::DataType::Edict:
|
||||
g_activeMessageContext->setEdict(edictByIndexAmx(*value, 0 /* most friendly to use 0 as invalid index for message */));
|
||||
break;
|
||||
case IMessage::DataType::Param:
|
||||
{
|
||||
// bool:SetMessageData(MsgDataType:type, const argnumber, const value[]);
|
||||
cell *value = getAmxAddr(amx, params[arg_param_value]);
|
||||
size_t number = *getAmxAddr(amx, params[arg_value]) - 1;
|
||||
|
||||
CHECK_PARAMBOUNDS(number, g_activeMessageContext->getParamCount());
|
||||
|
||||
switch (g_activeMessageContext->getParamType(number))
|
||||
{
|
||||
case IMessage::ParamType::String:
|
||||
char stringbuf[256];
|
||||
g_activeMessageContext->setParamString(number, getAmxString(amx, params[arg_param_value], stringbuf));
|
||||
break;
|
||||
case IMessage::ParamType::Angle:
|
||||
case IMessage::ParamType::Coord:
|
||||
g_activeMessageContext->setParamFloat(number, *(float *)value);
|
||||
break;
|
||||
case IMessage::ParamType::Byte:
|
||||
case IMessage::ParamType::Char:
|
||||
case IMessage::ParamType::Short:
|
||||
case IMessage::ParamType::Long:
|
||||
case IMessage::ParamType::Entity:
|
||||
g_activeMessageContext->setParamInt(number, *value);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_activeMessageContext->setParamInt(number, *value);
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the parameter value for the specified index in the current game message.
|
||||
* Gets the message data value in the current game message
|
||||
*
|
||||
* @param index The index of the parameter to retrieve.
|
||||
* @param ... Additional parameters depending on the type of the parameter being retrieved.
|
||||
* @param type The type of message data that can be get
|
||||
* @param ... Additional args depending on the type of the message argument being retrieved (For more details, look at the enum MsgArgType)
|
||||
*
|
||||
* @return Returns the retrieved parameter value.
|
||||
* @return Returns value of argument in the current message
|
||||
*
|
||||
* native any:GetMessageParam(const number, any:...);
|
||||
* native any:GetMessageData(MsgDataType:type, any:...);
|
||||
*/
|
||||
cell AMX_NATIVE_CALL GetMessageParam(AMX *amx, cell *params)
|
||||
cell AMX_NATIVE_CALL GetMessageData(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_number, arg_value, arg_maxlen };
|
||||
enum args_e { arg_count, arg_type, arg_value, arg_param_value, arg_maxlen };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
@ -192,35 +232,57 @@ cell AMX_NATIVE_CALL GetMessageParam(AMX *amx, cell *params)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size_t number = params[arg_number] - 1;
|
||||
|
||||
cell *dstAddr = getAmxAddr(amx, params[arg_value]);
|
||||
|
||||
switch (g_activeMessageContext->getParamType(number))
|
||||
IMessage::DataType type = static_cast<IMessage::DataType>(params[arg_type]);
|
||||
switch (type)
|
||||
{
|
||||
case IMessage::ParamType::String:
|
||||
{
|
||||
if (PARAMS_COUNT != 3)
|
||||
return FALSE;
|
||||
|
||||
const char *argString = g_activeMessageContext->getParamString(number);
|
||||
setAmxString(dstAddr, argString ? argString : "", params[arg_maxlen]);
|
||||
case IMessage::DataType::Dest:
|
||||
return static_cast<cell>(g_activeMessageContext->getDest());
|
||||
case IMessage::DataType::Index:
|
||||
return g_activeMessageContext->getId();
|
||||
case IMessage::DataType::Origin:
|
||||
*(Vector *)getAmxAddr(amx, params[arg_value]) = g_activeMessageContext->getOrigin();
|
||||
return TRUE;
|
||||
}
|
||||
case IMessage::ParamType::Angle:
|
||||
case IMessage::ParamType::Coord:
|
||||
case IMessage::DataType::Edict:
|
||||
return indexOfEdictAmx(g_activeMessageContext->getEdict(), 0 /* most friendly to use 0 as invalid index for message */);
|
||||
case IMessage::DataType::Param:
|
||||
{
|
||||
float flValue = g_activeMessageContext->getParamFloat(number);
|
||||
if (PARAMS_COUNT > 1)
|
||||
*dstAddr = flValue;
|
||||
return flValue;
|
||||
size_t number = *getAmxAddr(amx, params[arg_value]) - 1; // arg_value as number
|
||||
|
||||
CHECK_PARAMBOUNDS(number, g_activeMessageContext->getParamCount());
|
||||
|
||||
cell *dstAddr = getAmxAddr(amx, params[arg_param_value]);
|
||||
|
||||
switch (g_activeMessageContext->getParamType(number))
|
||||
{
|
||||
case IMessage::ParamType::String:
|
||||
{
|
||||
if (PARAMS_COUNT != 4)
|
||||
return FALSE;
|
||||
|
||||
const char *argString = g_activeMessageContext->getParamString(number);
|
||||
setAmxString(dstAddr, argString ? argString : "", params[arg_maxlen]);
|
||||
return TRUE;
|
||||
}
|
||||
case IMessage::ParamType::Angle:
|
||||
case IMessage::ParamType::Coord:
|
||||
{
|
||||
float flValue = g_activeMessageContext->getParamFloat(number);
|
||||
if (PARAMS_COUNT > 2)
|
||||
*dstAddr = flValue;
|
||||
return flValue;
|
||||
}
|
||||
case IMessage::ParamType::Entity:
|
||||
case IMessage::ParamType::Byte:
|
||||
case IMessage::ParamType::Char:
|
||||
case IMessage::ParamType::Short:
|
||||
case IMessage::ParamType::Long:
|
||||
return g_activeMessageContext->getParamInt(number);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case IMessage::ParamType::Entity:
|
||||
case IMessage::ParamType::Byte:
|
||||
case IMessage::ParamType::Char:
|
||||
case IMessage::ParamType::Short:
|
||||
case IMessage::ParamType::Long:
|
||||
return g_activeMessageContext->getParamInt(number);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -229,15 +291,95 @@ cell AMX_NATIVE_CALL GetMessageParam(AMX *amx, cell *params)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type of the parameter at the specified index in the current game message.
|
||||
* Gets the message data original value in the current game message.
|
||||
*
|
||||
* @param index The index of the parameter to retrieve the type for.
|
||||
* @param type The type of message data that can be get
|
||||
* @param ... Additional args depending on the type of the message argument being retrieved (For more details, look at the enum MsgArgType)
|
||||
*
|
||||
* @return Returns the type of the parameter, look at the enum MsgParamType
|
||||
* @return Returns original value of argument in the current message
|
||||
*
|
||||
* native MsgParamType:GetMessageParamType(const number);
|
||||
* native any:GetMessageOrigData(MsgDataType:type, any:...);
|
||||
*/
|
||||
cell AMX_NATIVE_CALL GetMessageParamType(AMX *amx, cell *params)
|
||||
cell AMX_NATIVE_CALL GetMessageOrigData(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_type, arg_value, arg_param_value, arg_maxlen };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
if (!g_activeMessageContext)
|
||||
{
|
||||
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: trying to get argument without active hook.", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
IMessage::DataType type = static_cast<IMessage::DataType>(params[arg_type]);
|
||||
switch (type)
|
||||
{
|
||||
case IMessage::DataType::Dest:
|
||||
return static_cast<cell>(g_activeMessageContext->getOriginalDest());
|
||||
case IMessage::DataType::Index:
|
||||
return g_activeMessageContext->getId();
|
||||
case IMessage::DataType::Origin:
|
||||
*(Vector *)getAmxAddr(amx, params[arg_value]) = g_activeMessageContext->getOriginalOrigin();
|
||||
return TRUE;
|
||||
case IMessage::DataType::Edict:
|
||||
return indexOfEdictAmx(g_activeMessageContext->getOriginalEdict());
|
||||
case IMessage::DataType::Param:
|
||||
{
|
||||
size_t number = *getAmxAddr(amx, params[arg_value]) - 1; // arg_value as number
|
||||
|
||||
CHECK_PARAMBOUNDS(number, g_activeMessageContext->getParamCount());
|
||||
|
||||
cell *dstAddr = getAmxAddr(amx, params[arg_param_value]);
|
||||
|
||||
switch (g_activeMessageContext->getParamType(number))
|
||||
{
|
||||
case IMessage::ParamType::String:
|
||||
{
|
||||
if (PARAMS_COUNT != 4)
|
||||
return FALSE;
|
||||
|
||||
const char *argString = g_activeMessageContext->getOriginalParamString(number);
|
||||
setAmxString(dstAddr, argString ? argString : "", params[arg_maxlen]);
|
||||
return TRUE;
|
||||
}
|
||||
case IMessage::ParamType::Angle:
|
||||
case IMessage::ParamType::Coord:
|
||||
{
|
||||
float flValue = g_activeMessageContext->getOriginalParamFloat(number);
|
||||
if (PARAMS_COUNT > 2)
|
||||
*dstAddr = flValue;
|
||||
return flValue;
|
||||
}
|
||||
case IMessage::ParamType::Entity:
|
||||
case IMessage::ParamType::Byte:
|
||||
case IMessage::ParamType::Char:
|
||||
case IMessage::ParamType::Short:
|
||||
case IMessage::ParamType::Long:
|
||||
return g_activeMessageContext->getOriginalParamInt(number);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type of the argument at the specified number in the current game message.
|
||||
*
|
||||
* @param number The number of the argument to retrieve the type for.
|
||||
*
|
||||
* @return Returns the type of the argument, look at the enum MsgArgType
|
||||
*
|
||||
* native MsgArgType:GetMessageArgType(const number);
|
||||
*/
|
||||
cell AMX_NATIVE_CALL GetMessageArgType(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_number };
|
||||
|
||||
@ -251,26 +393,21 @@ cell AMX_NATIVE_CALL GetMessageParamType(AMX *amx, cell *params)
|
||||
|
||||
size_t number = params[arg_number] - 1;
|
||||
|
||||
size_t paramCount = g_activeMessageContext->getParamCount();
|
||||
if (number < 0 || number >= paramCount)
|
||||
{
|
||||
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: invalid message argument %d.", __FUNCTION__, number);
|
||||
return FALSE;
|
||||
}
|
||||
CHECK_PARAMBOUNDS(number, g_activeMessageContext->getParamCount());
|
||||
|
||||
return static_cast<cell>(g_activeMessageContext->getParamType(number));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the number of parameters in the current game message.
|
||||
* Retrieves the number of argument in the current game message.
|
||||
*
|
||||
* @return Returns the number of parameters in the current game message.
|
||||
* @return Returns the number of argument in the current game message.
|
||||
*
|
||||
* native GetMessageParamCount();
|
||||
* native GetMessageArgsNum();
|
||||
*/
|
||||
cell AMX_NATIVE_CALL GetMessageParamCount(AMX *amx, cell *params)
|
||||
cell AMX_NATIVE_CALL GetMessageArgsNum(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_number };
|
||||
enum args_e { arg_count };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
@ -283,58 +420,6 @@ cell AMX_NATIVE_CALL GetMessageParamCount(AMX *amx, cell *params)
|
||||
return g_activeMessageContext->getParamCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the origin of the current game message.
|
||||
*
|
||||
* @param origin An array to store the origin coordinates of the game message.
|
||||
*
|
||||
* @return Returns true if the origin is successfully retrieved, otherwise false.
|
||||
*
|
||||
* native bool:GetMessageOrigin(Float:origin[3]);
|
||||
*/
|
||||
cell AMX_NATIVE_CALL GetMessageOrigin(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_number, arg_origin };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
if (!g_activeMessageContext)
|
||||
{
|
||||
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: trying to get argument without active hook.", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const float *messageOrigin = g_activeMessageContext->getOrigin();
|
||||
if (!messageOrigin)
|
||||
return FALSE;
|
||||
|
||||
Vector &outVec = *(Vector *)getAmxAddr(amx, params[arg_origin]);
|
||||
outVec = messageOrigin;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the destination of the current message.
|
||||
*
|
||||
* @return Returns the destination of the current message.
|
||||
*
|
||||
* native GetMessageDest();
|
||||
*/
|
||||
cell AMX_NATIVE_CALL GetMessageDest(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_number, arg_origin };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
if (!g_activeMessageContext)
|
||||
{
|
||||
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: trying to get argument without active hook.", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return static_cast<cell>(g_activeMessageContext->getDest());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the block type for the specified message ID.
|
||||
*
|
||||
@ -385,25 +470,120 @@ cell AMX_NATIVE_CALL GetMessageBlock(AMX *amx, cell *params)
|
||||
return static_cast<cell>(g_RehldsMessageManager->getMessageBlock(params[arg_id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the specified type of message data has been modified
|
||||
*
|
||||
* This native allows you to check if any part of the message data, such as its
|
||||
* destination, type, origin, receiver, or any the specific argument of the message, has been modified
|
||||
*
|
||||
* @param type The type of the data to check for modification
|
||||
* This can be one of the following:
|
||||
* - MsgAny: Check if any part of the message has been modified
|
||||
* - MsgDest: Check if the destination has been modified
|
||||
* - MsgIndex: Check if the message ID has been modified
|
||||
* - MsgOrigin: Check if the origin has been modified
|
||||
* - MsgTargetId: Check if the index of the recipient client has been modified
|
||||
* - MsgArg: Check if a specific argument of the message has been modified
|
||||
*
|
||||
* @param number The number of the argument to check for modification (used only when type is MsgDataType:MsgArg)
|
||||
* Default value is -1, which means the argument number is not applicable
|
||||
*
|
||||
* @return Returns true if the specified data type has been modified, false otherwise
|
||||
*
|
||||
* native bool:IsMessageDataModified(MsgDataType:type = MsgAny, const number = -1);
|
||||
*/
|
||||
cell AMX_NATIVE_CALL IsMessageDataModified(AMX *amx, cell *params)
|
||||
{
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
enum args_e { arg_count, arg_type, arg_number };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
if (!g_activeMessageContext)
|
||||
{
|
||||
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: trying to get argument without active hook.", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size_t number = -1;
|
||||
|
||||
IMessage::DataType type = static_cast<IMessage::DataType>(params[arg_type]);
|
||||
if (type == IMessage::DataType::Param)
|
||||
{
|
||||
number = params[arg_number] - 1;
|
||||
|
||||
CHECK_PARAMBOUNDS(number, g_activeMessageContext->getParamCount());
|
||||
}
|
||||
|
||||
return g_activeMessageContext->isDataModified(type, number) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a specific type of message data to its original value
|
||||
*
|
||||
* @param type The type of the data to check for modification
|
||||
* This can be one of the following:
|
||||
* - MsgAny: Reset all modified message data to its original values
|
||||
* - MsgDest: Reset the destination to its original value
|
||||
* - MsgIndex: Reset the message ID to its original value
|
||||
* - MsgOrigin: Reset the origin to its original value
|
||||
* - MsgTargetId: Reset the index of the recipient client to its original value
|
||||
* - MsgArg: Reset a specific argument of the message to its original value
|
||||
*
|
||||
* @param number The number of the argument to reset (used only when type is MsgDataType:MsgArg)
|
||||
* Default value is -1, which means all arguments will be reset.
|
||||
*
|
||||
* @return Returns true if the modified data type was reset, otherwise false.
|
||||
*
|
||||
* native bool:ResetModifiedMessageData(MsgDataType:type = MsgAny, const number = -1);
|
||||
*/
|
||||
cell AMX_NATIVE_CALL ResetModifiedMessageData(AMX *amx, cell *params)
|
||||
{
|
||||
enum args_e { arg_count, arg_type, arg_number };
|
||||
|
||||
CHECK_REQUIREMENTS(ReHLDS);
|
||||
|
||||
if (!g_activeMessageContext)
|
||||
{
|
||||
AMXX_LogError(amx, AMX_ERR_NATIVE, "%s: trying to set argument without active hook.", __FUNCTION__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
size_t number = -1;
|
||||
|
||||
IMessage::DataType type = static_cast<IMessage::DataType>(params[arg_type]);
|
||||
if (type == IMessage::DataType::Param && params[arg_number] != -1)
|
||||
{
|
||||
number = params[arg_number] - 1;
|
||||
|
||||
CHECK_PARAMBOUNDS(number, g_activeMessageContext->getParamCount());
|
||||
}
|
||||
|
||||
return g_activeMessageContext->resetModifiedData(type, number) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
AMX_NATIVE_INFO HookMessage_Natives[] =
|
||||
{
|
||||
{ "RegisterMessage", RegisterMessage },
|
||||
{ "UnregisterMessage", UnregisterMessage },
|
||||
{ "RegisterMessage", RegisterMessage },
|
||||
{ "UnregisterMessage", UnregisterMessage },
|
||||
|
||||
{ "EnableHookMessage", EnableHookMessage },
|
||||
{ "DisableHookMessage", DisableHookMessage },
|
||||
{ "EnableHookMessage", EnableHookMessage },
|
||||
{ "DisableHookMessage", DisableHookMessage },
|
||||
|
||||
{ "GetMessageParam", GetMessageParam },
|
||||
{ "GetMessageParamType", GetMessageParamType },
|
||||
{ "GetMessageParamCount", GetMessageParamCount },
|
||||
{ "SetMessageData", SetMessageData },
|
||||
{ "GetMessageData", GetMessageData },
|
||||
|
||||
{ "GetMessageOrigin", GetMessageOrigin },
|
||||
{ "GetMessageDest", GetMessageDest },
|
||||
{ "GetMessageOrigData", GetMessageOrigData },
|
||||
|
||||
{ "SetMessageParam", SetMessageParam },
|
||||
{ "GetMessageArgType", GetMessageArgType },
|
||||
{ "GetMessageArgsNum", GetMessageArgsNum },
|
||||
|
||||
{ "SetMessageBlock", SetMessageBlock },
|
||||
{ "GetMessageBlock", GetMessageBlock },
|
||||
{ "SetMessageBlock", SetMessageBlock },
|
||||
{ "GetMessageBlock", GetMessageBlock },
|
||||
|
||||
{ "IsMessageDataModified", IsMessageDataModified },
|
||||
{ "ResetModifiedMessageData", ResetModifiedMessageData },
|
||||
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
@ -31,9 +31,9 @@ inline size_t indexOfEdictAmx(const entvars_t* pev)
|
||||
return index;
|
||||
}
|
||||
|
||||
inline size_t indexOfEdictAmx(const edict_t *pEdict)
|
||||
inline size_t indexOfEdictAmx(const edict_t *pEdict, const int INVALID_INDEX = AMX_NULLENT)
|
||||
{
|
||||
size_t index = AMX_NULLENT;
|
||||
size_t index = INVALID_INDEX;
|
||||
if (likely(pEdict != nullptr))
|
||||
index = indexOfEdict(pEdict);
|
||||
return index;
|
||||
@ -54,10 +54,10 @@ inline IGameClient* clientByIndex(const int index)
|
||||
}
|
||||
|
||||
// safe to index -1
|
||||
inline edict_t* edictByIndexAmx(const int index)
|
||||
inline edict_t* edictByIndexAmx(const int index, const int INVALID_INDEX = AMX_NULLENT)
|
||||
{
|
||||
auto ed = g_pEdicts + index;
|
||||
if (unlikely(index < 0)) // == AMX_NULLENT
|
||||
if (unlikely(index <= INVALID_INDEX)) // == AMX_NULLENT
|
||||
ed = nullptr;
|
||||
return ed;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user