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.

309 lines
8.1 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "cbase.h"
  8. #include "ServerNetworkProperty.h"
  9. #include "tier0/dbg.h"
  10. #include "gameinterface.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include "tier0/memdbgon.h"
  13. extern CTimedEventMgr g_NetworkPropertyEventMgr;
  14. //-----------------------------------------------------------------------------
  15. // Save/load
  16. //-----------------------------------------------------------------------------
  17. BEGIN_DATADESC_NO_BASE( CServerNetworkProperty )
  18. // DEFINE_FIELD( m_pOuter, FIELD_CLASSPTR ),
  19. // DEFINE_FIELD( m_pPev, FIELD_CLASSPTR ),
  20. // DEFINE_FIELD( m_PVSInfo, PVSInfo_t ),
  21. // DEFINE_FIELD( m_pServerClass, FIELD_CLASSPTR ),
  22. DEFINE_GLOBAL_FIELD( m_hParent, FIELD_EHANDLE ),
  23. // DEFINE_FIELD( m_TimerEvent, CEventRegister ),
  24. // DEFINE_FIELD( m_bPendingStateChange, FIELD_BOOLEAN ),
  25. END_DATADESC()
  26. //-----------------------------------------------------------------------------
  27. // Constructor, destructor
  28. //-----------------------------------------------------------------------------
  29. CServerNetworkProperty::CServerNetworkProperty()
  30. {
  31. Init( NULL );
  32. }
  33. CServerNetworkProperty::~CServerNetworkProperty()
  34. {
  35. /* Free our transmit proxy.
  36. if ( m_pTransmitProxy )
  37. {
  38. m_pTransmitProxy->Release();
  39. }*/
  40. engine->CleanUpEntityClusterList( &m_PVSInfo );
  41. // remove the attached edict if it exists
  42. DetachEdict();
  43. }
  44. //-----------------------------------------------------------------------------
  45. // Initialization
  46. //-----------------------------------------------------------------------------
  47. void CServerNetworkProperty::Init( CBaseEntity *pEntity )
  48. {
  49. // NOTE: We're in pEntity's constructor so we can't call virtual methods of pEntity here
  50. m_pPev = NULL;
  51. m_pOuter = pEntity;
  52. m_pServerClass = NULL;
  53. // m_pTransmitProxy = NULL;
  54. m_bPendingStateChange = false;
  55. m_PVSInfo.m_nClusterCount = 0;
  56. m_TimerEvent.Init( &g_NetworkPropertyEventMgr, this );
  57. }
  58. void CServerNetworkProperty::CacheServerClass()
  59. {
  60. m_pServerClass = m_pOuter->GetServerClass();
  61. }
  62. //-----------------------------------------------------------------------------
  63. // Connects, disconnects edicts
  64. //-----------------------------------------------------------------------------
  65. void CServerNetworkProperty::AttachEdict( edict_t *pRequiredEdict )
  66. {
  67. Assert ( !m_pPev );
  68. // see if there is an edict allocated for it, otherwise get one from the engine
  69. if ( !pRequiredEdict )
  70. {
  71. pRequiredEdict = engine->CreateEdict();
  72. }
  73. m_pPev = pRequiredEdict;
  74. m_pPev->SetEdict( GetBaseEntity(), true );
  75. }
  76. void CServerNetworkProperty::DetachEdict()
  77. {
  78. if ( m_pPev )
  79. {
  80. m_pPev->SetEdict( NULL, false );
  81. engine->RemoveEdict( m_pPev );
  82. m_pPev = NULL;
  83. }
  84. }
  85. //-----------------------------------------------------------------------------
  86. // Entity handles
  87. //-----------------------------------------------------------------------------
  88. IHandleEntity *CServerNetworkProperty::GetEntityHandle( )
  89. {
  90. return m_pOuter;
  91. }
  92. void CServerNetworkProperty::Release()
  93. {
  94. delete m_pOuter;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Returns the network parent
  98. //-----------------------------------------------------------------------------
  99. CServerNetworkProperty* CServerNetworkProperty::GetNetworkParent()
  100. {
  101. CBaseEntity *pParent = m_hParent.Get();
  102. return pParent ? pParent->NetworkProp() : NULL;
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Marks for deletion
  106. //-----------------------------------------------------------------------------
  107. void CServerNetworkProperty::MarkForDeletion()
  108. {
  109. m_pOuter->AddEFlags( EFL_KILLME );
  110. }
  111. bool CServerNetworkProperty::IsMarkedForDeletion() const
  112. {
  113. return ( m_pOuter->GetEFlags() & EFL_KILLME ) != 0;
  114. }
  115. //-----------------------------------------------------------------------------
  116. // PVS information
  117. //-----------------------------------------------------------------------------
  118. void CServerNetworkProperty::RecomputePVSInformation()
  119. {
  120. if ( m_pPev && ( ( m_pPev->m_fStateFlags & FL_EDICT_DIRTY_PVS_INFORMATION ) != 0 ) )
  121. {
  122. m_pPev->m_fStateFlags &= ~FL_EDICT_DIRTY_PVS_INFORMATION;
  123. engine->BuildEntityClusterList( edict(), &m_PVSInfo );
  124. }
  125. }
  126. //-----------------------------------------------------------------------------
  127. // Serverclass
  128. //-----------------------------------------------------------------------------
  129. ServerClass* CServerNetworkProperty::GetServerClass()
  130. {
  131. return m_pServerClass;
  132. }
  133. const char* CServerNetworkProperty::GetClassName() const
  134. {
  135. return STRING(m_pOuter->m_iClassname);
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Transmit proxies
  139. /*-----------------------------------------------------------------------------
  140. void CServerNetworkProperty::SetTransmitProxy( CBaseTransmitProxy *pProxy )
  141. {
  142. if ( m_pTransmitProxy )
  143. {
  144. m_pTransmitProxy->Release();
  145. }
  146. m_pTransmitProxy = pProxy;
  147. if ( m_pTransmitProxy )
  148. {
  149. m_pTransmitProxy->AddRef();
  150. }
  151. }*/
  152. //-----------------------------------------------------------------------------
  153. // PVS rules
  154. //-----------------------------------------------------------------------------
  155. bool CServerNetworkProperty::IsInPVS( const edict_t *pRecipient, const void *pvs, int pvssize )
  156. {
  157. RecomputePVSInformation();
  158. // ignore if not touching a PV leaf
  159. // negative leaf count is a node number
  160. // If no pvs, add any entity
  161. Assert( pvs && ( edict() != pRecipient ) );
  162. unsigned char *pPVS = ( unsigned char * )pvs;
  163. if ( m_PVSInfo.m_nClusterCount < 0 ) // too many clusters, use headnode
  164. {
  165. return ( engine->CheckHeadnodeVisible( m_PVSInfo.m_nHeadNode, pPVS, pvssize ) != 0);
  166. }
  167. for ( int i = 0; i < m_PVSInfo.m_nClusterCount; i++ )
  168. {
  169. if (pPVS[m_PVSInfo.m_pClusters[i] >> 3] & (1 << (m_PVSInfo.m_pClusters[i] & 7) ))
  170. return true;
  171. }
  172. return false; // not visible
  173. }
  174. //-----------------------------------------------------------------------------
  175. // PVS: this function is called a lot, so it avoids function calls
  176. //-----------------------------------------------------------------------------
  177. bool CServerNetworkProperty::IsInPVS( const CCheckTransmitInfo *pInfo )
  178. {
  179. // PVS data must be up to date
  180. Assert( !m_pPev || ( ( m_pPev->m_fStateFlags & FL_EDICT_DIRTY_PVS_INFORMATION ) == 0 ) );
  181. int i;
  182. // Early out if the areas are connected
  183. if ( !m_PVSInfo.m_nAreaNum2 )
  184. {
  185. for ( i=0; i< pInfo->m_AreasNetworked; i++ )
  186. {
  187. int clientArea = pInfo->m_Areas[i];
  188. if ( clientArea == m_PVSInfo.m_nAreaNum || engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum ) )
  189. break;
  190. }
  191. }
  192. else
  193. {
  194. // doors can legally straddle two areas, so
  195. // we may need to check another one
  196. for ( i=0; i< pInfo->m_AreasNetworked; i++ )
  197. {
  198. int clientArea = pInfo->m_Areas[i];
  199. if ( clientArea == m_PVSInfo.m_nAreaNum || clientArea == m_PVSInfo.m_nAreaNum2 )
  200. break;
  201. if ( engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum ) )
  202. break;
  203. if ( engine->CheckAreasConnected( clientArea, m_PVSInfo.m_nAreaNum2 ) )
  204. break;
  205. }
  206. }
  207. if ( i == pInfo->m_AreasNetworked )
  208. {
  209. // areas not connected
  210. return false;
  211. }
  212. // ignore if not touching a PV leaf
  213. // negative leaf count is a node number
  214. // If no pvs, add any entity
  215. Assert( edict() != pInfo->m_pClientEnt );
  216. unsigned char *pPVS = ( unsigned char * )pInfo->m_PVS;
  217. if ( m_PVSInfo.m_nClusterCount < 0 ) // too many clusters, use headnode
  218. {
  219. return (engine->CheckHeadnodeVisible( m_PVSInfo.m_nHeadNode, pPVS, pInfo->m_nPVSSize ) != 0);
  220. }
  221. for ( i = m_PVSInfo.m_nClusterCount; --i >= 0; )
  222. {
  223. int nCluster = m_PVSInfo.m_pClusters[i];
  224. if ( ((int)(pPVS[nCluster >> 3])) & BitVec_BitInByte( nCluster ) )
  225. return true;
  226. }
  227. return false; // not visible
  228. }
  229. void CServerNetworkProperty::SetUpdateInterval( float val )
  230. {
  231. if ( val == 0 )
  232. m_TimerEvent.StopUpdates();
  233. else
  234. m_TimerEvent.SetUpdateInterval( val );
  235. }
  236. void CServerNetworkProperty::FireEvent()
  237. {
  238. // Our timer went off. If our state has changed in the background, then
  239. // trigger a state change in the edict.
  240. if ( m_bPendingStateChange )
  241. {
  242. m_pPev->StateChanged();
  243. m_bPendingStateChange = false;
  244. }
  245. }