diff --git a/rehlds/engine/host.cpp b/rehlds/engine/host.cpp index 673b329..9cd73e6 100644 --- a/rehlds/engine/host.cpp +++ b/rehlds/engine/host.cpp @@ -375,7 +375,8 @@ void EXT_FUNC SV_ClientPrintf_internal(const char *Dest) { char string[1024]; - Q_strlcpy(string, Dest, min(strlen(Dest) + 1, sizeof(string))); + Q_strlcpy(string, Dest); + MSG_WriteByte(&host_client->netchan.message, svc_print); MSG_WriteString(&host_client->netchan.message, string); } diff --git a/rehlds/public/rehlds/IMessageManager.h b/rehlds/public/rehlds/IMessageManager.h index d0cabb3..c93a2ec 100644 --- a/rehlds/public/rehlds/IMessageManager.h +++ b/rehlds/public/rehlds/IMessageManager.h @@ -69,7 +69,7 @@ public: /** * @brief Data types for message data */ - enum class DataType : uint8_t + enum class DataType : uint8 { Any, // Any part of the message Dest, // Destination of the message diff --git a/rehlds/rehlds/rehlds_messagemngr_impl.cpp b/rehlds/rehlds/rehlds_messagemngr_impl.cpp index 4b381de..5340519 100644 --- a/rehlds/rehlds/rehlds_messagemngr_impl.cpp +++ b/rehlds/rehlds/rehlds_messagemngr_impl.cpp @@ -18,6 +18,284 @@ #include "precompiled.h" +/** + * @brief Implementation interface for defining message parameters and behavior for a game message object + */ +class MessageImpl: public IMessage +{ +public: + MessageImpl(); + ~MessageImpl() = default; + + /** + * @brief Returns the number of parameters in the message + * @return The number of parameters + */ + int getParamCount() const { return m_paramCount; } + + /** + * @brief Returns the type of the parameter at the given index + * @param index The index of the parameter + * @return The type of the parameter + */ + ParamType getParamType(size_t index) const { return m_params[index].type; } + + /** + * @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 + */ + int getParamInt(size_t index) const; + + /** + * @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 + */ + float getParamFloat(size_t index) const; + + /** + * @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 + */ + const char *getParamString(size_t index) const; + + /** + * @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 + */ + 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 + * @param value The float value to set + */ + void setParamFloat(size_t index, float value); + + /** + * @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 + */ + void setParamVec(size_t index, const float *pos); + + /** + * @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 + */ + 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_Storage[BACK].dest; } + Dest getOriginalDest() const { return m_Storage[FRONT].dest; } + + /** + * @brief Sets the index of the message + */ + 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_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_Storage[BACK].edict; } + edict_t *getOriginalEdict() const { return m_Storage[FRONT].edict; } + + /** + * @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 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 id, const float *origin, edict_t *edict); + + // Sets the buffer for the message + void setBuffer(sizebuf_t *pbuf); + + // Set the copyback buffer for the message + void setCopybackBuffer(sizebuf_t *pbuf); + + // Adds a parameter to the message + void addParam(IMessage::ParamType type, size_t length); + + // Clears the message after execution + void clear(); + + template + void setParamPrimitive(size_t index, T value); + + // 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); + + enum + { + 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 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 : 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 : static_cast(DataType::Max); +}; + +/** +* Inline methods +*/ +inline void MessageImpl::setModifiedDataBit(DataType type) +{ + m_modifiedDataBits |= ((1 << static_cast(DataType::Any)) | (1 << static_cast(type))); +} + +inline void MessageImpl::unsetModifiedDataBit(DataType type) +{ + m_modifiedDataBits &= ~((1 << static_cast(DataType::Any)) | (1 << static_cast(type))); +} + +inline bool MessageImpl::isDataTypeModified(DataType type) const +{ + return (m_modifiedDataBits & (1 << static_cast(type))) != 0; +} + // Constructs a Message object MessageImpl::MessageImpl() { diff --git a/rehlds/rehlds/rehlds_messagemngr_impl.h b/rehlds/rehlds/rehlds_messagemngr_impl.h index 549d1bb..f016b19 100644 --- a/rehlds/rehlds/rehlds_messagemngr_impl.h +++ b/rehlds/rehlds/rehlds_messagemngr_impl.h @@ -24,284 +24,6 @@ #include // std::unique_ptr #include // std::move -/** - * @brief Implementation interface for defining message parameters and behavior for a game message object - */ -class MessageImpl: public IMessage -{ -public: - MessageImpl(); - ~MessageImpl() = default; - - /** - * @brief Returns the number of parameters in the message - * @return The number of parameters - */ - int getParamCount() const { return m_paramCount; } - - /** - * @brief Returns the type of the parameter at the given index - * @param index The index of the parameter - * @return The type of the parameter - */ - ParamType getParamType(size_t index) const { return m_params[index].type; } - - /** - * @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 - */ - int getParamInt(size_t index) const; - - /** - * @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 - */ - float getParamFloat(size_t index) const; - - /** - * @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 - */ - const char *getParamString(size_t index) const; - - /** - * @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 - */ - 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 - * @param value The float value to set - */ - void setParamFloat(size_t index, float value); - - /** - * @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 - */ - void setParamVec(size_t index, const float *pos); - - /** - * @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 - */ - 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_Storage[BACK].dest; } - Dest getOriginalDest() const { return m_Storage[FRONT].dest; } - - /** - * @brief Sets the index of the message - */ - 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_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_Storage[BACK].edict; } - edict_t *getOriginalEdict() const { return m_Storage[FRONT].edict; } - - /** - * @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 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 id, const float *origin, edict_t *edict); - - // Sets the buffer for the message - void setBuffer(sizebuf_t *pbuf); - - // Set the copyback buffer for the message - void setCopybackBuffer(sizebuf_t *pbuf); - - // Adds a parameter to the message - void addParam(IMessage::ParamType type, size_t length); - - // Clears the message after execution - void clear(); - - template - void setParamPrimitive(size_t index, T value); - - // 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); - - enum - { - 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 : 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(DataType::Any)) | (1 << static_cast(type))); -} - -inline void MessageImpl::unsetModifiedDataBit(DataType type) -{ - m_modifiedDataBits &= ~((1 << static_cast(DataType::Any)) | (1 << static_cast(type))); -} - -inline bool MessageImpl::isDataTypeModified(DataType type) const -{ - return (m_modifiedDataBits & (1 << static_cast(type))) != 0; -} - /** * @brief Implementation interface manages hooks and blocking behavior game messages */ @@ -446,8 +168,8 @@ private: }; static const size_t MAX_MSGSTACK = 16; // The maximum size of the message stack, 16 it should be enough - MessagePool m_pool; // A fixed-size memory pool stack for reusable - MessageStack m_stack; + MessagePool m_pool; // A fixed-size memory pool stack for reusable + MessageStack m_stack; using HookRegistry_t = IVoidHookChainRegistryImpl; HookRegistry_t *m_hooks[MAX_USERMESSAGES]{};