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.
781 lines
23 KiB
781 lines
23 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef NETWORKVAR_H |
|
#define NETWORKVAR_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
|
|
#include "tier0/dbg.h" |
|
#include "convar.h" |
|
|
|
#if defined( CLIENT_DLL ) || defined( GAME_DLL ) |
|
#include "basehandle.h" |
|
#endif |
|
|
|
|
|
#pragma warning( disable : 4284 ) // warning C4284: return type for 'CNetworkVarT<int>::operator ->' is 'int *' (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) |
|
|
|
#define MyOffsetOf( type, var ) ( (intp)&((type*)0)->var ) |
|
|
|
#ifdef _DEBUG |
|
extern bool g_bUseNetworkVars; |
|
#define CHECK_USENETWORKVARS if(g_bUseNetworkVars) |
|
#else |
|
#define CHECK_USENETWORKVARS // don't check for g_bUseNetworkVars |
|
#endif |
|
|
|
|
|
|
|
inline int InternalCheckDeclareClass( const char *pClassName, const char *pClassNameMatch, void *pTestPtr, void *pBasePtr ) |
|
{ |
|
// This makes sure that casting from ThisClass to BaseClass works right. You'll get a compiler error if it doesn't |
|
// work at all, and you'll get a runtime error if you use multiple inheritance. |
|
Assert( pTestPtr == pBasePtr ); |
|
|
|
// This is triggered by IMPLEMENT_SERVER_CLASS. It does DLLClassName::CheckDeclareClass( #DLLClassName ). |
|
// If they didn't do a DECLARE_CLASS in DLLClassName, then it'll be calling its base class's version |
|
// and the class names won't match. |
|
Assert( (void*)pClassName == (void*)pClassNameMatch ); |
|
return 0; |
|
} |
|
|
|
|
|
template <typename T> |
|
inline int CheckDeclareClass_Access( T *, const char *pShouldBe ) |
|
{ |
|
return T::CheckDeclareClass( pShouldBe ); |
|
} |
|
|
|
#ifndef _STATIC_LINKED |
|
#ifdef _MSC_VER |
|
#if defined(_DEBUG) && (_MSC_VER > 1200 ) |
|
#define VALIDATE_DECLARE_CLASS 1 |
|
#endif |
|
#endif |
|
#endif |
|
|
|
#ifdef VALIDATE_DECLARE_CLASS |
|
|
|
#define DECLARE_CLASS( className, baseClassName ) \ |
|
typedef baseClassName BaseClass; \ |
|
typedef className ThisClass; \ |
|
template <typename T> friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ |
|
static int CheckDeclareClass( const char *pShouldBe ) \ |
|
{ \ |
|
InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \ |
|
return CheckDeclareClass_Access( (BaseClass *)NULL, #baseClassName ); \ |
|
} |
|
|
|
// Use this macro when you have a base class, but it's part of a library that doesn't use network vars |
|
// or any of the things that use ThisClass or BaseClass. |
|
#define DECLARE_CLASS_GAMEROOT( className, baseClassName ) \ |
|
typedef baseClassName BaseClass; \ |
|
typedef className ThisClass; \ |
|
template <typename T> friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ |
|
static int CheckDeclareClass( const char *pShouldBe ) \ |
|
{ \ |
|
return InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \ |
|
} |
|
|
|
// Deprecated macro formerly used to work around VC++98 bug |
|
#define DECLARE_CLASS_NOFRIEND( className, baseClassName ) \ |
|
DECLARE_CLASS( className, baseClassName ) |
|
|
|
#define DECLARE_CLASS_NOBASE( className ) \ |
|
typedef className ThisClass; \ |
|
template <typename T> friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \ |
|
static int CheckDeclareClass( const char *pShouldBe ) \ |
|
{ \ |
|
return InternalCheckDeclareClass( pShouldBe, #className, 0, 0 ); \ |
|
} |
|
|
|
#else |
|
#define DECLARE_CLASS( className, baseClassName ) \ |
|
typedef baseClassName BaseClass; \ |
|
typedef className ThisClass; |
|
|
|
#define DECLARE_CLASS_GAMEROOT( className, baseClassName ) DECLARE_CLASS( className, baseClassName ) |
|
#define DECLARE_CLASS_NOFRIEND( className, baseClassName ) DECLARE_CLASS( className, baseClassName ) |
|
|
|
#define DECLARE_CLASS_NOBASE( className ) typedef className ThisClass; |
|
#endif |
|
|
|
|
|
|
|
|
|
// All classes that contain CNetworkVars need a NetworkStateChanged() function. If the class is not an entity, |
|
// it needs to forward the call to the entity it's in. These macros can help. |
|
|
|
// These macros setup an entity pointer in your class. Use IMPLEMENT_NETWORKVAR_CHAIN before you do |
|
// anything inside the class itself. |
|
class CBaseEntity; |
|
class CAutoInitEntPtr |
|
{ |
|
public: |
|
CAutoInitEntPtr() |
|
{ |
|
m_pEnt = NULL; |
|
} |
|
CBaseEntity *m_pEnt; |
|
}; |
|
|
|
//TODO: Currently, these don't get the benefit of tracking changes to individual vars. |
|
// Would be nice if they did. |
|
#define DECLARE_NETWORKVAR_CHAIN() \ |
|
CAutoInitEntPtr __m_pChainEntity; \ |
|
void NetworkStateChanged() { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); } \ |
|
void NetworkStateChanged( void *pVar ) { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); } |
|
|
|
#define IMPLEMENT_NETWORKVAR_CHAIN( varName ) \ |
|
(varName)->__m_pChainEntity.m_pEnt = this; |
|
|
|
|
|
|
|
// Use this macro when you want to embed a structure inside your entity and have CNetworkVars in it. |
|
template< class T > |
|
static inline void DispatchNetworkStateChanged( T *pObj ) |
|
{ |
|
CHECK_USENETWORKVARS pObj->NetworkStateChanged(); |
|
} |
|
template< class T > |
|
static inline void DispatchNetworkStateChanged( T *pObj, void *pVar ) |
|
{ |
|
CHECK_USENETWORKVARS pObj->NetworkStateChanged( pVar ); |
|
} |
|
|
|
|
|
#define DECLARE_EMBEDDED_NETWORKVAR() \ |
|
template <typename T> friend int ServerClassInit(T *); \ |
|
template <typename T> friend int ClientClassInit(T *); \ |
|
virtual void NetworkStateChanged() {} virtual void NetworkStateChanged( void *pProp ) {} |
|
|
|
// NOTE: Assignment operator is disabled because it doesn't call copy constructors of scalar types within the aggregate, so they are not marked changed |
|
#define CNetworkVarEmbedded( type, name ) \ |
|
class NetworkVar_##name; \ |
|
friend class NetworkVar_##name; \ |
|
static inline int GetOffset_##name() { return MyOffsetOf(ThisClass,name); } \ |
|
typedef ThisClass ThisClass_##name; \ |
|
class NetworkVar_##name : public type \ |
|
{ \ |
|
template< class T > NetworkVar_##name& operator=( const T &val ) { *((type*)this) = val; return *this; } \ |
|
public: \ |
|
void CopyFrom( const type &src ) { *((type *)this) = src; NetworkStateChanged(); } \ |
|
virtual void NetworkStateChanged() \ |
|
{ \ |
|
DispatchNetworkStateChanged( (ThisClass_##name*)( ((char*)this) - GetOffset_##name() ) ); \ |
|
} \ |
|
virtual void NetworkStateChanged( void *pVar ) \ |
|
{ \ |
|
DispatchNetworkStateChanged( (ThisClass_##name*)( ((char*)this) - GetOffset_##name() ), pVar ); \ |
|
} \ |
|
}; \ |
|
NetworkVar_##name name; |
|
|
|
template<typename T> |
|
FORCEINLINE void NetworkVarConstruct( T &x ) { x = T(0); } |
|
FORCEINLINE void NetworkVarConstruct( color32_s &x ) { x.r = x.g = x.b = x.a = 0; } |
|
|
|
template< class Type, class Changer > |
|
class CNetworkVarBase |
|
{ |
|
public: |
|
inline CNetworkVarBase() |
|
{ |
|
NetworkVarConstruct( m_Value ); |
|
} |
|
|
|
template< class C > |
|
const Type& operator=( const C &val ) |
|
{ |
|
return Set( ( const Type )val ); |
|
} |
|
|
|
template< class C > |
|
const Type& operator=( const CNetworkVarBase< C, Changer > &val ) |
|
{ |
|
return Set( ( const Type )val.m_Value ); |
|
} |
|
|
|
const Type& Set( const Type &val ) |
|
{ |
|
if ( memcmp( &m_Value, &val, sizeof(Type) ) ) |
|
{ |
|
NetworkStateChanged(); |
|
m_Value = val; |
|
} |
|
return m_Value; |
|
} |
|
|
|
Type& GetForModify() |
|
{ |
|
NetworkStateChanged(); |
|
return m_Value; |
|
} |
|
|
|
template< class C > |
|
const Type& operator+=( const C &val ) |
|
{ |
|
return Set( m_Value + ( const Type )val ); |
|
} |
|
|
|
template< class C > |
|
const Type& operator-=( const C &val ) |
|
{ |
|
return Set( m_Value - ( const Type )val ); |
|
} |
|
|
|
template< class C > |
|
const Type& operator/=( const C &val ) |
|
{ |
|
return Set( m_Value / ( const Type )val ); |
|
} |
|
|
|
template< class C > |
|
const Type& operator*=( const C &val ) |
|
{ |
|
return Set( m_Value * ( const Type )val ); |
|
} |
|
|
|
template< class C > |
|
const Type& operator^=( const C &val ) |
|
{ |
|
return Set( m_Value ^ ( const Type )val ); |
|
} |
|
|
|
template< class C > |
|
const Type& operator|=( const C &val ) |
|
{ |
|
return Set( m_Value | ( const Type )val ); |
|
} |
|
|
|
const Type& operator++() |
|
{ |
|
return (*this += 1); |
|
} |
|
|
|
Type operator--() |
|
{ |
|
return (*this -= 1); |
|
} |
|
|
|
Type operator++( int ) // postfix version.. |
|
{ |
|
Type val = m_Value; |
|
(*this += 1); |
|
return val; |
|
} |
|
|
|
Type operator--( int ) // postfix version.. |
|
{ |
|
Type val = m_Value; |
|
(*this -= 1); |
|
return val; |
|
} |
|
|
|
// For some reason the compiler only generates type conversion warnings for this operator when used like |
|
// CNetworkVarBase<unsigned char> = 0x1 |
|
// (it warns about converting from an int to an unsigned char). |
|
template< class C > |
|
const Type& operator&=( const C &val ) |
|
{ |
|
return Set( m_Value & ( const Type )val ); |
|
} |
|
|
|
operator const Type&() const |
|
{ |
|
return m_Value; |
|
} |
|
|
|
const Type& Get() const |
|
{ |
|
return m_Value; |
|
} |
|
|
|
const Type* operator->() const |
|
{ |
|
return &m_Value; |
|
} |
|
|
|
Type m_Value; |
|
|
|
protected: |
|
inline void NetworkStateChanged() |
|
{ |
|
Changer::NetworkStateChanged( this ); |
|
} |
|
}; |
|
|
|
|
|
template< class Type, class Changer > |
|
class CNetworkColor32Base : public CNetworkVarBase< Type, Changer > |
|
{ |
|
public: |
|
inline void Init( byte rVal, byte gVal, byte bVal ) |
|
{ |
|
SetR( rVal ); |
|
SetG( gVal ); |
|
SetB( bVal ); |
|
} |
|
inline void Init( byte rVal, byte gVal, byte bVal, byte aVal ) |
|
{ |
|
SetR( rVal ); |
|
SetG( gVal ); |
|
SetB( bVal ); |
|
SetA( aVal ); |
|
} |
|
|
|
const Type& operator=( const Type &val ) |
|
{ |
|
return this->Set( val ); |
|
} |
|
|
|
const Type& operator=( const CNetworkColor32Base<Type,Changer> &val ) |
|
{ |
|
return CNetworkVarBase<Type,Changer>::Set( val.m_Value ); |
|
} |
|
|
|
inline byte GetR() const { return CNetworkColor32Base<Type,Changer>::m_Value.r; } |
|
inline byte GetG() const { return CNetworkColor32Base<Type,Changer>::m_Value.g; } |
|
inline byte GetB() const { return CNetworkColor32Base<Type,Changer>::m_Value.b; } |
|
inline byte GetA() const { return CNetworkColor32Base<Type,Changer>::m_Value.a; } |
|
inline void SetR( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.r, val ); } |
|
inline void SetG( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.g, val ); } |
|
inline void SetB( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.b, val ); } |
|
inline void SetA( byte val ) { SetVal( CNetworkColor32Base<Type,Changer>::m_Value.a, val ); } |
|
|
|
protected: |
|
inline void SetVal( byte &out, const byte &in ) |
|
{ |
|
if ( out != in ) |
|
{ |
|
CNetworkVarBase< Type, Changer >::NetworkStateChanged(); |
|
out = in; |
|
} |
|
} |
|
}; |
|
|
|
|
|
// Network vector wrapper. |
|
template< class Type, class Changer > |
|
class CNetworkVectorBase : public CNetworkVarBase< Type, Changer > |
|
{ |
|
public: |
|
inline void Init( float ix=0, float iy=0, float iz=0 ) |
|
{ |
|
SetX( ix ); |
|
SetY( iy ); |
|
SetZ( iz ); |
|
} |
|
|
|
const Type& operator=( const Type &val ) |
|
{ |
|
return CNetworkVarBase< Type, Changer >::Set( val ); |
|
} |
|
|
|
const Type& operator=( const CNetworkVectorBase<Type,Changer> &val ) |
|
{ |
|
return CNetworkVarBase<Type,Changer>::Set( val.m_Value ); |
|
} |
|
|
|
inline float GetX() const { return CNetworkVectorBase<Type,Changer>::m_Value.x; } |
|
inline float GetY() const { return CNetworkVectorBase<Type,Changer>::m_Value.y; } |
|
inline float GetZ() const { return CNetworkVectorBase<Type,Changer>::m_Value.z; } |
|
inline float operator[]( int i ) const { return CNetworkVectorBase<Type,Changer>::m_Value[i]; } |
|
|
|
inline void SetX( float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value.x, val ); } |
|
inline void SetY( float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value.y, val ); } |
|
inline void SetZ( float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value.z, val ); } |
|
inline void Set( int i, float val ) { DetectChange( CNetworkVectorBase<Type,Changer>::m_Value[i], val ); } |
|
|
|
bool operator==( const Type &val ) const |
|
{ |
|
return CNetworkVectorBase<Type,Changer>::m_Value == (Type)val; |
|
} |
|
|
|
bool operator!=( const Type &val ) const |
|
{ |
|
return CNetworkVectorBase<Type,Changer>::m_Value != (Type)val; |
|
} |
|
|
|
const Type operator+( const Type &val ) const |
|
{ |
|
return CNetworkVectorBase<Type,Changer>::m_Value + val; |
|
} |
|
|
|
const Type operator-( const Type &val ) const |
|
{ |
|
return CNetworkVectorBase<Type,Changer>::m_Value - val; |
|
} |
|
|
|
const Type operator*( const Type &val ) const |
|
{ |
|
return CNetworkVectorBase<Type,Changer>::m_Value * val; |
|
} |
|
|
|
const Type& operator*=( float val ) |
|
{ |
|
return CNetworkVarBase< Type, Changer >::Set( CNetworkVectorBase<Type,Changer>::m_Value * val ); |
|
} |
|
|
|
const Type operator*( float val ) const |
|
{ |
|
return CNetworkVectorBase<Type,Changer>::m_Value * val; |
|
} |
|
|
|
const Type operator/( const Type &val ) const |
|
{ |
|
return CNetworkVectorBase<Type,Changer>::m_Value / val; |
|
} |
|
|
|
private: |
|
inline void DetectChange( float &out, float in ) |
|
{ |
|
if ( out != in ) |
|
{ |
|
CNetworkVectorBase<Type,Changer>::NetworkStateChanged(); |
|
out = in; |
|
} |
|
} |
|
}; |
|
|
|
|
|
// Network vector wrapper. |
|
template< class Type, class Changer > |
|
class CNetworkQuaternionBase : public CNetworkVarBase< Type, Changer > |
|
{ |
|
public: |
|
inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 ) |
|
{ |
|
SetX( ix ); |
|
SetY( iy ); |
|
SetZ( iz ); |
|
SetW( iw ); |
|
} |
|
|
|
const Type& operator=( const Type &val ) |
|
{ |
|
return CNetworkVarBase< Type, Changer >::Set( val ); |
|
} |
|
|
|
const Type& operator=( const CNetworkQuaternionBase<Type,Changer> &val ) |
|
{ |
|
return CNetworkVarBase<Type,Changer>::Set( val.m_Value ); |
|
} |
|
|
|
inline float GetX() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.x; } |
|
inline float GetY() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.y; } |
|
inline float GetZ() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.z; } |
|
inline float GetW() const { return CNetworkQuaternionBase<Type,Changer>::m_Value.w; } |
|
inline float operator[]( int i ) const { return CNetworkQuaternionBase<Type,Changer>::m_Value[i]; } |
|
|
|
inline void SetX( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.x, val ); } |
|
inline void SetY( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.y, val ); } |
|
inline void SetZ( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.z, val ); } |
|
inline void SetW( float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value.w, val ); } |
|
inline void Set( int i, float val ) { DetectChange( CNetworkQuaternionBase<Type,Changer>::m_Value[i], val ); } |
|
|
|
bool operator==( const Type &val ) const |
|
{ |
|
return CNetworkQuaternionBase<Type,Changer>::m_Value == (Type)val; |
|
} |
|
|
|
bool operator!=( const Type &val ) const |
|
{ |
|
return CNetworkQuaternionBase<Type,Changer>::m_Value != (Type)val; |
|
} |
|
|
|
const Type operator+( const Type &val ) const |
|
{ |
|
return CNetworkQuaternionBase<Type,Changer>::m_Value + val; |
|
} |
|
|
|
const Type operator-( const Type &val ) const |
|
{ |
|
return CNetworkQuaternionBase<Type,Changer>::m_Value - val; |
|
} |
|
|
|
const Type operator*( const Type &val ) const |
|
{ |
|
return CNetworkQuaternionBase<Type,Changer>::m_Value * val; |
|
} |
|
|
|
const Type& operator*=( float val ) |
|
{ |
|
return CNetworkQuaternionBase< Type, Changer >::Set( CNetworkQuaternionBase<Type,Changer>::m_Value * val ); |
|
} |
|
|
|
const Type operator*( float val ) const |
|
{ |
|
return CNetworkQuaternionBase<Type,Changer>::m_Value * val; |
|
} |
|
|
|
const Type operator/( const Type &val ) const |
|
{ |
|
return CNetworkQuaternionBase<Type,Changer>::m_Value / val; |
|
} |
|
|
|
private: |
|
inline void DetectChange( float &out, float in ) |
|
{ |
|
if ( out != in ) |
|
{ |
|
CNetworkQuaternionBase<Type,Changer>::NetworkStateChanged(); |
|
out = in; |
|
} |
|
} |
|
}; |
|
|
|
|
|
// Network ehandle wrapper. |
|
#if defined( CLIENT_DLL ) || defined( GAME_DLL ) |
|
inline void NetworkVarConstruct( CBaseHandle &x ) {} |
|
|
|
template< class Type, class Changer > |
|
class CNetworkHandleBase : public CNetworkVarBase< CBaseHandle, Changer > |
|
{ |
|
public: |
|
const Type* operator=( const Type *val ) |
|
{ |
|
return Set( val ); |
|
} |
|
|
|
const Type& operator=( const CNetworkHandleBase<Type,Changer> &val ) |
|
{ |
|
const CBaseHandle &handle = CNetworkVarBase<CBaseHandle,Changer>::Set( val.m_Value ); |
|
return *(const Type*)handle.Get(); |
|
} |
|
|
|
bool operator !() const |
|
{ |
|
return !CNetworkHandleBase<Type,Changer>::m_Value.Get(); |
|
} |
|
|
|
operator Type*() const |
|
{ |
|
return static_cast< Type* >( CNetworkHandleBase<Type,Changer>::m_Value.Get() ); |
|
} |
|
|
|
const Type* Set( const Type *val ) |
|
{ |
|
if ( CNetworkHandleBase<Type,Changer>::m_Value != val ) |
|
{ |
|
this->NetworkStateChanged(); |
|
CNetworkHandleBase<Type,Changer>::m_Value = val; |
|
} |
|
return val; |
|
} |
|
|
|
Type* Get() const |
|
{ |
|
return static_cast< Type* >( CNetworkHandleBase<Type,Changer>::m_Value.Get() ); |
|
} |
|
|
|
Type* operator->() const |
|
{ |
|
return static_cast< Type* >( CNetworkHandleBase<Type,Changer>::m_Value.Get() ); |
|
} |
|
|
|
bool operator==( const Type *val ) const |
|
{ |
|
return CNetworkHandleBase<Type,Changer>::m_Value == val; |
|
} |
|
|
|
bool operator!=( const Type *val ) const |
|
{ |
|
return CNetworkHandleBase<Type,Changer>::m_Value != val; |
|
} |
|
}; |
|
|
|
|
|
|
|
#define CNetworkHandle( type, name ) CNetworkHandleInternal( type, name, NetworkStateChanged ) |
|
|
|
#define CNetworkHandleInternal( type, name, stateChangedFn ) \ |
|
NETWORK_VAR_START( type, name ) \ |
|
NETWORK_VAR_END( type, name, CNetworkHandleBase, stateChangedFn ) |
|
#endif |
|
|
|
|
|
// Use this macro to define a network variable. |
|
#define CNetworkVar( type, name ) \ |
|
NETWORK_VAR_START( type, name ) \ |
|
NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged ) |
|
|
|
|
|
// Use this macro when you have a base class with a variable, and it doesn't have that variable in a SendTable, |
|
// but a derived class does. Then, the entity is only flagged as changed when the variable is changed in |
|
// an entity that wants to transmit the variable. |
|
#define CNetworkVarForDerived( type, name ) \ |
|
virtual void NetworkStateChanged_##name() {} \ |
|
virtual void NetworkStateChanged_##name( void *pVar ) {} \ |
|
NETWORK_VAR_START( type, name ) \ |
|
NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name ) |
|
|
|
#define CNetworkVectorForDerived( name ) \ |
|
virtual void NetworkStateChanged_##name() {} \ |
|
virtual void NetworkStateChanged_##name( void *pVar ) {} \ |
|
CNetworkVectorInternal( Vector, name, NetworkStateChanged_##name ) |
|
|
|
#define CNetworkHandleForDerived( type, name ) \ |
|
virtual void NetworkStateChanged_##name() {} \ |
|
virtual void NetworkStateChanged_##name( void *pVar ) {} \ |
|
CNetworkHandleInternal( type, name, NetworkStateChanged_##name ) |
|
|
|
#define CNetworkArrayForDerived( type, name, count ) \ |
|
virtual void NetworkStateChanged_##name() {} \ |
|
virtual void NetworkStateChanged_##name( void *pVar ) {} \ |
|
CNetworkArrayInternal( type, name, count, NetworkStateChanged_##name ) |
|
|
|
#define IMPLEMENT_NETWORK_VAR_FOR_DERIVED( name ) \ |
|
virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \ |
|
virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); } |
|
|
|
|
|
// This virtualizes the change detection on the variable, but it is ON by default. |
|
// Use this when you have a base class in which MOST of its derived classes use this variable |
|
// in their SendTables, but there are a couple that don't (and they |
|
// can use DISABLE_NETWORK_VAR_FOR_DERIVED). |
|
#define CNetworkVarForDerived_OnByDefault( type, name ) \ |
|
virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \ |
|
virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); } \ |
|
NETWORK_VAR_START( type, name ) \ |
|
NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name ) |
|
|
|
#define DISABLE_NETWORK_VAR_FOR_DERIVED( name ) \ |
|
virtual void NetworkStateChanged_##name() {} \ |
|
virtual void NetworkStateChanged_##name( void *pVar ) {} |
|
|
|
|
|
|
|
// Vectors + some convenient helper functions. |
|
#define CNetworkVector( name ) CNetworkVectorInternal( Vector, name, NetworkStateChanged ) |
|
#define CNetworkQAngle( name ) CNetworkVectorInternal( QAngle, name, NetworkStateChanged ) |
|
|
|
#define CNetworkVectorInternal( type, name, stateChangedFn ) \ |
|
NETWORK_VAR_START( type, name ) \ |
|
NETWORK_VAR_END( type, name, CNetworkVectorBase, stateChangedFn ) |
|
|
|
#define CNetworkQuaternion( name ) \ |
|
NETWORK_VAR_START( Quaternion, name ) \ |
|
NETWORK_VAR_END( Quaternion, name, CNetworkQuaternionBase, NetworkStateChanged ) |
|
|
|
// Helper for color32's. Contains GetR(), SetR(), etc.. functions. |
|
#define CNetworkColor32( name ) \ |
|
NETWORK_VAR_START( color32, name ) \ |
|
NETWORK_VAR_END( color32, name, CNetworkColor32Base, NetworkStateChanged ) |
|
|
|
|
|
#define CNetworkString( name, length ) \ |
|
class NetworkVar_##name; \ |
|
friend class NetworkVar_##name; \ |
|
typedef ThisClass MakeANetworkVar_##name; \ |
|
class NetworkVar_##name \ |
|
{ \ |
|
public: \ |
|
NetworkVar_##name() { m_Value[0] = '\0'; } \ |
|
operator const char*() const { return m_Value; } \ |
|
const char* Get() const { return m_Value; } \ |
|
char* GetForModify() \ |
|
{ \ |
|
NetworkStateChanged(); \ |
|
return m_Value; \ |
|
} \ |
|
protected: \ |
|
inline void NetworkStateChanged() \ |
|
{ \ |
|
CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->NetworkStateChanged(); \ |
|
} \ |
|
private: \ |
|
char m_Value[length]; \ |
|
}; \ |
|
NetworkVar_##name name; |
|
|
|
|
|
|
|
|
|
// Use this to define networked arrays. |
|
// You can access elements for reading with operator[], and you can set elements with the Set() function. |
|
#define CNetworkArrayInternal( type, name, count, stateChangedFn ) \ |
|
class NetworkVar_##name; \ |
|
friend class NetworkVar_##name; \ |
|
typedef ThisClass MakeANetworkVar_##name; \ |
|
class NetworkVar_##name \ |
|
{ \ |
|
public: \ |
|
inline NetworkVar_##name() \ |
|
{ \ |
|
for ( int i = 0 ; i < count ; ++i ) \ |
|
NetworkVarConstruct( m_Value[i] ); \ |
|
} \ |
|
template <typename T> friend int ServerClassInit(T *); \ |
|
const type& operator[]( int i ) const \ |
|
{ \ |
|
return Get( i ); \ |
|
} \ |
|
\ |
|
const type& Get( int i ) const \ |
|
{ \ |
|
Assert( i >= 0 && i < count ); \ |
|
return m_Value[i]; \ |
|
} \ |
|
\ |
|
type& GetForModify( int i ) \ |
|
{ \ |
|
Assert( i >= 0 && i < count ); \ |
|
NetworkStateChanged( i ); \ |
|
return m_Value[i]; \ |
|
} \ |
|
\ |
|
void Set( int i, const type &val ) \ |
|
{ \ |
|
Assert( i >= 0 && i < count ); \ |
|
if( memcmp( &m_Value[i], &val, sizeof(type) ) ) \ |
|
{ \ |
|
NetworkStateChanged( i ); \ |
|
m_Value[i] = val; \ |
|
} \ |
|
} \ |
|
const type* Base() const { return m_Value; } \ |
|
int Count() const { return count; } \ |
|
protected: \ |
|
inline void NetworkStateChanged( int net_change_index ) \ |
|
{ \ |
|
CHECK_USENETWORKVARS ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name)))->stateChangedFn( &m_Value[net_change_index] ); \ |
|
} \ |
|
type m_Value[count]; \ |
|
}; \ |
|
NetworkVar_##name name; |
|
|
|
|
|
#define CNetworkArray( type, name, count ) CNetworkArrayInternal( type, name, count, NetworkStateChanged ) |
|
|
|
|
|
// Internal macros used in definitions of network vars. |
|
#define NETWORK_VAR_START( type, name ) \ |
|
class NetworkVar_##name; \ |
|
friend class NetworkVar_##name; \ |
|
typedef ThisClass MakeANetworkVar_##name; \ |
|
class NetworkVar_##name \ |
|
{ \ |
|
public: \ |
|
template <typename T> friend int ServerClassInit(T *); |
|
|
|
|
|
#define NETWORK_VAR_END( type, name, base, stateChangedFn ) \ |
|
public: \ |
|
static inline void NetworkStateChanged( void *ptr ) \ |
|
{ \ |
|
CHECK_USENETWORKVARS ((ThisClass*)(((char*)ptr) - MyOffsetOf(ThisClass,name)))->stateChangedFn( ptr ); \ |
|
} \ |
|
}; \ |
|
base< type, NetworkVar_##name > name; |
|
|
|
|
|
|
|
#endif // NETWORKVAR_H
|
|
|