summaryrefslogtreecommitdiff
path: root/game/server/recipientfilter.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/recipientfilter.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'game/server/recipientfilter.cpp')
-rw-r--r--game/server/recipientfilter.cpp415
1 files changed, 415 insertions, 0 deletions
diff --git a/game/server/recipientfilter.cpp b/game/server/recipientfilter.cpp
new file mode 100644
index 0000000..64889b3
--- /dev/null
+++ b/game/server/recipientfilter.cpp
@@ -0,0 +1,415 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#include "cbase.h"
+#include "recipientfilter.h"
+#include "team.h"
+#include "ipredictionsystem.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+static IPredictionSystem g_RecipientFilterPredictionSystem;
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CRecipientFilter::CRecipientFilter()
+{
+ Reset();
+}
+
+CRecipientFilter::~CRecipientFilter()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : src -
+//-----------------------------------------------------------------------------
+void CRecipientFilter::CopyFrom( const CRecipientFilter& src )
+{
+ m_bReliable = src.IsReliable();
+ m_bInitMessage = src.IsInitMessage();
+
+ m_bUsingPredictionRules = src.IsUsingPredictionRules();
+ m_bIgnorePredictionCull = src.IgnorePredictionCull();
+
+ int c = src.GetRecipientCount();
+ for ( int i = 0; i < c; ++i )
+ {
+ m_Recipients.AddToTail( src.GetRecipientIndex( i ) );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CRecipientFilter::Reset( void )
+{
+ m_bReliable = false;
+ m_bInitMessage = false;
+ m_Recipients.RemoveAll();
+ m_bUsingPredictionRules = false;
+ m_bIgnorePredictionCull = false;
+}
+
+void CRecipientFilter::MakeReliable( void )
+{
+ m_bReliable = true;
+}
+
+bool CRecipientFilter::IsReliable( void ) const
+{
+ return m_bReliable;
+}
+
+int CRecipientFilter::GetRecipientCount( void ) const
+{
+ return m_Recipients.Size();
+}
+
+int CRecipientFilter::GetRecipientIndex( int slot ) const
+{
+ if ( slot < 0 || slot >= GetRecipientCount() )
+ return -1;
+
+ return m_Recipients[ slot ];
+}
+
+void CRecipientFilter::AddAllPlayers( void )
+{
+ m_Recipients.RemoveAll();
+
+ int i;
+ for ( i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
+ if ( !pPlayer )
+ {
+ continue;
+ }
+
+ AddRecipient( pPlayer );
+ }
+}
+
+void CRecipientFilter::AddRecipient( const CBasePlayer *player )
+{
+ Assert( player );
+
+ if ( !player )
+ return;
+
+ int index = player->entindex();
+
+ // If we're predicting and this is not the first time we've predicted this sound
+ // then don't send it to the local player again.
+ if ( m_bUsingPredictionRules )
+ {
+ // Only add local player if this is the first time doing prediction
+ if ( g_RecipientFilterPredictionSystem.GetSuppressHost() == player )
+ {
+ return;
+ }
+ }
+
+ // Already in list
+ if ( m_Recipients.Find( index ) != m_Recipients.InvalidIndex() )
+ return;
+
+ m_Recipients.AddToTail( index );
+}
+
+void CRecipientFilter::RemoveAllRecipients( void )
+{
+ m_Recipients.RemoveAll();
+}
+
+void CRecipientFilter::RemoveRecipient( CBasePlayer *player )
+{
+ Assert( player );
+ if ( player )
+ {
+ int index = player->entindex();
+
+ // Remove it if it's in the list
+ m_Recipients.FindAndRemove( index );
+ }
+}
+
+void CRecipientFilter::RemoveRecipientByPlayerIndex( int playerindex )
+{
+ Assert( playerindex >= 1 && playerindex <= ABSOLUTE_PLAYER_LIMIT );
+
+ m_Recipients.FindAndRemove( playerindex );
+}
+
+void CRecipientFilter::AddRecipientsByTeam( CTeam *team )
+{
+ Assert( team );
+
+ int i;
+ int c = team->GetNumPlayers();
+ for ( i = 0 ; i < c ; i++ )
+ {
+ CBasePlayer *player = team->GetPlayer( i );
+ if ( !player )
+ continue;
+
+ AddRecipient( player );
+ }
+}
+
+void CRecipientFilter::RemoveRecipientsByTeam( CTeam *team )
+{
+ Assert( team );
+
+ int i;
+ int c = team->GetNumPlayers();
+ for ( i = 0 ; i < c ; i++ )
+ {
+ CBasePlayer *player = team->GetPlayer( i );
+ if ( !player )
+ continue;
+
+ RemoveRecipient( player );
+ }
+}
+
+void CRecipientFilter::RemoveRecipientsNotOnTeam( CTeam *team )
+{
+ Assert( team );
+
+ int i;
+ for ( i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ CBasePlayer *player = UTIL_PlayerByIndex( i );
+ if ( !player )
+ continue;
+
+ if ( player->GetTeam() != team )
+ {
+ RemoveRecipient( player );
+ }
+ }
+}
+
+void CRecipientFilter::AddPlayersFromBitMask( CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits )
+{
+ int index = playerbits.FindNextSetBit( 0 );
+
+ while ( index > -1 )
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( index + 1 );
+ if ( pPlayer )
+ {
+ AddRecipient( pPlayer );
+ }
+
+ index = playerbits.FindNextSetBit( index + 1 );
+ }
+}
+
+void CRecipientFilter::RemovePlayersFromBitMask( CBitVec< ABSOLUTE_PLAYER_LIMIT >& playerbits )
+{
+ int index = playerbits.FindNextSetBit( 0 );
+
+ while ( index > -1 )
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( index + 1 );
+ if ( pPlayer )
+ {
+ RemoveRecipient( pPlayer );
+ }
+
+ index = playerbits.FindNextSetBit( index + 1 );
+ }
+}
+
+void CRecipientFilter::AddRecipientsByPVS( const Vector& origin )
+{
+ if ( gpGlobals->maxClients == 1 )
+ {
+ AddAllPlayers();
+ }
+ else
+ {
+ CBitVec< ABSOLUTE_PLAYER_LIMIT > playerbits;
+ engine->Message_DetermineMulticastRecipients( false, origin, playerbits );
+ AddPlayersFromBitMask( playerbits );
+ }
+}
+
+void CRecipientFilter::RemoveRecipientsByPVS( const Vector& origin )
+{
+ if ( gpGlobals->maxClients == 1 )
+ {
+ m_Recipients.RemoveAll();
+ }
+ else
+ {
+ CBitVec< ABSOLUTE_PLAYER_LIMIT > playerbits;
+ engine->Message_DetermineMulticastRecipients( false, origin, playerbits );
+ RemovePlayersFromBitMask( playerbits );
+ }
+}
+
+
+
+void CRecipientFilter::AddRecipientsByPAS( const Vector& origin )
+{
+ if ( gpGlobals->maxClients == 1 )
+ {
+ AddAllPlayers();
+ }
+ else
+ {
+ CBitVec< ABSOLUTE_PLAYER_LIMIT > playerbits;
+ engine->Message_DetermineMulticastRecipients( true, origin, playerbits );
+ AddPlayersFromBitMask( playerbits );
+ }
+}
+
+bool CRecipientFilter::IsInitMessage( void ) const
+{
+ return m_bInitMessage;
+}
+
+void CRecipientFilter::MakeInitMessage( void )
+{
+ m_bInitMessage = true;
+}
+
+void CRecipientFilter::UsePredictionRules( void )
+{
+ if ( m_bUsingPredictionRules )
+ return;
+
+ m_bUsingPredictionRules = true;
+
+ // Cull list now, if needed
+ if ( GetRecipientCount() == 0 )
+ return;
+
+ CBasePlayer *pPlayer = ToBasePlayer( (CBaseEntity*)g_RecipientFilterPredictionSystem.GetSuppressHost() );
+
+ if ( pPlayer)
+ {
+ RemoveRecipient( pPlayer );
+ }
+}
+
+bool CRecipientFilter::IsUsingPredictionRules( void ) const
+{
+ return m_bUsingPredictionRules;
+}
+
+bool CRecipientFilter:: IgnorePredictionCull( void ) const
+{
+ return m_bIgnorePredictionCull;
+}
+
+void CRecipientFilter::SetIgnorePredictionCull( bool ignore )
+{
+ m_bIgnorePredictionCull = ignore;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Simple class to create a filter for all players on a given team
+//-----------------------------------------------------------------------------
+CTeamRecipientFilter::CTeamRecipientFilter( int team, bool isReliable )
+{
+ if (isReliable)
+ MakeReliable();
+
+ RemoveAllRecipients();
+
+ for ( int i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
+
+ if ( !pPlayer )
+ {
+ continue;
+ }
+
+ if ( pPlayer->GetTeamNumber() != team )
+ {
+ //If we're in the spectator team then we should be getting whatever messages the person I'm spectating gets.
+ if ( pPlayer->GetTeamNumber() == TEAM_SPECTATOR && (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE || pPlayer->GetObserverMode() == OBS_MODE_CHASE || pPlayer->GetObserverMode() == OBS_MODE_POI) )
+ {
+ if ( pPlayer->GetObserverTarget() )
+ {
+ if ( pPlayer->GetObserverTarget()->GetTeamNumber() != team )
+ continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ AddRecipient( pPlayer );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : origin -
+// ATTN_NORM -
+//-----------------------------------------------------------------------------
+void CPASAttenuationFilter::Filter( const Vector& origin, float attenuation /*= ATTN_NORM*/ )
+{
+ // Don't crop for attenuation in single player
+ if ( gpGlobals->maxClients == 1 )
+ return;
+
+ // CPASFilter adds them by pure PVS in constructor
+ if ( attenuation <= 0 )
+ return;
+
+ // Now remove recipients that are outside sound radius
+ float distance, maxAudible;
+ Vector vecRelative;
+
+ int c = GetRecipientCount();
+
+ for ( int i = c - 1; i >= 0; i-- )
+ {
+ int index = GetRecipientIndex( i );
+
+ CBaseEntity *ent = CBaseEntity::Instance( index );
+ if ( !ent || !ent->IsPlayer() )
+ {
+ Assert( 0 );
+ continue;
+ }
+
+ CBasePlayer *player = ToBasePlayer( ent );
+ if ( !player )
+ {
+ Assert( 0 );
+ continue;
+ }
+
+#ifndef _XBOX
+ // never remove the HLTV or Replay bot
+ if ( player->IsHLTV() || player->IsReplay() )
+ continue;
+#endif
+
+ VectorSubtract( player->EarPosition(), origin, vecRelative );
+ distance = VectorLength( vecRelative );
+ maxAudible = ( 2 * SOUND_NORMAL_CLIP_DIST ) / attenuation;
+ if ( distance <= maxAudible )
+ continue;
+
+ RemoveRecipient( player );
+ }
+} \ No newline at end of file