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.

231 lines
6.5 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifndef ENTITYLIST_BASE_H
  7. #define ENTITYLIST_BASE_H
  8. #ifdef _WIN32
  9. #pragma once
  10. #endif
  11. #include "const.h"
  12. #include "basehandle.h"
  13. #include "utllinkedlist.h"
  14. #include "ihandleentity.h"
  15. class CEntInfo
  16. {
  17. public:
  18. IHandleEntity *m_pEntity;
  19. int m_SerialNumber;
  20. CEntInfo *m_pPrev;
  21. CEntInfo *m_pNext;
  22. #ifdef GAME_DLL
  23. string_t m_iName;
  24. string_t m_iClassName;
  25. #endif
  26. void ClearLinks();
  27. };
  28. class CBaseEntityList
  29. {
  30. public:
  31. CBaseEntityList();
  32. ~CBaseEntityList();
  33. // Add and remove entities. iForcedSerialNum should only be used on the client. The server
  34. // gets to dictate what the networkable serial numbers are on the client so it can send
  35. // ehandles over and they work.
  36. CBaseHandle AddNetworkableEntity( IHandleEntity *pEnt, int index, int iForcedSerialNum = -1 );
  37. CBaseHandle AddNonNetworkableEntity( IHandleEntity *pEnt );
  38. void RemoveEntity( CBaseHandle handle );
  39. // Get an ehandle from a networkable entity's index (note: if there is no entity in that slot,
  40. // then the ehandle will be invalid and produce NULL).
  41. CBaseHandle GetNetworkableHandle( int iEntity ) const;
  42. // ehandles use this in their Get() function to produce a pointer to the entity.
  43. IHandleEntity* LookupEntity( const CBaseHandle &handle ) const;
  44. IHandleEntity* LookupEntityByNetworkIndex( int edictIndex ) const;
  45. // Use these to iterate over all the entities.
  46. CBaseHandle FirstHandle() const;
  47. CBaseHandle NextHandle( CBaseHandle hEnt ) const;
  48. static CBaseHandle InvalidHandle();
  49. const CEntInfo *FirstEntInfo() const;
  50. const CEntInfo *NextEntInfo( const CEntInfo *pInfo ) const;
  51. const CEntInfo *GetEntInfoPtr( const CBaseHandle &hEnt ) const;
  52. const CEntInfo *GetEntInfoPtrByIndex( int index ) const;
  53. // Used by Foundry when an entity is respawned/edited.
  54. // We force the new entity's ehandle to be the same so anyone pointing at it still gets a valid CBaseEntity out of their ehandle.
  55. void ForceEntSerialNumber( int iEntIndex, int iSerialNumber );
  56. // Overridables.
  57. protected:
  58. // These are notifications to the derived class. It can cache info here if it wants.
  59. virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle );
  60. // It is safe to delete the entity here. We won't be accessing the pointer after
  61. // calling OnRemoveEntity.
  62. virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle );
  63. private:
  64. CBaseHandle AddEntityAtSlot( IHandleEntity *pEnt, int iSlot, int iForcedSerialNum );
  65. void RemoveEntityAtSlot( int iSlot );
  66. private:
  67. class CEntInfoList
  68. {
  69. public:
  70. CEntInfoList();
  71. const CEntInfo *Head() const { return m_pHead; }
  72. const CEntInfo *Tail() const { return m_pTail; }
  73. CEntInfo *Head() { return m_pHead; }
  74. CEntInfo *Tail() { return m_pTail; }
  75. void AddToHead( CEntInfo *pElement ) { LinkAfter( NULL, pElement ); }
  76. void AddToTail( CEntInfo *pElement ) { LinkBefore( NULL, pElement ); }
  77. void LinkBefore( CEntInfo *pBefore, CEntInfo *pElement );
  78. void LinkAfter( CEntInfo *pBefore, CEntInfo *pElement );
  79. void Unlink( CEntInfo *pElement );
  80. bool IsInList( CEntInfo *pElement );
  81. private:
  82. CEntInfo *m_pHead;
  83. CEntInfo *m_pTail;
  84. };
  85. int GetEntInfoIndex( const CEntInfo *pEntInfo ) const;
  86. // The first MAX_EDICTS entities are networkable. The rest are client-only or server-only.
  87. CEntInfo m_EntPtrArray[NUM_ENT_ENTRIES];
  88. CEntInfoList m_activeList;
  89. CEntInfoList m_freeNonNetworkableList;
  90. };
  91. // ------------------------------------------------------------------------------------ //
  92. // Inlines.
  93. // ------------------------------------------------------------------------------------ //
  94. inline int CBaseEntityList::GetEntInfoIndex( const CEntInfo *pEntInfo ) const
  95. {
  96. Assert( pEntInfo );
  97. int index = (int)(pEntInfo - m_EntPtrArray);
  98. Assert( index >= 0 && index < NUM_ENT_ENTRIES );
  99. return index;
  100. }
  101. inline CBaseHandle CBaseEntityList::GetNetworkableHandle( int iEntity ) const
  102. {
  103. Assert( iEntity >= 0 && iEntity < MAX_EDICTS );
  104. if ( m_EntPtrArray[iEntity].m_pEntity )
  105. return CBaseHandle( iEntity, m_EntPtrArray[iEntity].m_SerialNumber );
  106. else
  107. return CBaseHandle();
  108. }
  109. inline IHandleEntity* CBaseEntityList::LookupEntity( const CBaseHandle &handle ) const
  110. {
  111. if ( handle.m_Index == INVALID_EHANDLE_INDEX )
  112. return NULL;
  113. // You can use this to determine when something is trying to resolve
  114. // handles to static props as if they were handles to ordinary props,
  115. // but in practice this is done a great deal and seems benign.
  116. /*
  117. // 0x40000000 = STATICPROP_EHANDLE_MASK
  118. AssertMsg( ( handle.GetSerialNumber() != (0x40000000 >> NUM_SERIAL_NUM_SHIFT_BITS) ) ,
  119. "Tried to look up a static prop as if it was a regular entity, a bad pointer and doom are the result.\n" );
  120. */
  121. const CEntInfo *pInfo = &m_EntPtrArray[ handle.GetEntryIndex() ];
  122. if ( pInfo->m_SerialNumber == handle.GetSerialNumber() )
  123. return pInfo->m_pEntity;
  124. else
  125. return NULL;
  126. }
  127. inline IHandleEntity* CBaseEntityList::LookupEntityByNetworkIndex( int edictIndex ) const
  128. {
  129. // (Legacy support).
  130. if ( edictIndex < 0 )
  131. return NULL;
  132. Assert( edictIndex < NUM_ENT_ENTRIES );
  133. return m_EntPtrArray[edictIndex].m_pEntity;
  134. }
  135. inline CBaseHandle CBaseEntityList::FirstHandle() const
  136. {
  137. if ( !m_activeList.Head() )
  138. return INVALID_EHANDLE;
  139. int index = GetEntInfoIndex( m_activeList.Head() );
  140. return CBaseHandle( index, m_EntPtrArray[index].m_SerialNumber );
  141. }
  142. inline CBaseHandle CBaseEntityList::NextHandle( CBaseHandle hEnt ) const
  143. {
  144. int iSlot = hEnt.GetEntryIndex();
  145. CEntInfo *pNext = m_EntPtrArray[iSlot].m_pNext;
  146. if ( !pNext )
  147. return INVALID_EHANDLE;
  148. int index = GetEntInfoIndex( pNext );
  149. return CBaseHandle( index, m_EntPtrArray[index].m_SerialNumber );
  150. }
  151. inline CBaseHandle CBaseEntityList::InvalidHandle()
  152. {
  153. return INVALID_EHANDLE;
  154. }
  155. inline const CEntInfo *CBaseEntityList::FirstEntInfo() const
  156. {
  157. return m_activeList.Head();
  158. }
  159. inline const CEntInfo *CBaseEntityList::NextEntInfo( const CEntInfo *pInfo ) const
  160. {
  161. return pInfo->m_pNext;
  162. }
  163. inline const CEntInfo *CBaseEntityList::GetEntInfoPtr( const CBaseHandle &hEnt ) const
  164. {
  165. int iSlot = hEnt.GetEntryIndex();
  166. return &m_EntPtrArray[iSlot];
  167. }
  168. inline const CEntInfo *CBaseEntityList::GetEntInfoPtrByIndex( int index ) const
  169. {
  170. return &m_EntPtrArray[index];
  171. }
  172. inline void CBaseEntityList::ForceEntSerialNumber( int iEntIndex, int iSerialNumber )
  173. {
  174. m_EntPtrArray[iEntIndex].m_SerialNumber = iSerialNumber;
  175. }
  176. extern CBaseEntityList *g_pEntityList;
  177. #endif // ENTITYLIST_BASE_H