Counter Strike : Global Offensive Source Code
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.

843 lines
23 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifndef NETWORKVAR_H
  7. #define NETWORKVAR_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "tier0/dbg.h"
  12. #include "tier0/platform.h"
  13. #include "convar.h"
  14. #if defined( CLIENT_DLL ) || defined( GAME_DLL )
  15. #include "basehandle.h"
  16. #endif
  17. #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)
  18. #define MyOffsetOf( type, var ) ( (int)(intp)&((type*)0)->var )
  19. #ifdef _DEBUG
  20. #undef new
  21. extern bool g_bUseNetworkVars;
  22. #define CHECK_USENETWORKVARS if(g_bUseNetworkVars)
  23. // Use START_ and END_CHECK_USENETWORKVARS if your code is longer than one line.
  24. #define START_CHECK_USENETWORKVARS if(g_bUseNetworkVars) {
  25. #define END_CHECK_USENETWORKVARS }
  26. #else
  27. #define CHECK_USENETWORKVARS // don't check for g_bUseNetworkVars
  28. #define START_CHECK_USENETWORKVARS
  29. #define END_CHECK_USENETWORKVARS
  30. #endif
  31. //
  32. // Networkvar flags.
  33. //
  34. #define NETWORKVAR_IS_A_VECTOR 0x0001 // Is it any type of network vector?
  35. #define NETWORKVAR_VECTOR_XYZ_FLAG 0x0002 // Is it a CNetworkVectorXYZ?
  36. #define NETWORKVAR_VECTOR_XY_SEPARATEZ_FLAG 0x0004 // Is it a CNetworkVectorXY_SeparateZ?
  37. #define NETWORKVAR_ALL_FLAGS ( NETWORKVAR_IS_A_VECTOR | NETWORKVAR_VECTOR_XYZ_FLAG | NETWORKVAR_VECTOR_XY_SEPARATEZ_FLAG )
  38. // network vars use memcmp when fields are set. To ensure proper behavior your
  39. // object's memory should be initialized to zero. This happens for entities automatically
  40. // use this for other classes.
  41. class CMemZeroOnNew
  42. {
  43. public:
  44. void *operator new( size_t nSize )
  45. {
  46. void *pMem = MemAlloc_Alloc( nSize );
  47. V_memset( pMem, 0, nSize );
  48. return pMem;
  49. }
  50. void* operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
  51. {
  52. void *pMem = MemAlloc_Alloc( nSize, pFileName, nLine );
  53. V_memset( pMem, 0, nSize );
  54. return pMem;
  55. }
  56. void operator delete(void *pData)
  57. {
  58. if ( pData )
  59. {
  60. g_pMemAlloc->Free(pData);
  61. }
  62. }
  63. void operator delete( void* pData, int nBlockUse, const char *pFileName, int nLine )
  64. {
  65. if ( pData )
  66. {
  67. g_pMemAlloc->Free(pData, pFileName, nLine );
  68. }
  69. }
  70. };
  71. inline int InternalCheckDeclareClass( const char *pClassName, const char *pClassNameMatch, void *pTestPtr, void *pBasePtr )
  72. {
  73. // This makes sure that casting from ThisClass to BaseClass works right. You'll get a compiler error if it doesn't
  74. // work at all, and you'll get a runtime error if you use multiple inheritance.
  75. Assert( pTestPtr == pBasePtr );
  76. // This is triggered by IMPLEMENT_SERVER_CLASS. It does DLLClassName::CheckDeclareClass( #DLLClassName ).
  77. // If they didn't do a DECLARE_CLASS in DLLClassName, then it'll be calling its base class's version
  78. // and the class names won't match.
  79. Assert( (void*)pClassName == (void*)pClassNameMatch );
  80. return 0;
  81. }
  82. template <typename T>
  83. inline int CheckDeclareClass_Access( T *, const char *pShouldBe )
  84. {
  85. return T::CheckDeclareClass( pShouldBe );
  86. }
  87. #ifndef _STATIC_LINKED
  88. #ifdef _MSC_VER
  89. #if defined(_DEBUG) && (_MSC_VER > 1200 )
  90. #define VALIDATE_DECLARE_CLASS 1
  91. #endif
  92. #endif
  93. #endif
  94. #ifdef VALIDATE_DECLARE_CLASS
  95. #define DECLARE_CLASS( className, baseClassName ) \
  96. typedef baseClassName BaseClass; \
  97. typedef className ThisClass; \
  98. template <typename T> friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \
  99. static int CheckDeclareClass( const char *pShouldBe ) \
  100. { \
  101. InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \
  102. return CheckDeclareClass_Access( (BaseClass *)NULL, #baseClassName ); \
  103. }
  104. // Use this macro when you have a base class, but it's part of a library that doesn't use network vars
  105. // or any of the things that use ThisClass or BaseClass.
  106. #define DECLARE_CLASS_GAMEROOT( className, baseClassName ) \
  107. typedef baseClassName BaseClass; \
  108. typedef className ThisClass; \
  109. template <typename T> friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \
  110. static int CheckDeclareClass( const char *pShouldBe ) \
  111. { \
  112. return InternalCheckDeclareClass( pShouldBe, #className, (ThisClass*)0xFFFFF, (BaseClass*)(ThisClass*)0xFFFFF ); \
  113. }
  114. // Deprecated macro formerly used to work around VC++98 bug
  115. #define DECLARE_CLASS_NOFRIEND( className, baseClassName ) \
  116. DECLARE_CLASS( className, baseClassName )
  117. #define DECLARE_CLASS_NOBASE( className ) \
  118. typedef className ThisClass; \
  119. template <typename T> friend int CheckDeclareClass_Access(T *, const char *pShouldBe); \
  120. static int CheckDeclareClass( const char *pShouldBe ) \
  121. { \
  122. return InternalCheckDeclareClass( pShouldBe, #className, 0, 0 ); \
  123. }
  124. #else
  125. #define DECLARE_CLASS( className, baseClassName ) \
  126. typedef baseClassName BaseClass; \
  127. typedef className ThisClass;
  128. #define DECLARE_CLASS_GAMEROOT( className, baseClassName ) DECLARE_CLASS( className, baseClassName )
  129. #define DECLARE_CLASS_NOFRIEND( className, baseClassName ) DECLARE_CLASS( className, baseClassName )
  130. #define DECLARE_CLASS_NOBASE( className ) typedef className ThisClass;
  131. #endif
  132. // All classes that contain CNetworkVars need a NetworkStateChanged() function. If the class is not an entity,
  133. // it needs to forward the call to the entity it's in. These macros can help.
  134. // These macros setup an entity pointer in your class. Use IMPLEMENT_NETWORKVAR_CHAIN before you do
  135. // anything inside the class itself.
  136. class CBaseEntity;
  137. class CAutoInitEntPtr
  138. {
  139. public:
  140. CAutoInitEntPtr()
  141. {
  142. m_pEnt = NULL;
  143. }
  144. CBaseEntity *m_pEnt;
  145. };
  146. //TODO: Currently, these don't get the benefit of tracking changes to individual vars.
  147. // Would be nice if they did.
  148. #define DECLARE_NETWORKVAR_CHAIN() \
  149. CAutoInitEntPtr __m_pChainEntity; \
  150. void NetworkStateChanged() { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); } \
  151. void NetworkStateChanged( void *pVar ) { CHECK_USENETWORKVARS __m_pChainEntity.m_pEnt->NetworkStateChanged(); }
  152. #define IMPLEMENT_NETWORKVAR_CHAIN( varName ) \
  153. (varName)->__m_pChainEntity.m_pEnt = this;
  154. // Use this macro when you want to embed a structure inside your entity and have CNetworkVars in it.
  155. template< class T >
  156. static inline void DispatchNetworkStateChanged( T *pObj )
  157. {
  158. CHECK_USENETWORKVARS pObj->NetworkStateChanged();
  159. }
  160. template< class T >
  161. static inline void DispatchNetworkStateChanged( T *pObj, void *pVar )
  162. {
  163. CHECK_USENETWORKVARS pObj->NetworkStateChanged( pVar );
  164. }
  165. #define DECLARE_EMBEDDED_NETWORKVAR() \
  166. template <typename T> friend int ServerClassInit( T * ); \
  167. template <typename T> friend int ClientClassInit( T * ); \
  168. virtual void NetworkStateChanged() {} virtual void NetworkStateChanged( void *pProp ) {}
  169. template < typename T, typename ContainingClass, typename GetOffset >
  170. class NetworkVarEmbedded : public T
  171. {
  172. private:
  173. // NOTE: Assignment operator is disabled because it doesn't call copy constructors of scalar types within the aggregate, so they are not marked changed
  174. template< class U > NetworkVarEmbedded& operator=( U &&val ) = delete;
  175. T& Data() { return *this; }
  176. const T& Data() const { return *this; }
  177. public:
  178. operator const T& () const { return Data(); }
  179. // $$$REI TODO: Why doesn't this implementation work as an assignment operator?
  180. template< typename U >
  181. void CopyFrom( U&& src ) {
  182. Data() = Forward<U>( src );
  183. NetworkStateChanged();
  184. }
  185. const T* Get( void ) const { return &Data(); }
  186. T* Get( void ) { return &Data(); }
  187. ContainingClass* GetEmbeddedVarOuterPtr() { return ( ContainingClass* )( ( ( char* )this ) - GetOffset::Get() ); }
  188. virtual void NetworkStateChanged()
  189. {
  190. ContainingClass *pOuter = GetEmbeddedVarOuterPtr();
  191. DispatchNetworkStateChanged( pOuter );
  192. }
  193. virtual void NetworkStateChanged( void *pVar )
  194. {
  195. ContainingClass *pOuter = GetEmbeddedVarOuterPtr();
  196. DispatchNetworkStateChanged( pOuter, pVar );
  197. }
  198. };
  199. #define CNetworkVarEmbedded( type, name ) \
  200. struct GetOffset_##name{ static FORCEINLINE int Get() { return MyOffsetOf( ThisClass, name ); } }; \
  201. typedef NetworkVarEmbedded< type, ThisClass, GetOffset_##name > NetworkVar_##name; \
  202. friend class NetworkVarEmbedded< type, ThisClass, GetOffset_##name >; \
  203. NetworkVar_##name name;
  204. // Zero the object -- necessary for CNetworkVar and possibly other cases.
  205. template<typename T>
  206. FORCEINLINE void EnsureValidValue( T &x ) { x = T(0); }
  207. // For types that cannot compile the line above (such as QAngle, Vector, etc.)
  208. // define a EnsureValidValue overload in the appropriate header files.
  209. class CNetworkVarFlagsBase
  210. {
  211. public:
  212. // A combination of NETWORKVAR_ flags. SendProps store these for additional information
  213. // about what kind of CNetworkVar the SendProp is linked to.
  214. static FORCEINLINE int GetNetworkVarFlags() { return 0; }
  215. };
  216. // when we box ints into floats, the comparison of floats doesn't work
  217. template <typename T>
  218. inline bool NetworkParanoidUnequal( const T &a, const T &b )
  219. {
  220. return a != b;
  221. }
  222. template <>
  223. inline bool NetworkParanoidUnequal( const float &a, const float &b )
  224. {
  225. //return 0 != memcmp( &a, &b, sizeof( a ) );
  226. union
  227. {
  228. float f32;
  229. uint32 u32;
  230. } p, q;
  231. p.f32 = a;
  232. q.f32 = b;
  233. return p.u32 != q.u32;
  234. }
  235. template <>
  236. inline bool NetworkParanoidUnequal( const double &a, const double &b )
  237. {
  238. // return 0 != memcmp( &a, &b, sizeof( a ) );
  239. union
  240. {
  241. double f64;
  242. uint64 u64;
  243. } p, q;
  244. p.f64 = a;
  245. q.f64 = b;
  246. return p.u64 != q.u64;
  247. }
  248. template< class Type, class Changer >
  249. class CNetworkVarBase : public CNetworkVarFlagsBase
  250. {
  251. public:
  252. CNetworkVarBase()
  253. {
  254. // Always initialize m_Value. Not doing this means that the initial behavior
  255. // is random. For float types this random behavior can persist arbitrarily
  256. // long because of our non-IEEE comparisons which may make NaN be equal to
  257. // everything.
  258. EnsureValidValue( m_Value );
  259. }
  260. FORCEINLINE explicit CNetworkVarBase( Type val )
  261. : m_Value( val )
  262. {
  263. NetworkStateChanged();
  264. }
  265. FORCEINLINE const Type& SetDirect( const Type &val )
  266. {
  267. NetworkStateChanged();
  268. m_Value = val;
  269. return m_Value;
  270. }
  271. FORCEINLINE const Type& Set( const Type &val )
  272. {
  273. if ( NetworkParanoidUnequal( m_Value, val ) )
  274. {
  275. NetworkStateChanged();
  276. m_Value = val;
  277. }
  278. return m_Value;
  279. }
  280. template< class C >
  281. FORCEINLINE const Type& operator=( const C &val )
  282. {
  283. return Set( ( const Type )val );
  284. }
  285. template< class C >
  286. FORCEINLINE const Type& operator=( const CNetworkVarBase< C, Changer > &val )
  287. {
  288. return Set( ( const Type )val.m_Value );
  289. }
  290. FORCEINLINE Type& GetForModify()
  291. {
  292. NetworkStateChanged();
  293. return m_Value;
  294. }
  295. template< class C >
  296. FORCEINLINE const Type& operator+=( const C &val )
  297. {
  298. return Set( m_Value + ( const Type )val );
  299. }
  300. template< class C >
  301. FORCEINLINE const Type& operator-=( const C &val )
  302. {
  303. return Set( m_Value - ( const Type )val );
  304. }
  305. template< class C >
  306. FORCEINLINE const Type& operator/=( const C &val )
  307. {
  308. return Set( m_Value / ( const Type )val );
  309. }
  310. template< class C >
  311. FORCEINLINE const Type& operator*=( const C &val )
  312. {
  313. return Set( m_Value * ( const Type )val );
  314. }
  315. template< class C >
  316. FORCEINLINE const Type& operator^=( const C &val )
  317. {
  318. return Set( m_Value ^ ( const Type )val );
  319. }
  320. template< class C >
  321. FORCEINLINE const Type& operator|=( const C &val )
  322. {
  323. return Set( m_Value | ( const Type )val );
  324. }
  325. FORCEINLINE const Type& operator++()
  326. {
  327. return (*this += 1);
  328. }
  329. FORCEINLINE Type operator--()
  330. {
  331. return (*this -= 1);
  332. }
  333. FORCEINLINE Type operator++( int ) // postfix version..
  334. {
  335. Type val = m_Value;
  336. (*this += 1);
  337. return val;
  338. }
  339. FORCEINLINE Type operator--( int ) // postfix version..
  340. {
  341. Type val = m_Value;
  342. (*this -= 1);
  343. return val;
  344. }
  345. // For some reason the compiler only generates type conversion warnings for this operator when used like
  346. // CNetworkVarBase<unsigned char> = 0x1
  347. // (it warns about converting from an int to an unsigned char).
  348. template< class C >
  349. FORCEINLINE const Type& operator&=( const C &val )
  350. {
  351. return Set( m_Value & ( const Type )val );
  352. }
  353. FORCEINLINE operator const Type&() const
  354. {
  355. return m_Value;
  356. }
  357. FORCEINLINE const Type& Get() const
  358. {
  359. return m_Value;
  360. }
  361. FORCEINLINE const Type* operator->() const
  362. {
  363. return &m_Value;
  364. }
  365. Type m_Value;
  366. protected:
  367. FORCEINLINE void NetworkStateChanged()
  368. {
  369. Changer::NetworkStateChanged( this );
  370. }
  371. FORCEINLINE void NetworkStateChanged( void *pVar )
  372. {
  373. Changer::NetworkStateChanged( this, pVar );
  374. }
  375. };
  376. #include "networkvar_vector.h"
  377. template< class Type, class Changer >
  378. class CNetworkColor32Base : public CNetworkVarBase< Type, Changer >
  379. {
  380. typedef CNetworkVarBase< Type, Changer > base;
  381. public:
  382. inline void Init( byte rVal, byte gVal, byte bVal )
  383. {
  384. SetR( rVal );
  385. SetG( gVal );
  386. SetB( bVal );
  387. }
  388. inline void Init( byte rVal, byte gVal, byte bVal, byte aVal )
  389. {
  390. SetR( rVal );
  391. SetG( gVal );
  392. SetB( bVal );
  393. SetA( aVal );
  394. }
  395. const Type& operator=( const Type &val )
  396. {
  397. return this->Set( val );
  398. }
  399. const Type& operator=( const CNetworkColor32Base<Type,Changer> &val )
  400. {
  401. return base::Set( val.m_Value );
  402. }
  403. inline byte GetR() const { return this->m_Value.r; }
  404. inline byte GetG() const { return this->m_Value.g; }
  405. inline byte GetB() const { return this->m_Value.b; }
  406. inline byte GetA() const { return this->m_Value.a; }
  407. inline void SetR( byte val ) { SetVal( this->m_Value.r, val ); }
  408. inline void SetG( byte val ) { SetVal( this->m_Value.g, val ); }
  409. inline void SetB( byte val ) { SetVal( this->m_Value.b, val ); }
  410. inline void SetA( byte val ) { SetVal( this->m_Value.a, val ); }
  411. protected:
  412. inline void SetVal( byte &out, const byte &in )
  413. {
  414. if ( out != in )
  415. {
  416. this->NetworkStateChanged();
  417. out = in;
  418. }
  419. }
  420. };
  421. // Network quaternion wrapper.
  422. template< class Type, class Changer >
  423. class CNetworkQuaternionBase : public CNetworkVarBase< Type, Changer >
  424. {
  425. typedef CNetworkVarBase< Type, Changer > base;
  426. public:
  427. inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 )
  428. {
  429. base::Set( Quaternion( ix, iy, iz, iw ) );
  430. }
  431. const Type& operator=( const Type &val )
  432. {
  433. return Set( val );
  434. }
  435. const Type& operator=( const CNetworkQuaternionBase<Type,Changer> &val )
  436. {
  437. return Set( val.m_Value );
  438. }
  439. inline float GetX() const { return this->m_Value.x; }
  440. inline float GetY() const { return this->m_Value.y; }
  441. inline float GetZ() const { return this->m_Value.z; }
  442. inline float GetW() const { return this->m_Value.w; }
  443. inline float operator[]( int i ) const { return this->m_Value[i]; }
  444. inline void SetX( float val ) { DetectChange( this->m_Value.x, val ); }
  445. inline void SetY( float val ) { DetectChange( this->m_Value.y, val ); }
  446. inline void SetZ( float val ) { DetectChange( this->m_Value.z, val ); }
  447. inline void SetW( float val ) { DetectChange( this->m_Value.w, val ); }
  448. inline void Set( int i, float val ) { DetectChange( this->m_Value[i], val ); }
  449. bool operator==( const Type &val ) const
  450. {
  451. return !NetworkParanoidUnequal( this->m_Value, ( Type )val );
  452. }
  453. bool operator!=( const Type &val ) const
  454. {
  455. return NetworkParanoidUnequal( this->m_Value, val );
  456. }
  457. const Type operator+( const Type &val ) const
  458. {
  459. return this->m_Value + val;
  460. }
  461. const Type operator-( const Type &val ) const
  462. {
  463. return this->m_Value - val;
  464. }
  465. const Type operator*( const Type &val ) const
  466. {
  467. return this->m_Value * val;
  468. }
  469. const Type& operator*=( float val )
  470. {
  471. return Set( this->m_Value * val );
  472. }
  473. const Type operator*( float val ) const
  474. {
  475. return this->m_Value * val;
  476. }
  477. const Type operator/( const Type &val ) const
  478. {
  479. return this->m_Value / val;
  480. }
  481. private:
  482. inline void DetectChange( float &out, float in )
  483. {
  484. if ( NetworkParanoidUnequal( out, in ) )
  485. {
  486. this->NetworkStateChanged();
  487. out = in;
  488. }
  489. }
  490. };
  491. // Network ehandle wrapper.
  492. #if defined( CLIENT_DLL ) || defined( GAME_DLL )
  493. template< class Type, class Changer >
  494. class CNetworkHandleBase : public CNetworkVarBase< CBaseHandle, Changer >
  495. {
  496. typedef CNetworkVarBase< CBaseHandle, Changer > base;
  497. public:
  498. const Type* operator=( const Type *val )
  499. {
  500. return Set( val );
  501. }
  502. const Type& operator=( const CNetworkHandleBase<Type,Changer> &val )
  503. {
  504. const CBaseHandle &handle = CNetworkVarBase<CBaseHandle,Changer>::Set( val.m_Value );
  505. return *(const Type*)handle.Get();
  506. }
  507. bool operator !() const
  508. {
  509. return !this->m_Value.Get();
  510. }
  511. operator Type*() const
  512. {
  513. return static_cast< Type* >( this->m_Value.Get() );
  514. }
  515. const Type* Set( const Type *val )
  516. {
  517. if ( CNetworkHandleBase<Type,Changer>::m_Value != val )
  518. {
  519. this->NetworkStateChanged();
  520. CNetworkHandleBase<Type,Changer>::m_Value = val;
  521. }
  522. return val;
  523. }
  524. Type* Get() const
  525. {
  526. return static_cast< Type* >( CNetworkHandleBase<Type,Changer>::m_Value.Get() );
  527. }
  528. Type* operator->() const
  529. {
  530. return static_cast< Type* >( CNetworkHandleBase<Type,Changer>::m_Value.Get() );
  531. }
  532. bool operator==( const Type *val ) const
  533. {
  534. return CNetworkHandleBase<Type,Changer>::m_Value == val;
  535. }
  536. bool operator!=( const Type *val ) const
  537. {
  538. return CNetworkHandleBase<Type,Changer>::m_Value != val;
  539. }
  540. };
  541. #define CNetworkHandle( type, name ) CNetworkHandleInternal( type, name, NetworkStateChanged )
  542. #define CNetworkHandleInternal( type, name, stateChangedFn ) \
  543. NETWORK_VAR_START( type, name ) \
  544. NETWORK_VAR_END( type, name, CNetworkHandleBase, stateChangedFn )
  545. #endif
  546. // Use this macro to define a network variable.
  547. #define CNetworkVar( type, name ) \
  548. NETWORK_VAR_START( type, name ) \
  549. NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged )
  550. // Use this macro when you have a base class with a variable, and it doesn't have that variable in a SendTable,
  551. // but a derived class does. Then, the entity is only flagged as changed when the variable is changed in
  552. // an entity that wants to transmit the variable.
  553. #define CNetworkVarForDerived( type, name ) \
  554. virtual void NetworkStateChanged_##name() {} \
  555. virtual void NetworkStateChanged_##name( void *pVar ) {} \
  556. NETWORK_VAR_START( type, name ) \
  557. NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name )
  558. #define CNetworkHandleForDerived( type, name ) \
  559. virtual void NetworkStateChanged_##name() {} \
  560. virtual void NetworkStateChanged_##name( void *pVar ) {} \
  561. CNetworkHandleInternal( type, name, NetworkStateChanged_##name )
  562. #define CNetworkArrayForDerived( type, name, count ) \
  563. virtual void NetworkStateChanged_##name() {} \
  564. virtual void NetworkStateChanged_##name( void *pVar ) {} \
  565. CNetworkArrayInternal( type, name, count, NetworkStateChanged_##name )
  566. #define IMPLEMENT_NETWORK_VAR_FOR_DERIVED( name ) \
  567. virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \
  568. virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); }
  569. // This virtualizes the change detection on the variable, but it is ON by default.
  570. // Use this when you have a base class in which MOST of its derived classes use this variable
  571. // in their SendTables, but there are a couple that don't (and they
  572. // can use DISABLE_NETWORK_VAR_FOR_DERIVED).
  573. #define CNetworkVarForDerived_OnByDefault( type, name ) \
  574. virtual void NetworkStateChanged_##name() { CHECK_USENETWORKVARS NetworkStateChanged(); } \
  575. virtual void NetworkStateChanged_##name( void *pVar ) { CHECK_USENETWORKVARS NetworkStateChanged( pVar ); } \
  576. NETWORK_VAR_START( type, name ) \
  577. NETWORK_VAR_END( type, name, CNetworkVarBase, NetworkStateChanged_##name )
  578. #define DISABLE_NETWORK_VAR_FOR_DERIVED( name ) \
  579. virtual void NetworkStateChanged_##name() {} \
  580. virtual void NetworkStateChanged_##name( void *pVar ) {}
  581. #define CNetworkQuaternion( name ) \
  582. NETWORK_VAR_START( Quaternion, name ) \
  583. NETWORK_VAR_END( Quaternion, name, CNetworkQuaternionBase, NetworkStateChanged )
  584. // Helper for color32's. Contains GetR(), SetR(), etc.. functions.
  585. #define CNetworkColor32( name ) \
  586. NETWORK_VAR_START( color32, name ) \
  587. NETWORK_VAR_END( color32, name, CNetworkColor32Base, NetworkStateChanged )
  588. #define CNetworkString( name, length ) \
  589. class NetworkVar_##name; \
  590. friend class NetworkVar_##name; \
  591. typedef ThisClass MakeANetworkVar_##name; \
  592. class NetworkVar_##name : public CNetworkVarFlagsBase\
  593. { \
  594. public: \
  595. operator const char*() const { return m_Value; } \
  596. const char* Get() const { return m_Value; } \
  597. char* GetForModify() \
  598. { \
  599. NetworkStateChanged(); \
  600. return m_Value; \
  601. } \
  602. protected: \
  603. inline void NetworkStateChanged() \
  604. { \
  605. START_CHECK_USENETWORKVARS \
  606. ThisClass *pThis = ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name))); \
  607. pThis->NetworkStateChanged(); \
  608. END_CHECK_USENETWORKVARS \
  609. } \
  610. private: \
  611. char m_Value[length]; \
  612. }; \
  613. typedef NetworkVar_##name NetworkVarType_##name; \
  614. NetworkVar_##name name;
  615. // Use this to define networked arrays.
  616. // You can access elements for reading with operator[], and you can set elements with the Set() function.
  617. #define CNetworkArrayInternal( type, name, count, stateChangedFn ) \
  618. class NetworkVar_##name; \
  619. friend class NetworkVar_##name; \
  620. typedef ThisClass MakeANetworkVar_##name; \
  621. class NetworkVar_##name \
  622. { \
  623. public: \
  624. template <typename T> friend int ServerClassInit(T *); \
  625. const type& operator[]( int i ) const \
  626. { \
  627. return Get( i ); \
  628. } \
  629. \
  630. const type& Get( int i ) const \
  631. { \
  632. Assert( i >= 0 && i < count ); \
  633. return m_Value[i]; \
  634. } \
  635. \
  636. type& GetForModify( int i ) \
  637. { \
  638. Assert( i >= 0 && i < count ); \
  639. NetworkStateChanged( i ); \
  640. return m_Value[i]; \
  641. } \
  642. \
  643. void Set( int i, const type &val ) \
  644. { \
  645. Assert( i >= 0 && i < count ); \
  646. if( memcmp( &m_Value[i], &val, sizeof(type) ) ) \
  647. { \
  648. NetworkStateChanged( i ); \
  649. m_Value[i] = val; \
  650. } \
  651. } \
  652. const type* Base() const { return m_Value; } \
  653. int Count() const { return count; } \
  654. type m_Value[count]; \
  655. protected: \
  656. inline void NetworkStateChanged( int index ) \
  657. { \
  658. START_CHECK_USENETWORKVARS \
  659. ThisClass *pThis = ((ThisClass*)(((char*)this) - MyOffsetOf(ThisClass,name))); \
  660. pThis->stateChangedFn( &m_Value[index] ); \
  661. END_CHECK_USENETWORKVARS \
  662. } \
  663. }; \
  664. NetworkVar_##name name;
  665. #define CNetworkArray( type, name, count ) CNetworkArrayInternal( type, name, count, NetworkStateChanged )
  666. // Internal macros used in definitions of network vars.
  667. #define NETWORK_VAR_START( networkVarType, networkVarName ) \
  668. class NetworkVar_##networkVarName; \
  669. friend class NetworkVar_##networkVarName; \
  670. typedef ThisClass MakeANetworkVar_##networkVarName; \
  671. class NetworkVar_##networkVarName \
  672. { \
  673. public: \
  674. template <typename T> friend int ServerClassInit(T *);
  675. // pChangedPtr could be the Y or Z component of a vector, so possibly != to pNetworkVar.
  676. #define NETWORK_VAR_END( networkVarType, networkVarName, baseClassName, stateChangedFn ) \
  677. public: \
  678. static inline void NetworkStateChanged( void *pNetworkVar, void *pChangedPtr ) \
  679. { \
  680. START_CHECK_USENETWORKVARS \
  681. ThisClass *pThis = ( (ThisClass*)(((char*)pNetworkVar) - MyOffsetOf(ThisClass,networkVarName)) ); \
  682. pThis->stateChangedFn( pChangedPtr ); \
  683. END_CHECK_USENETWORKVARS \
  684. } \
  685. static inline void NetworkStateChanged( void *pNetworkVar ) \
  686. { \
  687. NetworkStateChanged( pNetworkVar, pNetworkVar ); \
  688. } \
  689. }; \
  690. typedef baseClassName< networkVarType, NetworkVar_##networkVarName > NetworkVarType_##networkVarName; \
  691. baseClassName< networkVarType, NetworkVar_##networkVarName > networkVarName;
  692. #endif // NETWORKVAR_H