//----------------------------------------------------------------------------- // Purpose: // Input : playerIndex - // ping - // packetloss - //----------------------------------------------------------------------------- void UTIL_GetPlayerConnectionInfo( int playerIndex, int& ping, int &packetloss ) { edict_t *pEntity = pAdminOP.GetEntityList()+playerIndex; CBasePlayer *player = (CBasePlayer *)VFuncs::Instance(pEntity); INetChannelInfo *nci = engine->GetPlayerNetInfo(playerIndex); if ( nci && player && pAdminOP.pAOPPlayers[playerIndex-1].NotBot() ) { float latency = nci->GetAvgLatency( FLOW_OUTGOING ); // in seconds // that should be the correct latency, we assume that cmdrate is higher // then updaterate, what is the case for default settings const char * szCmdRate = engine->GetClientConVarValue( playerIndex, "cl_cmdrate" ); int nCmdRate = max( 1, Q_atoi( szCmdRate ) ); latency -= (0.5f/nCmdRate) + TICKS_TO_TIME( 1.0f ); // correct latency // in GoldSrc we had a different, not fixed tickrate. so we have to adjust // Source pings by half a tick to match the old GoldSrc pings. latency -= TICKS_TO_TIME( 0.5f ); ping = latency * 1000.0f; // as msecs ping = clamp( ping, 5, 1000 ); // set bounds, dont show pings under 5 msecs packetloss = 100.0f * nci->GetAvgLoss( FLOW_INCOMING ); // loss in percentage packetloss = clamp( packetloss, 0, 100 ); } else { ping = 0; packetloss = 0; } }
static cell_t GetAvgLatency(IPluginContext *pContext, const cell_t *params) { int client = params[1]; float value; CPlayer *pPlayer = g_Players.GetPlayerByIndex(client); if (!pPlayer) { return pContext->ThrowNativeError("Client index %d is invalid", client); } else if (!pPlayer->IsInGame()) { return pContext->ThrowNativeError("Client %d is not in game", client); } else if (pPlayer->IsFakeClient()) { return pContext->ThrowNativeError("Client %d is a bot", client); } INetChannelInfo *pInfo = engine->GetPlayerNetInfo(client); if (pInfo == NULL) { return sp_ftoc(-1); } if (params[2] == MAX_FLOWS) { value = pInfo->GetAvgLatency(FLOW_INCOMING) + pInfo->GetAvgLatency(FLOW_OUTGOING); } else { value = pInfo->GetAvgLatency(params[2]); } return sp_ftoc(value); }
//--------------------------------------------------------------------------------- // Purpose: Do timed afk if needed //--------------------------------------------------------------------------------- void ManiPing::GameFrame(void) { if (war_mode) return; if (mani_high_ping_kick.GetInt() == 0) return; // High ping kicker enabled if (next_check > gpGlobals->curtime) { return; } next_check = gpGlobals->curtime + 1.5; bool all_pings_high = true; // Use 80% of limit as global ping spikes may not bring all players over the // spike ping limit although all players will have their pings increase int global_ping_limit = (int) (mani_high_ping_kick_ping_limit.GetFloat() * 0.8); for (int i = 0; i < max_players; i++) { ping_player_t *ptr = &(ping_player_list[i]); ptr->in_use = true; ptr->player.index = i + 1; if (!FindPlayerByIndex(&ptr->player)) { ptr->in_use = false; continue; } if (ptr->player.is_bot) { ptr->in_use = false; continue; } // Valid player INetChannelInfo *nci = engine->GetPlayerNetInfo(i + 1); float ping = nci->GetAvgLatency(0); const char * szCmdRate = engine->GetClientConVarValue( i + 1, "cl_cmdrate" ); int nCmdRate = (20 > Q_atoi( szCmdRate )) ? 20 : Q_atoi(szCmdRate); ping -= (0.5f/nCmdRate) + TICKS_TO_TIME( 1.0f ); // correct latency // in GoldSrc we had a different, not fixed tickrate. so we have to adjust // Source pings by half a tick to match the old GoldSrc pings. ping -= TICKS_TO_TIME( 0.5f ); ping = ping * 1000.0f; // as msecs ptr->current_ping = clamp( ping, 5, 1000 ); // set bounds, dont show pings under 5 msecs // Crude attempt to protect against all pings from being high and kicking everyone if (ptr->current_ping < global_ping_limit) { all_pings_high = false; } } for (int i = 0; i < max_players; i++) { if (!ping_list[i].check_ping || !ping_player_list[i].in_use) { continue; } if (all_pings_high) { ping_player_list[i].current_ping = mani_high_ping_kick_ping_limit.GetInt() / 2; } if (ping_list[i].count == 0) { // Init ping ping_list[i].average_ping = ping_player_list[i].current_ping; } else { ping_list[i].average_ping += ping_player_list[i].current_ping; } // Bump up average ping ping_list[i].count += 1; if (ping_list[i].count > mani_high_ping_kick_samples_required.GetInt()) { if ((ping_list[i].average_ping / ping_list[i].count) > mani_high_ping_kick_ping_limit.GetInt()) { player_t *ptr = &(ping_player_list[i].player); SayToAll (ORANGE_CHAT, false, "Player %s was autokicked for breaking the %ims ping limit on this server\n", ptr->name, mani_high_ping_kick_ping_limit.GetInt() ); char log_reason[256]; snprintf(log_reason, sizeof(log_reason), "[MANI_ADMIN_PLUGIN] Kicked player [%s] steam id [%s] for exceeding ping limit\n", ptr->name, ptr->steam_id); UTIL_KickPlayer(ptr, (char *) mani_high_ping_kick_message.GetString(), (char *) mani_high_ping_kick_message.GetString(), log_reason); ping_list[i].check_ping = false; } else { ping_list[i].count = 0; } } } }
//--------------------------------------------------------------------------------- // Purpose: Builds up a list of players that are 'kickable' //--------------------------------------------------------------------------------- void ManiReservedSlot::BuildPlayerKickList( player_t *player_ptr, int *players_on_server ) { player_t temp_player; active_player_t active_player; FreeList((void **) &active_player_list, &active_player_list_size); for (int i = 1; i <= max_players; i ++) { #if defined ( GAME_CSGO ) edict_t *pEntity = PEntityOfEntIndex(i); #else edict_t *pEntity = engine->PEntityOfEntIndex(i); #endif if( pEntity && !pEntity->IsFree()) { if ( player_ptr && ( pEntity == player_ptr->entity ) ) continue; IPlayerInfo *playerinfo = playerinfomanager->GetPlayerInfo( pEntity ); if (playerinfo && playerinfo->IsConnected()) { Q_strcpy(active_player.steam_id, playerinfo->GetNetworkIDString()); if (FStrEq("BOT", active_player.steam_id)) { continue; } INetChannelInfo *nci = engine->GetPlayerNetInfo(i); if (!nci) { continue; } active_player.entity = pEntity; active_player.ping = nci->GetAvgLatency(0); const char * szCmdRate = engine->GetClientConVarValue( i, "cl_cmdrate" ); int nCmdRate = (20 > Q_atoi( szCmdRate )) ? 20 : Q_atoi(szCmdRate); active_player.ping -= (0.5f/nCmdRate) + TICKS_TO_TIME( 1.0f ); // correct latency // in GoldSrc we had a different, not fixed tickrate. so we have to adjust // Source pings by half a tick to match the old GoldSrc pings. active_player.ping -= TICKS_TO_TIME( 0.5f ); active_player.ping = active_player.ping * 1000.0f; // as msecs active_player.ping = ((5 > active_player.ping) ? 5:active_player.ping); // set bounds, dont show pings under 5 msecs active_player.time_connected = nci->GetTimeConnected(); Q_strcpy(active_player.ip_address, nci->GetAddress()); if (gpManiGameType->IsSpectatorAllowed() && playerinfo->GetTeamIndex () == gpManiGameType->GetSpectatorIndex()) { active_player.is_spectator = true; } else { active_player.is_spectator = false; } active_player.user_id = playerinfo->GetUserID(); Q_strcpy(active_player.name, playerinfo->GetName()); if ( players_on_server ) *players_on_server = *players_on_server + 1; active_player.kills = playerinfo->GetFragCount(); active_player.deaths = playerinfo->GetDeathCount(); Q_strcpy(temp_player.steam_id, active_player.steam_id); Q_strcpy(temp_player.ip_address, active_player.ip_address); Q_strcpy(temp_player.name, active_player.name); temp_player.is_bot = false; if (IsPlayerInReserveList(&temp_player)) { continue; } active_player.index = i; if (mani_reserve_slots_include_admin.GetInt() == 1 && gpManiClient->HasAccess(active_player.index, ADMIN, ADMIN_BASIC_ADMIN)) { continue; } if (gpManiClient->HasAccess(active_player.index, IMMUNITY, IMMUNITY_RESERVE)) { continue; } AddToList((void **) &active_player_list, sizeof(active_player_t), &active_player_list_size); active_player_list[active_player_list_size - 1] = active_player; } } } }