csgo-2018-source/public/networkvar_vector.h

342 lines
9.4 KiB
C
Raw Normal View History

2021-07-25 12:11:47 +08:00
//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//
// Included by networkvar.h
//
//==================================================================================================
#ifndef NETWORKVAR_VECTOR_H
#define NETWORKVAR_VECTOR_H
#ifdef _WIN32
#pragma once
#endif
// This is the normal case.. you've got a SendPropVector to match your CNetworkVector
#define CNetworkVector( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged, CNetworkVectorBase )
// This variant of a CNetworkVector should be used if you want to use SendPropFloat
// on each individual component of the vector.
#define CNetworkVectorXYZ( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged, CNetworkVectorXYZBase )
// This variant of a CNetworkVector should be used if you want to use SendPropVectorXY
// for the XY components and SendPropFloat for the Z component.
#define CNetworkVectorXY_SeparateZ( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged, CNetworkVectorXY_SeparateZBase )
// This is the normal case.. you've got a SendPropQAngle to match your CNetworkQAngle
#define CNetworkQAngle( name ) CNetworkVectorInternal( QAngle, name, NetworkStateChanged, CNetworkVectorBase )
// This variant of a CNetworkQAngle should be used if you want to use SendPropFloat
// on each individual component of the vector.
#define CNetworkQAngleXYZ( name ) CNetworkVectorInternal( QAngle, name, NetworkStateChanged, CNetworkVectorXYZBase )
//
// Use these variants if you want the networkvar to not trigger a change in the baseclass
// version but you might want it to trigger changes in derived classes that do network that variable.
//
#define CNetworkVectorForDerived( name ) \
virtual void NetworkStateChanged_##name() {} \
virtual void NetworkStateChanged_##name( void *pVar ) {} \
CNetworkVectorInternal( Vector, name, NetworkStateChanged_##name, CNetworkVectorBase )
#define CNetworkVectorXYZForDerived( name ) \
virtual void NetworkStateChanged_##name() {} \
virtual void NetworkStateChanged_##name( void *pVar ) {} \
CNetworkVectorInternal( Vector, name, NetworkStateChanged_##name, CNetworkVectorXYZBase )
#define CNetworkVectorInternal( type, name, stateChangedFn, baseClass ) \
NETWORK_VAR_START( type, name ) \
NETWORK_VAR_END( type, name, baseClass, stateChangedFn )
// Network vector wrapper.
//
// The common base is shared between all CNetworkVectors.
// It includes everything but the Set() and operator=() functions,
// because the behavior of each of those is different for each vector type.
template< class Type, class Changer >
class CNetworkVectorCommonBase : public CNetworkVarBase< Type, Changer >
{
typedef CNetworkVarBase< Type, Changer > base;
public:
FORCEINLINE void Init( float ix=0, float iy=0, float iz=0 )
{
base::Set( Type( ix, iy, iz ) );
}
FORCEINLINE float GetX() const { return this->m_Value.x; }
FORCEINLINE float GetY() const { return this->m_Value.y; }
FORCEINLINE float GetZ() const { return this->m_Value.z; }
FORCEINLINE float operator[]( int i ) const { return this->m_Value[i]; }
FORCEINLINE bool operator==( const Type &val ) const
{
return this->m_Value == (Type)val;
}
FORCEINLINE bool operator!=( const Type &val ) const
{
return this->m_Value != (Type)val;
}
FORCEINLINE const Type operator+( const Type &val ) const
{
return this->m_Value + val;
}
FORCEINLINE const Type operator-( const Type &val ) const
{
return this->m_Value - val;
}
FORCEINLINE const Type operator*( const Type &val ) const
{
return this->m_Value * val;
}
FORCEINLINE const Type& operator*=( float val )
{
return base::Set( this->m_Value * val );
}
FORCEINLINE const Type operator*( float val ) const
{
return this->m_Value * val;
}
FORCEINLINE const Type operator/( const Type &val ) const
{
return this->m_Value / val;
}
protected:
FORCEINLINE void DetectChange( float &out, float in )
{
if ( out != in )
{
this->NetworkStateChanged();
out = in;
}
}
};
//
// This is for a CNetworkVector that only generates one change offset.
// It should only ever be used with SendPropVector/QAngle.
//
// Single-component things like SendPropFloat should never refer to it because
// they require the network var to report an offset for each component.
//
template< class Type, class Changer >
class CNetworkVectorBase : public CNetworkVectorCommonBase< Type, Changer >
{
typedef CNetworkVarBase< Type, Changer > base;
public:
static FORCEINLINE int GetNetworkVarFlags() { return NETWORKVAR_IS_A_VECTOR; }
FORCEINLINE const Type& operator=( const Type &val )
{
return base::Set( val );
}
FORCEINLINE const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
{
return base::Set( val.m_Value );
}
FORCEINLINE void SetX( float val ) { this->DetectChange( this->m_Value.x, val ); }
FORCEINLINE void SetY( float val ) { this->DetectChange( this->m_Value.y, val ); }
FORCEINLINE void SetZ( float val ) { this->DetectChange( this->m_Value.z, val ); }
FORCEINLINE void Set( int i, float val ) { this->DetectChange( this->m_Value[i], val ); }
FORCEINLINE const Type& operator*=( float val )
{
return base::Set( this->m_Value * val );
}
};
//
// This variant of a CNetworkVector should be used if you want to use SendPropFloat
// on each individual component of the vector.
//
template< class Type, class Changer >
class CNetworkVectorXYZBase : public CNetworkVectorCommonBase< Type, Changer >
{
typedef CNetworkVectorCommonBase< Type, Changer > base;
public:
static FORCEINLINE int GetNetworkVarFlags() { return NETWORKVAR_IS_A_VECTOR | NETWORKVAR_VECTOR_XYZ_FLAG; }
FORCEINLINE const Type& operator=( const Type &val )
{
return Set( val );
}
FORCEINLINE const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
{
return Set( val.m_Value );
}
FORCEINLINE const Type& Set( const Type &val )
{
SetX( val.x );
SetY( val.y );
SetZ( val.z );
return this->m_Value;
}
FORCEINLINE Type& GetForModify()
{
this->NetworkStateChanged( &((float*)this)[0] );
this->NetworkStateChanged( &((float*)this)[1] );
this->NetworkStateChanged( &((float*)this)[2] );
return this->m_Value;
}
FORCEINLINE const Type& SetDirect( const Type &val )
{
GetForModify() = val;
return this->m_Value;
}
FORCEINLINE void SetX( float val ) { DetectChange( 0, val ); }
FORCEINLINE void SetY( float val ) { DetectChange( 1, val ); }
FORCEINLINE void SetZ( float val ) { DetectChange( 2, val ); }
FORCEINLINE void Set( int i, float val ) { DetectChange( i, val ); }
FORCEINLINE const Type& operator+=( const Type &val )
{
return Set( this->m_Value + val );
}
FORCEINLINE const Type& operator-=( const Type &val )
{
return Set( this->m_Value - val );
}
FORCEINLINE const Type& operator*=( float val )
{
return Set( this->m_Value * val );
}
FORCEINLINE const Type& operator/=( float val )
{
return Set( this->m_Value / val );
}
private:
FORCEINLINE void DetectChange( int nComponent, float in )
{
float *pVar = &((float*)this)[nComponent];
if ( *pVar != in )
{
if ( pVar != &((float*)this)[0] )
{
this->NetworkStateChanged( &((float*)this)[0] ); // Always mark the start of the vector as changed
}
this->NetworkStateChanged( pVar );
*pVar = in;
}
}
};
//
// This variant of a CNetworkVector should be used if you want to use SendPropVectorXY
// for the XY components and SendPropFloat for the Z component.
//
template< class Type, class Changer >
class CNetworkVectorXY_SeparateZBase : public CNetworkVectorCommonBase< Type, Changer >
{
typedef CNetworkVectorCommonBase< Type, Changer > base;
public:
static FORCEINLINE int GetNetworkVarFlags() { return NETWORKVAR_IS_A_VECTOR | NETWORKVAR_VECTOR_XY_SEPARATEZ_FLAG; }
FORCEINLINE const Type& operator=( const Type &val )
{
return Set( val );
}
FORCEINLINE const Type& operator=( const CNetworkVectorBase<Type,Changer> &val )
{
return Set( val.m_Value );
}
FORCEINLINE const Type& Set( const Type &val )
{
SetX( val.x );
SetY( val.y );
SetZ( val.z );
return this->m_Value;
}
FORCEINLINE Type& GetForModify()
{
this->NetworkStateChanged( &((float*)this)[0] ); // Mark the offset of our XY SendProp as changed.
this->NetworkStateChanged( &((float*)this)[2] ); // Mark the offset of our Z SendProp as changed.
return this->m_Value;
}
FORCEINLINE const Type& SetDirect( const Type &val )
{
GetForModify() = val;
return this->m_Value;
}
FORCEINLINE void SetX( float val ) { DetectChange( 0, val ); }
FORCEINLINE void SetY( float val ) { DetectChange( 1, val ); }
FORCEINLINE void SetZ( float val ) { DetectChange( 2, val ); }
FORCEINLINE void Set( int i, float val ) { DetectChange( i, val ); }
FORCEINLINE const Type& operator+=( const Type &val )
{
return Set( this->m_Value + val );
}
FORCEINLINE const Type& operator-=( const Type &val )
{
return Set( this->m_Value - val );
}
FORCEINLINE const Type& operator*=( float val )
{
return Set( this->m_Value * val );
}
FORCEINLINE const Type& operator/=( float val )
{
return Set( this->m_Value / val );
}
private:
FORCEINLINE void DetectChange( int nComponent, float in )
{
float *pVar = &((float*)this)[nComponent];
if ( *pVar != in )
{
this->NetworkStateChanged( &((float*)this)[0] ); // Mark the offset of our XY SendProp as changed.
this->NetworkStateChanged( &((float*)this)[2] ); // Mark the offset of our Z SendProp as changed.
*pVar = in;
}
}
};
#endif // NETWORKVAR_VECTOR_H