Fix printing to demo console on CS:S linux
This is getting rediculous. Our own native calls IClient::ClientPrintf to print stuff to the demo console. The engine's Host_Client_Printf uses the CGameClient vtable's ClientPrintf. To catch the output of the "status" command, we have to hook both vtables on linux... Windows casts to IClient in Host_Client_Printf, so no need to do that there.
This commit is contained in:
parent
7b8f2a73f8
commit
9ae2431375
@ -11,6 +11,13 @@ SH_DECL_MANUALHOOK0_void(CHLTVServer_Shutdown, 0, 0, 0);
|
||||
|
||||
// Stuff to print to demo console
|
||||
SH_DECL_HOOK0_void_vafmt(IClient, ClientPrintf, SH_NOATTRIB, 0);
|
||||
|
||||
// Linux has the ClientPrintf method in both CGameClient and IClient's vtables
|
||||
// and uses both.. Need to hook both....... i guess?
|
||||
#ifndef WIN32
|
||||
SH_DECL_MANUALHOOK0_void_vafmt(CGameClient_ClientPrintf, 0, 0, 0);
|
||||
#endif
|
||||
|
||||
// This should be large enough.
|
||||
#define FAKE_VTBL_LENGTH 70
|
||||
static void *FakeNetChanVtbl[FAKE_VTBL_LENGTH];
|
||||
@ -107,8 +114,14 @@ void HLTVServerWrapper::Hook()
|
||||
SH_ADD_HOOK(IClient, ExecuteStringCommand, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnHLTVBotExecuteStringCommand), false);
|
||||
SH_ADD_HOOK(IClient, ExecuteStringCommand, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnHLTVBotExecuteStringCommand_Post), true);
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
SH_ADD_HOOK(IClient, ClientPrintf, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnHLTVBotClientPrintf_Post), false);
|
||||
#endif
|
||||
SH_ADD_HOOK(IClient, ClientPrintf, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnIClient_ClientPrintf_Post), false);
|
||||
#ifndef WIN32
|
||||
// The IClient vtable is +4 from the CBaseClient vtable due to multiple inheritance.
|
||||
void *pGameClient = (void *)((intptr_t)pClient - 4);
|
||||
if (g_HLTVServers.HasClientPrintfOffset())
|
||||
SH_ADD_MANUALHOOK(CGameClient_ClientPrintf, pGameClient, SH_MEMBER(this, &HLTVServerWrapper::OnCGameClient_ClientPrintf_Post), false);
|
||||
#endif // !WIN32
|
||||
#endif // SOURCE_ENGINE != SE_CSGO
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,8 +146,14 @@ void HLTVServerWrapper::Unhook()
|
||||
SH_REMOVE_HOOK(IClient, ExecuteStringCommand, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnHLTVBotExecuteStringCommand), false);
|
||||
SH_REMOVE_HOOK(IClient, ExecuteStringCommand, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnHLTVBotExecuteStringCommand_Post), true);
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
SH_REMOVE_HOOK(IClient, ClientPrintf, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnHLTVBotClientPrintf_Post), false);
|
||||
#endif
|
||||
SH_REMOVE_HOOK(IClient, ClientPrintf, pClient, SH_MEMBER(this, &HLTVServerWrapper::OnIClient_ClientPrintf_Post), false);
|
||||
#ifndef WIN32
|
||||
// The IClient vtable is +4 from the CBaseClient vtable due to multiple inheritance.
|
||||
void *pGameClient = (void *)((intptr_t)pClient - 4);
|
||||
if (g_HLTVServers.HasClientPrintfOffset())
|
||||
SH_REMOVE_MANUALHOOK(CGameClient_ClientPrintf, pGameClient, SH_MEMBER(this, &HLTVServerWrapper::OnCGameClient_ClientPrintf_Post), false);
|
||||
#endif // !WIN32
|
||||
#endif // SOURCE_ENGINE != SE_CSGO
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -190,19 +209,38 @@ bool HLTVServerWrapper::OnHLTVBotExecuteStringCommand_Post(const char *s)
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
void HLTVServerWrapper::OnHLTVBotClientPrintf_Post(const char* buf)
|
||||
void HLTVServerWrapper::OnCGameClient_ClientPrintf_Post(const char* buf)
|
||||
{
|
||||
void *pGameClient = META_IFACEPTR(void);
|
||||
IClient *pClient = (IClient *)((intptr_t)pGameClient + 4);
|
||||
HandleClientPrintf(pClient, buf);
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void HLTVServerWrapper::OnIClient_ClientPrintf_Post(const char* buf)
|
||||
{
|
||||
IClient *pClient = META_IFACEPTR(IClient);
|
||||
HandleClientPrintf(pClient, buf);
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void HLTVServerWrapper::HandleClientPrintf(IClient *pClient, const char* buf)
|
||||
{
|
||||
// Craft our own "NetChan" pointer
|
||||
static int offset = -1;
|
||||
if (!g_pGameConf->GetOffset("CBaseClient::m_NetChannel", &offset) || offset == -1)
|
||||
{
|
||||
smutils->LogError(myself, "Failed to find CBaseClient::m_NetChannel offset. Can't print to demo console.");
|
||||
RETURN_META(MRES_IGNORED);
|
||||
return;
|
||||
}
|
||||
|
||||
IClient *pClient = META_IFACEPTR(IClient);
|
||||
|
||||
#ifdef WIN32
|
||||
void *pNetChannel = (void *)((char *)pClient + offset);
|
||||
#else
|
||||
void *pNetChannel = (void *)((char *)pClient + offset - 4);
|
||||
#endif
|
||||
// Set our fake netchannel
|
||||
*(void **)pNetChannel = &FakeNetChan;
|
||||
// Call ClientPrintf again, this time with a "Netchannel" set on the bot.
|
||||
@ -210,8 +248,6 @@ void HLTVServerWrapper::OnHLTVBotClientPrintf_Post(const char* buf)
|
||||
SH_CALL(pClient, &IClient::ClientPrintf)("%s", buf);
|
||||
// Set the fake netchannel back to 0.
|
||||
*(void **)pNetChannel = nullptr;
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -232,6 +268,18 @@ void HLTVServerWrapperManager::InitHooks()
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
#ifndef WIN32
|
||||
if (g_pGameConf->GetOffset("CGameClient::ClientPrintf", &offset))
|
||||
{
|
||||
SH_MANUALHOOK_RECONFIGURE(CGameClient_ClientPrintf, offset, 0, 0);
|
||||
m_bHasClientPrintfOffset = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
smutils->LogError(myself, "Failed to find CGameClient::ClientPrintf offset. Won't catch \"status\" console output.");
|
||||
}
|
||||
#endif // !WIN32
|
||||
|
||||
if (g_pGameConf->GetOffset("CNetChan::SendNetMsg", &offset))
|
||||
{
|
||||
if (offset >= FAKE_VTBL_LENGTH)
|
||||
@ -390,6 +438,11 @@ bool HLTVServerWrapperManager::HasShutdownOffset()
|
||||
return m_bHasShutdownOffset;
|
||||
}
|
||||
|
||||
bool HLTVServerWrapperManager::HasClientPrintfOffset()
|
||||
{
|
||||
return m_bHasClientPrintfOffset;
|
||||
}
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
bool HLTVServerWrapperManager::OnHLTVBotNetChanSendNetMsg(INetMessage &msg, bool bForceReliable, bool bVoice)
|
||||
{
|
||||
|
@ -57,7 +57,9 @@ private:
|
||||
void OnHLTVServerShutdown();
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
void OnHLTVBotClientPrintf_Post(const char *buf);
|
||||
void OnIClient_ClientPrintf_Post(const char *buf);
|
||||
void OnCGameClient_ClientPrintf_Post(const char *buf);
|
||||
void HandleClientPrintf(IClient *pClient, const char* buf);
|
||||
#endif
|
||||
|
||||
private:
|
||||
@ -80,6 +82,7 @@ public:
|
||||
int GetInstanceNumber(IHLTVServer *hltvserver);
|
||||
|
||||
IDemoRecorder *GetDemoRecorderPtr(IHLTVServer *hltv);
|
||||
bool HasClientPrintfOffset();
|
||||
bool HasShutdownOffset();
|
||||
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
@ -90,6 +93,7 @@ private:
|
||||
#if SOURCE_ENGINE != SE_CSGO
|
||||
bool m_bSendNetMsgHooked = false;
|
||||
#endif
|
||||
bool m_bHasClientPrintfOffset = false;
|
||||
bool m_bHasShutdownOffset = false;
|
||||
ke::Vector<ke::AutoPtr<HLTVServerWrapper>> m_HLTVServers;
|
||||
};
|
||||
|
@ -174,7 +174,12 @@
|
||||
"CBaseClient::m_NetChannel"
|
||||
{
|
||||
"windows" "192"
|
||||
"linux" "164"
|
||||
"linux" "196"
|
||||
}
|
||||
|
||||
"CGameClient::ClientPrintf"
|
||||
{
|
||||
"linux" "24"
|
||||
}
|
||||
|
||||
"CBaseServer::BroadcastPrintf"
|
||||
|
Loading…
Reference in New Issue
Block a user