mirror of
https://github.com/rehlds/rehlds.git
synced 2025-01-14 07:38:04 +03:00
Enhanced API interface game message manager
Bump major API version Minor refactoring
This commit is contained in:
parent
c9f9bbfff9
commit
0f45ec09fa
@ -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;
|
||||
};
|
||||
|
@ -21,53 +21,60 @@
|
||||
// Constructs a Message object
|
||||
MessageImpl::MessageImpl()
|
||||
{
|
||||
m_buffer.buffername = "MessageManager/Begin/End";
|
||||
m_buffer.data = m_bufferData;
|
||||
m_buffer.flags = SIZEBUF_ALLOW_OVERFLOW;
|
||||
m_buffer.cursize = 0;
|
||||
m_buffer.maxsize = sizeof(m_bufferData);
|
||||
|
||||
m_paramCount = 0;
|
||||
m_paramCount = 0;
|
||||
m_modifiedDataBits = 0;
|
||||
}
|
||||
|
||||
// Sets the active state of the message with the given parameters
|
||||
void MessageImpl::setActive(int dest, int type, const float *origin, edict_t *edict)
|
||||
void MessageImpl::setActive(int dest, int id, const float *origin, edict_t *edict)
|
||||
{
|
||||
m_dest = static_cast<Dest>(dest);
|
||||
m_type = type;
|
||||
m_edict = edict;
|
||||
// Initialize storage buffers
|
||||
for (int i = 0; i < MAX_STORAGE; i++)
|
||||
{
|
||||
Storage_t &storage = m_Storage[i];
|
||||
storage.buf.cursize = 0;
|
||||
storage.dest = static_cast<Dest>(dest);
|
||||
storage.msgid = id;
|
||||
storage.edict = edict;
|
||||
|
||||
// Reset buffer size
|
||||
m_buffer.flags = SIZEBUF_ALLOW_OVERFLOW;
|
||||
m_buffer.cursize = 0;
|
||||
// Copy origin vector if provided
|
||||
if (origin)
|
||||
VectorCopy(origin, storage.origin);
|
||||
else
|
||||
VectorClear(storage.origin);
|
||||
}
|
||||
|
||||
// Copy origin vector if provided
|
||||
if (origin)
|
||||
VectorCopy(origin, m_origin);
|
||||
else
|
||||
VectorClear(m_origin);
|
||||
m_paramCount = 0;
|
||||
m_modifiedDataBits = 0;
|
||||
}
|
||||
|
||||
// Sets the buffer for the message
|
||||
void MessageImpl::setBuffer(sizebuf_t *pbuf)
|
||||
{
|
||||
// Copy data from the provided buffer to the message buffer
|
||||
memcpy(m_buffer.data, pbuf->data, pbuf->cursize);
|
||||
m_buffer.cursize = pbuf->cursize;
|
||||
for (int i = 0; i < MAX_STORAGE; i++)
|
||||
{
|
||||
Storage_t &storage = m_Storage[i];
|
||||
Q_memcpy(storage.buf.data, pbuf->data, pbuf->cursize);
|
||||
storage.buf.cursize = pbuf->cursize;
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the copyback buffer for the message
|
||||
void MessageImpl::setCopybackBuffer(sizebuf_t *pbuf)
|
||||
{
|
||||
const Storage_t &storage = m_Storage[BACK];
|
||||
|
||||
// Copy data from the message buffer back to the provided buffer
|
||||
memcpy(pbuf->data, m_buffer.data, m_buffer.cursize);
|
||||
pbuf->cursize = m_buffer.cursize;
|
||||
Q_memcpy(pbuf->data, storage.buf.data, storage.buf.cursize);
|
||||
pbuf->cursize = storage.buf.cursize;
|
||||
}
|
||||
|
||||
// Clears the message parameters
|
||||
void MessageImpl::clear()
|
||||
{
|
||||
m_paramCount = 0;
|
||||
m_modifiedDataBits = 0;
|
||||
}
|
||||
|
||||
// An array containing fixed sizes for various types of parameters
|
||||
@ -87,9 +94,9 @@ static size_t SIZEOF_PARAMTYPE[] =
|
||||
void MessageImpl::addParam(IMessage::ParamType type, size_t length)
|
||||
{
|
||||
Param_t ¶m = m_params[m_paramCount++];
|
||||
param.type = type;
|
||||
param.len = (length == -1) ? SIZEOF_PARAMTYPE[static_cast<size_t>(type)] : length;
|
||||
param.pos = gMsgBuffer.cursize;
|
||||
param.type = type;
|
||||
param.newlen = param.oldlen = (length == -1) ? SIZEOF_PARAMTYPE[static_cast<size_t>(type)] : length;
|
||||
param.posBack = param.posFront = gMsgBuffer.cursize;
|
||||
}
|
||||
|
||||
// Sets the value of a primitive parameter at the given index
|
||||
@ -97,12 +104,11 @@ template <typename T>
|
||||
void MessageImpl::setParamPrimitive(size_t index, T value)
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index < 0 || index >= m_paramCount)
|
||||
if (index >= m_paramCount)
|
||||
return;
|
||||
|
||||
const Param_t ¶m = m_params[index];
|
||||
|
||||
void *pbuf = m_buffer.data + param.pos;
|
||||
Param_t ¶m = m_params[index];
|
||||
void *pbuf = m_Storage[BACK].buf.data + param.posBack;
|
||||
|
||||
// Set value based on parameter type
|
||||
switch (param.type)
|
||||
@ -118,7 +124,7 @@ void MessageImpl::setParamPrimitive(size_t index, T value)
|
||||
*(int16 *)pbuf = value;
|
||||
break;
|
||||
case IMessage::ParamType::Long:
|
||||
*(uint16 *)pbuf = value;
|
||||
*(uint32 *)pbuf = value;
|
||||
break;
|
||||
case IMessage::ParamType::Angle:
|
||||
// Convert angle value to byte representation with loss of precision
|
||||
@ -133,7 +139,10 @@ void MessageImpl::setParamPrimitive(size_t index, T value)
|
||||
}
|
||||
|
||||
// Mark message as modified
|
||||
m_modified = true;
|
||||
param.modified = true;
|
||||
|
||||
// Mark the overall status as changed
|
||||
setModifiedDataBit(DataType::Param);
|
||||
}
|
||||
|
||||
// Transforms the buffer after setting a string parameter at the given index
|
||||
@ -143,8 +152,10 @@ void MessageImpl::setTxformBuffer(size_t index, size_t startPos, size_t oldLengt
|
||||
int32_t diffLength = newLength - oldLength;
|
||||
if (diffLength != 0)
|
||||
{
|
||||
sizebuf_t &buf = m_Storage[BACK].buf;
|
||||
|
||||
// Check if the buffer size limit will be exceeded
|
||||
if (m_buffer.cursize + diffLength > m_buffer.maxsize)
|
||||
if (buf.cursize + diffLength > buf.maxsize)
|
||||
{
|
||||
Sys_Error(
|
||||
"%s: Refusing to transform string with %i param of user message of %i bytes, "
|
||||
@ -152,13 +163,18 @@ void MessageImpl::setTxformBuffer(size_t index, size_t startPos, size_t oldLengt
|
||||
}
|
||||
|
||||
// Move the data in the buffer
|
||||
size_t moveLength = m_buffer.cursize - (startPos + oldLength);
|
||||
Q_memmove(m_buffer.data + startPos + newLength, m_buffer.data + startPos + oldLength, moveLength);
|
||||
m_buffer.cursize += diffLength;
|
||||
size_t moveLength = buf.cursize - (startPos + oldLength);
|
||||
if (moveLength > 0)
|
||||
Q_memmove(buf.data + startPos + newLength, buf.data + startPos + oldLength, moveLength);
|
||||
|
||||
buf.cursize += diffLength;
|
||||
|
||||
if (newLength < oldLength)
|
||||
Q_memset(buf.data + startPos + newLength + moveLength, 0, oldLength - newLength);
|
||||
|
||||
// Update the position of all subsequent parameters
|
||||
for (size_t i = index + 1; i < m_paramCount; i++)
|
||||
m_params[i].pos += diffLength;
|
||||
m_params[i].posBack += diffLength;
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,12 +182,13 @@ void MessageImpl::setTxformBuffer(size_t index, size_t startPos, size_t oldLengt
|
||||
int MessageImpl::getParamInt(size_t index) const
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index < 0 || index >= m_paramCount)
|
||||
if (index >= m_paramCount)
|
||||
return 0;
|
||||
|
||||
// Get the parameter value based on its type
|
||||
void *buf = m_buffer.data + m_params[index].pos;
|
||||
switch (m_params[index].type)
|
||||
const Param_t ¶m = m_params[index];
|
||||
const void *buf = m_Storage[BACK].buf.data + param.posBack;
|
||||
switch (param.type)
|
||||
{
|
||||
case IMessage::ParamType::Byte:
|
||||
return *(uint8 *)buf;
|
||||
@ -181,7 +198,7 @@ int MessageImpl::getParamInt(size_t index) const
|
||||
case IMessage::ParamType::Entity:
|
||||
return *(int16 *)buf;
|
||||
case IMessage::ParamType::Long:
|
||||
return *(uint16 *)buf;
|
||||
return *(uint32 *)buf;
|
||||
default:
|
||||
return 0; // bad type
|
||||
}
|
||||
@ -191,12 +208,12 @@ int MessageImpl::getParamInt(size_t index) const
|
||||
float MessageImpl::getParamFloat(size_t index) const
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index < 0 || index >= m_paramCount)
|
||||
if (index >= m_paramCount)
|
||||
return 0;
|
||||
|
||||
// Get the parameter value based on its type
|
||||
const Param_t ¶m = m_params[index];
|
||||
void *buf = m_buffer.data + param.pos;
|
||||
const void *buf = m_Storage[BACK].buf.data + param.posBack;
|
||||
switch (param.type)
|
||||
{
|
||||
case IMessage::ParamType::Angle:
|
||||
@ -214,13 +231,74 @@ float MessageImpl::getParamFloat(size_t index) const
|
||||
const char *MessageImpl::getParamString(size_t index) const
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index < 0 || index >= m_paramCount)
|
||||
if (index >= m_paramCount)
|
||||
return nullptr;
|
||||
|
||||
// Get the parameter value if it is a string
|
||||
const Param_t ¶m = m_params[index];
|
||||
if (param.type == IMessage::ParamType::String)
|
||||
return (const char *)m_buffer.data + param.pos;
|
||||
return (const char *)m_Storage[BACK].buf.data + param.posBack;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int MessageImpl::getOriginalParamInt(size_t index) const
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index >= m_paramCount)
|
||||
return 0;
|
||||
|
||||
// Get the parameter value based on its type
|
||||
const Param_t ¶m = m_params[index];
|
||||
const void *buf = m_Storage[FRONT].buf.data + param.posFront;
|
||||
switch (param.type)
|
||||
{
|
||||
case IMessage::ParamType::Byte:
|
||||
return *(uint8 *)buf;
|
||||
case IMessage::ParamType::Char:
|
||||
return *(int8 *)buf;
|
||||
case IMessage::ParamType::Short:
|
||||
case IMessage::ParamType::Entity:
|
||||
return *(int16 *)buf;
|
||||
case IMessage::ParamType::Long:
|
||||
return *(uint32 *)buf;
|
||||
default:
|
||||
return 0; // bad type
|
||||
}
|
||||
}
|
||||
|
||||
float MessageImpl::getOriginalParamFloat(size_t index) const
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index >= m_paramCount)
|
||||
return 0;
|
||||
|
||||
// Get the parameter value based on its type
|
||||
const Param_t ¶m = m_params[index];
|
||||
const void *buf = m_Storage[FRONT].buf.data + param.posFront;
|
||||
switch (param.type)
|
||||
{
|
||||
case IMessage::ParamType::Angle:
|
||||
return (float)(*(uint8 *)buf * (360.0 / 256.0));
|
||||
case IMessage::ParamType::Coord:
|
||||
return (float)(*(int16 *)buf * (1.0 / 8));
|
||||
default:
|
||||
break; // bad type
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *MessageImpl::getOriginalParamString(size_t index) const
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index >= m_paramCount)
|
||||
return nullptr;
|
||||
|
||||
// Get the parameter value if it is a string
|
||||
const Param_t ¶m = m_params[index];
|
||||
if (param.type == IMessage::ParamType::String)
|
||||
return (const char *)m_Storage[FRONT].buf.data + param.posFront;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -244,13 +322,13 @@ void MessageImpl::setParamVec(size_t index, const float *pos)
|
||||
return;
|
||||
|
||||
// Ensure index is within bounds
|
||||
if (index < 0 || (index + 3) >= m_paramCount)
|
||||
if ((index + 3) >= m_paramCount)
|
||||
return;
|
||||
|
||||
// Get the parameter position in the buffer
|
||||
const Param_t ¶m = m_params[index];
|
||||
Param_t ¶m = m_params[index];
|
||||
|
||||
int16 *pbuf = (int16 *)m_buffer.data + param.pos;
|
||||
int16 *pbuf = (int16 *)m_Storage[BACK].buf.data + param.posBack;
|
||||
|
||||
// Set each component of the vector parameter
|
||||
*(int16 *)pbuf++ = (int16)(pos[0] * 8.0);
|
||||
@ -258,7 +336,10 @@ void MessageImpl::setParamVec(size_t index, const float *pos)
|
||||
*(int16 *)pbuf++ = (int16)(pos[2] * 8.0);
|
||||
|
||||
// Mark message as modified
|
||||
m_modified = true;
|
||||
param.modified = true;
|
||||
|
||||
// Mark the overall status as modified
|
||||
setModifiedDataBit(DataType::Param);
|
||||
}
|
||||
|
||||
// Sets the string value of the parameter at the given index
|
||||
@ -268,77 +349,276 @@ void MessageImpl::setParamString(size_t index, const char *value)
|
||||
return;
|
||||
|
||||
// Ensure index is within bounds
|
||||
if (index < 0 || index >= m_paramCount)
|
||||
if (index >= m_paramCount)
|
||||
return;
|
||||
|
||||
// Calculate the length of the string
|
||||
size_t length = Q_strlen(value) + 1;
|
||||
const Param_t ¶m = m_params[index];
|
||||
Param_t ¶m = m_params[index];
|
||||
|
||||
param.newlen = Q_strlen(value) + 1;
|
||||
|
||||
// Transform buffer to accommodate the new string length
|
||||
setTxformBuffer(index, param.pos, param.len, length);
|
||||
setTxformBuffer(index, param.posBack, param.oldlen, param.newlen);
|
||||
|
||||
// Copy the string value to the buffer
|
||||
memcpy(m_buffer.data + param.pos, value, length);
|
||||
Q_memcpy(m_Storage[BACK].buf.data + param.posBack, value, param.newlen);
|
||||
|
||||
// Mark message as modified
|
||||
m_modified = true;
|
||||
param.modified = true;
|
||||
|
||||
// Mark the overall status as modified
|
||||
setModifiedDataBit(DataType::Param);
|
||||
}
|
||||
|
||||
MessageManagerImpl::MessageManagerImpl()
|
||||
// Sets the destination of the message
|
||||
void MessageImpl::setDest(Dest dest)
|
||||
{
|
||||
m_Storage[BACK].dest = dest;
|
||||
setModifiedDataBit(DataType::Dest);
|
||||
}
|
||||
|
||||
// Sets the type of the message
|
||||
void MessageImpl::setId(int msg_id)
|
||||
{
|
||||
m_Storage[BACK].msgid = msg_id;
|
||||
setModifiedDataBit(DataType::Index);
|
||||
}
|
||||
|
||||
// Sets the origin of the message
|
||||
void MessageImpl::setOrigin(const float *origin)
|
||||
{
|
||||
// Copy origin vector if provided
|
||||
if (origin)
|
||||
VectorCopy(origin, m_Storage[BACK].origin);
|
||||
else
|
||||
VectorClear(m_Storage[BACK].origin);
|
||||
|
||||
setModifiedDataBit(DataType::Origin);
|
||||
}
|
||||
|
||||
//Sets the edict associated with the message
|
||||
void MessageImpl::setEdict(edict_t *pEdict)
|
||||
{
|
||||
m_Storage[BACK].edict = pEdict;
|
||||
setModifiedDataBit(DataType::Edict);
|
||||
}
|
||||
|
||||
bool MessageImpl::isDataModified(DataType type, size_t index) const
|
||||
{
|
||||
if (!isDataTypeModified(type))
|
||||
return false;
|
||||
|
||||
if (type == DataType::Param && index != -1)
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index >= m_paramCount)
|
||||
return false;
|
||||
|
||||
const Param_t ¶m = m_params[index];
|
||||
return param.modified;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MessageImpl::resetParam(size_t index)
|
||||
{
|
||||
Param_t ¶m = m_params[index];
|
||||
|
||||
void *pbackbuf = m_Storage[BACK].buf.data + param.posBack;
|
||||
const void *pfrontbuf = m_Storage[FRONT].buf.data + param.posFront;
|
||||
|
||||
// Set value based on parameter type
|
||||
switch (param.type)
|
||||
{
|
||||
case IMessage::ParamType::Byte:
|
||||
*(uint8 *)pbackbuf = *(uint8 *)pfrontbuf;
|
||||
break;
|
||||
case IMessage::ParamType::Char:
|
||||
*(int8 *)pbackbuf = *(int8 *)pfrontbuf;
|
||||
break;
|
||||
case IMessage::ParamType::Short:
|
||||
case IMessage::ParamType::Entity:
|
||||
*(int16 *)pbackbuf = *(int16 *)pfrontbuf;
|
||||
break;
|
||||
case IMessage::ParamType::Long:
|
||||
*(uint32 *)pbackbuf = *(uint32 *)pfrontbuf;
|
||||
break;
|
||||
case IMessage::ParamType::Angle:
|
||||
*(uint8 *)pbackbuf = *(uint8 *)pfrontbuf;
|
||||
break;
|
||||
case IMessage::ParamType::Coord:
|
||||
*(int16 *)pbackbuf = *(int16 *)pfrontbuf;
|
||||
break;
|
||||
case IMessage::ParamType::String:
|
||||
// Return the original string value from the front buffer
|
||||
setTxformBuffer(index, param.posBack, param.newlen, param.oldlen);
|
||||
Q_memcpy(pbackbuf, pfrontbuf, param.oldlen);
|
||||
param.newlen = param.oldlen;
|
||||
break;
|
||||
default:
|
||||
return; // bad type
|
||||
}
|
||||
|
||||
// Unmark message as modified
|
||||
param.modified = false;
|
||||
}
|
||||
|
||||
// Resets a specific message parameter to its original value
|
||||
bool MessageImpl::resetModifiedData(DataType type, size_t index)
|
||||
{
|
||||
Storage_t &storageBack = m_Storage[BACK];
|
||||
const Storage_t &storageFront = m_Storage[FRONT];
|
||||
|
||||
unsetModifiedDataBit(type);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// Resets all message parameters and storage data to their original values
|
||||
case DataType::Any:
|
||||
{
|
||||
// Update the position of all subsequent parameters
|
||||
for (size_t i = 0; i < m_paramCount; i++)
|
||||
{
|
||||
Param_t ¶m = m_params[i];
|
||||
param.posBack = param.posFront;
|
||||
param.newlen = param.oldlen;
|
||||
param.modified = false; // Unmark message as modified
|
||||
}
|
||||
|
||||
// Copy front storage data to back buffer data
|
||||
Q_memcpy(storageBack.buf.data, storageFront.buf.data, storageFront.buf.maxsize);
|
||||
|
||||
storageBack.dest = storageFront.dest;
|
||||
storageBack.msgid = storageFront.msgid;
|
||||
storageBack.edict = storageFront.edict;
|
||||
|
||||
VectorCopy(storageFront.origin, storageBack.origin);
|
||||
|
||||
m_modifiedDataBits = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
case DataType::Dest:
|
||||
storageBack.dest = storageFront.dest;
|
||||
break;
|
||||
case DataType::Index:
|
||||
storageBack.msgid = storageFront.msgid;
|
||||
break;
|
||||
case DataType::Origin:
|
||||
VectorCopy(storageFront.origin, storageBack.origin);
|
||||
break;
|
||||
case DataType::Edict:
|
||||
storageBack.edict = storageFront.edict;
|
||||
break;
|
||||
case DataType::Param:
|
||||
{
|
||||
// Reset a specific parameter
|
||||
if (index != -1)
|
||||
{
|
||||
// Ensure index is within bounds
|
||||
if (index < m_paramCount)
|
||||
resetParam(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < m_paramCount; i++)
|
||||
resetParam(i);
|
||||
}
|
||||
|
||||
// Recalc modified data bits
|
||||
for (size_t i = 0; i < m_paramCount; i++)
|
||||
{
|
||||
const Param_t ¶m = m_params[i];
|
||||
if (param.modified)
|
||||
{
|
||||
setModifiedDataBit(DataType::Param);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there was any other modified data, mark Any as overall modified data
|
||||
if (m_modifiedDataBits != 0)
|
||||
setModifiedDataBit(DataType::Any);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageManagerImpl::MessageManagerImpl() : m_stack(m_pool)
|
||||
{
|
||||
m_inblock = false;
|
||||
m_inhook = false;
|
||||
}
|
||||
|
||||
// Register hook function for the game message type
|
||||
void MessageManagerImpl::registerHook(int msgType, hookfunc_t handler, int priority)
|
||||
void MessageManagerImpl::registerHook(int msg_id, hookfunc_t handler, int priority)
|
||||
{
|
||||
m_hooks[msgType].registerHook(handler, priority);
|
||||
if (!m_hooks[msg_id])
|
||||
m_hooks[msg_id] = new HookRegistry_t;
|
||||
|
||||
if (m_hooks[msg_id]->findHook(handler))
|
||||
return; // already registered
|
||||
|
||||
m_hooks[msg_id]->registerHook(handler, priority);
|
||||
}
|
||||
|
||||
// Unregister hook function for the game message type
|
||||
void MessageManagerImpl::unregisterHook(int msgType, hookfunc_t handler)
|
||||
void MessageManagerImpl::unregisterHook(int msg_id, hookfunc_t handler)
|
||||
{
|
||||
m_hooks[msgType].unregisterHook(handler);
|
||||
if (!m_hooks[msg_id])
|
||||
return;
|
||||
|
||||
m_hooks[msg_id]->unregisterHook(handler);
|
||||
|
||||
if (m_hooks[msg_id]->getCount() == 0)
|
||||
{
|
||||
delete m_hooks[msg_id];
|
||||
m_hooks[msg_id] = nullptr;
|
||||
m_pool.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Get the block type for the game message type
|
||||
IMessage::BlockType MessageManagerImpl::getMessageBlock(int msgType) const
|
||||
IMessage::BlockType MessageManagerImpl::getMessageBlock(int msg_id) const
|
||||
{
|
||||
return m_blocks[msgType];
|
||||
return m_blocks[msg_id];
|
||||
}
|
||||
|
||||
// Set the block type for the game message type
|
||||
void MessageManagerImpl::setMessageBlock(int msgType, IMessage::BlockType blockType)
|
||||
void MessageManagerImpl::setMessageBlock(int msg_id, IMessage::BlockType blockType)
|
||||
{
|
||||
m_blocks[msgType] = blockType;
|
||||
m_blocks[msg_id] = blockType;
|
||||
}
|
||||
|
||||
bool MessageManagerImpl::MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
|
||||
bool MessageManagerImpl::MessageBegin(int msg_dest, int msg_id, const float *pOrigin, edict_t *ed)
|
||||
{
|
||||
// Check if the message type is blocked
|
||||
if (m_blocks[msg_type] != IMessage::BlockType::Not)
|
||||
if (m_blocks[msg_id] != IMessage::BlockType::Not)
|
||||
{
|
||||
m_inblock = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if there are hooks registered for the message type
|
||||
m_inhook = m_hooks[msg_type].getCount() > 0;
|
||||
m_inhook = (m_hooks[msg_id] && m_hooks[msg_id]->getCount() > 0);
|
||||
|
||||
if (m_inhook)
|
||||
{
|
||||
// Check for stack overflow
|
||||
if (m_stack.size() >= m_stack.max_size() - 1)
|
||||
Sys_Error("%s: stack overflow in #%i user message.\nIndicate potential recursive calls...\n", __func__, msg_type);
|
||||
Sys_Error("%s: stack overflow in #%i user message.\nIndicate potential recursive calls...\n", __func__, msg_id);
|
||||
|
||||
// Push a new game message onto the stack
|
||||
m_stack.push();
|
||||
MessageImpl &msg = m_stack.push();
|
||||
|
||||
// Initialize the message
|
||||
MessageImpl &msg = m_stack.back();
|
||||
msg.setActive(msg_dest, msg_type, pOrigin, ed);
|
||||
msg.setActive(msg_dest, msg_id, pOrigin, ed);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -347,7 +627,7 @@ bool MessageManagerImpl::MessageBegin(int msg_dest, int msg_type, const float *p
|
||||
static void EXT_FUNC SendUserMessageData(IMessage *msg)
|
||||
{
|
||||
// Set global variables with message data
|
||||
gMsgType = msg->getType();
|
||||
gMsgType = msg->getId();
|
||||
gMsgEntity = msg->getEdict();
|
||||
gMsgDest = static_cast<int>(msg->getDest());
|
||||
|
||||
@ -383,11 +663,11 @@ bool MessageManagerImpl::MessageEnd()
|
||||
gMsgStarted = FALSE;
|
||||
|
||||
// Get the message from the top of the stack
|
||||
MessageImpl &msg = m_stack.back();
|
||||
MessageImpl &msg = m_stack.top();
|
||||
|
||||
// Set buffer from global buffer and call hookchain
|
||||
msg.setBuffer(&gMsgBuffer);
|
||||
m_hooks[msg.getType()].callChain(SendUserMessageData, &msg);
|
||||
m_hooks[msg.getId()]->callChain(SendUserMessageData, &msg);
|
||||
m_inhook = false;
|
||||
|
||||
// Clear the message and pop from the stack
|
||||
@ -407,7 +687,7 @@ bool MessageManagerImpl::WriteParam(IMessage::ParamType type, size_t length)
|
||||
if (m_inhook)
|
||||
{
|
||||
// Add parameter to top stack message
|
||||
MessageImpl &msg = m_stack.back();
|
||||
MessageImpl &msg = m_stack.top();
|
||||
msg.addParam(type, length);
|
||||
}
|
||||
|
||||
@ -418,14 +698,14 @@ bool MessageManagerImpl::WriteParam(IMessage::ParamType type, size_t length)
|
||||
// Functions intercept to handle messages
|
||||
//
|
||||
|
||||
void EXT_FUNC PF_MessageBegin_Intercept(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
|
||||
void EXT_FUNC PF_MessageBegin_Intercept(int msg_dest, int msg_id, const float *pOrigin, edict_t *ed)
|
||||
{
|
||||
// Set global message type
|
||||
gMsgType = msg_type;
|
||||
gMsgType = msg_id;
|
||||
|
||||
// Begin message manager
|
||||
if (MessageManager().MessageBegin(msg_dest, msg_type, pOrigin, ed))
|
||||
PF_MessageBegin_I(msg_dest, msg_type, pOrigin, ed);
|
||||
if (MessageManager().MessageBegin(msg_dest, msg_id, pOrigin, ed))
|
||||
PF_MessageBegin_I(msg_dest, msg_id, pOrigin, ed);
|
||||
}
|
||||
|
||||
void EXT_FUNC PF_MessageEnd_Intercept(void)
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include "IMessageManager.h"
|
||||
#include "hookchains.h"
|
||||
|
||||
#include <memory> // std::unique_ptr
|
||||
#include <algorithm> // std::move
|
||||
|
||||
/**
|
||||
* @brief Implementation interface for defining message parameters and behavior for a game message object
|
||||
*/
|
||||
@ -71,6 +74,27 @@ public:
|
||||
*/
|
||||
void setParamInt(size_t index, int value);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
int getOriginalParamInt(size_t index) const;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
float getOriginalParamFloat(size_t index) const;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
const char* getOriginalParamString(size_t index) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the float value of the parameter at the given index
|
||||
* @param index The index of the parameter
|
||||
@ -92,42 +116,101 @@ public:
|
||||
*/
|
||||
void setParamString(size_t index, const char *string);
|
||||
|
||||
/**
|
||||
* @brief Sets the destination of the message
|
||||
*/
|
||||
void setDest(Dest dest);
|
||||
|
||||
/**
|
||||
* @brief Returns the destination of the message
|
||||
* @return The destination of the message
|
||||
*/
|
||||
Dest getDest() const { return m_dest; }
|
||||
Dest getDest() const { return m_Storage[BACK].dest; }
|
||||
Dest getOriginalDest() const { return m_Storage[FRONT].dest; }
|
||||
|
||||
/**
|
||||
* @brief Returns the type of the message
|
||||
* @return The type of the message
|
||||
* @brief Sets the index of the message
|
||||
*/
|
||||
int getType() const { return m_type; }
|
||||
void setId(int msg_id);
|
||||
|
||||
/**
|
||||
* @brief Returns the index of the message
|
||||
* @return The index of the message
|
||||
*/
|
||||
int getId() const { return m_Storage[BACK].msgid; }
|
||||
int getOriginalId() const { return m_Storage[FRONT].msgid; }
|
||||
|
||||
/**
|
||||
* @brief Sets the origin of the message
|
||||
*/
|
||||
void setOrigin(const float *origin);
|
||||
|
||||
/**
|
||||
* @brief Returns the origin of the message
|
||||
* @return The origin of the message
|
||||
*/
|
||||
const float *getOrigin() const { return m_origin; }
|
||||
const float *getOrigin() const { return m_Storage[BACK].origin; }
|
||||
const float *getOriginalOrigin() const { return m_Storage[FRONT].origin; }
|
||||
|
||||
/**
|
||||
* @brief Sets the edict associated with the message
|
||||
*/
|
||||
void setEdict(edict_t *pEdict);
|
||||
|
||||
/**
|
||||
* @brief Returns the edict associated with the message
|
||||
* @return The edict associated with the message
|
||||
*/
|
||||
edict_t *getEdict() const { return m_edict; }
|
||||
edict_t *getEdict() const { return m_Storage[BACK].edict; }
|
||||
edict_t *getOriginalEdict() const { return m_Storage[FRONT].edict; }
|
||||
|
||||
/**
|
||||
* @brief Returns whether the message has been modified
|
||||
* @return True if the message has been modified, false otherwise
|
||||
* @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
|
||||
*/
|
||||
bool isModified() const { return m_modified; }
|
||||
bool isDataModified(DataType type, size_t index) const;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
bool resetModifiedData(DataType type, size_t index = -1);
|
||||
|
||||
private:
|
||||
|
||||
friend class MessageManagerImpl;
|
||||
|
||||
// Sets the active state of the message with the given parameters
|
||||
void setActive(int dest, int type, const float *origin, edict_t *edict);
|
||||
void setActive(int dest, int id, const float *origin, edict_t *edict);
|
||||
|
||||
// Sets the buffer for the message
|
||||
void setBuffer(sizebuf_t *pbuf);
|
||||
@ -147,27 +230,78 @@ private:
|
||||
// Transforms buffer after sets string for a parameter at the given index
|
||||
void setTxformBuffer(size_t index, size_t startPos, size_t oldLength, size_t newLength);
|
||||
|
||||
bool m_modified; // Flag indicating whether the message has been modified
|
||||
Dest m_dest; // The destination of the message
|
||||
int m_type; // The type of the message
|
||||
float m_origin[3]; // The origin of the message
|
||||
edict_t* m_edict; // The edict associated with the message
|
||||
|
||||
uint8 m_bufferData[512]; // The buffer data for the message 'm_buffer'
|
||||
sizebuf_t m_buffer; // The buffer for the message
|
||||
|
||||
struct Param_t
|
||||
enum
|
||||
{
|
||||
ParamType type; // The type of the parameter
|
||||
size_t pos; // The position of the parameter in the buffer
|
||||
size_t len; // The length of the parameter in the buffer
|
||||
FRONT, // Original buffer storage data
|
||||
BACK, // Current modifiable buffer storage data
|
||||
MAX_STORAGE
|
||||
};
|
||||
|
||||
struct Storage_t
|
||||
{
|
||||
// The buffer storage data for the message 'm_buffer' (variable-length message limited to one byte is 256)
|
||||
uint8_t bufData[256]{};
|
||||
|
||||
// The buffer for the message
|
||||
sizebuf_t buf = { "MsgMngr/Begin/End", SIZEBUF_ALLOW_OVERFLOW, bufData, sizeof(bufData), 0 };
|
||||
|
||||
// The destination of the message
|
||||
Dest dest{};
|
||||
|
||||
// The index of the message
|
||||
int msgid{0};
|
||||
|
||||
// The origin of the message
|
||||
float origin[3]{0,0,0};
|
||||
|
||||
// The edict associated with the message
|
||||
edict_t *edict{nullptr};
|
||||
};
|
||||
|
||||
Storage_t m_Storage[MAX_STORAGE];
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct Param_t
|
||||
{
|
||||
bool modified : 1; // Flag indicating whether the message param has been modified
|
||||
ParamType type : 3; // The type of the parameter
|
||||
size_t posBack : 9; // The current position of the parameter in the buffer
|
||||
size_t posFront : 9; // The stock position of the parameter in the buffer
|
||||
size_t oldlen : 9; // The length of the parameter in the buffer
|
||||
size_t newlen : 9; // The length of the parameter in the buffer
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static const size_t MAX_PARAMS = 16; // The maximum number of parameters allowed in the message
|
||||
Param_t m_params[MAX_PARAMS]; // The array of parameters in the message
|
||||
size_t m_paramCount; // The number of parameters in the message
|
||||
Param_t m_params[MAX_PARAMS]{}; // The array of parameters in the message
|
||||
size_t m_paramCount : 4; // The number of parameters in the message
|
||||
|
||||
void resetParam(size_t index);
|
||||
|
||||
void setModifiedDataBit(DataType type);
|
||||
void unsetModifiedDataBit(DataType type);
|
||||
bool isDataTypeModified(DataType type) const;
|
||||
uint8 m_modifiedDataBits : DataType::Max;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inline methods
|
||||
*/
|
||||
inline void MessageImpl::setModifiedDataBit(DataType type)
|
||||
{
|
||||
m_modifiedDataBits |= ((1 << static_cast<int>(DataType::Any)) | (1 << static_cast<int>(type)));
|
||||
}
|
||||
|
||||
inline void MessageImpl::unsetModifiedDataBit(DataType type)
|
||||
{
|
||||
m_modifiedDataBits &= ~((1 << static_cast<int>(DataType::Any)) | (1 << static_cast<int>(type)));
|
||||
}
|
||||
|
||||
inline bool MessageImpl::isDataTypeModified(DataType type) const
|
||||
{
|
||||
return (m_modifiedDataBits & (1 << static_cast<int>(type))) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation interface manages hooks and blocking behavior game messages
|
||||
*/
|
||||
@ -194,35 +328,35 @@ 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
|
||||
*/
|
||||
IMessage::BlockType getMessageBlock(int msgType) const;
|
||||
IMessage::BlockType getMessageBlock(int msg_id) const;
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
void setMessageBlock(int msgType, IMessage::BlockType blockType);
|
||||
void setMessageBlock(int msg_id, IMessage::BlockType blockType);
|
||||
|
||||
/**
|
||||
* @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)
|
||||
*/
|
||||
void registerHook(int msgType, hookfunc_t handler, int priority = HC_PRIORITY_DEFAULT);
|
||||
void registerHook(int msg_id, hookfunc_t handler, int priority = HC_PRIORITY_DEFAULT);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*/
|
||||
void unregisterHook(int msgType, hookfunc_t handler);
|
||||
void unregisterHook(int msg_id, hookfunc_t handler);
|
||||
|
||||
private:
|
||||
friend void PF_MessageBegin_Intercept(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed);
|
||||
friend void PF_MessageBegin_Intercept(int msg_dest, int msg_id, const float *pOrigin, edict_t *ed);
|
||||
friend void PF_MessageEnd_Intercept();
|
||||
friend void PF_WriteByte_Intercept(int iValue);
|
||||
friend void PF_WriteChar_Intercept(int iValue);
|
||||
@ -233,7 +367,7 @@ private:
|
||||
friend void PF_WriteString_Intercept(const char *sz);
|
||||
friend void PF_WriteEntity_Intercept(int iValue);
|
||||
|
||||
bool MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed);
|
||||
bool MessageBegin(int msg_dest, int msg_id, const float *pOrigin, edict_t *ed);
|
||||
bool MessageEnd();
|
||||
|
||||
private:
|
||||
@ -243,31 +377,81 @@ private:
|
||||
bool m_inhook; // Flag indicating whether a message hook is currently active
|
||||
|
||||
/**
|
||||
* @brief Helper a templated Stack class to manage a stack of Message objects
|
||||
* @brief The fixed-size memory pool holds a list of free objects
|
||||
* @tparam T The type of objects stored in the stack
|
||||
* @tparam MAX The maximum size of the stack
|
||||
*/
|
||||
template <typename T, size_t MAX>
|
||||
class Stack
|
||||
class MessagePool
|
||||
{
|
||||
public:
|
||||
void push() { _size++; }
|
||||
void pop () { _size--; }
|
||||
std::unique_ptr<T> acquire()
|
||||
{
|
||||
if (_size > 0)
|
||||
return std::move(_freeObjects[--_size]); // reusing
|
||||
return std::make_unique<T>(); // initialize constructor for new element
|
||||
}
|
||||
|
||||
void release(std::unique_ptr<T> obj)
|
||||
{
|
||||
if (_size < MAX)
|
||||
_freeObjects[_size++] = std::move(obj);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
while (_size > 0)
|
||||
_freeObjects[--_size].reset();
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _size{0u};
|
||||
std::unique_ptr<T> _freeObjects[MAX]{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper a templated MessageStack class to manage a stack of Message objects with fixed size
|
||||
* @tparam T The type of objects stored in the stack
|
||||
* @tparam MAX The maximum size of the stack
|
||||
*/
|
||||
template <typename T, size_t MAX>
|
||||
class MessageStack
|
||||
{
|
||||
public:
|
||||
MessageStack(MessagePool<T, MAX> &pool) : _pool(pool) {}
|
||||
|
||||
T &push()
|
||||
{
|
||||
std::unique_ptr<T> msg = _pool.acquire();
|
||||
_activeObjects[_size++] = std::move(msg);
|
||||
return *_activeObjects[_size - 1];
|
||||
}
|
||||
|
||||
void pop()
|
||||
{
|
||||
if (_size > 0)
|
||||
_pool.release(std::move(_activeObjects[--_size]));
|
||||
}
|
||||
|
||||
size_t size() const { return _size; }
|
||||
size_t max_size() const { return MAX; }
|
||||
|
||||
const T &back() const { return _data[_size - 1]; }
|
||||
T &back() { return _data[_size - 1]; }
|
||||
const T &top() const { return *_activeObjects[_size - 1]; }
|
||||
T &top() { return *_activeObjects[_size - 1]; }
|
||||
|
||||
private:
|
||||
size_t _size = 0u;
|
||||
T _data[MAX]{};
|
||||
size_t _size{0u};
|
||||
std::unique_ptr<T> _activeObjects[MAX]{};
|
||||
MessagePool<T, MAX> &_pool;
|
||||
};
|
||||
|
||||
static const size_t MAX_MSGSTACK = 16; // The maximum size of the message stack, 16 it should be enough
|
||||
Stack<MessageImpl, MAX_MSGSTACK> m_stack;
|
||||
MessagePool<MessageImpl, MAX_MSGSTACK> m_pool; // A fixed-size memory pool stack for reusable
|
||||
MessageStack<MessageImpl, MAX_MSGSTACK> m_stack;
|
||||
|
||||
using HookRegistry_t = IVoidHookChainRegistryImpl<IMessage *>;
|
||||
HookRegistry_t *m_hooks[MAX_USERMESSAGES]{};
|
||||
|
||||
IVoidHookChainRegistryImpl<IMessage *> m_hooks [MAX_USERMESSAGES]{}; // The array of hook chain registries for each message type
|
||||
IMessage::BlockType m_blocks[MAX_USERMESSAGES]{}; // The array of blocking behaviors for each message type
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user