mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Engine: add new netmsg 'SVC_SetClassVar'
Netmessage SVC_SetClassVar allows the server to change class settings securely on the client. This was implemented due to popular demand, and previous approaches using a combination of ClientCommands (Cbuf and NET_StringCmd) were deemed insecure and unreliable.
This commit is contained in:
parent
3b1622af95
commit
b11d7e3c9b
@ -4,6 +4,8 @@ inline bool(*v_SetupGamemode)(const char* pszPlayList);
|
||||
|
||||
/* ==== CONCOMMANDCALLBACK ============================================================================================================================================== */
|
||||
inline void(*v__Cmd_Exec_f)(const CCommand& args);
|
||||
inline bool(*v__setClassVarServer_f)(const CCommand& args);
|
||||
inline bool(*v__setClassVarClient_f)(const CCommand& args);
|
||||
#ifndef DEDICATED
|
||||
inline void(*v__UIScript_Reset_f)();
|
||||
#endif // !DEDICATED
|
||||
@ -41,6 +43,8 @@ class VCallback : public IDetour
|
||||
{
|
||||
LogFunAdr("SetupGamemode", v_SetupGamemode);
|
||||
LogFunAdr("Cmd_Exec_f", v__Cmd_Exec_f);
|
||||
LogFunAdr("SetClassVarServer_f", v__setClassVarServer_f);
|
||||
LogFunAdr("SetClassVarClient_f", v__setClassVarClient_f);
|
||||
#ifndef DEDICATED
|
||||
LogFunAdr("UIScript_Reset_f", v__UIScript_Reset_f);
|
||||
#endif // !DEDICATED
|
||||
@ -49,6 +53,8 @@ class VCallback : public IDetour
|
||||
{
|
||||
g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B D9 48 C7 C0 ?? ?? ?? ??").GetPtr(v_SetupGamemode);
|
||||
g_GameDll.FindPatternSIMD("40 55 53 48 8D AC 24 ?? ?? ?? ?? B8 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 2B E0 48 8B D9").GetPtr(v__Cmd_Exec_f);
|
||||
g_GameDll.FindPatternSIMD("41 56 48 83 EC ?? 8B 05 ?? ?? ?? ?? 4C 8B F1 FF C0").GetPtr(v__setClassVarServer_f);
|
||||
g_GameDll.FindPatternSIMD("4C 8B DC 57 48 81 EC ?? ?? ?? ?? 8B 05").GetPtr(v__setClassVarClient_f);
|
||||
#ifndef DEDICATED
|
||||
g_GameDll.FindPatternSIMD("40 55 41 54 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 45 33 E4 48 8D 0D").GetPtr(v__UIScript_Reset_f);
|
||||
#endif // !DEDICATED
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "tier1/cvar.h"
|
||||
#include "engine/net.h"
|
||||
#include "common/netmessages.h"
|
||||
#include "common/callback.h"
|
||||
#include "game/shared/usermessages.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
@ -64,6 +65,37 @@ bool SVC_UserMessage::ProcessImpl()
|
||||
return SVC_UserMessage_Process(this); // Need to return original.
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Net message to change class settings vars on the client
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool SVC_SetClassVar::ReadFromBuffer(bf_read* buffer)
|
||||
{
|
||||
const bool set = buffer->ReadString(m_szSetting, sizeof(m_szSetting));
|
||||
const bool var = buffer->ReadString(m_szVariable, sizeof(m_szVariable));
|
||||
|
||||
return set && var;
|
||||
}
|
||||
bool SVC_SetClassVar::WriteToBuffer(bf_write* buffer)
|
||||
{
|
||||
const bool set = buffer->WriteString(m_szSetting);
|
||||
const bool var = buffer->WriteString(m_szVariable);
|
||||
|
||||
return set && var;
|
||||
}
|
||||
bool SVC_SetClassVar::Process(void)
|
||||
{
|
||||
const char* pArgs[3] = {
|
||||
"_setClassVarClient",
|
||||
m_szSetting,
|
||||
m_szVariable
|
||||
};
|
||||
|
||||
CCommand command((int)V_ARRAYSIZE(pArgs), pArgs, cmd_source_t::kCommandSrcCode);
|
||||
v__setClassVarClient_f(command);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Below functions are hooked as playlist overrides can be abused from the client.
|
||||
// The client could basically manage the server's playlists. Only allow read/write
|
||||
@ -122,7 +154,7 @@ bool Base_CmdKeyValues::WriteToBufferImpl(Base_CmdKeyValues* thisptr, bf_write*
|
||||
// determine whether or not the message should be copied into the replay buffer,
|
||||
// regardless of the 'CNetMessage::m_Group' type.
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
bool ShouldReplayMessage(const CNetMessage* msg)
|
||||
bool ShouldReplayMessage(const CNetMessage* msg) // todo(amos): rename to 'CanReplayMessage'
|
||||
{
|
||||
switch (msg->GetType())
|
||||
{
|
||||
|
@ -162,6 +162,15 @@ enum NetMessageType
|
||||
clc_AntiCheat = 63,
|
||||
clc_AntiCheatChallenge = 64,
|
||||
clc_GamepadMsg = 65,
|
||||
|
||||
// NOTE: if you make new netmessages, the order should be as follows:
|
||||
// - NET (messages shared between server & client).
|
||||
// - SVC (messages originating from the server).
|
||||
// - CLC (messages originating from the client.
|
||||
// Reorder message indices to retain consistency here.
|
||||
// --------------------------------------------------------------------
|
||||
// From here on, SDK netmessages are enumerated.
|
||||
svc_SetClassVar = 66,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -176,10 +185,16 @@ enum NetMessageGroup
|
||||
class CNetMessage : public INetMessage
|
||||
{
|
||||
public:
|
||||
virtual void SetNetChannel(CNetChan* netchan) { m_NetChannel = netchan; }
|
||||
virtual void SetReliable(bool state) { m_bReliable = state; }
|
||||
virtual bool IsReliable(void) const { return m_bReliable; }
|
||||
virtual int GetGroup(void) const { return m_nGroup; }
|
||||
virtual CNetChan* GetNetChannel(void) const { return m_NetChannel; }
|
||||
|
||||
int m_nGroup;
|
||||
bool m_bReliable;
|
||||
CNetChan* m_NetChannel;
|
||||
INetMessageHandler* m_pMessageHandler;
|
||||
INetChannelHandler* m_pMessageHandler;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -445,6 +460,43 @@ private:
|
||||
bf_write m_DataOut;
|
||||
};
|
||||
|
||||
class SVC_SetClassVar : public CNetMessage
|
||||
{
|
||||
public:
|
||||
SVC_SetClassVar() = default;
|
||||
SVC_SetClassVar(const char* setting, const char* var)
|
||||
{
|
||||
V_strncpy(m_szSetting, setting, sizeof(m_szSetting));
|
||||
V_strncpy(m_szVariable, var, sizeof(m_szVariable));
|
||||
|
||||
m_szSetting[sizeof(m_szSetting) - 1] = '\0';
|
||||
m_szVariable[sizeof(m_szVariable) - 1] = '\0';
|
||||
|
||||
m_nGroup = 2; // must be set to 2 to avoid being copied into replay buffer
|
||||
}
|
||||
|
||||
virtual bool ReadFromBuffer(bf_read* buffer);
|
||||
virtual bool WriteToBuffer(bf_write* buffer);
|
||||
|
||||
virtual bool Process(void);
|
||||
|
||||
virtual int GetType(void) const { return svc_SetClassVar; };
|
||||
virtual const char* GetName(void) const { return "svc_SetClassVar"; };
|
||||
|
||||
virtual const char* ToString(void) const
|
||||
{
|
||||
static char szBuf[4096];
|
||||
V_snprintf(szBuf, sizeof(szBuf), "%s: setting \"%s\", variable \"%s\"", this->GetName(), m_szSetting, m_szVariable);
|
||||
|
||||
return szBuf;
|
||||
};
|
||||
|
||||
virtual size_t GetSize(void) const { return sizeof(SVC_SetClassVar); }
|
||||
|
||||
char m_szSetting[128];
|
||||
char m_szVariable[128];
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
// Client messages:
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -509,6 +509,7 @@ void CClientState::Reconnect()
|
||||
//---------------------------------------------------------------------------------
|
||||
void CClientState::RegisterNetMsgs(CNetChan* chan)
|
||||
{
|
||||
REGISTER_SVC_MSG(SetClassSettingsVar);
|
||||
}
|
||||
|
||||
void VClientState::Detour(const bool bAttach) const
|
||||
|
Loading…
x
Reference in New Issue
Block a user