Exemplo n.º 1
0
//-----------------------------------------------------------------------------
// 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;
    }
}
Exemplo n.º 2
0
// 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 ) );
	}
}
Exemplo n.º 3
0
//---------------------------------------------------------------------------------
// 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;
			}
		}
	}
}
Exemplo n.º 5
0
void CHLTVDirector::StartNewShot()
{
	// we can remove all events the
	int smallestTick = MAX(0, gpGlobals->tickcount - TIME_TO_TICKS(HLTV_MAX_DELAY) );
    RemoveEventsFromHistory( smallestTick );

	if ( m_iCameraMan > 0 )
	{
		// we already have an active camera man,
		// wait until he releases the "record" lock
		FinishCameraManShot();
		return;	
	}

	if ( StartCameraManShot() )
	{
		// now we have an active camera man
		return;
	} 

    // ok, no camera man active, now check how much time
	// we have for the next shot, if the time diff to the next
	// important event we have to switch to is too short (<2sec)
	// just extent the current shot and don't start a new one

	// check the next 8 seconds for interrupts/important events
	m_nNextShotTick = m_nBroadcastTick + TIME_TO_TICKS( MAX_SHOT_LENGTH );

	if ( m_nBroadcastTick <= 0 )
	{
		// game hasn't started yet, we are still in the broadcast delay hole
		IGameEvent *msg = gameeventmanager->CreateEvent( "hltv_message", true );

		if ( msg )
		{
			msg->SetString("text", "Please wait for broadcast to start ..." );
			
			// send spectators the HLTV director command as a game event
			m_pHLTVServer->BroadcastEvent( msg );
			gameeventmanager->FreeEvent( msg );
		}

		StartBestFixedCameraShot( true );
		return;
	}

	int index = FindFirstEvent( m_nBroadcastTick );

	while( index != m_EventHistory.InvalidIndex() )
	{
		CGameEvent &dc = m_EventHistory[index];

		if ( dc.m_Tick >= m_nNextShotTick )
			break; // we have searched enough

		// a camera man is always interrupting auto director
		if ( Q_strcmp( dc.m_Event->GetName(), "hltv_cameraman") == 0 )
		{
			if ( dc.m_Event->GetInt("index") > 0 )
			{
				// stop the next cut when this cameraman starts recording
				m_nNextShotTick = dc.m_Tick;
				break;
			}
		}

		index = m_EventHistory.NextInorder( index );
	} 

	float flDuration = TICKS_TO_TIME(m_nNextShotTick - m_nBroadcastTick);

	if ( flDuration < MIN_SHOT_LENGTH )
		return;	// not enough time for a new shot

	// find the most intesting game event for next shot
	CGameEvent *dc = FindBestGameEvent();

	if ( dc )
	{
		// show the game event
		CreateShotFromEvent( dc );
	}
	else
	{
		// no interesting events found, start random shot
		StartRandomShot();
	}
}