You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
7.5 KiB
272 lines
7.5 KiB
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: implements various common send proxies |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "sendproxy.h" |
|
#include "basetypes.h" |
|
#include "baseentity.h" |
|
#include "team.h" |
|
#include "player.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
void SendProxy_Color32ToInt( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) |
|
{ |
|
color32 *pIn = (color32*)pData; |
|
*((unsigned int*)&pOut->m_Int) = ((unsigned int)pIn->r << 24) | ((unsigned int)pIn->g << 16) | ((unsigned int)pIn->b << 8) | ((unsigned int)pIn->a); |
|
} |
|
|
|
void SendProxy_EHandleToInt( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID) |
|
{ |
|
CBaseHandle *pHandle = (CBaseHandle*)pVarData; |
|
|
|
if ( pHandle && pHandle->Get() ) |
|
{ |
|
int iSerialNum = pHandle->GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; |
|
pOut->m_Int = pHandle->GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS); |
|
} |
|
else |
|
{ |
|
pOut->m_Int = INVALID_NETWORKED_EHANDLE_VALUE; |
|
} |
|
} |
|
|
|
void SendProxy_IntAddOne( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID) |
|
{ |
|
int *pInt = (int *)pVarData; |
|
|
|
pOut->m_Int = (*pInt) + 1; |
|
} |
|
|
|
void SendProxy_ShortAddOne( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID) |
|
{ |
|
short *pInt = (short *)pVarData; |
|
|
|
pOut->m_Int = (*pInt) + 1; |
|
} |
|
|
|
SendProp SendPropBool( |
|
char *pVarName, |
|
int offset, |
|
int sizeofVar ) |
|
{ |
|
Assert( sizeofVar == sizeof( bool ) ); |
|
return SendPropInt( pVarName, offset, sizeofVar, 1, SPROP_UNSIGNED ); |
|
} |
|
|
|
|
|
SendProp SendPropEHandle( |
|
char *pVarName, |
|
int offset, |
|
int flags, |
|
int sizeofVar, |
|
SendVarProxyFn proxyFn ) |
|
{ |
|
return SendPropInt( pVarName, offset, sizeofVar, NUM_NETWORKED_EHANDLE_BITS, SPROP_UNSIGNED|flags, proxyFn ); |
|
} |
|
|
|
SendProp SendPropIntWithMinusOneFlag( char *pVarName, int offset, int sizeofVar, int nBits, SendVarProxyFn proxyFn ) |
|
{ |
|
return SendPropInt( pVarName, offset, sizeofVar, nBits, SPROP_UNSIGNED, proxyFn ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Proxy that only sends data to team members |
|
// Input : *pStruct - |
|
// *pData - |
|
// *pOut - |
|
// objectID - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
void* SendProxy_OnlyToTeam( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) |
|
{ |
|
CBaseEntity *pEntity = (CBaseEntity*)pStruct; |
|
if ( pEntity ) |
|
{ |
|
CTeam *pTeam = pEntity->GetTeam(); |
|
if ( pTeam ) |
|
{ |
|
pRecipients->ClearAllRecipients(); |
|
for ( int i=0; i < pTeam->GetNumPlayers(); i++ ) |
|
pRecipients->SetRecipient( pTeam->GetPlayer( i )->GetClientIndex() ); |
|
|
|
return (void*)pVarData; |
|
} |
|
} |
|
|
|
return NULL; |
|
} |
|
REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( SendProxy_OnlyToTeam ); |
|
|
|
#define TIME_BITS 24 |
|
|
|
// This table encodes edict data. |
|
static void SendProxy_Time( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) |
|
{ |
|
float clock_base = floor( gpGlobals->curtime ); |
|
float t = *( float * )pVarData; |
|
float dt = t - clock_base; |
|
int addt = Floor2Int( 1000.0f * dt + 0.5f ); |
|
// TIME_BITS bits gives us TIME_BITS-1 bits plus sign bit |
|
int maxoffset = 1 << ( TIME_BITS - 1); |
|
|
|
addt = clamp( addt, -maxoffset, maxoffset ); |
|
|
|
pOut->m_Int = addt; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pVarName - |
|
// sizeofVar - |
|
// flags - |
|
// pId - |
|
// Output : SendProp |
|
//----------------------------------------------------------------------------- |
|
SendProp SendPropTime( |
|
char *pVarName, |
|
int offset, |
|
int sizeofVar ) |
|
{ |
|
// return SendPropInt( pVarName, offset, sizeofVar, TIME_BITS, 0, SendProxy_Time ); |
|
// FIXME: Re-enable above when it doesn't cause lots of deltas |
|
return SendPropFloat( pVarName, offset, sizeofVar, -1, SPROP_NOSCALE ); |
|
} |
|
|
|
#if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID ) |
|
#define PREDICTABLE_ID_BITS 31 |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Converts a predictable Id to an integer |
|
// Input : *pStruct - |
|
// *pVarData - |
|
// *pOut - |
|
// iElement - |
|
// objectID - |
|
//----------------------------------------------------------------------------- |
|
static void SendProxy_PredictableIdToInt( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) |
|
{ |
|
CPredictableId* pId = ( CPredictableId * )pVarData; |
|
if ( pId ) |
|
{ |
|
pOut->m_Int = pId->GetRaw(); |
|
} |
|
else |
|
{ |
|
pOut->m_Int = 0; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pVarName - |
|
// sizeofVar - |
|
// flags - |
|
// pId - |
|
// Output : SendProp |
|
//----------------------------------------------------------------------------- |
|
SendProp SendPropPredictableId( |
|
char *pVarName, |
|
int offset, |
|
int sizeofVar ) |
|
{ |
|
return SendPropInt( pVarName, offset, sizeofVar, PREDICTABLE_ID_BITS, SPROP_UNSIGNED, SendProxy_PredictableIdToInt ); |
|
} |
|
|
|
#endif |
|
|
|
void SendProxy_StringT_To_String( const SendProp *pProp, const void *pStruct, const void *pVarData, DVariant *pOut, int iElement, int objectID ) |
|
{ |
|
string_t &str = *((string_t*)pVarData); |
|
pOut->m_pString = (char*)STRING( str ); |
|
} |
|
|
|
|
|
SendProp SendPropStringT( char *pVarName, int offset, int sizeofVar ) |
|
{ |
|
// Make sure it's the right type. |
|
Assert( sizeofVar == sizeof( string_t ) ); |
|
|
|
return SendPropString( pVarName, offset, DT_MAX_STRING_BUFFERSIZE, 0, SendProxy_StringT_To_String ); |
|
} |
|
|
|
|
|
void CSendProxyRecipients::SetRecipient( int iClient ) |
|
{ |
|
m_Bits.Set( iClient ); |
|
} |
|
|
|
void CSendProxyRecipients::ClearRecipient( int iClient ) |
|
{ |
|
m_Bits.Clear( iClient ); |
|
} |
|
|
|
void CSendProxyRecipients::SetOnly( int iClient ) |
|
{ |
|
m_Bits.ClearAll(); |
|
SetRecipient( iClient ); |
|
|
|
CBaseEntity *pEntity = CBaseEntity::Instance( iClient + 1 ); |
|
if ( pEntity && pEntity->IsPlayer() ) |
|
{ |
|
CBasePlayer *pPlayer = static_cast< CBasePlayer * >( pEntity ); |
|
if ( pPlayer->IsSplitScreenPlayer() ) |
|
{ |
|
if ( pPlayer->GetSplitScreenPlayerOwner() ) |
|
{ |
|
SetRecipient( pPlayer->GetSplitScreenPlayerOwner()->entindex() - 1 ); |
|
} |
|
else |
|
{ |
|
AssertOnce( !"CSendProxyRecipients::SetOnly: NULL pPlayer->GetSplitScreenPlayerOwner()" ); |
|
} |
|
} |
|
else |
|
{ |
|
CUtlVector< CHandle< CBasePlayer> > &list = pPlayer->GetSplitScreenPlayers(); |
|
for ( int i = 0; i < list.Count(); ++i ) |
|
{ |
|
if ( !list[ i ] ) |
|
continue; |
|
|
|
int iEntIndex = list[ i ]->entindex(); |
|
SetRecipient( iEntIndex - 1 ); |
|
} |
|
} |
|
} |
|
} |
|
|
|
void CSendProxyRecipients::ExcludeOnly( int iClient ) |
|
{ |
|
m_Bits.SetAll(); |
|
ClearRecipient( iClient ); |
|
CBaseEntity *pEntity = CBaseEntity::Instance( iClient + 1 ); |
|
if ( pEntity && pEntity->IsPlayer() ) |
|
{ |
|
CBasePlayer *pPlayer = static_cast< CBasePlayer * >( pEntity ); |
|
if ( pPlayer->IsSplitScreenPlayer() ) |
|
{ |
|
if ( pPlayer->GetSplitScreenPlayerOwner() ) |
|
{ |
|
ClearRecipient( pPlayer->GetSplitScreenPlayerOwner()->entindex() - 1 ); |
|
} |
|
} |
|
else |
|
{ |
|
CUtlVector< CHandle< CBasePlayer> > &list = pPlayer->GetSplitScreenPlayers(); |
|
for ( int i = 0; i < list.Count(); ++i ) |
|
{ |
|
if ( !list[ i ] ) |
|
continue; |
|
|
|
int iEntIndex = list[ i ]->entindex(); |
|
ClearRecipient( iEntIndex - 1 ); |
|
} |
|
} |
|
} |
|
}
|
|
|