mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Engine: rework class var command and netmsg design
New command '_setClassVarClient' only sets the class var on the client, similar to how '_setClassVarServer' only sets it on the server. Command 'set' still has its old behavior, setting it on the server and client. The netmsg SVC_SetClassVar now only runs the _setClassVarClient handler, and if the netmsg was successfully sent, the code runs the _setClassVarServer handler directly instead of relying on the client to NET_StringMsg it in. This is a lot more reliable, secure and performant than the previous approach and drops the requirement of setting sv_cheats to function.
This commit is contained in:
parent
432cb923cc
commit
d312597c91
@ -23,6 +23,7 @@
|
||||
#endif // !DEDICATED
|
||||
#include "engine/client/client.h"
|
||||
#include "engine/net.h"
|
||||
#include "engine/cmd.h"
|
||||
#include "engine/host_cmd.h"
|
||||
#include "engine/host_state.h"
|
||||
#include "engine/enginetrace.h"
|
||||
@ -256,6 +257,33 @@ void LanguageChanged_f(IConVar* pConVar, const char* pOldString, float flOldValu
|
||||
}
|
||||
|
||||
#ifndef DEDICATED
|
||||
void setClassVarClient_f(const CCommand& args)
|
||||
{
|
||||
v__setClassVarClient_f(args);
|
||||
}
|
||||
|
||||
static ConCommand _setClassVarClient("_setClassVarClient", setClassVarClient_f, "Set a class var on the client", FCVAR_DEVELOPMENTONLY|FCVAR_CLIENTDLL|FCVAR_CHEAT|FCVAR_SERVER_CAN_EXECUTE);
|
||||
|
||||
/*
|
||||
=====================
|
||||
Set_f
|
||||
|
||||
Set a class var on the server & client.
|
||||
=====================
|
||||
*/
|
||||
void Set_f(const CCommand& args)
|
||||
{
|
||||
v__setClassVarClient_f(args);
|
||||
|
||||
const char* key = args.Arg(1);
|
||||
const char* val = args.Arg(2);
|
||||
|
||||
char buf[256];
|
||||
V_snprintf(buf, sizeof(buf), "_setClassVarServer %s \"%s\"\n", key, val);
|
||||
|
||||
Cbuf_AddText(ECommandTarget_t::CBUF_FIRST_PLAYER, buf, cmd_source_t::kCommandSrcInvalid);
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
Mat_CrossHair_f
|
||||
@ -583,7 +611,6 @@ void UIScript_Reset_f()
|
||||
}
|
||||
#endif // !DEDICATED
|
||||
|
||||
|
||||
void VCallback::Detour(const bool bAttach) const
|
||||
{
|
||||
DetourSetup(&v__Cmd_Exec_f, &Cmd_Exec_f, bAttach);
|
||||
|
@ -4,12 +4,16 @@ 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);
|
||||
inline void(*v__setClassVarServer_f)(const CCommand& args);
|
||||
inline void(*v__setClassVarClient_f)(const CCommand& args);
|
||||
#ifndef DEDICATED
|
||||
inline void(*v__UIScript_Reset_f)();
|
||||
#endif // !DEDICATED
|
||||
|
||||
#ifndef CLIENT_DLL
|
||||
inline int* g_nCommandClientIndex = nullptr;
|
||||
#endif // !CLIENT_DLL
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void MP_GameMode_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValue, ChangeUserData_t pUserData);
|
||||
#ifndef CLIENT_DLL
|
||||
@ -25,6 +29,7 @@ void GFX_NVN_Changed_f(IConVar* pConVar, const char* pOldString, float flOldValu
|
||||
#endif // !DEDICATED
|
||||
void LanguageChanged_f(IConVar* pConVar, const char* pOldString, float flOldValue, ChangeUserData_t pUserData);
|
||||
#ifndef DEDICATED
|
||||
void Set_f(const CCommand& args);
|
||||
void Mat_CrossHair_f(const CCommand& args);
|
||||
void Line_f(const CCommand& args);
|
||||
void Sphere_f(const CCommand& args);
|
||||
@ -36,6 +41,7 @@ void CVHelp_f(const CCommand& args);
|
||||
void CVList_f(const CCommand& args);
|
||||
void CVDiff_f(const CCommand& args);
|
||||
void CVFlag_f(const CCommand& args);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
class VCallback : public IDetour
|
||||
{
|
||||
@ -59,7 +65,12 @@ class VCallback : public IDetour
|
||||
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
|
||||
}
|
||||
virtual void GetVar(void) const { }
|
||||
virtual void GetVar(void) const
|
||||
{
|
||||
#ifndef CLIENT_DLL
|
||||
CMemory(v__setClassVarServer_f).FindPatternSelf("8B 05").ResolveRelativeAddressSelf(2, 6).GetPtr(g_nCommandClientIndex);
|
||||
#endif // !CLIENT_DLL
|
||||
}
|
||||
virtual void GetCon(void) const { }
|
||||
virtual void Detour(const bool bAttach) const;
|
||||
};
|
||||
|
@ -385,6 +385,7 @@ void ConCommand_InitShipped(void)
|
||||
//-------------------------------------------------------------------------
|
||||
// CLIENT DLL |
|
||||
ConCommand* give = g_pCVar->FindCommand("give");
|
||||
ConCommand* set = g_pCVar->FindCommand("set");
|
||||
#endif // !DEDICATED
|
||||
|
||||
help->m_fnCommandCallback = CVHelp_f;
|
||||
@ -403,6 +404,7 @@ void ConCommand_InitShipped(void)
|
||||
#ifndef DEDICATED
|
||||
mat_crosshair->m_fnCommandCallback = Mat_CrossHair_f;
|
||||
give->m_fnCompletionCallback = Game_Give_f_CompletionFunc;
|
||||
set->m_fnCommandCallback = Set_f;
|
||||
#endif // !DEDICATED
|
||||
|
||||
/// ------------------------------------------------------ [ FLAG REMOVAL ]
|
||||
@ -474,6 +476,7 @@ void ConCommand_PurgeShipped(void)
|
||||
"getpos_bind",
|
||||
"connect",
|
||||
"silent_connect",
|
||||
"set",
|
||||
"ping",
|
||||
"gameui_activate",
|
||||
"gameui_hide",
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <engine/host_state.h>
|
||||
#include <networksystem/hostmanager.h>
|
||||
#include "player.h"
|
||||
#include <common/callback.h>
|
||||
|
||||
/*
|
||||
=====================
|
||||
@ -279,16 +280,8 @@ namespace VScriptCode
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: sets a class var on the server and each client
|
||||
// TODO: currently, this relies on the client running _secClassVarServer
|
||||
// for its player class vars to be adjusted on the server as well. Not really
|
||||
// exploitable on the client as omitting this will prevent the server from
|
||||
// setting it in their player instance effectively screwing up the prediction,
|
||||
// but it might be nice to run it from the server and propagate all changes to
|
||||
// each client individually from an architectural point of view.
|
||||
// Furthermore (only for SetClassVarSynced, not the individual one from
|
||||
// PlayerStruct) it might also be good to research potential ways to track
|
||||
// class var changes and sync them back to clients connecting after this has
|
||||
// been called.
|
||||
// TODO: it might also be good to research potential ways to track class var
|
||||
// changes and sync them back to clients connecting after this has been called.
|
||||
//-----------------------------------------------------------------------------
|
||||
SQRESULT SetClassVarSynced(HSQUIRRELVM v)
|
||||
{
|
||||
@ -310,8 +303,17 @@ namespace VScriptCode
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
|
||||
}
|
||||
|
||||
const char* pArgs[3] = {
|
||||
"_setClassVarServer",
|
||||
key,
|
||||
val
|
||||
};
|
||||
|
||||
SVC_SetClassVar msg(key, val);
|
||||
const CCommand cmd((int)V_ARRAYSIZE(pArgs), pArgs, cmd_source_t::kCommandSrcCode);
|
||||
|
||||
bool failure = false;
|
||||
const int oldIdx = *g_nCommandClientIndex;
|
||||
|
||||
for (int i = 0; i < gpGlobals->maxClients; i++)
|
||||
{
|
||||
@ -321,10 +323,17 @@ namespace VScriptCode
|
||||
if (client->GetSignonState() != SIGNONSTATE::SIGNONSTATE_FULL)
|
||||
continue;
|
||||
|
||||
if (!client->SendNetMsgEx(&msg, false, true, false))
|
||||
if (client->SendNetMsgEx(&msg, false, true, false))
|
||||
{
|
||||
*g_nCommandClientIndex = client->GetUserID();
|
||||
v__setClassVarServer_f(cmd);
|
||||
}
|
||||
else // Not all clients have their class var set.
|
||||
failure = true;
|
||||
}
|
||||
|
||||
*g_nCommandClientIndex = oldIdx;
|
||||
|
||||
sq_pushbool(v, !failure);
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
}
|
||||
@ -364,8 +373,25 @@ namespace VScriptCode
|
||||
SVC_SetClassVar msg(key, val);
|
||||
|
||||
const bool success = client->SendNetMsgEx(&msg, false, true, false);
|
||||
sq_pushbool(v, success);
|
||||
|
||||
if (success)
|
||||
{
|
||||
const char* pArgs[3] = {
|
||||
"_setClassVarServer",
|
||||
key,
|
||||
val
|
||||
};
|
||||
|
||||
const CCommand cmd((int)V_ARRAYSIZE(pArgs), pArgs, cmd_source_t::kCommandSrcCode);
|
||||
const int oldIdx = *g_nCommandClientIndex;
|
||||
|
||||
*g_nCommandClientIndex = client->GetUserID();
|
||||
v__setClassVarServer_f(cmd);
|
||||
|
||||
*g_nCommandClientIndex = oldIdx;
|
||||
}
|
||||
|
||||
sq_pushbool(v, success);
|
||||
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user