Team Fortress 2 Source Code as on 22/4/2020
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

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