Add Left 4 Dead support

Spectator client connections aren't tested yet - don't have the game
installed.
This commit is contained in:
Peace-Maker 2016-12-04 21:05:06 -07:00
parent cab2bc24ac
commit e622428037
6 changed files with 200 additions and 2 deletions

View File

@ -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]

View File

@ -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<CLC_SplitPlayerConnect *> &, 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<CNetMessagePB<16, CCLCMsg_SplitPlayerConnect, 0, true> *, CUtlMemory<CNetMessagePB<16, CCLCMsg_SplitPlayerConnect, 0, true> *, 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<NetMsg_SplitPlayerConnect *> &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<CLC_SplitPlayerConnect *> &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

View File

@ -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<NetMsg_SplitPlayerConnect *> &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<CLC_SplitPlayerConnect *> &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);

View File

@ -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)

View File

@ -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;
};

View File

@ -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"
}
}
}
}