void AnalyzeGameState(const udtCuGamestateMessage& gameState) { _demoTakerClientNumber = gameState.ClientNumber; PrintInfo(""); PrintInfo("================================"); PrintInfo("New Game State"); PrintInfo("================================"); std::string playerName; udtCuConfigString cs; for(u32 i = 0; i < ID_MAX_CLIENTS; ++i) { udtCuGetConfigString(_cuContext, &cs, (u32)_protocolFirstPlayerCsIdx + i); if(cs.ConfigString != NULL && cs.ConfigStringLength > 0) { if(ExtractPlayerName(playerName, cs.ConfigString, _protocol)) { _players[i].Name = playerName; _players[i].Valid = true; PrintInfo("Player: %s (client %u)%s", playerName.c_str(), i, (s32)i == _demoTakerClientNumber ? " <== demo taker" : ""); } } } PrintInfo("================================"); }
void AnalyzeCommand(const udtCuCommandMessage& command, s32 serverTimeMs) { if(!command.IsConfigString) { return; } const s32 clientNumber = command.ConfigStringIndex - _protocolFirstPlayerCsIdx; if(clientNumber < 0 || clientNumber >= ID_MAX_CLIENTS) { // Not a player config string. return; } // Config string update commands always have 3 tokens: // 1. "cs" // 2. The index of the config string to update. // 3. The actual content, in quotes. if(command.TokenCount != 3) { // Not a proper config string command. return; } std::string serverTime; FormatServerTime(serverTime, serverTimeMs); const std::string configString = command.CommandTokens[2]; std::string playerName; Player& player = _players[clientNumber]; if(configString.empty() || !ExtractPlayerName(playerName, configString, _protocol)) { PrintInfo("%s Player %s left (client %u)", serverTime.c_str(), player.Name.c_str(), (u32)clientNumber); player.Name = ""; player.Valid = false; return; } const bool wasValid = player.Valid; player.Valid = true; if(!wasValid) { PrintInfo("%s Player %s joined (client %u)", serverTime.c_str(), playerName.c_str(), (u32)clientNumber); player.Name = playerName; } else if(playerName != player.Name) { PrintInfo("%s Player %s renamed to %s (client %u)", serverTime.c_str(), player.Name.c_str(), playerName.c_str(), (u32)clientNumber); player.Name = playerName; } }
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 { if (!pCookie || (size_t)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); // SourceTV doesn't validate steamids?! char rejectReason[255]; m_SpectatorPreConnectFwd->PushString(pchName); m_SpectatorPreConnectFwd->PushStringEx(passwordBuffer, 255, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); m_SpectatorPreConnectFwd->PushString(ipString); m_SpectatorPreConnectFwd->PushStringEx(rejectReason, 255, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK); cell_t retVal = 1; m_SpectatorPreConnectFwd->Execute(&retVal); IServer *server = META_IFACEPTR(IServer); if (retVal == 0) { if (m_bHasRejectConnectionOffset) { #if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_LEFT4DEAD || SOURCE_ENGINE == SE_LEFT4DEAD2 SH_MCALL(server, CHLTVServer_RejectConnection)(address, rejectReason); #else SH_MCALL(server, CHLTVServer_RejectConnection)(address, iClientChallenge, rejectReason); #endif } RETURN_META_VALUE(MRES_SUPERCEDE, nullptr); } // 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 || SOURCE_ENGINE == SE_LEFT4DEAD2 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 if (!client) RETURN_META_VALUE(MRES_SUPERCEDE, nullptr); HookClient(client); HLTVServerWrapper *wrapper = g_HLTVServers.GetWrapper(server); if (wrapper) { HLTVClientWrapper *clientWrapper = wrapper->GetClient(client->GetPlayerSlot() + 1); clientWrapper->Initialize(ipString, pchPassword, client); } m_SpectatorConnectedFwd->PushCell(client->GetPlayerSlot() + 1); m_SpectatorConnectedFwd->Execute(); // Don't call the hooked function again, just return its value. RETURN_META_VALUE(MRES_SUPERCEDE, client); }