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.

308 lines
8.1 KiB

  1. //========= Copyright 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. m_pPev = NULL;
  50. m_pOuter = pEntity;
  51. m_pServerClass = NULL;
  52. // m_pTransmitProxy = NULL;
  53. m_bPendingStateChange = false;
  54. m_PVSInfo.m_nClusterCount = 0;
  55. m_TimerEvent.Init( &g_NetworkPropertyEventMgr, this );
  56. }
  57. //-----------------------------------------------------------------------------
  58. // Connects, disconnects edicts
  59. //-----------------------------------------------------------------------------
  60. void CServerNetworkProperty::AttachEdict( edict_t *pRequiredEdict )
  61. {
  62. Assert ( !m_pPev );
  63. // see if there is an edict allocated for it, otherwise get one from the engine
  64. if ( !pRequiredEdict )
  65. {
  66. pRequiredEdict = engine->CreateEdict();
  67. }
  68. m_pPev = pRequiredEdict;
  69. m_pPev->SetEdict( GetBaseEntity(), true );
  70. }
  71. void CServerNetworkProperty::DetachEdict()
  72. {
  73. if ( m_pPev )
  74. {
  75. m_pPev->SetEdict( NULL, false );
  76. engine->RemoveEdict( m_pPev );
  77. m_pPev = NULL;
  78. }
  79. }
  80. //-----------------------------------------------------------------------------
  81. // Entity handles
  82. //-----------------------------------------------------------------------------
  83. IHandleEntity *CServerNetworkProperty::GetEntityHandle( )
  84. {
  85. return m_pOuter;
  86. }
  87. void CServerNetworkProperty::Release()
  88. {
  89. delete m_pOuter;
  90. // Don't zero m_pOuter or reference any member variables after
  91. // the delete call because the object may be deleted.
  92. //m_pOuter = NULL;
  93. }
  94. //-----------------------------------------------------------------------------
  95. // Returns the network parent
  96. //-----------------------------------------------------------------------------
  97. CServerNetworkProperty* CServerNetworkProperty::GetNetworkParent()
  98. {
  99. CBaseEntity *pParent = m_hParent.Get();
  100. return pParent ? pParent->NetworkProp() : NULL;
  101. }
  102. //-----------------------------------------------------------------------------
  103. // Marks for deletion
  104. //-----------------------------------------------------------------------------
  105. void CServerNetworkProperty::MarkForDeletion()
  106. {
  107. m_pOuter->AddEFlags( EFL_KILLME );
  108. }
  109. bool CServerNetworkProperty::IsMarkedForDeletion() const
  110. {
  111. return ( m_pOuter->GetEFlags() & EFL_KILLME ) != 0;
  112. }
  113. //-----------------------------------------------------------------------------
  114. // PVS information
  115. //-----------------------------------------------------------------------------
  116. void CServerNetworkProperty::RecomputePVSInformation()
  117. {
  118. if ( m_pPev && ( ( m_pPev->m_fStateFlags & FL_EDICT_DIRTY_PVS_INFORMATION ) != 0 ) )
  119. {
  120. m_pPev->m_fStateFlags &= ~FL_EDICT_DIRTY_PVS_INFORMATION;
  121. engine->BuildEntityClusterList( edict(), &m_PVSInfo );
  122. }
  123. }
  124. //-----------------------------------------------------------------------------
  125. // Serverclass
  126. //-----------------------------------------------------------------------------
  127. ServerClass* CServerNetworkProperty::GetServerClass()
  128. {
  129. if ( !m_pServerClass )
  130. m_pServerClass = m_pOuter->GetServerClass();
  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 = m_PVSInfo.m_nClusterCount; --i >= 0; )
  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. }