From e622428037325d45524cd6e3f6d0325a1d06ed87 Mon Sep 17 00:00:00 2001 From: Peace-Maker Date: Sun, 4 Dec 2016 21:05:06 -0700 Subject: [PATCH] Add Left 4 Dead support Spectator client connections aren't tested yet - don't have the game installed. --- AMBuilder | 2 +- forwards.cpp | 14 +++- forwards.h | 3 + hltvserverwrapper.cpp | 10 +++ ihltvdemorecorder.h | 3 + sourcetvmanager.games.txt | 170 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 200 insertions(+), 2 deletions(-) diff --git a/AMBuilder b/AMBuilder index 37120f6..be3ff3a 100644 --- a/AMBuilder +++ b/AMBuilder @@ -31,7 +31,7 @@ else: project.sources += sourceFiles -for sdk_name in ['css', 'tf2', 'dods', 'hl2dm', 'csgo']: +for sdk_name in ['css', 'tf2', 'dods', 'hl2dm', 'csgo', 'l4d']: if sdk_name not in Extension.sdks: continue sdk = Extension.sdks[sdk_name] diff --git a/forwards.cpp b/forwards.cpp index 14ebefb..67d5aa8 100644 --- a/forwards.cpp +++ b/forwards.cpp @@ -54,6 +54,14 @@ SH_DECL_HOOK1_void(IClient, Disconnect, SH_NOATTRIB, 0, const char *); SH_DECL_MANUALHOOK1_void(CBaseClient_Disconnect, 0, 0, 0, const char *); #endif // !WIN32 +#elif SOURCE_ENGINE == SE_LEFT4DEAD +SH_DECL_MANUALHOOK10(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, const netadr_t &, int, int, int, const char *, const char *, const char *, int, CUtlVector &, bool); +SH_DECL_MANUALHOOK1_void_vafmt(CHLTVServer_RejectConnection, 0, 0, 0, const netadr_t &); +SH_DECL_HOOK0_void_vafmt(IClient, Disconnect, SH_NOATTRIB, 0); +#ifndef WIN32 +SH_DECL_MANUALHOOK0_void_vafmt(CBaseClient_Disconnect, 0, 0, 0); +#endif // !WIN32 + #else SH_DECL_MANUALHOOK9(CHLTVServer_ConnectClient, 0, 0, 0, IClient *, netadr_t &, int, int, int, int, const char *, const char *, const char *, int); SH_DECL_MANUALHOOK3_void(CHLTVServer_RejectConnection, 0, 0, 0, const netadr_t &, int, const char *); @@ -288,6 +296,8 @@ char passwordBuffer[255]; #if SOURCE_ENGINE == SE_CSGO // CHLTVServer::ConnectClient(ns_address const&, int, int, int, char const*, char const*, char const*, int, CUtlVector *, CUtlMemory *, int>> &, bool, CrossPlayPlatform_t, unsigned char const*, int) IClient *CForwardManager::OnSpectatorConnect(const netadr_t & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown) +#elif SOURCE_ENGINE == SE_LEFT4DEAD +IClient *CForwardManager::OnSpectatorConnect(const netadr_t & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector &pSplitPlayerConnectVector, bool bUnknown) #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 @@ -324,7 +334,7 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol, { if (m_bHasRejectConnectionOffset) { -#if SOURCE_ENGINE == SE_CSGO +#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_LEFT4DEAD SH_MCALL(server, CHLTVServer_RejectConnection)(address, rejectReason); #else SH_MCALL(server, CHLTVServer_RejectConnection)(address, iClientChallenge, rejectReason); @@ -336,6 +346,8 @@ IClient *CForwardManager::OnSpectatorConnect(netadr_t & address, int nProtocol, // Call the original function. #if SOURCE_ENGINE == SE_CSGO IClient *client = SH_MCALL(server, CHLTVServer_ConnectClient)(address, nProtocol, iChallenge, nAuthProtocol, pchName, passwordBuffer, pCookie, cbCookie, pSplitPlayerConnectVector, bUnknown, platform, pUnknown, iUnknown); +#elif SOURCE_ENGINE == SE_LEFT4DEAD + IClient *client = SH_MCALL(server, CHLTVServer_ConnectClient)(address, nProtocol, iChallenge, nAuthProtocol, pchName, passwordBuffer, pCookie, cbCookie, pSplitPlayerConnectVector, bUnknown); #else IClient *client = SH_MCALL(server, CHLTVServer_ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, passwordBuffer, pCookie, cbCookie); #endif diff --git a/forwards.h b/forwards.h index 267a14d..ddf0ec5 100644 --- a/forwards.h +++ b/forwards.h @@ -99,6 +99,9 @@ private: #if SOURCE_ENGINE == SE_CSGO void OnStopRecording(CGameInfo const *info); IClient *OnSpectatorConnect(const netadr_t & address, int nProtocol, int iChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie, CUtlVector &pSplitPlayerConnectVector, bool bUnknown, CrossPlayPlatform_t platform, const unsigned char *pUnknown, int iUnknown); +#elif SOURCE_ENGINE == SE_LEFT4DEAD + void OnStopRecording(); + IClient *OnSpectatorConnect(const netadr_t & address, int nProtocol, int iChallenge, int iClientChallenge, const char * pchName, const char * pchPassword, const char * pCookie, int, CUtlVector &pSplitPlayerConnectVector, bool bUnknown); #else void OnStopRecording(); IClient *OnSpectatorConnect(netadr_t &address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie); diff --git a/hltvserverwrapper.cpp b/hltvserverwrapper.cpp index 5f0b792..1b51571 100644 --- a/hltvserverwrapper.cpp +++ b/hltvserverwrapper.cpp @@ -254,7 +254,12 @@ void HLTVServerWrapper::OnCGameClient_ClientPrintf_Post(const char* buf) IClient *pClient = (IClient *)((intptr_t)pGameClient + 4); HandleClientPrintf(pClient, buf); +#if SOURCE_ENGINE == SE_LEFT4DEAD + // Left4Dead doesn't check the netchan before using it + RETURN_META(MRES_SUPERCEDE); +#else RETURN_META(MRES_IGNORED); +#endif } void HLTVServerWrapper::OnIClient_ClientPrintf_Post(const char* buf) @@ -262,7 +267,12 @@ void HLTVServerWrapper::OnIClient_ClientPrintf_Post(const char* buf) IClient *pClient = META_IFACEPTR(IClient); HandleClientPrintf(pClient, buf); +#if SOURCE_ENGINE == SE_LEFT4DEAD + // Left4Dead doesn't check the netchan before using it + RETURN_META(MRES_SUPERCEDE); +#else RETURN_META(MRES_IGNORED); +#endif } void HLTVServerWrapper::HandleClientPrintf(IClient *pClient, const char* buf) diff --git a/ihltvdemorecorder.h b/ihltvdemorecorder.h index 8b95a4a..04f2b50 100644 --- a/ihltvdemorecorder.h +++ b/ihltvdemorecorder.h @@ -26,6 +26,9 @@ public: virtual void RecordPacket(void) = 0; virtual void RecordServerClasses(ServerClass *pClasses) = 0; virtual void RecordStringTables(void) = 0; +#if SOURCE_ENGINE == SE_LEFT4DEAD + virtual void RecordCustomData(int, void const *, unsigned int) = 0; +#endif virtual void ResetDemoInterpolation(void) = 0; }; diff --git a/sourcetvmanager.games.txt b/sourcetvmanager.games.txt index 90def65..92a9f44 100644 --- a/sourcetvmanager.games.txt +++ b/sourcetvmanager.games.txt @@ -336,4 +336,174 @@ } } } + + "left4dead" + { + "Addresses" + { + "host_client" + { + "windows" + { + "signature" "host_client" + "read" "43" + } + "linux" + { + "signature" "host_client" + } + } + + "CHLTVServer::m_DemoRecorder" + { + "windows" + { + "signature" "CHLTVServer::Shutdown" + "read" "5" + } + "linux" + { + "signature" "CHLTVServer::Shutdown" + "read" "22" + } + } + } + "Offsets" + { + "CNetChan::SendNetMsg" + { + "windows" "41" + "linux" "42" + } + + "CBaseClient::m_NetChannel" + { + "windows" "224" + "linux" "228" + } + + "CGameClient::ClientPrintf" + { + "linux" "26" + } + + "CBaseServer::BroadcastPrintf" + { + "windows" "34" + "linux" "35" + } + + "CHLTVServer::ConnectClient" + { + "windows" "48" + "linux" "49" + } + + "CHLTVServer::RejectConnection" + { + "windows" "46" + "linux" "47" + } + + "CHLTVServer::GetChallengeType" + { + "windows" "52" + "linux" "53" + } + + "CBaseClient::ActivatePlayer" + { + "windows" "15" + "linux" "61" + } + + "CBaseClient::FireGameEvent" + { + "windows" "1" + "linux" "2" + } + + "CBaseClient::Disconnect" + { + "linux" "15" + } + + "CHLTVServer::Shutdown" + { + "windows" "40" + "linux" "41" + } + + "CHLTVDirector::m_iPVSEntity" + { + "windows" "16" + "linux" "16" + } + + "CHLTVDirector::m_vPVSOrigin" + { + "windows" "20" + "linux" "20" + } + + "CHLTVDirector::m_nNextShotTick" + { + "windows" "40" + "linux" "40" + } + "CHLTVDemoRecorder_BaseOffset" + { + "windows" "0" + "linux" "4" + } + } + "Signatures" + { + "host_client" + { + "library" "engine" + "linux" "@host_client" + // ping(CCommand const&) "Client ping times:\n" + "windows" "\x55\x8B\xEC\x83\xE4\xC0\x83\xEC\x34\x83\x3D\x2A\x2A\x2A\x2A\x01" + } + + "CHLTVServer::BroadcastEventLocal" + { + "library" "engine" + "linux" "@_ZN11CHLTVServer19BroadcastEventLocalEP10IGameEventb" + // "SourceTV broadcast local event: %s\n" + "windows" "\x81\xEC\x50\x04\x00\x00\x53\x55\x33\xDB" + } + + "CHLTVServer::BroadcastLocalChat" + { + "library" "engine" + "linux" "@_ZN11CHLTVServer18BroadcastLocalChatEPKcS1_" + // "hltv_chat" + "windows" "\x81\xEC\x54\x04\x00\x00\x53\x55" + } + + "CHLTVServer::Shutdown" + { + "library" "engine" + "linux" "@_ZN11CHLTVServer8ShutdownEv" + // "SourceTV stop." + "windows" "\x56\x8B\xF1\x8B\x86\x2A\x2A\x2A\x2A\x8B\x50\x2A\x8D\x8E\x2A\x2A\x2A\x2A\xFF\xD2\x8B\x86\x2A\x2A\x2A\x2A\x8B\x50\x2A\x8D\x8E" + } + + // StartRecording and StopRecording are virtual, but get called directly in the linux binary.. + // Need to add a detour. + "CHLTVDemoRecorder::StartRecording" + { + "library" "engine" + "linux" "@_ZN17CHLTVDemoRecorder14StartRecordingEPKcb" + } + + "CHLTVDemoRecorder::StopRecording" + { + "library" "engine" + "linux" "@_ZN17CHLTVDemoRecorder13StopRecordingEv" + } + } + } } \ No newline at end of file