mirror of
https://github.com/rehlds/rehlds.git
synced 2025-01-14 15:48:04 +03:00
Implement API interface game message manager
This commit is contained in:
parent
a761efa75d
commit
c9f9bbfff9
@ -182,6 +182,7 @@ set(ENGINE_SRCS
|
|||||||
rehlds/public_amalgamation.cpp
|
rehlds/public_amalgamation.cpp
|
||||||
rehlds/rehlds_api_impl.cpp
|
rehlds/rehlds_api_impl.cpp
|
||||||
rehlds/rehlds_interfaces_impl.cpp
|
rehlds/rehlds_interfaces_impl.cpp
|
||||||
|
rehlds/rehlds_messagemngr_impl.cpp
|
||||||
rehlds/rehlds_security.cpp
|
rehlds/rehlds_security.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1083,6 +1083,10 @@ void LoadThisDll(const char *szDllFilename)
|
|||||||
goto IgnoreThisDLL;
|
goto IgnoreThisDLL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef REHLDS_API
|
||||||
|
MessageManager().Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
pfnGiveFnptrsToDll(&g_engfuncsExportedToDlls, &gGlobalVariables);
|
pfnGiveFnptrsToDll(&g_engfuncsExportedToDlls, &gGlobalVariables);
|
||||||
if (g_iextdllMac == MAX_EXTENSION_DLL)
|
if (g_iextdllMac == MAX_EXTENSION_DLL)
|
||||||
{
|
{
|
||||||
|
@ -119,6 +119,7 @@
|
|||||||
<ClCompile Include="..\rehlds\FlightRecorderImpl.cpp" />
|
<ClCompile Include="..\rehlds\FlightRecorderImpl.cpp" />
|
||||||
<ClCompile Include="..\rehlds\flight_recorder.cpp" />
|
<ClCompile Include="..\rehlds\flight_recorder.cpp" />
|
||||||
<ClCompile Include="..\rehlds\main.cpp" />
|
<ClCompile Include="..\rehlds\main.cpp" />
|
||||||
|
<ClCompile Include="..\rehlds\rehlds_messagemngr_impl.cpp" />
|
||||||
<ClCompile Include="..\rehlds\rehlds_api_impl.cpp" />
|
<ClCompile Include="..\rehlds\rehlds_api_impl.cpp" />
|
||||||
<ClCompile Include="..\rehlds\rehlds_interfaces_impl.cpp" />
|
<ClCompile Include="..\rehlds\rehlds_interfaces_impl.cpp" />
|
||||||
<ClCompile Include="..\rehlds\hookchains_impl.cpp" />
|
<ClCompile Include="..\rehlds\hookchains_impl.cpp" />
|
||||||
@ -386,6 +387,7 @@
|
|||||||
<ClInclude Include="..\public\rehlds\eiface.h" />
|
<ClInclude Include="..\public\rehlds\eiface.h" />
|
||||||
<ClInclude Include="..\public\rehlds\FlightRecorder.h" />
|
<ClInclude Include="..\public\rehlds\FlightRecorder.h" />
|
||||||
<ClInclude Include="..\public\rehlds\hookchains.h" />
|
<ClInclude Include="..\public\rehlds\hookchains.h" />
|
||||||
|
<ClInclude Include="..\public\rehlds\IMessageManager.h" />
|
||||||
<ClInclude Include="..\public\rehlds\keydefs.h" />
|
<ClInclude Include="..\public\rehlds\keydefs.h" />
|
||||||
<ClInclude Include="..\public\rehlds\maintypes.h" />
|
<ClInclude Include="..\public\rehlds\maintypes.h" />
|
||||||
<ClInclude Include="..\public\rehlds\model.h" />
|
<ClInclude Include="..\public\rehlds\model.h" />
|
||||||
@ -439,6 +441,7 @@
|
|||||||
<ClInclude Include="..\rehlds\FlightRecorderImpl.h" />
|
<ClInclude Include="..\rehlds\FlightRecorderImpl.h" />
|
||||||
<ClInclude Include="..\rehlds\flight_recorder.h" />
|
<ClInclude Include="..\rehlds\flight_recorder.h" />
|
||||||
<ClInclude Include="..\rehlds\hookchains_impl.h" />
|
<ClInclude Include="..\rehlds\hookchains_impl.h" />
|
||||||
|
<ClInclude Include="..\rehlds\rehlds_messagemngr_impl.h" />
|
||||||
<ClInclude Include="..\rehlds\platform.h" />
|
<ClInclude Include="..\rehlds\platform.h" />
|
||||||
<ClInclude Include="..\rehlds\precompiled.h" />
|
<ClInclude Include="..\rehlds\precompiled.h" />
|
||||||
<ClInclude Include="..\rehlds\RehldsRuntimeConfig.h" />
|
<ClInclude Include="..\rehlds\RehldsRuntimeConfig.h" />
|
||||||
|
@ -341,6 +341,9 @@
|
|||||||
<ClCompile Include="..\testsuite\memory.cpp">
|
<ClCompile Include="..\testsuite\memory.cpp">
|
||||||
<Filter>testsuite</Filter>
|
<Filter>testsuite</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\rehlds\rehlds_messagemngr_impl.cpp">
|
||||||
|
<Filter>rehlds</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\version\version.h">
|
<ClInclude Include="..\version\version.h">
|
||||||
@ -1060,5 +1063,11 @@
|
|||||||
<ClInclude Include="..\testsuite\memory.h">
|
<ClInclude Include="..\testsuite\memory.h">
|
||||||
<Filter>testsuite</Filter>
|
<Filter>testsuite</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\rehlds\rehlds_messagemngr_impl.h">
|
||||||
|
<Filter>rehlds</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\public\rehlds\IMessageManager.h">
|
||||||
|
<Filter>public\rehlds</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
223
rehlds/public/rehlds/IMessageManager.h
Normal file
223
rehlds/public/rehlds/IMessageManager.h
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface for defining message parameters and behavior for a individual message object
|
||||||
|
*/
|
||||||
|
class IMessage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief The parameter types for a message
|
||||||
|
*/
|
||||||
|
enum class ParamType : uint8
|
||||||
|
{
|
||||||
|
Byte,
|
||||||
|
Char,
|
||||||
|
Short,
|
||||||
|
Long,
|
||||||
|
Angle,
|
||||||
|
Coord,
|
||||||
|
String,
|
||||||
|
Entity,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Blocking behavior types for messages
|
||||||
|
*/
|
||||||
|
enum class BlockType : uint8
|
||||||
|
{
|
||||||
|
Not, // Not a block
|
||||||
|
Once, // Block once
|
||||||
|
Set // Set block
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Message destinations
|
||||||
|
*/
|
||||||
|
enum class Dest : uint8
|
||||||
|
{
|
||||||
|
BROADCAST, // Unreliable to all
|
||||||
|
ONE, // Reliable to one (msg_entity)
|
||||||
|
ALL, // Reliable to all
|
||||||
|
INIT, // Write to the init string
|
||||||
|
PVS, // Ents in PVS of org
|
||||||
|
PAS, // Ents in PAS of org
|
||||||
|
PVS_R, // Reliable to PVS
|
||||||
|
PAS_R, // Reliable to PAS
|
||||||
|
ONE_UNRELIABLE, // Send to one client, but don't put in reliable stream, put in unreliable datagram
|
||||||
|
SPEC, // Sends to all spectator proxies
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~IMessage() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the number of parameters in the message
|
||||||
|
* @return The number of parameters
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the destination of the message
|
||||||
|
* @return The destination of the message
|
||||||
|
*/
|
||||||
|
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 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
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
|
||||||
|
// This must be the last virtual function in class
|
||||||
|
#ifdef REHLDS_SELF
|
||||||
|
// Set the copyback buffer for the message
|
||||||
|
virtual void setCopybackBuffer(struct sizebuf_s *pbuf) = 0;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MESSAGEMNGR_VERSION_MAJOR 1
|
||||||
|
#define MESSAGEMNGR_VERSION_MINOR 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interface manages hooks and blocking behavior game messages
|
||||||
|
*/
|
||||||
|
class IMessageManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using hookfunc_t = void (*)(IVoidHookChain<IMessage *> *chain, IMessage *msg);
|
||||||
|
|
||||||
|
virtual ~IMessageManager() {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the major version of the MessageManager
|
||||||
|
* @return The major version
|
||||||
|
*/
|
||||||
|
virtual int getMajorVersion() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the minor version of the MessageManager
|
||||||
|
* @return The minor version
|
||||||
|
*/
|
||||||
|
virtual int getMinorVersion() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the blocking behavior for the given message type
|
||||||
|
* @param msgType The message type
|
||||||
|
* @return The blocking behavior for the given message type
|
||||||
|
*/
|
||||||
|
virtual IMessage::BlockType getMessageBlock(int msgType) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the blocking behavior for the given message type
|
||||||
|
* @param msgType The message type
|
||||||
|
* @param blockType The blocking behavior to set
|
||||||
|
*/
|
||||||
|
virtual void setMessageBlock(int msgType, 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 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregisters a hook function for the given message type
|
||||||
|
* @param msgType The message type to unregister the hook for
|
||||||
|
* @param handler The hook function to unregister
|
||||||
|
*/
|
||||||
|
virtual void unregisterHook(int msgType, hookfunc_t handler) = 0;
|
||||||
|
};
|
@ -31,6 +31,7 @@
|
|||||||
#include "rehlds_interfaces.h"
|
#include "rehlds_interfaces.h"
|
||||||
#include "hookchains.h"
|
#include "hookchains.h"
|
||||||
#include "FlightRecorder.h"
|
#include "FlightRecorder.h"
|
||||||
|
#include "IMessageManager.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "ObjectList.h"
|
#include "ObjectList.h"
|
||||||
@ -446,6 +447,7 @@ public:
|
|||||||
virtual IRehldsServerStatic* GetServerStatic() = 0;
|
virtual IRehldsServerStatic* GetServerStatic() = 0;
|
||||||
virtual IRehldsServerData* GetServerData() = 0;
|
virtual IRehldsServerData* GetServerData() = 0;
|
||||||
virtual IRehldsFlightRecorder* GetFlightRecorder() = 0;
|
virtual IRehldsFlightRecorder* GetFlightRecorder() = 0;
|
||||||
|
virtual IMessageManager *GetMessageManager() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001"
|
#define VREHLDS_HLDS_API_VERSION "VREHLDS_HLDS_API_VERSION001"
|
||||||
|
@ -90,3 +90,7 @@ void AbstractHookChainRegistry::removeHook(void* hookFunc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AbstractHookChainRegistry::getCount() const {
|
||||||
|
return m_NumHooks;
|
||||||
|
}
|
||||||
|
@ -109,10 +109,11 @@ protected:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addHook(void* hookFunc, int priority);
|
void addHook(void* hookFunc, int priority);
|
||||||
bool findHook(void* hookFunc) const;
|
|
||||||
void removeHook(void* hookFunc);
|
void removeHook(void* hookFunc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int getCount() const;
|
||||||
|
bool findHook(void* hookFunc) const;
|
||||||
AbstractHookChainRegistry();
|
AbstractHookChainRegistry();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -132,9 +133,14 @@ public:
|
|||||||
EXT_FUNC virtual void registerHook(hookfunc_t hook, int priority) {
|
EXT_FUNC virtual void registerHook(hookfunc_t hook, int priority) {
|
||||||
addHook((void*)hook, priority);
|
addHook((void*)hook, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXT_FUNC virtual void unregisterHook(hookfunc_t hook) {
|
EXT_FUNC virtual void unregisterHook(hookfunc_t hook) {
|
||||||
removeHook((void*)hook);
|
removeHook((void*)hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const {
|
||||||
|
return getCount() == 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ...t_args>
|
template<typename ...t_args>
|
||||||
@ -157,4 +163,8 @@ public:
|
|||||||
EXT_FUNC virtual void unregisterHook(hookfunc_t hook) {
|
EXT_FUNC virtual void unregisterHook(hookfunc_t hook) {
|
||||||
removeHook((void*)hook);
|
removeHook((void*)hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const {
|
||||||
|
return getCount() == 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "rehlds_api_impl.h"
|
#include "rehlds_api_impl.h"
|
||||||
#include "FlightRecorderImpl.h"
|
#include "FlightRecorderImpl.h"
|
||||||
#include "flight_recorder.h"
|
#include "flight_recorder.h"
|
||||||
|
#include "rehlds_messagemngr_impl.h"
|
||||||
#include "rehlds_security.h"
|
#include "rehlds_security.h"
|
||||||
|
|
||||||
#include "dlls/cdll_dll.h"
|
#include "dlls/cdll_dll.h"
|
||||||
|
@ -917,6 +917,10 @@ IRehldsServerData* EXT_FUNC CRehldsApi::GetServerData() {
|
|||||||
return &g_RehldsServerData;
|
return &g_RehldsServerData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMessageManager* EXT_FUNC CRehldsApi::GetMessageManager() {
|
||||||
|
return &MessageManager();
|
||||||
|
}
|
||||||
|
|
||||||
IRehldsFlightRecorder* EXT_FUNC CRehldsApi::GetFlightRecorder() {
|
IRehldsFlightRecorder* EXT_FUNC CRehldsApi::GetFlightRecorder() {
|
||||||
return g_FlightRecorder;
|
return g_FlightRecorder;
|
||||||
}
|
}
|
||||||
|
@ -391,6 +391,7 @@ public:
|
|||||||
virtual IRehldsServerStatic* GetServerStatic();
|
virtual IRehldsServerStatic* GetServerStatic();
|
||||||
virtual IRehldsServerData* GetServerData();
|
virtual IRehldsServerData* GetServerData();
|
||||||
virtual IRehldsFlightRecorder* GetFlightRecorder();
|
virtual IRehldsFlightRecorder* GetFlightRecorder();
|
||||||
|
virtual IMessageManager* GetMessageManager();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern sizebuf_t* GetNetMessage_api();
|
extern sizebuf_t* GetNetMessage_api();
|
||||||
|
508
rehlds/rehlds/rehlds_messagemngr_impl.cpp
Normal file
508
rehlds/rehlds/rehlds_messagemngr_impl.cpp
Normal file
@ -0,0 +1,508 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.h"
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the active state of the message with the given parameters
|
||||||
|
void MessageImpl::setActive(int dest, int type, const float *origin, edict_t *edict)
|
||||||
|
{
|
||||||
|
m_dest = static_cast<Dest>(dest);
|
||||||
|
m_type = type;
|
||||||
|
m_edict = edict;
|
||||||
|
|
||||||
|
// Reset buffer size
|
||||||
|
m_buffer.flags = SIZEBUF_ALLOW_OVERFLOW;
|
||||||
|
m_buffer.cursize = 0;
|
||||||
|
|
||||||
|
// Copy origin vector if provided
|
||||||
|
if (origin)
|
||||||
|
VectorCopy(origin, m_origin);
|
||||||
|
else
|
||||||
|
VectorClear(m_origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the copyback buffer for the message
|
||||||
|
void MessageImpl::setCopybackBuffer(sizebuf_t *pbuf)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clears the message parameters
|
||||||
|
void MessageImpl::clear()
|
||||||
|
{
|
||||||
|
m_paramCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// An array containing fixed sizes for various types of parameters
|
||||||
|
static size_t SIZEOF_PARAMTYPE[] =
|
||||||
|
{
|
||||||
|
sizeof(uint8), // Byte
|
||||||
|
sizeof(int8), // Char
|
||||||
|
sizeof(int16), // Short
|
||||||
|
sizeof(uint32), // Long
|
||||||
|
sizeof(uint8), // Angle
|
||||||
|
sizeof(int16), // Coord
|
||||||
|
0, // String
|
||||||
|
sizeof(int16), // Entity
|
||||||
|
};
|
||||||
|
|
||||||
|
// Adds a parameter to the message
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the value of a primitive parameter at the given index
|
||||||
|
template <typename T>
|
||||||
|
void MessageImpl::setParamPrimitive(size_t index, T value)
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || index >= m_paramCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Param_t ¶m = m_params[index];
|
||||||
|
|
||||||
|
void *pbuf = m_buffer.data + param.pos;
|
||||||
|
|
||||||
|
// Set value based on parameter type
|
||||||
|
switch (param.type)
|
||||||
|
{
|
||||||
|
case IMessage::ParamType::Byte:
|
||||||
|
*(uint8 *)pbuf = value;
|
||||||
|
break;
|
||||||
|
case IMessage::ParamType::Char:
|
||||||
|
*(int8 *)pbuf = value;
|
||||||
|
break;
|
||||||
|
case IMessage::ParamType::Short:
|
||||||
|
case IMessage::ParamType::Entity:
|
||||||
|
*(int16 *)pbuf = value;
|
||||||
|
break;
|
||||||
|
case IMessage::ParamType::Long:
|
||||||
|
*(uint16 *)pbuf = value;
|
||||||
|
break;
|
||||||
|
case IMessage::ParamType::Angle:
|
||||||
|
// Convert angle value to byte representation with loss of precision
|
||||||
|
*(uint8 *)pbuf = (int64)(fmod((double)value, 360.0) * 256.0 / 360.0) & 0xff;
|
||||||
|
break;
|
||||||
|
case IMessage::ParamType::Coord:
|
||||||
|
// Convert coordinate value to short integer representation with loss of precision
|
||||||
|
*(int16 *)pbuf = (int16)(int)(value * 8.0);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return; // bad type
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark message as modified
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transforms the buffer after setting a string parameter at the given index
|
||||||
|
void MessageImpl::setTxformBuffer(size_t index, size_t startPos, size_t oldLength, size_t newLength)
|
||||||
|
{
|
||||||
|
// Calculate the difference in length
|
||||||
|
int32_t diffLength = newLength - oldLength;
|
||||||
|
if (diffLength != 0)
|
||||||
|
{
|
||||||
|
// Check if the buffer size limit will be exceeded
|
||||||
|
if (m_buffer.cursize + diffLength > m_buffer.maxsize)
|
||||||
|
{
|
||||||
|
Sys_Error(
|
||||||
|
"%s: Refusing to transform string with %i param of user message of %i bytes, "
|
||||||
|
"user message size limit is %i bytes\n", __func__, index, gMsgBuffer.cursize + diffLength, gMsgBuffer.maxsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Update the position of all subsequent parameters
|
||||||
|
for (size_t i = index + 1; i < m_paramCount; i++)
|
||||||
|
m_params[i].pos += diffLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the integer value of the parameter at the given index
|
||||||
|
int MessageImpl::getParamInt(size_t index) const
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || 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)
|
||||||
|
{
|
||||||
|
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 *(uint16 *)buf;
|
||||||
|
default:
|
||||||
|
return 0; // bad type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the float value of the parameter at the given index
|
||||||
|
float MessageImpl::getParamFloat(size_t index) const
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || 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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the string value of the parameter at the given index
|
||||||
|
const char *MessageImpl::getParamString(size_t index) const
|
||||||
|
{
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || 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 nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the integer value of the parameter at the given index
|
||||||
|
void MessageImpl::setParamInt(size_t index, int value)
|
||||||
|
{
|
||||||
|
setParamPrimitive(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the float value of the parameter at the given index
|
||||||
|
void MessageImpl::setParamFloat(size_t index, float value)
|
||||||
|
{
|
||||||
|
setParamPrimitive(index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the vector value of the parameter at the given index
|
||||||
|
void MessageImpl::setParamVec(size_t index, const float *pos)
|
||||||
|
{
|
||||||
|
if (!pos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || (index + 3) >= m_paramCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Get the parameter position in the buffer
|
||||||
|
const Param_t ¶m = m_params[index];
|
||||||
|
|
||||||
|
int16 *pbuf = (int16 *)m_buffer.data + param.pos;
|
||||||
|
|
||||||
|
// Set each component of the vector parameter
|
||||||
|
*(int16 *)pbuf++ = (int16)(pos[0] * 8.0);
|
||||||
|
*(int16 *)pbuf++ = (int16)(pos[1] * 8.0);
|
||||||
|
*(int16 *)pbuf++ = (int16)(pos[2] * 8.0);
|
||||||
|
|
||||||
|
// Mark message as modified
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the string value of the parameter at the given index
|
||||||
|
void MessageImpl::setParamString(size_t index, const char *value)
|
||||||
|
{
|
||||||
|
if (!value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ensure index is within bounds
|
||||||
|
if (index < 0 || index >= m_paramCount)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Calculate the length of the string
|
||||||
|
size_t length = Q_strlen(value) + 1;
|
||||||
|
const Param_t ¶m = m_params[index];
|
||||||
|
|
||||||
|
// Transform buffer to accommodate the new string length
|
||||||
|
setTxformBuffer(index, param.pos, param.len, length);
|
||||||
|
|
||||||
|
// Copy the string value to the buffer
|
||||||
|
memcpy(m_buffer.data + param.pos, value, length);
|
||||||
|
|
||||||
|
// Mark message as modified
|
||||||
|
m_modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageManagerImpl::MessageManagerImpl()
|
||||||
|
{
|
||||||
|
m_inblock = false;
|
||||||
|
m_inhook = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register hook function for the game message type
|
||||||
|
void MessageManagerImpl::registerHook(int msgType, hookfunc_t handler, int priority)
|
||||||
|
{
|
||||||
|
m_hooks[msgType].registerHook(handler, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unregister hook function for the game message type
|
||||||
|
void MessageManagerImpl::unregisterHook(int msgType, hookfunc_t handler)
|
||||||
|
{
|
||||||
|
m_hooks[msgType].unregisterHook(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the block type for the game message type
|
||||||
|
IMessage::BlockType MessageManagerImpl::getMessageBlock(int msgType) const
|
||||||
|
{
|
||||||
|
return m_blocks[msgType];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the block type for the game message type
|
||||||
|
void MessageManagerImpl::setMessageBlock(int msgType, IMessage::BlockType blockType)
|
||||||
|
{
|
||||||
|
m_blocks[msgType] = blockType;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageManagerImpl::MessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
|
||||||
|
{
|
||||||
|
// Check if the message type is blocked
|
||||||
|
if (m_blocks[msg_type] != 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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Push a new game message onto the stack
|
||||||
|
m_stack.push();
|
||||||
|
|
||||||
|
// Initialize the message
|
||||||
|
MessageImpl &msg = m_stack.back();
|
||||||
|
msg.setActive(msg_dest, msg_type, pOrigin, ed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EXT_FUNC SendUserMessageData(IMessage *msg)
|
||||||
|
{
|
||||||
|
// Set global variables with message data
|
||||||
|
gMsgType = msg->getType();
|
||||||
|
gMsgEntity = msg->getEdict();
|
||||||
|
gMsgDest = static_cast<int>(msg->getDest());
|
||||||
|
|
||||||
|
gMsgOrigin[0] = msg->getOrigin()[0];
|
||||||
|
gMsgOrigin[1] = msg->getOrigin()[1];
|
||||||
|
gMsgOrigin[2] = msg->getOrigin()[2];
|
||||||
|
|
||||||
|
gMsgStarted = TRUE;
|
||||||
|
|
||||||
|
// Copy message data to global buffer and call end of the hookchain
|
||||||
|
msg->setCopybackBuffer(&gMsgBuffer);
|
||||||
|
PF_MessageEnd_I();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageManagerImpl::MessageEnd()
|
||||||
|
{
|
||||||
|
// Check if in block mode
|
||||||
|
if (m_inblock)
|
||||||
|
{
|
||||||
|
m_inblock = false;
|
||||||
|
|
||||||
|
// Unblock the message type if it was blocked once
|
||||||
|
if (m_blocks[gMsgType] == IMessage::BlockType::Once)
|
||||||
|
m_blocks[gMsgType] = IMessage::BlockType::Not;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if not in hook
|
||||||
|
if (!m_inhook)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
gMsgStarted = FALSE;
|
||||||
|
|
||||||
|
// Get the message from the top of the stack
|
||||||
|
MessageImpl &msg = m_stack.back();
|
||||||
|
|
||||||
|
// Set buffer from global buffer and call hookchain
|
||||||
|
msg.setBuffer(&gMsgBuffer);
|
||||||
|
m_hooks[msg.getType()].callChain(SendUserMessageData, &msg);
|
||||||
|
m_inhook = false;
|
||||||
|
|
||||||
|
// Clear the message and pop from the stack
|
||||||
|
msg.clear();
|
||||||
|
m_stack.pop();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageManagerImpl::WriteParam(IMessage::ParamType type, size_t length)
|
||||||
|
{
|
||||||
|
// Check if in block mode
|
||||||
|
if (m_inblock)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if in hook mode
|
||||||
|
if (m_inhook)
|
||||||
|
{
|
||||||
|
// Add parameter to top stack message
|
||||||
|
MessageImpl &msg = m_stack.back();
|
||||||
|
msg.addParam(type, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functions intercept to handle messages
|
||||||
|
//
|
||||||
|
|
||||||
|
void EXT_FUNC PF_MessageBegin_Intercept(int msg_dest, int msg_type, const float *pOrigin, edict_t *ed)
|
||||||
|
{
|
||||||
|
// Set global message type
|
||||||
|
gMsgType = msg_type;
|
||||||
|
|
||||||
|
// Begin message manager
|
||||||
|
if (MessageManager().MessageBegin(msg_dest, msg_type, pOrigin, ed))
|
||||||
|
PF_MessageBegin_I(msg_dest, msg_type, pOrigin, ed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_MessageEnd_Intercept(void)
|
||||||
|
{
|
||||||
|
// End message manager
|
||||||
|
if (MessageManager().MessageEnd())
|
||||||
|
PF_MessageEnd_I(); // Call original message end function if the manager allows it
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteByte_Intercept(int iValue)
|
||||||
|
{
|
||||||
|
// Write byte parameter to the message if the manager allows it
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::Byte))
|
||||||
|
PF_WriteByte_I(iValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteChar_Intercept(int iValue)
|
||||||
|
{
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::Char))
|
||||||
|
PF_WriteChar_I(iValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteShort_Intercept(int iValue)
|
||||||
|
{
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::Short))
|
||||||
|
PF_WriteShort_I(iValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteLong_Intercept(int iValue)
|
||||||
|
{
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::Long))
|
||||||
|
PF_WriteLong_I(iValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteAngle_Intercept(float flValue)
|
||||||
|
{
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::Angle))
|
||||||
|
PF_WriteAngle_I(flValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteCoord_Intercept(float flValue)
|
||||||
|
{
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::Coord))
|
||||||
|
PF_WriteCoord_I(flValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteString_Intercept(const char *sz)
|
||||||
|
{
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::String, sz ? Q_strlen(sz) + 1 : 1))
|
||||||
|
PF_WriteString_I(sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXT_FUNC PF_WriteEntity_Intercept(int iValue)
|
||||||
|
{
|
||||||
|
if (MessageManager().WriteParam(IMessage::ParamType::Entity))
|
||||||
|
PF_WriteEntity_I(iValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialization function to set up function interception
|
||||||
|
void MessageManagerImpl::Init()
|
||||||
|
{
|
||||||
|
// Set function callback to intercept functions
|
||||||
|
g_engfuncsExportedToDlls.pfnMessageBegin = PF_MessageBegin_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteByte = PF_WriteByte_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteChar = PF_WriteChar_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteShort = PF_WriteShort_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteLong = PF_WriteLong_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteAngle = PF_WriteAngle_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteCoord = PF_WriteCoord_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteString = PF_WriteString_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnWriteEntity = PF_WriteEntity_Intercept;
|
||||||
|
g_engfuncsExportedToDlls.pfnMessageEnd = PF_MessageEnd_Intercept;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageManagerImpl &MessageManager()
|
||||||
|
{
|
||||||
|
// Instance of the message manager singleton
|
||||||
|
static MessageManagerImpl instance{};
|
||||||
|
return instance;
|
||||||
|
}
|
277
rehlds/rehlds/rehlds_messagemngr_impl.h
Normal file
277
rehlds/rehlds/rehlds_messagemngr_impl.h
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IMessageManager.h"
|
||||||
|
#include "hookchains.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 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 Returns the destination of the message
|
||||||
|
* @return The destination of the message
|
||||||
|
*/
|
||||||
|
Dest getDest() const { return m_dest; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the type of the message
|
||||||
|
* @return The type of the message
|
||||||
|
*/
|
||||||
|
int getType() const { return m_type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the origin of the message
|
||||||
|
* @return The origin of the message
|
||||||
|
*/
|
||||||
|
const float *getOrigin() const { return m_origin; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the edict associated with the message
|
||||||
|
* @return The edict associated with the message
|
||||||
|
*/
|
||||||
|
edict_t *getEdict() const { return m_edict; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether the message has been modified
|
||||||
|
* @return True if the message has been modified, false otherwise
|
||||||
|
*/
|
||||||
|
bool isModified() const { return m_modified; }
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 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 <typename T>
|
||||||
|
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);
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implementation interface manages hooks and blocking behavior game messages
|
||||||
|
*/
|
||||||
|
class MessageManagerImpl: public IMessageManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
MessageManagerImpl();
|
||||||
|
~MessageManagerImpl() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the major version of the MessageManager
|
||||||
|
* @return The major version
|
||||||
|
*/
|
||||||
|
int getMajorVersion() const { return MESSAGEMNGR_VERSION_MAJOR; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the minor version of the MessageManager
|
||||||
|
* @return The minor version
|
||||||
|
*/
|
||||||
|
int getMinorVersion() const { return MESSAGEMNGR_VERSION_MINOR; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the blocking behavior for the given message type
|
||||||
|
* @param msgType The message type
|
||||||
|
* @return The blocking behavior for the given message type
|
||||||
|
*/
|
||||||
|
IMessage::BlockType getMessageBlock(int msgType) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the blocking behavior for the given message type
|
||||||
|
* @param msgType The message type
|
||||||
|
* @param blockType The blocking behavior to set
|
||||||
|
*/
|
||||||
|
void setMessageBlock(int msgType, IMessage::BlockType blockType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers a hook function for the given message type
|
||||||
|
* @param msgType 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unregisters a hook function for the given message type
|
||||||
|
* @param msgType The message type to unregister the hook for
|
||||||
|
* @param handler The hook function to unregister
|
||||||
|
*/
|
||||||
|
void unregisterHook(int msgType, hookfunc_t handler);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend void PF_MessageBegin_Intercept(int msg_dest, int msg_type, 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);
|
||||||
|
friend void PF_WriteShort_Intercept(int iValue);
|
||||||
|
friend void PF_WriteLong_Intercept(int iValue);
|
||||||
|
friend void PF_WriteAngle_Intercept(float flValue);
|
||||||
|
friend void PF_WriteCoord_Intercept(float flValue);
|
||||||
|
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 MessageEnd();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool WriteParam(IMessage::ParamType type, size_t length = -1);
|
||||||
|
|
||||||
|
bool m_inblock; // Flag indicating whether a message block is currently active
|
||||||
|
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
|
||||||
|
* @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
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void push() { _size++; }
|
||||||
|
void pop () { _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]; }
|
||||||
|
private:
|
||||||
|
size_t _size = 0u;
|
||||||
|
T _data[MAX]{};
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The singleton instance of the MessageManager
|
||||||
|
*/
|
||||||
|
extern MessageManagerImpl &MessageManager();
|
Loading…
x
Reference in New Issue
Block a user