void HLTVServerWrapper::Hook() { if (!m_Connected) return; g_pSTVForwards.HookServer(this); if (m_DemoRecorder) g_pSTVForwards.HookRecorder(m_DemoRecorder); if (g_HLTVServers.HasShutdownOffset()) SH_ADD_MANUALHOOK(CHLTVServer_Shutdown, m_HLTVServer->GetBaseServer(), SH_MEMBER(this, &HLTVServerWrapper::OnHLTVServerShutdown), false); if (iserver) { IClient *pClient = iserver->GetClient(m_HLTVServer->GetHLTVSlot()); if (pClient) { 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::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 } } }
void HolidayManager::HookIfNecessary() { // Already hooked if (m_iHookID) return; // Nothing wants us if (m_isHolidayForward->GetFunctionCount() == 0) return; void *pGameRules = GetGameRules(); if (!pGameRules) { if (m_bInMap) { g_pSM->LogError(myself, "Gamerules ptr not found. TF2_OnIsHolidayActive will not be available."); } return; } static int offset = -1; if (offset == -1) { if (!g_pGameConf->GetOffset("IsHolidayActive", &offset)) { g_pSM->LogError(myself, "IsHolidayActive gamedata offset missing. TF2_OnIsHolidayActive will not be available."); return; } SH_MANUALHOOK_RECONFIGURE(IsHolidayActive, offset, 0, 0); } m_iHookID = SH_ADD_MANUALHOOK(IsHolidayActive, pGameRules, SH_MEMBER(this, &HolidayManager::Hook_IsHolidayActive), false); }
void CHookManager::OnClientPutInServer(int client) { if (!PRCH_enabled) return; if (!PRCH_used) return; edict_t *pEdict = PEntityOfEntIndex(client); if (!pEdict) { return; } IServerUnknown *pUnknown = pEdict->GetUnknown(); if (!pUnknown) { return; } CBaseEntity *pEntity = pUnknown->GetBaseEntity(); if (!pEntity) { return; } SH_ADD_MANUALHOOK(PlayerRunCmdHook, pEntity, SH_MEMBER(this, &CHookManager::PlayerRunCmd), false); }
void CForwardManager::HookClient(IClient *client) { // Hook ExecuteStringCommand for chat messages g_pSTVCommonHooks.AddSpectatorHook(this, client); void *pGameClient = (void *)((intptr_t)client - 4); if (m_bHasActivatePlayerOffset) SH_ADD_MANUALHOOK(CBaseClient_ActivatePlayer, pGameClient, SH_MEMBER(this, &CForwardManager::OnSpectatorPutInServer), true); // Linux' engine uses the CGameClient vtable internally, but we're using the IClient vtable to kick players. // Need to hook both to catch all cases >.< SH_ADD_HOOK(IClient, Disconnect, client, SH_MEMBER(this, &CForwardManager::IClient_OnSpectatorDisconnect), false); #ifndef WIN32 if (m_bHasDisconnectOffset) SH_ADD_MANUALHOOK(CBaseClient_Disconnect, pGameClient, SH_MEMBER(this, &CForwardManager::BaseClient_OnSpectatorDisconnect), false); #endif }
/** * Manage the wrappers! */ void HLTVServerWrapperManager::InitHooks() { int offset; if (g_pGameConf->GetOffset("CHLTVServer::Shutdown", &offset)) { SH_MANUALHOOK_RECONFIGURE(CHLTVServer_Shutdown, offset, 0, 0); m_bHasShutdownOffset = true; } else { smutils->LogError(myself, "Failed to find CHLTVServer::Shutdown offset."); } #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) { smutils->LogError(myself, "CNetChan::SendNetMsg offset too big. Need to raise define and recompile. Contact the author."); } else { // This is a hack. Bots don't have a net channel, but ClientPrintf tries to call m_NetChannel->SendNetMsg directly. // CGameClient::SendNetMsg would have redirected it to the hltvserver correctly, but isn't used there.. // We craft a fake object with a large enough "vtable" and hook it using sourcehook. // Before a call to ClientPrintf, this fake object is set as CBaseClient::m_NetChannel, so ClientPrintf creates // the SVC_Print INetMessage and calls our "hooked" m_NetChannel->SendNetMsg function. // In that function we just call CGameClient::SendNetMsg with the given INetMessage to flow it through the same // path as other net messages. SH_MANUALHOOK_RECONFIGURE(NetChan_SendNetMsg, offset, 0, 0); SH_ADD_MANUALHOOK(NetChan_SendNetMsg, &FakeNetChan, SH_MEMBER(this, &HLTVServerWrapperManager::OnHLTVBotNetChanSendNetMsg), false); m_bSendNetMsgHooked = true; } } else { smutils->LogError(myself, "Failed to find CNetChan::SendNetMsg offset. Can't print to demo console."); } #endif }
void CForwardManager::HookServer(HLTVServerWrapper *wrapper) { IServer *server = wrapper->GetBaseServer(); if (m_bHasClientConnectOffset) SH_ADD_MANUALHOOK(CHLTVServer_ConnectClient, server, SH_MEMBER(this, &CForwardManager::OnSpectatorConnect), false); if (m_bHasGetChallengeTypeOffset) SH_ADD_MANUALHOOK(CHLTVServer_GetChallengeType, server, SH_MEMBER(this, &CForwardManager::OnGetChallengeType), false); // Hook all already connected clients as well for late loading for (int i = 0; i < server->GetClientCount(); i++) { IClient *client = server->GetClient(i); if (client->IsConnected()) { HookClient(client); // Ip and password unknown :( // Could add more gamedata to fetch it if people really lateload the extension and expect it to work :B wrapper->GetClient(i + 1)->Initialize("", "", client); } } }