Extract player name in ConnectClient hook in CS:GO
CS:GO doesn't send the client name in plain text, but wraps it in some protobuf construct. Parse that list of client convars for the player name and use it in the SourceTV_OnSpectatorPreConnect forward
This commit is contained in:
parent
4bb751afaf
commit
10f7fa56a1
35
AMBuilder
35
AMBuilder
@ -7,7 +7,8 @@ projectName = 'sourcetvmanager'
|
||||
sourceFiles = [
|
||||
'extension.cpp',
|
||||
'natives.cpp',
|
||||
'forwards.cpp'
|
||||
'forwards.cpp',
|
||||
'hltvdirectorwrapper.cpp'
|
||||
]
|
||||
|
||||
###############
|
||||
@ -31,5 +32,37 @@ for sdk_name in ['css', 'csgo']:
|
||||
sdk = Extension.sdks[sdk_name]
|
||||
|
||||
binary = Extension.HL2Config(project, projectName + '.ext.' + sdk.ext, sdk)
|
||||
compiler = binary.compiler
|
||||
|
||||
if sdk.name == 'csgo':
|
||||
compiler.cxxincludes += [
|
||||
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
|
||||
]
|
||||
|
||||
if builder.target_platform == 'linux':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'linux32', 'release', 'libprotobuf.a')
|
||||
elif builder.target_platform == 'mac':
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
|
||||
elif builder.target_platform == 'windows':
|
||||
msvc_ver = compiler.version
|
||||
vs_year = ''
|
||||
if msvc_ver == 1800:
|
||||
vs_year = '2013'
|
||||
else:
|
||||
raise Exception('Cannot find libprotobuf for MSVC version "' + str(compiler.version) + '"')
|
||||
|
||||
if 'DEBUG' in compiler.defines:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'debug', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
else:
|
||||
lib_path = os.path.join(sdk.path, 'lib', 'win32', 'release', 'vs' + vs_year, 'libprotobuf.lib')
|
||||
compiler.linkflags.insert(0, binary.Dep(lib_path))
|
||||
|
||||
binary.sources += [
|
||||
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
|
||||
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
|
||||
]
|
||||
|
||||
Extension.extensions = builder.Add(project)
|
||||
|
39
forwards.cpp
39
forwards.cpp
@ -42,7 +42,7 @@ SH_DECL_HOOK0_void(IDemoRecorder, StopRecording, SH_NOATTRIB, 0)
|
||||
#endif
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
SH_DECL_MANUALHOOK13(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, netadr_s &, int, int, int, const char *, const char *, const char *, int, CUtlVector<INetMessage *> &, bool, CrossPlayPlatform_t, const unsigned char *, int);
|
||||
SH_DECL_MANUALHOOK13(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, netadr_s &, int, int, int, const char *, const char *, const char *, int, CUtlVector<NetMsg_SplitPlayerConnect *> &, bool, CrossPlayPlatform_t, const unsigned char *, int);
|
||||
SH_DECL_HOOK1_void(IClient, Disconnect, SH_NOATTRIB, 0, const char *);
|
||||
#else
|
||||
SH_DECL_MANUALHOOK9(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, netadr_t &, int, int, int, int, const char *, const char *, const char *, int);
|
||||
@ -188,6 +188,31 @@ static void RejectConnection(IServer *server, netadr_t &address, char *pchReason
|
||||
pRejectConnection->Execute(vstk, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static bool ExtractPlayerName(CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, char *name, int maxlen)
|
||||
{
|
||||
for (int i = 0; i < pSplitPlayerConnectVector.Count(); i++)
|
||||
{
|
||||
NetMsg_SplitPlayerConnect *split = pSplitPlayerConnectVector[i];
|
||||
if (!split->has_convars())
|
||||
continue;
|
||||
|
||||
const CMsg_CVars cvars = split->convars();
|
||||
for (int c = 0; c < cvars.cvars_size(); c++)
|
||||
{
|
||||
const CMsg_CVars_CVar cvar = cvars.cvars(c);
|
||||
if (!cvar.has_name() || !cvar.has_value())
|
||||
continue;
|
||||
|
||||
if (!strcmp(cvar.name().c_str(), "name"))
|
||||
{
|
||||
strncpy(name, cvar.value().c_str(), maxlen);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
static void RejectConnection(IServer *server, netadr_t &address, int iClientChallenge, char *pchReason)
|
||||
{
|
||||
@ -239,7 +264,7 @@ static void RejectConnection(IServer *server, netadr_t &address, int iClientChal
|
||||
char passwordBuffer[255];
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
// CHLTVServer::ConnectClient(ns_address const&, int, int, int, char const*, char const*, char const*, int, CUtlVector<CNetMessagePB<16, CCLCMsg_SplitPlayerConnect, 0, true> *, CUtlMemory<CNetMessagePB<16, CCLCMsg_SplitPlayerConnect, 0, true> *, int>> &, bool, CrossPlayPlatform_t, unsigned char const*, int)
|
||||
IClient *CForwardManager::OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<INetMessage *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown)
|
||||
IClient *CForwardManager::OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown)
|
||||
#else
|
||||
IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie)
|
||||
#endif
|
||||
@ -247,6 +272,14 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol,
|
||||
if (!pCookie || cbCookie < sizeof(uint64))
|
||||
RETURN_META_VALUE(MRES_IGNORED, nullptr);
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
// CS:GO doesn't send the player name in pchName, but only in the client info convars.
|
||||
// Try to extract the name from the protobuf msg.
|
||||
char playerName[MAX_PLAYER_NAME_LENGTH];
|
||||
if (ExtractPlayerName(pSplitPlayerConnectVector, playerName, sizeof(playerName)))
|
||||
pchName = playerName;
|
||||
#endif
|
||||
|
||||
char ipString[16];
|
||||
V_snprintf(ipString, sizeof(ipString), "%u.%u.%u.%u", address.ip[0], address.ip[1], address.ip[2], address.ip[3]);
|
||||
V_strncpy(passwordBuffer, pchPassword, 255);
|
||||
@ -283,7 +316,7 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol,
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
IClient *CForwardManager::OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<INetMessage *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char * pUnknown, int iUnknown)
|
||||
IClient *CForwardManager::OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char * pUnknown, int iUnknown)
|
||||
#else
|
||||
IClient *CForwardManager::OnSpectatorConnect_Post(netadr_t & address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie)
|
||||
#endif
|
||||
|
18
forwards.h
18
forwards.h
@ -35,6 +35,20 @@
|
||||
#include "extension.h"
|
||||
#include "netadr.h"
|
||||
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
#include "netmessages.pb.h"
|
||||
|
||||
template <int Type, class NetMessage, int Group, bool reliable>
|
||||
class CNetMessagePB : public INetMessage, public NetMessage {
|
||||
public:
|
||||
~CNetMessagePB() {}
|
||||
|
||||
};
|
||||
|
||||
typedef CNetMessagePB<16, CCLCMsg_SplitPlayerConnect, 0, true> NetMsg_SplitPlayerConnect;
|
||||
|
||||
#endif
|
||||
|
||||
class CGameInfo;
|
||||
|
||||
class CForwardManager
|
||||
@ -57,8 +71,8 @@ private:
|
||||
void OnStartRecording_Post(const char *filename, bool bContinuously);
|
||||
#if SOURCE_ENGINE == SE_CSGO
|
||||
void OnStopRecording_Post(CGameInfo const *info);
|
||||
IClient *OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<INetMessage *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
|
||||
IClient *OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<INetMessage *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
|
||||
IClient *OnSpectatorConnect(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
|
||||
IClient *OnSpectatorConnect_Post(netadr_s & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector<NetMsg_SplitPlayerConnect *> &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown);
|
||||
#else
|
||||
void OnStopRecording_Post();
|
||||
IClient *OnSpectatorConnect(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie);
|
||||
|
@ -303,7 +303,7 @@ native SourceTV_KickClient(client, const String:sReason[]);
|
||||
* This is called before any other validation has happened.
|
||||
* Similar to the OnClientPreConnectEx forward in the Connect extension by asherkin.
|
||||
*
|
||||
* @param name The player name (always empty in CS:GO).
|
||||
* @param name The player name.
|
||||
* @param password The password the client used to connect. Can be overwritten.
|
||||
* @param ip The ip address of the client.
|
||||
* @param rejectReason Buffer to write the reject reason to, if you want to reject the client from connecting.
|
||||
|
Loading…
Reference in New Issue
Block a user