//----------------------------------------------------------------------------- // 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; } }
const char *CSizzPluginContext::GetPlayerIPPortString( int ent_index ) { INetChannelInfo *pNetInfo = m_pEngine->GetPlayerNetInfo(ent_index); if (pNetInfo) { return pNetInfo->GetAddress(); } return ""; }
void Firehose_Send(uint16_t port, size_t len, const uint8_t *src) { // auto t_begin = std::chrono::high_resolution_clock::now(); // for (int i = 1; i <= gpGlobals->maxClients; ++i) { for (int i = 1; i <= 1; ++i) { INetChannelInfo *info = engine->GetPlayerNetInfo(i); if (info == nullptr) continue; netadr_t c_addr(info->GetAddress()); if (!c_addr.IsValid()) continue; c_addr.SetPort(port); // DevMsg("Sending %u bytes to player %d: %s\n", len, i, c_addr.ToString()); int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) { Warning("Firehose_Send: socket creation failed: %s\n", strerror(errno)); continue; } sockaddr_in addr; c_addr.ToSockadr((sockaddr *)&addr); // bool retry; // do { // retry = false; // if (sendto(s, (const char *)src, len, 0, (const sockaddr *)&addr, sizeof(addr)) < 0) { // if (errno == ENOBUFS) { // retry = true; // } else { Warning("Firehose_Send: sendto failed: %s\n", strerror(errno)); // } } // } while (retry); #if defined _WINDOWS closesocket(s); #else close(s); #endif } // auto t_end = std::chrono::high_resolution_clock::now(); // auto dt = t_end - t_begin; // DevMsg("Firehose_Send: %lld ns\n", std::chrono::duration_cast<std::chrono::nanoseconds>(dt).count()); }
static cell_t IsTimingOut(IPluginContext *pContext, const cell_t *params) { int client = params[1]; 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 1; } return pInfo->IsTimingOut() ? 1 : 0; }
//----------------------------------------------------------------------------- // Returns an address from the given PlayerInfo instance. //----------------------------------------------------------------------------- bool AddressFromPlayerInfo2( IPlayerInfo* pInfo, const char*& output ) { if (!pInfo) return false; if (pInfo->IsFakeClient() || V_strstr(pInfo->GetNetworkIDString(), "BOT")) { output = ""; return true; } unsigned int index; if (!IndexFromPlayerInfo(pInfo, index)) return false; INetChannelInfo* netinfo = engine->GetPlayerNetInfo(index); if (!netinfo) return false; output = netinfo->GetAddress(); return true; }
static cell_t GetAvgPackets(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 0; } if (params[2] == MAX_FLOWS) { value = pInfo->GetAvgPackets(FLOW_INCOMING) + pInfo->GetAvgPackets(FLOW_OUTGOING); } else { value = pInfo->GetAvgPackets(params[2]); } return sp_ftoc(value); }
// Called during player movement to set up/restore after lag compensation void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCmd *cmd ) { //DONT LAG COMP AGAIN THIS FRAME IF THERES ALREADY ONE IN PROGRESS //IF YOU'RE HITTING THIS THEN IT MEANS THERES A CODE BUG if ( m_pCurrentPlayer ) { Assert( m_pCurrentPlayer == NULL ); Warning( "Trying to start a new lag compensation session while one is already active!\n" ); return; } // sort out any changes to the AI indexing if ( m_bNeedsAIUpdate ) // to be called once per frame... must happen BEFORE lag compensation - {// if that happens, that is. if not its called at the end of the frame m_bNeedsAIUpdate = false; UpdateAIIndexes(); } // Assume no players or entities need to be restored m_RestorePlayer.ClearAll(); m_RestoreEntity.ClearAll(); m_bNeedToRestore = false; m_pCurrentPlayer = player; if ( !player->m_bLagCompensation // Player not wanting lag compensation || (gpGlobals->maxClients <= 1) // no lag compensation in single player || !sv_unlag.GetBool() // disabled by server admin || player->IsBot() // not for bots || player->IsObserver() // not for spectators ) return; // NOTE: Put this here so that it won't show up in single player mode. VPROF_BUDGET( "StartLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING ); Q_memset( m_RestoreData, 0, sizeof( m_RestoreData ) ); Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) ); Q_memset( m_EntityRestoreData, 0, sizeof( m_EntityRestoreData ) ); Q_memset( m_EntityChangeData, 0, sizeof( m_EntityChangeData ) ); // Get true latency // correct is the amout of time we have to correct game time float correct = 0.0f; INetChannelInfo *nci = engine->GetPlayerNetInfo( player->entindex() ); if ( nci ) { // add network latency correct+= nci->GetLatency( FLOW_OUTGOING ); } // calc number of view interpolation ticks - 1 int lerpTicks = TIME_TO_TICKS( player->m_fLerpTime ); // add view interpolation latency see C_BaseEntity::GetInterpolationAmount() correct += TICKS_TO_TIME( lerpTicks ); // check bouns [0,sv_maxunlag] correct = clamp( correct, 0.0f, sv_maxunlag.GetFloat() ); // correct tick send by player int targettick = cmd->tick_count - lerpTicks; // calc difference between tick send by player and our latency based tick float deltaTime = correct - TICKS_TO_TIME(gpGlobals->tickcount - targettick); if ( fabs( deltaTime ) > 0.2f ) { // difference between cmd time and latency is too big > 200ms, use time correction based on latency // DevMsg("StartLagCompensation: delta too big (%.3f)\n", deltaTime ); targettick = gpGlobals->tickcount - TIME_TO_TICKS( correct ); } // Iterate all active players const CBitVec<MAX_EDICTS> *pEntityTransmitBits = engine->GetEntityTransmitBitsForClient( player->entindex() - 1 ); for ( int i = 1; i <= gpGlobals->maxClients; i++ ) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( i ); if ( !pPlayer || player == pPlayer ) continue; // Custom checks for if things should lag compensate (based on things like what team the player is on). if ( !player->WantsLagCompensationOnEntity( pPlayer, cmd, pEntityTransmitBits ) ) continue; // Move other player back in time BacktrackPlayer( pPlayer, TICKS_TO_TIME( targettick ) ); } // also iterate all monsters CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs(); int nAIs = g_AI_Manager.NumAIs(); for ( int i = 0; i < nAIs; i++ ) { CAI_BaseNPC *pNPC = ppAIs[i]; // Custom checks for if things should lag compensate if ( !pNPC || !player->WantsLagCompensationOnEntity( pNPC, cmd, pEntityTransmitBits ) ) continue; // Move NPC back in time BacktrackEntity( pNPC, TICKS_TO_TIME( targettick ) ); } }
//--------------------------------------------------------------------------------- // 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; } } } }
//----------------------------------------------------------------------------- // Purpose: restarts the game //----------------------------------------------------------------------------- void CTFOptionsVideoPanel::OnApplyChanges() { BaseClass::OnApplyChanges(); if ( RequiresRestart() ) { INetChannelInfo *nci = engine->GetNetChannelInfo(); if ( nci ) { // Only retry if we're not running the server const char *pAddr = nci->GetAddress(); if ( pAddr ) { if ( Q_strncmp(pAddr,"127.0.0.1",9) && Q_strncmp(pAddr,"localhost",9) ) { engine->ClientCmd_Unrestricted( "retry\n" ); } else { engine->ClientCmd_Unrestricted( "disconnect\n" ); } } } } // resolution char sz[256]; //if ( m_nSelectedMode == -1 ) //{ // m_pMode->GetText(sz, 256); //} //else //{ m_pMode->GetItemText( m_nSelectedMode, sz, 256 ); //} int width = 0, height = 0; sscanf(sz, "%i x %i", &width, &height); Msg("VIDEO %s\n", sz); // windowed bool windowed = (m_pWindowed->GetActiveItem() > 0) ? true : false; // make sure there is a change const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard(); if ( config.m_VideoMode.m_Width != width || config.m_VideoMode.m_Height != height || config.Windowed() != windowed) { // set mode char szCmd[ 256 ]; Q_snprintf( szCmd, sizeof( szCmd ), "mat_setvideomode %i %i %i\n", width, height, windowed ? 1 : 0 ); Msg(szCmd); engine->ClientCmd_Unrestricted( szCmd ); } if (config.m_VideoMode.m_Width != width || config.m_VideoMode.m_Height != height || config.Windowed() != windowed) { MAINMENU_ROOT->LaunchInvalidatePanelsLayout(); } m_pGammaSlider->ApplyChanges(); // apply changes engine->ClientCmd_Unrestricted( "mat_savechanges\n" ); //VIDEOADV //if (!m_bUseChanges) // return; ApplyChangesToConVar("mat_dxlevel", m_pDXLevel->GetActiveItemUserData()->GetInt("dxlevel")); ApplyChangesToConVar("r_rootlod", 2 - m_pModelDetail->GetActiveItem()); ApplyChangesToConVar("mat_picmip", 2 - m_pTextureDetail->GetActiveItem()); // reset everything tied to the filtering mode, then the switch sets the appropriate one ApplyChangesToConVar("mat_trilinear", false); ApplyChangesToConVar("mat_forceaniso", 1); switch (m_pFilteringMode->GetActiveItem()) { case 0: break; case 1: ApplyChangesToConVar("mat_trilinear", true); break; case 2: ApplyChangesToConVar("mat_forceaniso", 2); break; case 3: ApplyChangesToConVar("mat_forceaniso", 4); break; case 4: ApplyChangesToConVar("mat_forceaniso", 8); break; case 5: ApplyChangesToConVar("mat_forceaniso", 16); break; } // Set the AA convars according to the menu item chosen int nActiveAAItem = m_pAntialiasingMode->GetActiveItem(); ApplyChangesToConVar("mat_antialias", m_nAAModes[nActiveAAItem].m_nNumSamples); ApplyChangesToConVar("mat_aaquality", m_nAAModes[nActiveAAItem].m_nQualityLevel); if (m_pHDR->IsEnabled()) { ConVarRef mat_hdr_level("mat_hdr_level"); Assert(mat_hdr_level.IsValid()); mat_hdr_level.SetValue(m_pHDR->GetActiveItem()); } if (m_pShadowDetail->GetActiveItem() == 0) // Blobby shadows { ApplyChangesToConVar("r_shadowrendertotexture", 0); // Turn off RTT shadows ApplyChangesToConVar("r_flashlightdepthtexture", 0); // Turn off shadow depth textures } else if (m_pShadowDetail->GetActiveItem() == 1) // RTT shadows only { ApplyChangesToConVar("r_shadowrendertotexture", 1); // Turn on RTT shadows ApplyChangesToConVar("r_flashlightdepthtexture", 0); // Turn off shadow depth textures } else if (m_pShadowDetail->GetActiveItem() == 2) // Shadow depth textures { ApplyChangesToConVar("r_shadowrendertotexture", 1); // Turn on RTT shadows ApplyChangesToConVar("r_flashlightdepthtexture", 1); // Turn on shadow depth textures } ApplyChangesToConVar("mat_reducefillrate", (m_pShaderDetail->GetActiveItem() > 0) ? 0 : 1); switch (m_pWaterDetail->GetActiveItem()) { default: case 0: #ifndef _X360 ApplyChangesToConVar("r_waterforceexpensive", false); #endif ApplyChangesToConVar("r_waterforcereflectentities", false); break; case 1: #ifndef _X360 ApplyChangesToConVar("r_waterforceexpensive", true); #endif ApplyChangesToConVar("r_waterforcereflectentities", false); break; case 2: #ifndef _X360 ApplyChangesToConVar("r_waterforceexpensive", true); #endif ApplyChangesToConVar("r_waterforcereflectentities", true); break; } m_pFOVSlider->ApplyChanges(); ApplyChangesToConVar("mat_vsync", m_pVSync->GetActiveItem()); ApplyChangesToConVar("mat_colorcorrection", m_pColorCorrection->GetActiveItem()); ApplyChangesToConVar("mat_queue_mode", m_pQueuedMode->GetActiveItem() * -1); ApplyChangesToConVar("mat_motion_blur_enabled", m_pMotionBlur->GetActiveItem()); }